Commit 8d42b26a authored by sim's avatar sim

Remove old web frontend

parent e710a96f
......@@ -2,7 +2,6 @@
Views are shared between these modules:
- `api`, for JSON and CSV interaction with data
- `pages`, to present HTML views to the user
- `contents`, for Python-generated contents
"""
......@@ -12,12 +11,10 @@ from django.views.generic.base import RedirectView as Redirect
from django.contrib.staticfiles.storage import staticfiles_storage as static
import gargantext.views.api.urls
import gargantext.views.pages.urls
urlpatterns = [ url(r'^admin/' , admin.site.urls )
, url(r'^api/' , include( gargantext.views.api.urls ) )
, url(r'^' , include( gargantext.views.pages.urls ) )
, url(r'^favicon.ico$', Redirect.as_view( url=static.url('favicon.ico')
, permanent=False), name="favicon" )
]
from django.contrib.auth import authenticate, login, logout
from django.core.urlresolvers import reverse_lazy
from django.views.generic import FormView
from django.shortcuts import redirect
from gargantext.util.db import session
from gargantext.models.users import User
from django import forms
from gargantext.models import Node, User
from gargantext.views.pages.projects import overview
from gargantext.views.pages.forms import AuthenticationForm
class LoginView(FormView):
form_class = AuthenticationForm
success_url = reverse_lazy(overview) #A la place de profile_view, choisir n'importe quelle vue
template_name = 'pages/main/login.html'
def form_valid(self, form):
username = form.cleaned_data['username']
password = form.cleaned_data['password']
user = authenticate(username=username, password=password)
if user is not None and user.is_active:
login(self.request, user)
node_user = session.query(Node).filter(Node.user_id == user.id, Node.typename== "USER").first()
#user hasn't been found inside Node table
#create it from auth table => node table
if node_user is None:
node_user = Node(
typename = 'USER',
#in node = > name
#in user = > username
name = user.username,
user_id = user.id,
)
node_user.hyperdata = {"language":"fr"}
session.add(node_user)
session.commit()
return super(LoginView, self).form_valid(form)
else:
return self.form_invalid(form)
def out(request):
"""Logout the user, and redirect to main page
"""
logout(request)
return redirect('/')
from gargantext.util.http import *
from gargantext.util.db import *
from gargantext.util.db_cache import cache
from gargantext.models import *
from gargantext.constants import *
from gargantext.settings import *
from datetime import datetime
from .main import get_user_params
from gargantext.constants import USER_LANG
def _get_user_project_corpus(request, project_id, corpus_id):
"""Helper method to get a corpus, knowing the project's and corpus' ID.
Raises HTTP errors when parameters (user, IDs...) are invalid.
"""
user = cache.User[request.user.id]
project = session.query(Node).filter(Node.id == project_id).first()
corpus = session.query(Node).filter(Node.id == corpus_id).filter(Node.parent_id == project_id).first()
if corpus is None:
raise Http404()
if not user.owns(corpus):
print("CORPORA: invalid user %i (User doesn't own this corpus)" % user.id)
return (False, user, project, corpus)
return (True, user, project, corpus)
@requires_auth
def docs_by_titles(request, project_id, corpus_id):
authorized, user, project, corpus = _get_user_project_corpus(request, project_id, corpus_id)
if not authorized:
return HttpResponseForbidden()
source_type = corpus.resources()[0]['type']
# response!
return render(
template_name = 'pages/corpora/titles.html',
request = request,
context = {
'debug': DEBUG,
'date': datetime.now(),
'project': project,
'corpus': corpus,
'resourcename' : get_resource(source_type)['name'],
'view': 'titles',
'user': request.user,
'user_parameters': get_user_params(user),
'languages': USER_LANG
},
)
@requires_auth
def docs_by_sources(request, project_id, corpus_id):
'''
Browse source titles for a given corpus
NB: javascript in page will GET counts from our api: facets?subfield=source
# TODO refactor Sources_dyna_charts_and_table.js
'''
# we pass our corpus to mark it's a corpora page
corpus = cache.Node[corpus_id]
# and the project just for project.id in corpusBannerTop
project = cache.Node[project_id]
user = cache.User[request.user.id]
source_type = corpus.resources()[0]['type']
# rendered page : sources.html
return render(
template_name = 'pages/corpora/sources.html',
request = request,
context = {
'debug': settings.DEBUG,
'date': datetime.now(),
'project': project,
'corpus' : corpus,
'resourcename' : get_resource(source_type)['name'],
'user': request.user,
'user_parameters': get_user_params(user),
'view': 'sources',
'languages': USER_LANG
},
)
@requires_auth
def docs_by_authors(request, project_id, corpus_id):
'''
Browse authors for a given corpus
NB: javascript in page will GET counts from our api: facets?subfield=author
# TODO refactor Author && Sources_dyna_charts_and_table.js
'''
# we pass our corpus to mark it's a corpora page
corpus = cache.Node[corpus_id]
# and the project just for project.id in corpusBannerTop
project = cache.Node[project_id]
user = cache.User[request.user.id]
source_type = corpus.resources()[0]['type']
# rendered page : sources.html
node_user = get_node_user(user)
return render(
template_name = 'pages/corpora/authors.html',
request = request,
context = {
'debug': settings.DEBUG,
'date': datetime.now(),
'project': project,
'corpus' : corpus,
'resourcename' : get_resource(source_type)['name'],
'view': 'authors',
'user': request.user,
'user_parameters': node_user.hyperdata,
'languages': USER_LANG
},
)
@requires_auth
def analytics(request, project_id, corpus_id):
authorized, user, project, corpus = _get_user_project_corpus(request, project_id, corpus_id)
if not authorized:
return HttpResponseForbidden()
source_type = corpus.resources()[0]['type']
# response!
return render(
template_name = 'pages/analytics/histories.html',
request = request,
context = {
'debug': DEBUG,
'date': datetime.now(),
'project': project,
'corpus': corpus,
'resourcename' : get_resource(source_type)['name'],
'view': 'analytics',
'user': request.user,
'user_parameters': get_user_params(user),
'languages': USER_LANG
},
)
from django import forms
from django.contrib.auth import (
authenticate, get_user_model, password_validation,
)
from django.contrib.auth.hashers import (
UNUSABLE_PASSWORD_PREFIX, identify_hasher,
)
from django.utils.html import format_html, format_html_join
from django.utils.text import capfirst
from django.utils.translation import ugettext, ugettext_lazy as _
from gargantext.models.users import User
class AuthenticationForm(forms.Form):
"""
Base class for authenticating users. Extend this to get a form that accepts
username/password logins.
"""
username = forms.CharField(max_length=254, widget=forms.TextInput(attrs={'class':"form-control", 'placeholder': "username"}))
password = forms.CharField(label=_("Password"), strip=False, widget=forms.PasswordInput(attrs={'class':'form-control', 'placeholder': 'Password'}))
error_messages = {
'invalid_login': _("Please enter a correct %(username)s and password. "
"Note that both fields may be case-sensitive."),
'inactive': _("This account is inactive."),
}
def __init__(self, request=None, *args, **kwargs):
"""
The 'request' parameter is set for custom auth use by subclasses.
The form data comes in via the standard 'data' kwarg.
"""
self.request = request
self.user_cache = None
super(AuthenticationForm, self).__init__(*args, **kwargs)
# Set the label for the "username" field.
UserModel = get_user_model()
self.username_field = UserModel._meta.get_field(UserModel.USERNAME_FIELD)
if self.fields['username'].label is None:
self.fields['username'].label = capfirst(self.username_field.verbose_name)
def clean(self):
username = self.cleaned_data.get('username')
password = self.cleaned_data.get('password')
if username and password:
self.user_cache = authenticate(username=username,
password=password)
if self.user_cache is None:
raise forms.ValidationError(
'Invalid username or password'
)
else:
self.confirm_login_allowed(self.user_cache)
return self.cleaned_data
def confirm_login_allowed(self, user):
"""
Controls whether the given User may log in. This is a policy setting,
independent of end-user authentication. This default behavior is to
allow login by active users, and reject login by inactive users.
If the given user cannot log in, this method should raise a
``forms.ValidationError``.
If the given user may log in, this method should return None.
"""
if not user.is_active:
raise forms.ValidationError(
'Compte Inactif'
)
def get_user_id(self):
if self.user_cache:
return self.user_cache.id
return None
def get_user(self):
return self.user_cache
from gargantext.util.http import *
from gargantext.util.db import session
from gargantext.models import Node, User
import datetime
from gargantext.util.generators import paragraphs, credits
from gargantext.constants import USER_LANG
def get_user_node(user):
if user is not None:
node_user = session.query(Node).filter(Node.user_id == user.id, Node.typename== "USER").first()
return node_user
else:
return None
def get_user_params(user):
node_user = get_user_node(user)
if node_user is not None:
return node_user.hyperdata
return {}
def home(request):
'''Home describes the platform.
A video draws the narratives.
If not logged a project test is shown.
'''
return render(
template_name = 'pages/main/home.html',
request = request,
context = {
'debug': settings.DEBUG,
'user': request.user,
'date': datetime.datetime.now(),
'paragraph_gargantua': paragraphs.gargantua(),
'paragraph_lorem' : paragraphs.lorem(),
'paragraph_tutoreil': paragraphs.tutoreil(),
'languages': USER_LANG,
'user_parameters': get_user_params(request.user)
},
)
def about(request):
'''About Gargantext, its team and sponsors
'''
return render(
template_name = 'pages/main/about.html',
request = request,
context = {
'user': request.user,
'date': datetime.datetime.now(),
'team' : credits.members(),
'teamPast': credits.membersPast(),
'institutions': credits.institutions(),
'labos': credits.labs(),
'grants': credits.grants(),
'user_parameters': get_user_params(request.user),
'languages': USER_LANG,
},
)
def robots(request):
'''Robots rules
'''
return render(
template_name = 'pages/main/robots.txt',
request = request,
content_type='text/plain',
)
def maintenance(request):
'''Gargantext out of service
'''
user_node = get_user_node(request.user)
return render(
template_name = 'pages/main/maintenance.html',
request = request,
context = {
'user': request.user,
'date': datetime.datetime.now(),
'user_parameters': get_user_params(request.user)
},
)
from gargantext.util.http import *
from gargantext.util.db import *
from gargantext.util.db_cache import cache
from gargantext.util.files import upload
from gargantext.models import *
from gargantext.constants import *
from .main import get_user_params
from gargantext.util.scheduling import scheduled
from gargantext.util.toolchain import parse_extract_indexhyperdata
from datetime import datetime
from collections import defaultdict
from django.utils.translation import ugettext_lazy
import re
def get_node_user(user):
node_user = session.query(Node).filter(Node.user_id == user.id, Node.typename == "USER").first()
if node_user is None:
node_user = Node(user_id = user.id,
typename = 'USER',
name = user.name,
)
#default language for now is 'fr'
node_user.hyperdata["language"] = "fr"
session.add(node_user)
session.commit()
print(node_user.hyperdata)
return node_user
@requires_auth
def overview(request):
'''This view show all projects for a given user.
Each project is described with hyperdata that are updateded on each following view.
To each project, we can link a resource that can be an image.
'''
user = cache.User[request.user.id]
print(user)
node_user = get_node_user(user)
# If POST method, creates a new project...
if request.method == 'POST':
name = str(request.POST['name'])
if name != '':
new_project = Node(
user_id = user.id,
typename = 'PROJECT',
name = name,
parent_id = node_user.id,
)
session.add(new_project)
session.commit()
# list of projects created by the logged user
user_projects = user.nodes(typename='PROJECT', order=True)
# list of contacts of the logged user
contacts_projects = list(user.contacts_nodes(typename='PROJECT'))
# render page
return render(
template_name = 'pages/projects/overview.html',
request = request,
context = {
'debug': settings.DEBUG,
'date': datetime.now(),
# projects owned by the user
'number': user_projects.count(),
'projects': user_projects,
'user_parameters': get_user_params(request.user),
'languages': USER_LANG,
# projects owned by the user's contacts
'common_users': (contact for contact, projects in contacts_projects),
'common_projects': sum((projects for contact, projects in contacts_projects), []),
# status refreshing params (when active workflows)
'status_refresh_initial_interval': PROJECT_VIEW_REFRESH_INTERVAL,
'status_refresh_max_attempts': PROJECT_VIEW_MAX_REFRESH_ATTEMPTS,
},
)
class NewCorpusForm(forms.Form):
#mapping choices based on ressource.type
source_list = [(resource["type"], resource["name"]) for resource in RESOURCETYPES]
source_list.insert(0, (0,"Select a database below"))
type = forms.ChoiceField(
choices = source_list,
widget = forms.Select(attrs={ 'onchange' :'CustomForSelect(this.value); checkReady()'})
)
name = forms.CharField( label='Name', max_length=199 ,
widget = forms.TextInput(attrs={ 'required': 'true', 'onkeyup':'checkReady()' })
)
file = forms.FileField(
widget = forms.FileInput(attrs={ 'onchange':'checkReady()' })
)
def clean_resource(self):
file_ = self.cleaned_data.get('file')
def clean_file(self):
file_ = self.cleaned_data.get('file')
if len(file_) > 1024 ** 3 : # we don't accept more than 1GB
raise forms.ValidationError(ugettext_lazy('File too heavy! (>1GB).'))
return file_
@requires_auth
def project(request, project_id):
# security check
project = session.query(Node).filter(Node.id == project_id).first()
user = cache.User[request.user.id]
node_user = get_node_user(user)
if project is None:
raise Http404()
if not user.owns(project):
return HttpResponseForbidden()
# end of security check
# new corpus
if request.method == 'POST':
corpus = project.add_child(
name = request.POST['name'],
typename = 'CORPUS',
)
corpus.add_resource(
type = int(request.POST['type']),
path = upload(request.FILES['file']),
)
session.add(corpus)
session.commit()
# parse_extract: fileparsing -> ngram extraction -> lists
scheduled(parse_extract_indexhyperdata)(corpus.id)
wait = True
else:
wait = False
# corpora within this project
corpora = project.children('CORPUS', order=True).all()
sourcename2corpora = defaultdict(list)
for corpus in corpora:
# we only consider the first resource of the corpus to determine its type
resources = corpus.resources()
if len(resources):
resource = resources[0]
#resource_type_name = RESOURCETYPES[resource['type']]['name']
resource_type_name = get_resource(resource["type"])["name"]
else:
print("(WARNING) PROJECT view: no listed resource")
# add some data for the viewer
corpus.count = corpus.children('DOCUMENT').count()
status = corpus.status()
if status is not None and not status['complete']:
if not status['error']:
corpus.status_message = '(in progress: %s, %d complete)' % (
status['action'].replace('_', ' '),
status['progress'],
)
else:
corpus.status_message = '(aborted: "%s" after %i docs)' % (
status['error'][-1],
status['progress']
)
else:
corpus.status_message = ''
# add
sourcename2corpora[resource_type_name].append(corpus)
# source & their respective counts
total_documentscount = 0
sourcename2documentscount = defaultdict(int)
for sourcename, corpora in sourcename2corpora.items():
sourcename = re.sub(' \(.*$', '', sourcename)
for corpus in corpora:
count = corpus.children('DOCUMENT').count()
sourcename2documentscount[sourcename] += count
total_documentscount += count
donut = [
{ 'source': sourcename,
'count': count,
'part' : round(count * 100.0 / total_documentscount, 1) if total_documentscount else 0,
}
for sourcename, count in sourcename2documentscount.items()
]
if wait:
return render(
template_name = 'pages/projects/wait.html',
request = request,
context = {
'form': NewCorpusForm,
'user': request.user,
'user_parameters': get_user_params(request.user),
'languages': USER_LANG,
'date': datetime.now(),
'project': project,
'donut': donut,
'list_corpora': dict(sourcename2corpora),
'whitelists': [],
'blacklists': [],
'cooclists': [],
'number': len(corpora),
'query_size': QUERY_SIZE_N_DEFAULT,
# status refreshing params (when active workflows)
'status_refresh_initial_interval': PROJECT_VIEW_REFRESH_INTERVAL,
'status_refresh_max_attempts': PROJECT_VIEW_MAX_REFRESH_ATTEMPTS,
},
)
# response!
return render(
template_name = 'pages/projects/project.html',
request = request,
context = {
'user_parameters': get_user_params(request.user),
"languages": USER_LANG,
'form': NewCorpusForm,
'user': request.user,
'date': datetime.now(),
'project': project,
'donut': donut,
'list_corpora': dict(sourcename2corpora),
'whitelists': [],
'blacklists': [],
'cooclists': [],
'number': len(corpora),
'query_size': QUERY_SIZE_N_DEFAULT,
# status refreshing params (when active workflows)
'status_refresh_initial_interval': PROJECT_VIEW_REFRESH_INTERVAL,
'status_refresh_max_attempts': PROJECT_VIEW_MAX_REFRESH_ATTEMPTS,
},
)
from gargantext.util.http import requires_auth, render, settings
from gargantext.util.db import session
from gargantext.util.db_cache import cache
from gargantext.models import Node
from gargantext.constants import get_resource
from gargantext.constants import USER_LANG
from .main import get_user_params
from datetime import datetime
@requires_auth
def ngramtable(request, project_id, corpus_id):
'''
Browse and modify all lists together.
=> maplist and mainlist terms in a table
with groupings as '+' nodes
=> uses API GET batch of lists
=> uses API PUT/DEL for list modifications
=> uses frontend AJAX through Ngrams_dyna_charts_and_table.js
# TODO refactor Ngrams_dyna_charts_and_table.js
'''
# corpus still necessary to find all lists
corpus = cache.Node[corpus_id]
# and the project just for project.id in corpusBannerTop
project = cache.Node[project_id]
# retrieve all corpora of this user for list import option
# POSSIBILITY: could do same task in ajax "only if needed"
# (use api for that when merged)
corpora_infos_q = (session.query(Node.id, Node.name)
.filter(Node.typename == "CORPUS")
.filter(Node.user_id == project.user_id))
# .filter(Node.id != corpus_id)
corpora_infos = corpora_infos_q.all()
source_type = corpus.resources()[0]['type']
# rendered page : terms.html
return render(
template_name = 'pages/corpora/terms.html',
request = request,
context = {
'debug': settings.DEBUG,
'user': request.user,
'date': datetime.now(),
'project': project,
'corpus' : corpus,
'resourcename' : get_resource(source_type)['name'],
'view': 'terms',
# for the CSV import modal
'importroute': "/api/ngramlists/import?onto_corpus=%i"% corpus.id,
'corporainfos' : corpora_infos,
#user params
'user_parameters': get_user_params(request.user),
'languages': USER_LANG
},
)
from django.conf.urls import url
from . import main
from . import projects, corpora, terms
from .auth import LoginView, out
urlpatterns = [
# presentation pages
url(r'^$', main.home),
url(r'^about/?$', main.about),
url(r'^robots.txt$', main.robots),
# maintenance mode
url(r'^maintenance/?$', main.maintenance),
# authentication
url(r'^auth/login/?$' , LoginView.as_view()),
url(r'^auth/logout/?$', out),
# projects
url(r'^projects/?$' , projects.overview),
url(r'^projects/(\d+)/?$' , projects.project),
# corpora
url(r'^projects/(\d+)/corpora/(\d+)/?$', corpora.docs_by_titles),
# corpus by sources
url(r'^projects/(\d+)/corpora/(\d+)/sources/?$', corpora.docs_by_sources),
# corpus by authors
url(r'^projects/(\d+)/corpora/(\d+)/authors/?$', corpora.docs_by_authors),
# terms table for the corpus
url(r'^projects/(\d+)/corpora/(\d+)/terms/?$', terms.ngramtable),
# Analytics
url(r'^projects/(\d+)/corpora/(\d+)/analytics/?$', corpora.analytics),
]
{% extends "pages/menu.html" %}
{% block content %}
{% load staticfiles %}
<div class="container">
<h3 class="help" id="filter_analytics">
<span class="glyphicon glyphicon-hand-right" aria-hidden="true"></span>
Filter your documents with terms and watch histories (you can compare all your corpora).
</h3>
</div>
<!-- All the templates used by the Javascript framework -->
{% verbatim %}
{% endverbatim %}
<script type="text/javascript" src="{% static "lib/jquery/2.2.0/jquery.min.js" %}"></script>
{% verbatim %}
<style type="text/css">
div.controller div.autocomplete {margin: 0; padding: 0; }
div.controller div.autocomplete * {background: transparent; }
div.controller div.autocomplete ul.suggestion-list {background: rgba(255,255,255,.75); }
div.controller .tags li.tag-item {background: transparent; border: solid 1px rgba(0,0,0,.1); box-shadow: inset .05em .1em .4em rgba(0,0,0,.4); border-radius: 0; font-weight: bold; }
div.controller div.autocomplete li.suggestion-item:hover, div.controller div.autocomplete li.suggestion-item.selected {background: rgba(0,0,0,.5)}
div.controller div.autocomplete li.suggestion-item em {background: transparent; }
div.controller div.tags>input {padding: 0; border: 0; outline: 0; box-shadow: none; background: transparent;}
div.controller div.tags>input::-webkit-input-placeholder,div.controller div.tags input::-webkit-input-placeholder {color: rgba(0,0,0,.25); }
div.controller, div.controller * {color: rgba(0,0,0,.75); }
div.controller button {background: none; border: solid 1px rgba(0,0,0,.25); box-shadow: .05em .1em .4em rgba(0,0,0,.5); opacity: .5; }
div.controller button:hover {opacity: .65; }
div.controller button:active {opacity: .8; }
div.controller>button {width: 100%; }
div.controller input[type=checkbox] {position: relative; top: .125em; }
div.controller input[type=text], div.controller select, div.controller div.tags {font-weight: bold; box-shadow: inset .05em .1em .4em rgba(0,0,0,.2); outline: solid 1px rgba(0,0,0,.125); border: 0; background: rgba(255,255,255,.5); }
div.controller input[type=text] {padding-left: 0.5em;}
ul.datasets {padding: 0; margin: 0; list-style: none; }
li.dataset {padding: 0.3em; border: solid 1px rgba(0,0,0,.125); margin-bottom: 0.5em; box-shadow: inset .1em .2em .8em rgba(0,0,0,.1) }
li.dataset * { }
li.dataset button {float: right; position: relative; top: -.15em; margin-left: .25em; }
li.dataset select {cursor: pointer; border: 0; padding: 0; }
ul.filters {list-style: none; margin: 0; padding: 0; margin-top: .25em;}
ul.filters>li {padding-top: .5em; margin-top: .5em; border-top: solid 1px rgba(0,0,0,.125);}
ul.filters>li>ul {list-style: none; padding-left: 0; margin-top: .5em; }
ul.filters>li>ul>li.inline {width: 30%; display: inline-block; }
ul.filters>li>ul>li>label {font-weight: normal; cursor: pointer; }
ul.filters>li input[type=checkbox] {opacity: .8;}
</style>
<div class="container">
<div ng-app="Gargantext" ng-controller="GraphController" class="controller">
<!-- add a new dataset -->
<button ng-click="addDataset()">Add a dataset</button>
<ul class="datasets">
<li class="dataset" ng-controller="DatasetController" ng-repeat="dataset in datasets" style="background-color:{{ getColor($index, datasets.length) }}">
<!-- main part -->
<div class="main">
<!-- buttons -->
<button ng-click="show_filters = !show_filters">{{ show_filters ? 'Hide' : 'Show' }} filters</button>
<button ng-click="removeDataset($index)">Remove dataset</button>
<!-- description of Y values -->
Evolution of the
<select ng-model="query_y.value" ng-options="value as key for (key, value) in {'documents count': 'documents_count', 'expressions count': 'ngrams_count'}" ng-change="updateDataset()"></select>
<select ng-model="query_y.is_relative" ng-options="value as key for (key, value) in {'in absolute terms': false}" ng-change="updateDataset()"></select>
<!-- <select ng-model="query_y.is_relative" ng-options="value as key for (key, value) in {'in absolute terms': false, 'relative to the': true}" ng-change="updateDataset()"></select>
-->
<span ng-if="query_y.is_relative">
<select ng-model="query_y.divided_by" ng-options="value as key for (key, value) in {'total expressions count': 'total_ngrams_count', 'total documents count': 'total_documents_count'}" ng-change="updateDataset()"></select>
</span>
</div>
<!-- filters -->
<ul class="filters" ng-show="show_filters">
<!-- filter corpora -->
<li>
<button ng-click="corporaSelectAll()">select all</button>
<button ng-click="corporaSelectNone()">select none</button>
...restrict to the following corpora:
<ul>
<li ng-repeat="corpus in corpora" class="inline">
<label>
<input type="checkbox" ng-model="corpus.is_selected" ng-change="updateHyperdataList();updateDataset()"/>
<span style="font-weight: {{ corpus.is_selected ? 'bold' : 'normal' }}">{{ corpus.name }}</span>
</label>
</li>
</ul>
</li>
<!-- filter ngrams -->
<li class="ngrams">
...only consider documents containing the following expressions:
<tags-input ng-model="query_y.ngrams" display-property="terms" placeholder="Add an expression" on-tag-added="updateDataset()" on-tag-removed="updateDataset()" add-from-autocomplete-only="true"
replace-spaces-with-dashes="false">
<auto-complete source="getNgrams($query)"></auto-complete>
</tags-input ng-model="tags">
</li>
<!-- filter hyperdata
<li>
<ul>
<li ng-repeat="hyperdata in hyperdataList">
...with
<span ng-if="!hyperdata.operator &amp;&amp; (!hyperdata.values || !hyperdata.value)">"{{ hyperdata.name }}"</span>
<strong ng-if="hyperdata.operator || (hyperdata.values &amp;&amp; hyperdata.value)">{{ hyperdata.name }}</strong>
<span ng-if="hyperdata.values">
is
<select ng-model="hyperdata.value" ng-options="value for value in hyperdata.values" ng-change="updateDataset()"></select>
</span>
<span ng-if="!hyperdata.values">
<select ng-model="hyperdata.operator" ng-options="operator.key as operator.label for operator in operators[hyperdata.type]"></select>
<input type="text" ng-if="hyperdata.operator" ng-model="hyperdata.value" ng-change="updateDataset()" placeholder="type a value here..." />
</span>
</li>
</ul>
</li>
-->
</ul>
</li>
</ul>
<!-- X-axis (time) resolution -->
<p>
(group results by
<select ng-model="query_x.resolution" ng-options="period as period for period in periods" ng-change="updateDatasets(true)"></select>)
</p>
<!-- data representation -->
Represent data with
<select ng-model="seriesOptions.type" ng-options="type for type in ['column', 'area', 'line']" ng-change="updateDatasets()"></select>
<span ng-show="seriesOptions.type == 'area' || seriesOptions.type == 'column'">
(<select ng-model="options.stacking" ng-options="value as key for (key, value) in {'with':true, 'without':false}" ng-change="updateDatasets()"></select> stacking)
</span>
<div class="graph">
<linechart data="graph.data" options="graph.options"></linechart>
</div>
</div>
{% endverbatim %}
<script type="text/javascript" src="{% static "lib/angular/1.2.26/angular.min.js" %}"></script>
<script type="text/javascript" src="{% static "lib/angular-cookies/1.2.29/angular-cookies.min.js" %}"></script>
<!-- <script type="text/javascript" src="{% static "lib/d3/d3/d3.v2.min.js" %}"></script> -->
<script type="text/javascript" src="{% static "lib/d3/n3.line-chart.min.js" %}"></script>
<script type="text/javascript" src="{% static "lib/ng-tags/ng-tags-input.min.js" %}"></script>
<link rel="stylesheet" href="{% static "lib/ng-tags/ng-tags-input.min.css" %}">
<script type="text/javascript" src="{% static "lib/gargantext/gargantext.angular.js" %}"></script>
{% endblock %}
{% extends "pages/menu.html"}
{% block css %}
{% load staticfiles %}
<link rel="stylesheet" type="text/css" href="{% static "lib/bootstrap/3.0.2/bootstrap.css" %}">
<link rel="stylesheet" type="text/css" href="{% static "lib/d3/dc.css"%}"/>
<link rel="stylesheet" type="text/css" href="{% static "lib/jquery/dynatable/jquery.dynatable.css"%}"/>
<link rel="stylesheet" type="text/css" href="{% static "lib/gargantext/tables.css"%}"/>
<link rel="stylesheet" type="text/css" href="{% static "lib/gargantext/charts.css"%}"/>
<script type="text/javascript" src="{% static "lib/d3/d3.js"%}"></script>
<script type="text/javascript" src="{% static "lib/d3/crossfilter.js"%}"></script>
<script type="text/javascript" src="{% static "lib/d3/dc.js"%}"></script>
{% endblock %}
{% block content %}
<div class="container">
<div class="col-md-3 col-md-offset-2">
<div id="monthly-move-chart">
<center>
Select a frequency group in the chart with blue bars to zoom in
<p align="center">
<!--<a class="btn btn-xs btn-default" role="button" href="/chart/corpus/{{ corpus.id }}/data.csv">Save</a>-->
<a class="btn btn-xs btn-default" href="javascript:volumeChart.filterAll();dc.redrawAll();">Reset</a></p>
<!-- <p style="font-size:70%">
<b>x</b>: amount of documents for the author
<b>y</b>: number of authors with that amount
</p> -->
<div class="clearfix"></div>
</center>
</div>
<div class="bs-callout">
<div class="row">
<div id="monthly-volume-chart"></div>
</div>
<div id="content_loader">
<br>
<center>
<!-- <img width="10%" src="{% static "img/ajax-loader.gif"%}"></img> -->
</center>
<br>
</div>
</div>
</div>
</div>
<div class="container">
<div class="jumbotron">
<div class="panel panel-default">
<div class="panel-heading">
<h2 class="panel-title">
<center>
<span class="glyphicon glyphicon-hand-down" aria-hidden="true"></span>
Publications by source
</center>
</h2>
</div>
<div class="panel-body">
<div id="div-table">
<!-- (table id="my-ajax-table") dynamically set by Authors_dyna_chart_and_table -->
</div>
</div>
</div> <!-- /div panel -->
</div> <!-- /jumbotron -->
<!--</div> This div is closed in the menu !-->
<script type="text/javascript" src="{% static "lib/jquery/dynatable/jquery.dynatable.js" %}"></script>
<!-- custom-lib for dynatable.js and dc.js -->
<script type="text/javascript" src="{% static "lib/gargantext/Authors_dyna_chart_and_table.js" %}"></script>
<script type="text/javascript" src="{% static "lib/gargantext/help.js" %}"></script>
{% endblock %}
{% extends "pages/menu.html"%}
{% load staticfiles %}
{% block css %}
<link rel="stylesheet" href="{% static "lib/bootstrap/3.0.2/bootstrap.css" %}">
<script type="text/javascript" src="{% static "lib/jquery/1.11.1/jquery.min.js" %}"></script>
<script type="text/javascript" src="{% static "lib/gargantext/garganrest.js" %}"></script>
<link rel="stylesheet" href="{% static "lib/jquery/1.11.2/jquery-ui.css" %}">
<script src="{% static "lib/jquery/1.11.1/jquery.min.js" %}" type="text/javascript"></script>
<style type="text/css">
.first-graph {
padding-top: 3em;
}
</style>
{% endblock %}
{% block content %}
<div class="container theme-showcase" role="main">
<h2>My Graphs </h2>
<ol id="graph-list">
{% if coocs %}
{% for cooc in coocs %}
<div id="graph_{{cooc.id}}" class="graph-elt">
<div class="row">
<div class="col-md-1 content"></div>
<div class="col-md-5 content">
<li>
<h4>{{cooc.name}}</h4>
{{cooc.date}}<br>
{% for key, value in coocs_count.items %}
{% if key == cooc.id %}
{% if value > 0 %}
From: {% if not cooc.hyperdata.parameters.start %} begin of corpus {% else %} {{cooc.hyperdata.parameters.start}} {% endif %}
, To: {% if not cooc.hyperdata.parameters.end %} end of corpus {% else %} {{cooc.hyperdata.parameters.end}} {% endif %}
<br>
<ul id="graph_{{cooc.id}}_finished">
<li>
<a href="/projects/{{project.id}}/corpora/{{corpus.id}}/explorer?cooc_id={{cooc.id}}&amp;distance=conditional&amp;bridgeness=5">
<span class="glyphicon glyphicon-eye-open" aria-hidden="true"></span>
{% if cooc.hyperdata.conditional %}
~{{ cooc.hyperdata.conditional.nodes }} nodes,
~{{ cooc.hyperdata.conditional.edges }} edges
with <b>Conditional</b> distance
{% else %}
Compute this graph with Conditional distance
{% endif %}
</a>
</li>
<li>
<a href="/projects/{{project.id}}/corpora/{{corpus.id}}/explorer?cooc_id={{cooc.id}}&amp;distance=distributional&amp;bridgeness=5">
<span class="glyphicon glyphicon-eye-open" aria-hidden="true"></span>
{% if cooc.hyperdata.distributional %}
~{{ cooc.hyperdata.distributional.nodes }} nodes,
~{{ cooc.hyperdata.distributional.edges }} edges
with <b>Distributional</b> distance
{% else %}
Compute this graph with Distributional distance
{% endif %}
</a>
</li>
</ul>
<br>
<!-- <li>{{cooc.id}}</li>
<ul>
<li>
<a href="/projects/{{project.id}}/corpora/{{corpus.id}}/explorer?cooc_id={{cooc.id}}&distance=conditional&bridgeness=5">
<span class="glyphicon glyphicon-eye-open" aria-hidden="true"></span>
Conditional
</a>
(with bridgeness
<a href="/projects/{{project.id}}/corpora/{{corpus.id}}/explorer?cooc_id={{cooc.id}}&distance=conditional&bridgeness=10">10</a>
or <a href="/projects/{{project.id}}/corpora/{{corpus.id}}/explorer?cooc_id={{cooc.id}}&distance=conditional&bridgeness=20">20</a>
or <a href="/projects/{{project.id}}/corpora/{{corpus.id}}/explorer?cooc_id={{cooc.id}}&distance=conditional&bridgeness=30">30</a>
)
</li>
<li>
<a href="/projects/{{project.id}}/corpora/{{corpus.id}}/explorer?cooc_id={{cooc.id}}&distance=distributional&bridgeness=5">
<span class="glyphicon glyphicon-eye-open" aria-hidden="true"></span>
Distributional
</a>
(with bridgeness
<a href="/projects/{{project.id}}/corpora/{{corpus.id}}/explorer?cooc_id={{cooc.id}}&distance=distributional&bridgeness=10">10</a>
or <a href="/projects/{{project.id}}/corpora/{{corpus.id}}/explorer?cooc_id={{cooc.id}}&distance=distributional&bridgeness=20">20</a>
or <a href="/projects/{{project.id}}/corpora/{{corpus.id}}/explorer?cooc_id={{cooc.id}}&distance=distributional&bridgeness=30">30</a>
)
</li>
</ul>
-->
{% else %}
<!--
<br> Processing (wait and reload the page)
!-->
<div class="progress">
<div class=" progress-bar progress-bar-striped active"
role="progressbar" aria-valuenow="45" aria-valuemin="0" aria-valuemax="100" style="width: 70%">
<span>
Processing (please wait)
</span>
</div>
</div>
{% endif %}
{% endif %}
{% endfor %}
</li>
</div>
<div class="col-md-3 content">
<!--
<a href="/projects/{{project.id}}/corpora/{{corpus.id}}/explorer?cooc_id={{cooc.id}}&distance=conditional"
title="View Graph">
<button type="button" class="btn btn-default" aria-label="Left Align">
<span class="glyphicon glyphicon-eye-open" aria-hidden="true"></span>
</button>
</a>
-->
<button type="button" class="btn btn-default" data-container="body" data-toggle="popover" data-placement="bottom"
data-content="
<ul>
<li
onclick=&quot;deleteGraph(event, {{cooc.id}})&quot;>
<a href='#'>Delete this</a>
</li>
</ul>
">
<span class="glyphicon glyphicon-trash" aria-hidden="true"
title='Delete this graph'></span>
</button>
</div>
</div>
</div>
{% endfor %}
{% else %}
<h3>
<span class="glyphicon glyphicon-flag" aria-hidden="true"></span>
You have not computed any graph already</h3>
<h4>
<span class="glyphicon glyphicon-question-sign" aria-hidden="true"></span>
What is Graph ?
</h4>
<ul>
<li>Graph is a conveniant tool to explore your documents</li>
<li>Nodes are terms selected in your Map List</li>
<li>Edges between nodes represent proximities of terms according to a specific distance between your documents.</li>
<ul>
<li>Conditional distance between the terms X and Y is the probability to have both terms X <b> and </b> Y in the same textual context.</li>
<li>Distributional distance between the terms X and Y is the probability to have same others terms in the same textual context as X <b>or</b> Y.</li>
</ul>
</ul>
<h4>
<span class="glyphicon glyphicon-hand-right" aria-hidden="true"></span>
How to compute a new graph ?
</h4>
<ol>
<li>Look at the menu</li>
<li>Click on Graphs</li>
<li>Choose a distance</li>
<li>Click on the distance or on MyGraph which is this page</li>
</ol>
<h4>
<span class="glyphicon glyphicon-ok-circle" aria-hidden="true"></span>
Do you want to test ?</h4>
<center>
<btn class="btn btn-primary" onclick="goFirstGraph()">
<span style="font-size:120%">Compute a new graph</span> <br/> with conditional distance
</btn>
</center>
{% endif %}
</ol>
<script type="text/javascript" src="{% static "lib/gargantext/help.js" %}"></script>
<script type="text/javascript">
// initial vars
var projectId = "{{project.id | escapejs}}"
var corpusId = "{{corpus.id | escapejs }}"
/**
* Some html block templates to render responses after the ajax of goFirstGraph
*
* TODO use template_literals returned by lazy function or any other better templating
*/
var processingHtml='\
<div class="progress">\
<div class=" progress-bar progress-bar-striped active"\
role="progressbar" aria-valuenow="45" aria-valuemin="0" aria-valuemax="100" style="width: 70%">\
<span>\
Processing\
</span>\
</div>\
</div>'
var finishedHtmlCondi='\
<br>\
From: begin of corpus\
, To: end of corpus\
<br>\
<ul id="graph_%%cooc_id%%_finished">\
<li>\
<a href="/projects/%%project_id%%/corpora/%%corpus_id%%/explorer?cooc_id=%%cooc_id%%&amp;distance=conditional&amp;bridgeness=5">\
<span class="glyphicon glyphicon-eye-open" style="font-size:150%"></span>\
~%%co_nb_nodes%% nodes,\
~%%co_nb_edges%% edges\
with <b>Conditional</b> distance\
</a>\
</li>\
<li>\
<a href="/projects/%%project_id%%/corpora/%%corpus_id%%/explorer?cooc_id=%%cooc_id%%&amp;distance=distributional&amp;bridgeness=5">\
<span class="glyphicon glyphicon-eye-open" aria-hidden="true"></span>\
Compute this graph with Distributional distance\
</a>\
</li>\
</ul>\
<br>'
var finishedHtmlDistri='\
<br>\
From: begin of corpus\
, To: end of corpus\
<br>\
<ul id="graph_%%cooc_id%%_finished">\
<li>\
<a href="/projects/%%project_id%%/corpora/%%corpus_id%%/explorer?cooc_id=%%cooc_id%%&amp;distance=conditional&amp;bridgeness=5">\
<span class="glyphicon glyphicon-eye-open" aria-hidden="true"></span>\
Compute this graph with Conditional distance\
</a>\
</li>\
<li>\
<a href="/projects/%%project_id%%/corpora/%%corpus_id%%/explorer?cooc_id=%%cooc_id%%&amp;distance=conditional&amp;bridgeness=5">\
<span class="glyphicon glyphicon-eye-open" style="font-size:150%"></span>\
~%%di_nb_nodes%% nodes,\
~%%di_nb_edges%% edges\
with <b>Distributional</b> distance\
</a>\
</li>\
</ul>\
<br>'
var finishedHtmlTemplate='\
<br>\
From: begin of corpus\
, To: end of corpus\
<br>\
<ul id="graph_%%cooc_id%%_finished">\
<li>\
<a href="/projects/%%project_id%%/corpora/%%corpus_id%%/explorer?cooc_id=%%cooc_id%%&amp;distance=conditional&amp;bridgeness=5">\
<span class="glyphicon glyphicon-eye-open" style="font-size:150%"></span>\
~%%co_nb_nodes%% nodes,\
~%%co_nb_edges%% edges\
with <b>Conditional</b> distance\
</a>\
</li>\
<li>\
<a href="/projects/%%project_id%%/corpora/%%corpus_id%%/explorer?cooc_id=%%cooc_id%%&amp;distance=distributional&amp;bridgeness=5">\
<span class="glyphicon glyphicon-eye-open" style="font-size:150%"></span>\
~%%di_nb_nodes%% nodes,\
~%%di_nb_edges%% edges\
with <b>Distributional</b> distance\
</a>\
</li>\
</ul>\
<br>'
var baseSkeletonTemplate='\
<div id="graph_%%cooc_id%%" class="graph-elt first-graph">\
<div class="row">\
<div class="col-md-1 content"></div>\
<div class="col-md-5 content">\
<li>\
<h4 title="%%cooc_id%%">%%cooc_name%%</h4>\
%%cooc_date%%\
\
%%HERE_RESPONSE_DEPENDANT%%\
\
</li>\
</div>\
<div class="col-md-3 content">\
<button type="button" class="btn btn-default" data-container="body" data-toggle="popover" data-placement="bottom"\
data-content="\
<ul>\
<li\
onclick=&quot;\
garganrest.nodes.delete(%%cooc_id%%, function(){$(\'#graph_\'+%%cooc_id%%).remove()});\
$(this).parent().parent().remove();\
&quot;>\
<a href=\'#\'>Delete this</a>\
</li>\
</ul>\
">\
<span class="glyphicon glyphicon-trash" aria-hidden="true"\
title=\'Delete this graph\'></span>\
</button>\
</div>\
</div>\
</div>'
// -----------------------------------------------------
// for testing on client side which need refresh
// -----------------------------------------------------
function testActiveGraphs() {
var activeGraphIds = []
for (var i in graphIds) {
var grid = graphIds[i]
if ((! document.getElementById('graph_'+grid+'_finished'))
&& (! trashedIds[grid])) {
activeGraphIds.push(grid)
}
}
return activeGraphIds
}
/**
* function showNewCoocDiv(status_code, cooc_id, cooc_name, cooc_date)
*
* (uses the templates to make a new cooc html appear)
*
* @param 'progress_status' || 'finished_status'
* @param projectId
* @param corpusId
* @param coocId
* @param coocName
* @param coocDate
* @param coNbNodes (optional <=> if finished_status on conditional)
* @param coNbEdges (optional <=> if finished_status on conditional)
* @param diNbNodes (optional <=> if finished_status on distributional)
* @param diNbEdges (optional <=> if finished_status on distributional)
*/
function showNewCoocDiv(statusCode,
coocId, coocName, coocDate,
coNbNodes, coNbEdges,
diNbNodes, diNbEdges) {
var resultHtml = baseSkeletonTemplate
// initial if
switch (statusCode) {
case "progress_status":
resultHtml = resultHtml.replace(/%%HERE_RESPONSE_DEPENDANT%%/,
processingHtml
)
break;
case "finished_status":
if ((typeof coNbNodes != 'undefined') && coNbNodes
&& (typeof diNbNodes != 'undefined') && diNbNodes) {
resultHtml = resultHtml.replace(/%%HERE_RESPONSE_DEPENDANT%%/,
finishedHtmlTemplate
)
} else if ((typeof coNbNodes != 'undefined') && ! (coNbNodes == null)) {
console.log("condi case", coNbNodes)
resultHtml = resultHtml.replace(/%%HERE_RESPONSE_DEPENDANT%%/,
finishedHtmlCondi
)
} else if ((typeof diNbNodes != 'undefined') && ! (diNbNodes == null)) {
console.log("distri case")
resultHtml = resultHtml.replace(/%%HERE_RESPONSE_DEPENDANT%%/,
finishedHtmlDistri
)
}
break;
default:
console.warning("showNewCoocDiv: can't show div (Unknown statusCode", statusCode,")");
return false
}
resultHtml = resultHtml.replace(/%%project_id%%/g, projectId);
resultHtml = resultHtml.replace(/%%corpus_id%%/g, corpusId);
resultHtml = resultHtml.replace(/%%cooc_id%%/g, coocId);
resultHtml = resultHtml.replace(/%%cooc_name%%/g, coocName);
resultHtml = resultHtml.replace(/%%cooc_date%%/g, formatDateLikeDjango(coocDate));
if (typeof coNbEdges != 'undefined' && typeof coNbNodes != 'undefined') {
resultHtml = resultHtml.replace(/%%co_nb_nodes%%/g, coNbNodes);
resultHtml = resultHtml.replace(/%%co_nb_edges%%/g, coNbEdges);
}
if (typeof diNbEdges != 'undefined' && typeof diNbNodes != 'undefined') {
resultHtml = resultHtml.replace(/%%di_nb_nodes%%/g, diNbNodes);
resultHtml = resultHtml.replace(/%%di_nb_edges%%/g, diNbEdges);
}
// what do we do with those results ?
switch (statusCode) {
case "progress_status":
// render the result in DOM
$('#graph-list').append(resultHtml)
return null
case "finished_status":
// replace the previous results
var previousDiv = document.getElementById('graph_'+coocId)
previousDiv.innerHTML = resultHtml
return true
}
}
/**
* function goFirstGraph()
*
* 1) run a "save new graph" ajax on graph api
* 2) retrieve the new cooc_id in immediate response
* 3) monitor status of the async generation
*/
function goFirstGraph() {
// ajax config vars
var graphApi = "/api/projects/{{project.id}}/corpora/{{ corpus.id }}/explorer"
var graphParams = "saveOnly=True&distance=conditional&bridgeness=5"
// vars we'll get at creation steps (1: graph init, 2: graph finish)
var coocId = null // 1 & 2
var coocName = null // 1 & 2
var coocDate = null // 1 & 2
var coNbNodes = null // 2
var coNbEdges = null // 2
// run the "save new graph" ajax
// -----------------------------
// cf. data["state"] == "saveOnly"
$.ajax({
method: "GET",
url: graphApi + '?' + graphParams,
beforeSend: function(xhr) {
xhr.setRequestHeader("X-CSRFToken", getCookie("csrftoken"));
},
success: function(data){
// console.log("data", data)
// 1 - retrieve the new coocId etc
if (data.id && data.name && data.date) {
coocId = data['id']
coocName = data['name']
coocDate = data['date']
}
// 2 - show the node with basic info and progressbar
showNewCoocDiv("progress_status",
coocId, coocName, coocDate)
// 3 - run status updating
// (it will call next step of
// showNewCoocDiv when ready)
console.log("goFirstGraph => keepCheckingGraphStatus on:", coocId)
keepCheckingGraphStatus(coocId)
},
error: function(result) {
console.log("result", result)
}
});
}
/**
* function keepCheckingGraphStatus(coocId)
*
* 1) keeps checking an API of cooc status
* 2) triggers showNewCoocDiv('finished_status') if ready
* or abandons after 5 attempts
*/
var currentJob = null
function keepCheckingGraphStatus(coocNodeId, nChecksArg) {
var graphReadyFlag = false
var nChecks = 0
if (typeof nChecksArg != 'undefined') {
nChecks = nChecksArg
}
console.log("checking status", nChecks)
nChecks ++
// var the_status_url = "/api/nodes/"+coocNodeId+"/status?format=json"
var the_url_to_check = "/api/nodes/"+coocNodeId+"?fields[]=hyperdata&fields[]=name&fields[]=date"
// we get all hyperdata instead of just statuses because
// we'll need hyperdata.conditional.nodes and edges
// remote call
$.ajax({
type: 'GET',
url: the_url_to_check,
success: function(data) {
// TODO hyperdata would contains statuses too
// var statuses = data['hyperdata']['statuses']
var coocNodeName = data['name']
var coocNodeDate = data['date']
// test if ready like this for the moment
if ((typeof data['hyperdata']['conditional'] != "undefined")
&& (typeof data['hyperdata']['distributional'] != "undefined")){
console.log("GRAPH is READY", coocNodeId)
graphReadyFlag = true
var coNbNodes = data['hyperdata']['conditional']['nodes']
var coNbEdges = data['hyperdata']['conditional']['edges']
var diNbNodes = data['hyperdata']['distributional']['nodes']
var diNbEdges = data['hyperdata']['distributional']['edges']
// console.warn("running callback for graph id:" + coocNodeId)
showNewCoocDiv("finished_status", coocNodeId,
coocNodeName, coocNodeDate,
coNbNodes, coNbEdges,
diNbNodes, diNbEdges)
} else if (typeof data['hyperdata']['conditional'] != "undefined"){
console.log("conditional GRAPH is READY", coocNodeId)
graphReadyFlag = true
var coNbNodes = data['hyperdata']['conditional']['nodes']
var coNbEdges = data['hyperdata']['conditional']['edges']
// console.warn("running callback for graph id:" + coocNodeId)
showNewCoocDiv("finished_status", coocNodeId,
coocNodeName, coocNodeDate,
coNbNodes, coNbEdges,
null, null)
} else if (typeof data['hyperdata']['distributional'] != "undefined"){
console.log("distributional GRAPH is READY", coocNodeId)
graphReadyFlag = true
var diNbNodes = data['hyperdata']['distributional']['nodes']
var diNbEdges = data['hyperdata']['distributional']['edges']
// console.warn("running callback for graph id:" + coocNodeId)
showNewCoocDiv("finished_status", coocNodeId,
coocNodeName, coocNodeDate,
null, null,
diNbNodes, diNbEdges)
}
// stopping conditions
if (graphReadyFlag || nChecks > 5) {
// we abandon after 5 checks
console.warn("stopping status checks for graph:",
coocNodeId)
return null
}
// scheduled recursion
else {
console.log("GRAPH not ready yet...", coocNodeId)
// decreasing intervals (preserving DB while "loosing interest")
var nextTime = nChecks * 3000
// schedule next check
currentJob = setTimeout(function(){keepCheckingGraphStatus(coocNodeId, nChecks)}, nextTime)
console.log("next status check in", nextTime/1000, "s" )
return false
}
},
error: function(data, s) {
console.warn("status GET: ajax err (s="+s+")")
console.log(data)
},
beforeSend: function(xhr) {
xhr.setRequestHeader("X-CSRFToken", getCookie("csrftoken"));
}
})
}
function stopCheckingGraphStatus() {
clearTimeout(currentJob)
}
// raw DB format: "2016-10-04T15:00:35Z" (ISOString)
// -----------------------
//
// but django default format: Oct. 4, 2016, 3:00 p.m.
// ------------------------
// cf. docs.djangoproject.com/en/dev/ref/settings/#date-format
//
// POSSIBLE: remove UTC from django and here (current timezone more practical)
function formatDateLikeDjango(isoDateTimeStr) {
asDate = new Date(isoDateTimeStr)
// ex: "Oct 4, 2016"
var newDateStr = asDate.toLocaleDateString(
'en-US',
{ 'year': 'numeric',
'month': 'short',
'day': 'numeric' })
// ex: 3:00 pm
var newTimeStr = asDate.toLocaleTimeString(
'en-US',
{ 'hour12': true,
'timeZone': 'UTC',
'hour': '2-digit',
'minute':'numeric'})
.toLowerCase()
// ex Oct 4, 2016, 3:00 pm => close enough !
return newDateStr + ', ' + newTimeStr
}
function deleteGraph(e, graphId) {
// prevents scroll back to top of page
e.preventDefault()
// register pending operation
trashedIds[graphId] = true ;
// POSSIBLE visual loader wheel
// REST and callback
garganrest.nodes.delete(
graphId,
function(){
$('#graph_'+graphId).remove()
delete trashedIds[graphId]
// remove any popover too
$('.popover').remove();
}
);
}
// main
// all graph ids
var graphDivs = document.getElementsByClassName('graph-elt')
var graphIds = []
// for graph ids whose delete is pending
var trashedIds = {}
for (var i = 0 ; i < graphDivs.length ; i++) {
// ex: graph_48
divId = graphDivs[i].id
if (divId) {
var graphId = divId.match(/[0-9]+$/).pop()
graphIds.push(graphId)
}
}
var activeGraphIds = testActiveGraphs()
if (activeGraphIds.length) {
// initial checks if page reloaded with active corpora
for (var i in activeGraphIds) {
// !careful with closure, async function & loop on i
// cf stackoverflow.com/a/21819961/2489184
(function(i) {
var myCoocId = activeGraphIds[i]
keepCheckingGraphStatus(activeGraphIds, 0)
})(i)
}
}
console.warn("hello", activeGraphIds)
</script>
{% endblock %}
{% extends "pages/menu.html"%}
{% load staticfiles %}
{% block css %}
<link rel="stylesheet" type="text/css" href="{% static "lib/d3/dc.css"%}"/>
<link rel="stylesheet" type="text/css" href="{% static "lib/jquery/dynatable/jquery.dynatable.css"%}"/>
<link rel="stylesheet" type="text/css" href="{% static "lib/gargantext/tables.css"%}"/>
<link rel="stylesheet" type="text/css" href="{% static "lib/gargantext/charts.css"%}"/>
<script type="text/javascript" src="{% static "lib/d3/d3.js"%}"></script>
<script type="text/javascript" src="{% static "lib/d3/crossfilter.js"%}"></script>
<script type="text/javascript" src="{% static "lib/d3/dc.js"%}"></script>
{% endblock %}
{% block content %}
<div class="container">
<div class="col-md-3 col-md-offset-2">
<div class="bs-callout">
<div class="row">
<div id="monthly-volume-chart"></div>
</div>
</div>
<div class="bs-callout">
<div class="row">
<div id="monthly-move-chart">
<center>
<p class="help" id="sources_time">Select a time range in the chart with blue bars to zoom in </p>
<p align="center">
<!--<a class="btn btn-xs btn-default" role="button" href="/chart/corpus/{{ corpus.id }}/data.csv">Save</a>-->
<a class="btn btn-xs btn-default" href="javascript:volumeChart.filterAll();dc.redrawAll();">Reset</a>
</p>
<div class="clearfix"></div>
</center>
</div>
</div>
<div id="content_loader">
<br>
<center>
<img width="10%" src="{% static "img/ajax-loader.gif"%}"></img>
</center>
<br>
</div>
</div>
</div>
</div>
<div class="container">
<div class="jumbotron">
<div class="panel panel-default">
<div class="panel-heading">
<h2 class="panel-title">
<center>
<span class="glyphicon glyphicon-hand-down" aria-hidden="true"></span>
Publications by source
</center>
</h2>
</div>
<div class="panel-body">
<div id="div-table">
<!-- (table id="my-ajax-table") dynamically set by Sources_dyna_chart_and_table -->
</div>
</div>
</div> <!-- /div panel -->
</div> <!-- /jumbotron -->
<!--</div> This div is closed in the menu !-->
<script type="text/javascript" src="{% static "lib/jquery/dynatable/jquery.dynatable.js" %}"></script>
<!-- custom-lib for dynatable.js and dc.js -->
<script type="text/javascript" src="{% static "lib/gargantext/Sources_dyna_chart_and_table.js" %}"></script>
<!-- <script type="text/javascript" src="{% static "lib/gargantext/help.js" %}"></script> -->
{% endblock %}
{% extends "pages/menu.html" %}
{% load staticfiles %}
{% block css %}
<link rel="stylesheet" type="text/css" href="{% static "lib/d3/dc.css"%}"/>
<link rel="stylesheet" type="text/css" href="{% static "lib/jquery/dynatable/jquery.dynatable.css"%}"/>
<link rel="stylesheet" type="text/css" href="{% static "lib/gargantext/tables.css"%}"/>
<link rel="stylesheet" type="text/css" href="{% static "lib/gargantext/charts.css"%}"/>
<style>
#corpuschoose {
max-width: 75%;
}
input[type="checkbox"].importcheck {
margin-right: 1em;
}
.announce {
font-size: 12px ;
padding-top: .5em;
}
#importsubmit {
margin-left: 25%;
padding: .3em .5em;
font-size: 120% ;
}
#formatinfos {
background-color: #CCC ;
font-size: 12px ;
padding: 1em;
border-radius: 1em;
margin: 1.5em;
}
#formatinfos table {
margin-left: 2.5em;
margin-bottom: 1em;
margin-top: 1em;
}
#formatinfos tr:hover {
font-weight: normal
}
#formatinfos td {
color: inherit ;
hover: none ;
}
#formatinfos h4 {
font-size: 14px;
color: #777;
font-weight: bold;
}
#formatinfos p {
font-size: 14px;
}
em {
font-weight:bold ;
}
</style>
<script type="text/javascript" src="{% static "lib/d3/d3.js"%}"></script>
<script type="text/javascript" src="{% static "lib/d3/crossfilter.js"%}"></script>
<script type="text/javascript" src="{% static "lib/d3/dc.js"%}"></script>
{% endblock %}
{% block content %}
<div class="container">
<div class="col-md-3 col-md-offset-2">
<div class="bs-callout">
<div class="row">
<div id="monthly-volume-chart"></div>
</div>
<div id="content_loader">
<br>
<center>
<img width="10%" src="{% static "img/ajax-loader.gif"%}"></img>
</center>
<br>
</div>
</div>
<div id="monthly-move-chart" class="bs-callout">
<center>
<p id="terms_time" class="help">Select a score/frequency range in the chart with blue bars to zoom in <p>
<p align="center">
<!--<a class="btn btn-xs btn-default" role="button" href="/chart/corpus/{{ corpus.id }}/data.csv">Save</a>-->
<a class="btn btn-xs btn-default" href="javascript:volumeChart.filterAll();dc.redrawAll();">Reset</a></p>
<div class="clearfix"></div>
</center>
</div>
</div>
</div>
</div>
<div class="container">
<!-- (values set by js) caching our DB ids (handy for list update commands) -->
<input type="hidden" id="mainlist_id" value=""></input>
<input type="hidden" id="maplist_id" value=""></input>
<input type="hidden" id="stoplist_id" value=""></input>
<input type="hidden" id="groups_id" value=""></input>
<input type="hidden" id="scores_id" value=""></input>
<div class="jumbotron">
<div class="panel panel-default">
<div class="panel-heading">
<h2 class="panel-title">
<center>
<span class="glyphicon glyphicon-hand-down" aria-hidden="true"></span>
Extracted terms
<!-- <button title='run test function' onclick="doATest()">
TEST
</button> -->
</center>
</h2>
<div class="savediv pull-left" style="margin-top:1.5em;padding-right:1em;" title="No changes to save">
<!-- save/import icon -->
<span class="needsaveicon glyphicon glyphicon-import"></span>
&nbsp;
<!-- save/import button -->
<button id="ImportListOrSaveAll" class="btn btn-warning" style="font-size:120%"
onclick="$('#csvimport').modal('show'); document.getElementById('importsubmit').disabled = false ;">
<b>Import a Termlist</b>
</button>
</div>
<!-- see in javascript function queries.functions['my_state_filter'] -->
<div id="filter_terms" class="pull-right help" style="margin-top:2.1em;padding-left:1em;">
<select id="picklistmenu" name="my_state_filter">
<option value='reset'>All terms</option>
<!-- <option value='1' selected="selected">Map terms only</option> -->
<option value='1'>Map terms</option>
<option value='0'>Other terms</option>
<option value='2'>Stop terms</option>
</select>
<select id="picktermtype" name="my_termtype_filter" style="margin-left:1em;">
<option value='reset'>All types</option>
<option value='mono'>One-word terms</option>
<option value='multi'>Multi-word terms</option>
</select>
</div>
</h4>
</div>
<div id="terms_table" class="panel-body">
<div id="div-table">
<!-- (table id="my-ajax-table") dynamically set by Ngrams_dyna_chart_and_table -->
</div>
<!-- copy of save button under the table -->
<div align="right" class="savediv" title="No changes to save">
<!-- need save status -->
<span class="needsaveicon glyphicon glyphicon-floppy-saved"></span>
&nbsp;
<button id="Save_All_Bottom" class="btn btn-muted" disabled>
<b>Save all changes</b>
</button>
</div>
</div>
</div> <!-- /div panel -->
</div> <!-- /jumbotron -->
<!--</div> This div is closed in the menu !-->
<div class="modal" aria-hidden="true" id="csvimport">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h3 id="myModalLabel">Import a Termlist</h3>
</div>
<div class="modal-body" id="uploadform">
<form id="importform"
onsubmit="return submitImport(event, this)"
enctype="multipart/form-data"
method="post">
{% csrf_token %}
<label>From another corpus:</label>
<select id="corpuschoose" name="corpuschoose">
<option selected value> -- select a corpus -- </option>
<!-- lists all corpora of this user -->
{% for corpusinfo in corporainfos %}
<option value="{{corpusinfo.id}}">{{corpusinfo.name}}</option>
{% endfor %}
</select>
<br/>
<p class="announce" onclick="toggleAdvancedCheckboxes()">
<span
id="corpusadvanced-icon"
class="glyphicon glyphicon-triangle-right"></span>
Advanced options
</p>
<div id="corpusadvanced" style="display:none;" class="input-group">
<input type="checkbox" class="importcheck" name="listtypes" id="listtypes-map" value="map" checked>import map terms</input>
<br/>
<input type="checkbox" class="importcheck" name="listtypes" id="listtypes-main" value="main">import normal terms</input>
<br/>
<input type="checkbox" class="importcheck" name="listtypes" id="listtypes-stop" value="stop">import stoplist terms</input>
</div>
<br/>
<br/>
<label>From a CSV on your disk:</label>
<input type="file" id="csvfile" name="csvfile" accept="text/csv">
<p class="announce" onclick="toggleFormatInfos()">
<span
id="formatinfos-icon"
class="glyphicon glyphicon-triangle-right"></span>
More info about the expected CSV format
</p>
<div id="formatinfos" style="display:none;">
<h4>Example table</h4>
<table class="table-condensed note">
<tr><th>status</th> <th>label</th> <th>forms</th></tr>
<tr><td>map</td> <td>barograph</td> <td></td></tr>
<tr><td>map</td> <td>seafaring</td> <td>seafarer|&amp;|ocean travel</td></tr>
<tr><td>main</td> <td>electromagnetic</td> <td>electro-magnetic</td></tr>
</table>
<h4>Remarks</h4>
<ul>
<li>Tabulation is the expected delimiter between columns.</li>
<li>The only mandatory column is <em>label</em>.</li>
<li>If <em>status</em> is absent, default target status is "map"</li>
<li>When a column is there, always add its header on the 1st line: <em>status</em>, <em>label</em>, <em>forms</em></li>
<li>The label will be always added as a form, even if it's not in 'forms' column</li>
<li>The string <em>|&amp;|</em> (3 characters) is the expected delimiter between forms.</li>
</ul>
</div>
<br/>
<div class="checkbox">
<label>
<input type="checkbox" id="importoverwrite"> Overwrite old lists
<script>
function updateSubmitLabel() {
$('#importsubmit').val($(this).is(':checked') ? 'Overwrite current table' : 'Import and merge with current table');
}
$(function() {
updateSubmitLabel.call($('#importoverwrite'));
$('#importoverwrite').change(updateSubmitLabel);
});
</script>
</label>
</div>
<br/>
<input type="submit" class="btn btn-xs btn-info" id="importsubmit" value="Import and merge with current table" />
</form>
</div>
<div class="modal-footer" id="formanswer"></div>
</div>
</div>
</div>
<script type="text/javascript" src="{% static "lib/jquery/dynatable/jquery.dynatable.js" %}"></script>
<!-- custom-lib for dynatable.js and dc.js -->
<script type="text/javascript" src="{% static "lib/gargantext/NGrams_dyna_chart_and_table.js" %}"></script>
<!-- import modal controllers -->
<script type="text/javascript">
var formatInfosOpen = false;
var corpusAdvancedOpen = false;
// declared here to enable inspection
var myFormData ;
function toggleAdvancedCheckboxes() {
// when already open => we close
if (corpusAdvancedOpen) {
// hide div
$('#corpusadvanced').hide()
// change icon
$('#corpusadvanced-icon')[0].classList.remove('glyphicon-triangle-bottom')
$('#corpusadvanced-icon')[0].classList.add('glyphicon-triangle-right')
// toggle flag
corpusAdvancedOpen = false;
}
else {
// opposite case
$('#corpusadvanced').show()
$('#corpusadvanced-icon')[0].classList.remove('glyphicon-triangle-right')
$('#corpusadvanced-icon')[0].classList.add('glyphicon-triangle-bottom')
corpusAdvancedOpen = true;
}
}
function toggleFormatInfos() {
// when already open => we close
if (formatInfosOpen) {
// hide div
$('#formatinfos').hide()
// change icon
$('#formatinfos-icon')[0].classList.remove('glyphicon-triangle-bottom')
$('#formatinfos-icon')[0].classList.add('glyphicon-triangle-right')
// toggle flag
formatInfosOpen = false;
}
else {
// opposite case
$('#formatinfos').show()
$('#formatinfos-icon')[0].classList.remove('glyphicon-triangle-right')
$('#formatinfos-icon')[0].classList.add('glyphicon-triangle-bottom')
formatInfosOpen = true;
}
}
/*
* Uses importroute variable from the django template
* Ex: /api/ngramlists/import?onto_corpus=corpus_id
*
* Uses input#csvfile as source data.
*/
function submitImport(e, formElt){
// don't do page reload of usual submits
e.preventDefault()
// parse the form (allows iteration like so: for (kv of myFormData))
myFormData = new FormData(formElt);
// user had 2 possibilities
var theCorpus = myFormData.get("corpuschoose")
var theFile = myFormData.get("csvfile")
// console.log(theCorpus)
// console.log(theFile)
if (theCorpus && theFile.name) {
// can't select both!
my_msg = "Please select a source corpus <em>or</em> choose a source file (not both!)."
}
else if (theFile.name) {
listmergeCsvPost(theFile)
my_msg = "CSV import in progress..."
}
else if (theCorpus) {
listmergeUpdate(myFormData)
my_msg = "Internal list import in progress..."
}
else {
my_msg = "Please provide an input source!"
console.warn('Ignoring "submit": no provided input')
}
$('#formanswer').html(
'<p style="color:#777;font-style:italic">'+my_msg+'</p>'
);
}
function listmergeUpdate(aFormData){
// console.log(aFormData)
// get the selected source corpus
// ex: "13308"
var sourceCorpusId = aFormData.get("corpuschoose")
// get checkbox entries into an array
// ex: ["map", "stop"]
var todoLists = aFormData.getAll("listtypes")
// base url ex: /api/ngramlists/import?onto_corpus=123
var theUrl = "{{importroute | safe}}"
// all params are added in the url like a GET
theUrl += "&from_corpus="+sourceCorpusId
theUrl += "&todo="+todoLists.join(',')
if ($('#importoverwrite').is(':checked'))
theUrl += "&overwrite=1"
// result url looks like this : /api/ngramlists/import?onto_corpus=2&from=13308&todo=map,stop
// console.log(theUrl)
// Update request
$.ajax({
url: theUrl,
type: 'PATCH',
async: true,
beforeSend: function(xhr) {
xhr.setRequestHeader("X-CSRFToken", getCookie("csrftoken"));
},
success: function(response) {
my_html = '<h3 style="color:green">IMPORT OK</h3>'
my_html += "<p class='note'>" + response['log'].replace(/\n/g, '<br/>') + "</p>"
my_html += "<p'>(this page will reload in 3s)</p>"
$('#formanswer').html(my_html);
console.log(response) ;
// reload after 3s
setTimeout("location.reload(true)", 3000);
},
error: function(result) {
my_html = '<h3 style="color:red">Error</h3>'
my_html += "<p>"+ result.responseJSON['err']+"</p>"
$('#formanswer').html(my_html);
console.error(result);
},
});
};
function listmergeCsvPost(theFile){
// 2MB ≈ 70000 ngrams
var max_size = 2097152
// debug
// console.log(theFile.name, "size", theFile.size, theFile.lastModifiedDate)
if (theFile.size > max_size) {
console.warn('Ignoring "submit": file is too big')
$('#formanswer').html(
'The import failed: your file is too big ('+max_size/1024+'kB max).'
);
return false
}
// normal case
else {
// append into an empty form (all other infos from old form were not for us)
var myFileFormData = new FormData();
myFileFormData.append("csvfile", theFile)
//postCorpusFile
$.ajax({
url: "{{importroute | safe}}" + ($('#importoverwrite').is(':checked') ? '&overwrite=1' : ''),
type: 'POST',
async: true,
contentType: false,
processData: false,
data: myFileFormData,
beforeSend: function(xhr) {
xhr.setRequestHeader("X-CSRFToken", getCookie("csrftoken"));
},
success: function(response) {
my_html = '<h3 style="color:green">File upload, you will receive a notification email</h3>'
my_html += "<p class='note'>" + response['log'].replace(/\n/g, '<br/>') + "</p>"
my_html += "<p'>(this page will reload in 30s)</p>"
$('#formanswer').html(my_html);
console.log(response) ;
// reload after 3s
setTimeout("location.reload(true)", 30000);
},
error: function(result, t) {
if (t != 'timeout') {
my_html = '<h3 style="color:red">Error</h3>'
my_html += "<p class='note'>please correct your CSV file and retry</p>"
my_html += "<p>"+ result.responseJSON['err']+"</p>"
}
else {
my_html = '<h3 style="color:red">Timeout</h3>'
my_html += "<p>The CSV import timed out.</p>"
my_html += "<p>(This bug is currently being fixed. <br/>The import and indexation are now continuing in background on our servers. Results will show in a few minutes.)</p>"
document.getElementById('importsubmit').disabled = true
}
$('#formanswer').html(my_html);
console.error(result);
},
timeout: 15000 // 15s
});
}
};
</script>
<!-- <script type="text/javascript" src="{% static "lib/gargantext/help.js" %}"></script> -->
{% endblock %}
{% extends "pages/menu.html"%}
{% load staticfiles %}
{% block css %}
<link rel="stylesheet" type="text/css" href="{% static "lib/d3/dc.css"%}"/>
<link rel="stylesheet" type="text/css" href="{% static "lib/jquery/dynatable/jquery.dynatable.css"%}"/>
<link rel="stylesheet" type="text/css" href="{% static "lib/gargantext/tables.css"%}"/>
<link rel="stylesheet" type="text/css" href="{% static "lib/gargantext/charts.css"%}"/>
<script type="text/javascript" src="{% static "lib/d3/d3.js"%}"></script>
<script type="text/javascript" src="{% static "lib/d3/crossfilter.js"%}"></script>
<script type="text/javascript" src="{% static "lib/d3/dc.js"%}"></script>
{% endblock %}
{% block content %}
<div class="container">
<div class="col-md-3 col-md-offset-2">
<div class="bs-callout">
<div class="row">
<div id="monthly-volume-chart"></div>
</div>
</div>
<div class="bs-callout">
<div class="row">
<div id="monthly-move-chart">
<center>
<p class="help" id="titles_time">Select a time range in the chart with blue bars to zoom in </p>
<p align="center">
<!--<a class="btn btn-xs btn-default" role="button" href="/chart/corpus/{{ corpus.id }}/data.csv">Save</a>-->
<a class="btn btn-xs btn-default" href="javascript:volumeChart.filterAll();dc.redrawAll();">Reset</a>
</p>
<div class="clearfix"></div>
</center>
</div>
</div>
<div id="content_loader">
<br>
<center>
<img width="10%" src="{% static "img/ajax-loader.gif"%}"></img>
</center>
<br>
</div>
</div>
</div>
</div>
<input type="hidden" id="list_id" value="{{ list_id }}"></input>
<div class="container">
<div class="jumbotron">
<div class="panel panel-default">
<div class="panel-heading">
<h2 class="panel-title">
<center>
<span class="glyphicon glyphicon-hand-down" aria-hidden="true"></span>
Publications by title
</center>
</h2>
<!-- search box with custom function in Docs_dyna_chart_and_tables.js -->
<div class="pull-left" style="margin-top:1.85em; font-size: 16px;">
<span class="glyphicon glyphicon-search" aria-hidden="true"></span>
Search:
<input type="search" id="doubleSearch"/>
<span style="font-size:70%;">
<span class="glyphicon glyphicon-filter" aria-hidden="true"></span>
<!-- Used by the #doubleSearch associated function -->
<input title="Search in Titles" id="searchTI" name="searchTI" type="checkbox" checked onclick="return false">
TI&nbsp;
</input>
<span class="glyphicon glyphicon-filter" aria-hidden="true"></span>
<input title="Search in Abstracts" id="searchAB" name="searchAB" type="checkbox">
AB&nbsp;&nbsp;
</input>
</span>
<span class="glyphicon glyphicon-filter" aria-hidden="true"></span>
<select id="docFilter" name="docFilter" class="help">
<option value="filter_all">All</option>
<option value="filter_favs">Favorite documents</option>
<option value="filter_dupl_all">Duplicates (title, date &amp; src)</option>
</select>
</div>
</div>
<div class="panel-body">
<div id="div-table"></div>
<p align="right">
<button id="empty-trash" class="btn btn-primary btn-lg" >
<span class="glyphicon glyphicon-trash" aria-hidden="true"></span>
Trash It!
</button>
</p>
</div>
</div>
</div>
<!--</div> This div is closed in the menu !-->
<!-- here goes import script js/bootstrap/bootstrap-multiselect.js, mais ca marche pas-->
<script type="text/javascript" src="{% static "lib/jquery/dynatable/jquery.dynatable.js" %}"></script>
<!-- custom-lib for dynatable.js and dc.js -->
<script type="text/javascript" src="{% static "lib/gargantext/Docs_dyna_chart_and_table.js" %}"></script>
<!-- <script type="text/javascript" src="{% static "lib/gargantext/help.js" %}"></script> -->
{% endblock %}
{% extends "pages/menu.html" %}
{% load staticfiles %}
{% block css %}
<script src="{% static "lib/jquery/1.11.1/jquery.min.js" %}" type="text/javascript"></script>
{% endblock %}
{% block content %}
<div class="container theme-showcase" role="main">
<div class="jumbotron">
<h1>About Gargantext</h1>
</div>
<div class="panel-group" id="accordion" role="tablist" aria-multiselectable="true">
<div class="panel panel-default">
<div class="panel-heading">
<h2 class="panel-title">
<a data-toggle="collapse" data-parent="#accordion" href="#collapseVersions">
<center>
<h2>
<span class="glyphicon glyphicon-question-sign" aria-hidden="true"></span>
Versions
<span class="glyphicon glyphicon-question-sign" aria-hidden="true"></span>
</h2>
</center>
</a>
</h2>
</div>
<div id="collapseVersions" class="panel-collapse collapse" role="tabpanel">
<div class="panel-body">
<div class="container">
<ul>
<li>
Versions 3.*
<ul>
<li>[NAME] Blue Jasmin</li>
<li>[CODE] Refactored</li>
<li>[DATABASE] New schema</li>
<li>[INSTALL] Easy Docker</li>
</ul>
</li>
<li>
Versions 2.*
<ul>
<li>[NAME] Red Lemon</li>
<li>[NLP] Turbo Parser, MELT</li>
<li>[FEATURE] Ngrams Table management</li>
<li>[FEATURE] Annotation local view</li>
<li>[FEATURE] Lexical Graph with temporal filter</li>
<li>[FEATURE] Graph bi-Partite</li>
</ul>
</li>
<li>
Versions from 1.0 to 1.9
<ul>
<li>[NAME] Rose Bonbon</li>
<li>[Law] Licence of Gargantext is (and will be for next versions) AGPL</li>
<li>[NLP] Turbo Parser, TreeTagger</li>
<li>[FEATURE] Advanced Chart</li>
<li>[FEATURE] Remove duplicates</li>
</ul>
</li>
<li>
Versions from 0.1 to 0.9
<ul>
<li>[NAME] Black Salade</li>
<li>[Law] Licence of Gargantext is GPL v3+ </li>
<li>[NLP] NLTK, TreeTagger</li>
<li>[FEATURE] Graph Explorer</li>
</ul>
</li>
</ul>
</div>
</div>
</div>
</div>
<div class="panel panel-default">
<div class="panel-heading">
<h2 class="panel-title">
<a data-toggle="collapse" data-parent="#accordion" href="#collapseCommunity">
<center>
<h2>
<span class="glyphicon glyphicon-question-sign" aria-hidden="true"></span>
Community
<span class="glyphicon glyphicon-question-sign" aria-hidden="true"></span>
</h2>
</center>
</a>
</h2>
</div>
<div id="collapseCommunity" class="panel-collapse collapse" role="tabpanel">
<div class="panel-body">
<div class="container">
<ul>
<li>
Newsletters : <a target="blank" href="https://phplist.iscpif.fr/?p=subscribe&id=2">subscribe</a>
</li>
<li>
Mailing-lists
<ul>
<li>User mailing-list: soon </li>
<li>Devel mailing-list: soon</li>
</ul>
</li>
<li>
Code and repository access
<ul>
<li>You are free to participate. Present yourself on mailing-lists or irc.</li>
</ul>
</li>
<li>
IRC
<ul>
<li>#gargantext on OFTC:</li>
<li>
<p><iframe src="http://webchat.oftc.net/?channels=#gargantext" width="500" height="350"></iframe></p>
<p>If the window is too small, just click <a href="http://webchat.oftc.net/?channels=#gargantext">here</a></p>
</li>
</ul>
</li>
</ul>
</div>
</div>
</div>
</div>
{% if team %}
<div class="panel panel-default">
<div class="panel-heading">
<h2 class="panel-title">
<a data-toggle="collapse" data-parent="#accordion" href="#collapseTeam">
<center>
<h2>
<span class="glyphicon glyphicon-question-sign" aria-hidden="true"></span>
Core team
<span class="glyphicon glyphicon-question-sign" aria-hidden="true"></span>
</h2>
</center>
</a>
</h2>
</div>
<div id="collapseTeam" class="panel-collapse collapse" role="tabpanel">
<div class="panel-body">
<div class="container">
<div class="row">
<div class="thumbnails">
{% for member in team %}
<div class="col-md-5 ">
<div class="thumbnail">
{% if member.picture %}
<img src="{% static "img/credits/"%}{{ member.picture }}" style="100px; height:150px">
{% else %}
<img src="{% static "img/logo.png" %}" style="100px; height:150px">
{% endif %}
<div class="caption">
<center>
<h3>{{ member.first_name }} {{member.last_name }}</h3>
{% if member.role %}
<p class="description">{{ member.role }}</p>
{% endif %}
{% if member.mail %}
<a href="mailto:{{ member.mail }}" class="btn btn-primary btn-xs">Mail</a>
{% endif %}
{% if member.website %}
<a href="{{ member.website }}" class="btn btn-primary btn-xs">Website</a>
{% endif %}
</center>
</div>
</div>
</div>
{% endfor %}
</div>
</div>
</div>
</div>
{% endif %}
{% if teamPast %}
<div class="panel panel-default">
<div class="panel-heading">
<h2 class="panel-title">
<a data-toggle="collapse" data-parent="#accordion" href="#collapseTeamPast">
<center>
<h2>
<span class="glyphicon glyphicon-question-sign" aria-hidden="true"></span>
Former Developers
<span class="glyphicon glyphicon-question-sign" aria-hidden="true"></span>
</h2>
</center>
</a>
</h2>
</div>
<div id="collapseTeamPast" class="panel-collapse collapse" role="tabpanel">
<div class="panel-body">
<div class="container">
<div class="row">
<div class="thumbnails">
{% for member in teamPast %}
<div class="col-md-5 ">
<div class="thumbnail">
<div class="caption">
<center>
<h3>{{ member.first_name }} {{member.last_name }}</h3>
{% if member.role %}
<p class="description">{{ member.role }}</p>
{% endif %}
</center>
</div>
</div>
</div>
{% endfor %}
</div>
</div>
</div>
</div>
</div>
</div>
{% endif %}
</div>
</div>
<div class="panel panel-default">
<div class="panel-heading">
<center>
<h2 class="panel-title">Institutional, research and financial support</h2>
<h3>Host institutions</h3>
<a href="http://www.cnrs.fr" target="_blank" >
<img src="{% static "img/credits/cnrs.png"%}" alt="CNRS" style="height:100px">
</a>
<a href="http://www.iscpif.fr" target="_blank" >
<img src="{% static "img/credits/iscpif.svg"%}" style="height:100px">
</a>
<a href="http://cams.ehess.fr" target="_blank" >
<img src="{% static "img/credits/cams.jpg"%}" style="height:100px">
</a>
<h3>Institutional Partners</h3>
<p>
{% for institution in institutions %}
<a href="{{ institution.website }}" target="_blank" >
<img src="{% static "img/credits/"%}{{ institution.picture }}" style="height:100px">
</a>
{% endfor %}
</p>
<h4>Laboratory Partners</h4>
<p>
{% for labo in labos %}
<a href="{{ labo.website }}" target="_blank" >
<img src="{% static "img/credits/"%}{{ labo.picture }}" style="height:50px">
</a>
{% endfor %}
</p>
<h4>Grants</h4>
{% for grant in grants %}
<a href="{{ grant.website }}" target="_blank" >
<img src="{% static "img/credits/"%}{{ grant.picture }}" style="height:100px">
</a>
{% endfor %}
</center>
</div>
</div>
</div>
{% endblock %}
{% extends "pages/menu.html" %}
{% load staticfiles %}
{% block css %}
<script src="{% static "lib/jquery/1.11.1/jquery.min.js" %}" type="text/javascript"></script>
{% endblock %}
{% block content %}
<div class="container">
<div class="jumbotron">
<div class="row">
<div class="col-md-8 content">
<h1>Gargantext</h1>
<p>A web platform to explore text-mining</p>
<p>
<a class="btn btn-primary btn-lg" href="/projects" title="Click and test by yourself">
<span class="glyphicon glyphicon-hand-right" aria-hidden="true"></span>
Log in
</a>
<a class="btn btn-warning btn-lg" target="blank" href="https://iscpif.fr/services/applyforourservices/" title="Fill the form to sign up">
<span class="glyphicon glyphicon-hand-right" aria-hidden="true"></span>
Sign Up
</a>
<a class="btn btn-success btn-lg" target="blank" href="https://iscpif.fr/gargantext/your-first-map/" title="Fill the form to sign up">
<span class="glyphicon glyphicon-hand-right" aria-hidden="true"></span>
Documentation
</a>
</p>
<span class="glyphicon glyphicon-warning-sign" aria-hidden="true"></span>
<i>
Some features may not work without a javascript optimized browser (Chromium for instance).
</i>
</p>
</div>
<div class="col-md-2 content">
<p class="right">
<div style="border:15px">
<img src="{% static "img/logo.png"%}" title="Logo designed by dacha and anoe" style="100px; height:150px; border:3px solid white">
</div>
</p>
</div>
</div>
</div>
<div class="container">
<div class="row">
<div class="content">
<center>
<img src="{% static "img/Gargantextuel-212x300.jpg"%}" title="Gargantextuel drawn by Cecile Meadel" style="border:2px solid black">
<!--
<h2>Introduction Video</h2>
<video width="320" height="240" controls>
<source src="movie.mp4" type="video/mp4">
<source src="movie.ogg" type="video/ogg">
Your browser does not support this video sorry. Try Firefox or Chromium.
</video>
-->
</center>
</div>
</div>
</div>
</div>
<div class="container">
<div class="row">
<div class="col-md-4 content">
<h3><a href="#" title="Random sentences in Gargantua's Books chapters, historically true">Historic</a></h3>
<p> {{ paragraph_gargantua }}</p>
</div>
<div class="col-md-4 content">
<h3><a href="#" title="Randomized words, semantically and syntaxically falses." >Presentation</a></h3>
<p> {{ paragraph_lorem }}
</p>
</div>
<div class="col-md-4 content">
<h3><a href="#" title="Randomized letters, true or false ?">Tutoreil</a></h3>
<p>
{{ paragraph_tutoreil }}
<!-- Why not French ? -->
<!-- find Cambridge source which inspired this -->
</p>
</div>
</div>
{% endblock %}
<script type="text/javascript" src="{% static "lib/gargantext/help.js" %}"></script>
<!DOCTYPE html>
<html>
{% load staticfiles %}
<meta http-equiv="content-type" content="text/html;charset=UTF-8" />
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title>Login | Gargantext</title>
<!-- Prevent the demo from appearing in search engines (REMOVE THIS) -->
<meta name="robots" content="noindex">
<!-- Material Design Icons -->
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<!-- Roboto Web Font -->
<link href="https://fonts.googleapis.com/css?family=Roboto:regular,bold,italic,thin,light,bolditalic,black,medium&amp;lang=en" rel="stylesheet">
<!-- App CSS -->
<link type="text/css" href="{% static "lib/bootstrap/4.0.0/login.min.css" %}" rel="stylesheet">
</head>
<body class="login">
<div class="row">
<div class="col-sm-10 col-sm-push-1 col-md-6 col-md-push-3 col-lg-6 col-lg-push-3">
<h2 class="text-primary center m-a-2">
<i class="material-icons md-36">control_point</i> <span class="icon-text">Gargantext</span>
</h2>
<div class="card-group">
<div class="card">
<div class="card-block">
<div class="center">
<h4 class="m-b-0"><span class="icon-text">Connexion</span></h4>
<p class="text-muted">Login to your account or <a target="blank" href="https://iscpif.fr/services/applyforourservices/">ask to get an access</a></p>
</div>
{% if form.errors %}
<div class="alert alert-danger fade in">
<a href="#" class="close" data-dismiss="alert" aria-label="close" title="close">×</a>
<strong>{{form.non_field_errors}}</strong>
</div>
{% endif %}
<form action="" method="post">
{% csrf_token %}
<div class="form-group">
{{form.username}}
</div>
<div class="form-group">
{{form.password}}
<div class="clearfix"></div>
</div>
<div class="center">
<div class="checkbox">
<label>
<input id="terms-accept" type="checkbox" value="" onclick="enableAuth(this)">
I accept the terms of uses <a href="http://gitlab.iscpif.fr/humanities/tofu/tree/master" target=blank>
[Read the terms of use]</a>.
</input>
</label>
</div>
<button id="login-button" type="submit" class="btn btn-primary btn-rounded" disabled>Login</button>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
<!-- jQuery -->
<script src="{% static "lib/jquery/1.11.1/jquery.min.js" %}"></script>
<!-- Bootstrap -->
<script src="{% static "lib/bootstrap/3.2.0/bootstrap.min.js" %}"></script>
<!-- checkbox => submit -->
<script type="text/javascript">
var okButton = document.getElementById('login-button')
function enableAuth(box) {
okButton.disabled = ! box.checked
}
</script>
</body>
</html>
{% extends "pages/menu.html" %}
{% block css %}
{% load staticfiles %}
<link rel="stylesheet" href="{% static "lib/bootstrap/3.0.2/bootstrap.css" %}">
<script src="{% static "lib/jquery/1.11.1/jquery.min.js" %}" type="text/javascript"></script>
{% endblock %}
{% block content %}
<div class="container theme-showcase" role="main">
<div class="jumbotron">
<h1>Gargantext in maintenance</h1>
<h2>Thanks for your comprehension</h2>
</div>
</div>
{% endblock %}
User-agent: *
Disallow : /auth/
Disallow : /projects/
<html>
{% load staticfiles %}
<head>
<link rel="shortcut icon" href="{% static "/favicon.ico" %}">
<script type="text/javascript" src="{% static "lib/jquery/1.11.1/jquery.min.js" %}"></script>
<link rel="stylesheet" type="text/css" href="{% static "lib/bootstrap/3.0.2/bootstrap.css" %}">
<link rel="stylesheet" type="text/css" href="{% static "lib/gargantext/menu.css"%}"/>
<!-- <script type="text/javascript" src="{% static "lib/gargantext/help.js" %}"></script> -->
{% block css %}
{% endblock %}
</head>
<body>
<!-- Fixed navbar -->
<div id="dafixedtop" class="navbar navbar-inverse navbar-fixed-top" role="navigation">
<div class="container">
<div class="navbar-inner">
<a class="navbar-brand" style="line-height:15px; height:10px; padding: 10px 10px;" href="/"><img src="{% static "img/logoSmall.png"%}" title="Back to home."></a>
</div>
<div class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<ul class="nav navbar-nav pull-left">
<li class="dropdown">
<a href="#" role="button" class="dropdown-toggle navbar-text" data-toggle="dropdown" title="Informations about Gargantext">
<span class="glyphicon glyphicon-info-sign" aria-hidden="true"></span>
Info
<i class="caret"></i>
</a>
<ul class="dropdown-menu">
<li>
<a
tabindex="-1" target="blank" title="Documentation and tutorials"
href='https://iscpif.fr/gargantext/your-first-map/' >
Documentation
</a>
</li>
<li class="divider"></li>
<li>
<a
tabindex="-1" target="blank" title="About"
href="/about/" title="More informations about the project, its sponsors and its authors">
About
</a>
</li>
</ul>
</li>
</ul>
{% if user.is_authenticated %}
<li><a href="/projects/" title="All your projects are here.">
<span class="glyphicon glyphicon-home" aria-hidden="true"></span>
Projects
</a>
</li>
{% endif %}
{% if project %}
<li><a href="/projects/{{project.id}}">
<span class="glyphicon glyphicon-book" aria-hidden="true"></span>
{{project.name | truncatechars:15}}
</a>
</li>
{% endif %}
{% if corpus %}
<li><a href="/projects/{{project.id}}/corpora/{{corpus.id}}">
<span class="glyphicon glyphicon-file" aria-hidden="true"></span>
{{corpus.name | truncatechars:25}}
</a>
</li>
{% endif %}
{% if view == "graph" %}
<li id="graph-rename" style="padding:15">
<span class="glyphicon glyphicon-edit" aria-hidden="true"></span>
<span id="graph-name" class="editable" ondblclick="makeEditable(this)">
Name your graph
</span>
</li>
<li style="padding:15">
<button class="hide" onclick="submitName(this)"></button>
<!-- £TODO put styles in a separate css file -->
<div id="handmade-popover" class="hide popover right" style="height: 42px; top:4px; min-width:100px; width:135px; display:block">
<div class="arrow"></div>
<div id="handmade-popover-content" class="minimsg popover-content">
Submitting...
</div>
</div>
</li>
{% endif %}
</ul>
<ul class="nav navbar-nav pull-right">
<li class="dropdown">
<a href="#" role="button" class="dropdown-toggle navbar-text" data-toggle="dropdown" title="That is your username">
<i class="icon-user"></i>
<span class="glyphicon glyphicon-user" aria-hidden="true" style="color:white"></span>
{{ user.username | truncatechars:15}}
<i class="caret"></i>
</a>
<ul class="dropdown-menu">
<li><a
tabindex="-1" target="blank" title="Send us a message (bug, thanks, congrats...)"
href='https://www.iscpif.fr/gargantext/feedback-and-bug-reports/' >
<span class="glyphicon glyphicon-bullhorn" aria-hidden="true"></span>
Report Feedback
</a>
</li>
<li class="divider"></li>
{% if user.is_authenticated %}
<li>
<a tabindex="-1" href="/auth/logout"
title="Click here to logout especially on public devices">
<span class="glyphicon glyphicon-log-out" aria-hidden="true"></span>
Logout
</a></li>
{% else %}
<li><a tabindex="-1" href="/auth/login">
<span class="glyphicon glyphicon-log-in" aria-hidden="true"></span>
Login
</a></li>
{% endif %}
</ul>
</li>
{% if user.is_authenticated %}
<li class="nav-item dropdown lang">
<a class="nav-link dropdown-toggle" id="lang" data-lang="{{user_parameters.language}}" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<img value="{{user_parameters.language}}" src="/static/img/{{user_parameters.language}}.png" width="25%"/>
<span class="label">{{user_parameters.language}}</span>
<i class="caret"></i>
</a>
<ul class="dropdown-menu" aria-labelledby="lang">
{% for lang in languages %}
{% if lang != user_parameters.language %}
<li class="dropdown-item new_lang">
<a class="new_lang" data-lang="{{lang}}"><img value="{{user_parameters.language}}" src="/static/img/{{lang}}.png" width="25%"/> <span>{{lang}}</span> </a></li>
{% endif %}
{% endfor %}
</ul>
</li>
{% endif %}
</ul>
</div>
</div>
{% if corpus %}
<div class="container">
<ul id="corporatop" class="nav nav-tabs navbar-static-top nav-justified">
<li>
<a type="button" class="btn btn-default {% if view == 'titles' %} active {% endif %}"
onclick="javascript:location.href='/projects/{{project.id}}/corpora/{{ corpus.id }}/'"
data-target='#' href='#'>
<span class="glyphicon glyphicon-folder-open" aria-hidden="true"></span>
&nbsp;Documents
</a>
</li>
<li>
<a type="button" class="btn btn-default {% if view == 'sources' %} active {% endif %}"
onclick="javascript:location.href='/projects/{{project.id}}/corpora/{{ corpus.id }}/sources'"
data-target='#' href='#'>
<span class="glyphicon glyphicon-globe" aria-hidden="true"></span>
Sources
</a>
</li>
<!--
<li>
<a type="button" class="btn btn-default {% if view == 'authors' %} active {% endif %}"
onclick="javascript:location.href='/projects/{{project.id}}/corpora/{{ corpus.id }}/authors'"
data-target='#' href='#'>Authors
<span class="glyphicon glyphicon-user" aria-hidden="true"></span>
</a>
</li>
-->
{% for state in corpus.hyperdata.statuses %}
{% if state.action == "Workflow" %}
{% if state.complete %}
<li>
<a type="button" class="btn btn-default {% if view == 'analytics' %} active {% endif %}"
onclick="javascript:location.href='/projects/{{project.id}}/corpora/{{ corpus.id }}/analytics'"
data-target='#' href='#'>
<span class="glyphicon glyphicon-signal" aria-hidden="true"></span>
Analytics
</a>
</li>
<li class="dropdown">
<a href="#graph" role="button" type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown" title="That is your username">
<span class="glyphicon glyphicon-map-marker" aria-hidden="true"></span>
Graphs
</a>
<i class="caret"></i>
<ul class="dropdown-menu">
<li>
<a tabindex="-1"
onclick="javascript:location.href='/projects/{{project.id}}/corpora/{{ corpus.id }}/myGraphs'"
data-target='#' href='#'>My Graphs
</a>
</li>
<li>
<a tabindex="-1"
data-url="/projects/{{project.id}}/corpora/{{ corpus.id }}/explorer?field1=ngrams&amp;field2=ngrams&amp;distance=conditional&amp;bridgeness=5" onclick='gotoexplorer(this)' >With conditional distance </a>
</li>
<li>
<a tabindex="-1"
data-url="/projects/{{project.id}}/corpora/{{ corpus.id }}/explorer?field1=ngrams&amp;field2=ngrams&amp;distance=distributional&amp;bridgeness=5" onclick='gotoexplorer(this)' >With distributional distance</a>
</li>
</ul>
</li>
<li>
<a type="button" class="btn btn-default {% if view == 'terms' %} active {% endif %}"
onclick="javascript:location.href='/projects/{{project.id}}/corpora/{{ corpus.id }}/terms'"
data-target='#' href='#'>
<span class="glyphicon glyphicon-text-width" aria-hidden="true"></span>
Terms
</a>
</li>
{% endif %}
{% endif %}
{% endfor %}
</ul>
</div>
{% endif %}
</div>
<!--/.nav-collapse -->
{% block corpusBannerTop %}
{% if corpus %}
{% if view != "graph" %}
<div class="container theme-showcase">
<div class="jumbotron" style="margin-bottom:0">
<br>
<br>
<br>
<div class="row">
<div class="col-md-6">
<h3>
<a href="/projects/{{project.id}}">
<span class="glyphicon glyphicon-book" aria-hidden="true"></span>
{{ project.name | truncatechars:50}}
</a>
</h3>
</div>
<!-- export button -->
<div class="col-md-6">
{% if view == 'terms' %}
<a id="export_terms" class="help btn pull-right">
</a>
<a class="btn btn-primary exportbtn pull-right" role="button"
href="/api/ngramlists/export?corpus={{corpus.id}}"
title="Export terms table in CSV">
Export terms table &nbsp; <span class="glyphicon glyphicon-download" aria-hidden="true"></span>
</a>
{% elif view == 'titles' %}
<a id="export_corpus" class="help btn pull-right">
</a>
<a class="btn btn-primary exportbtn pull-right" role="button"
href="/api/nodes?parent_id={{corpus.id}}&types[]=DOCUMENT&pagination_limit=100000&formated=csv"
title="Export full corpus in CSV">
Export corpus &nbsp;
<span class="glyphicon glyphicon-download" aria-hidden="true"></span>
</a>
{% else %}
<!-- TODO export source table -->
<!-- <a id="export_sources" class="help">
</a> -->
<!-- <a id="export_sources" class="help btn btn-primary exportbtn pull-right" role="button"
href="/api/nodes?parent_id={{corpus.id}}&types[]=DOCUMENT&pagination_limit=100000&formated=csv"
title="Export full corpus in CSV">
Export sources &nbsp;
<span class="glyphicon glyphicon-download" aria-hidden="true"></span>
</a><span class="help" id="export_sources"> -->
{% endif %}
</div>
</div>
<div class="row">
<div class="col-md-1">
</span>
</div>
<div class="col-md-6">
<h3>
<span class="glyphicon glyphicon-cd" aria-hidden="true"></span>
{{ resourcename | truncatechars:20 }}
</h3>
<h3>
<span class="glyphicon glyphicon-file" aria-hidden="true"></span>
{{ corpus.name | truncatechars:30 }}
</h3>
</div>
<div class="col-md-5">
<h3>
<span class="glyphicon glyphicon-calendar" aria-hidden="true"></span> {{ corpus.date }}
</h3>
<h3>
<span class="glyphicon glyphicon-user" aria-hidden="true"></span>
Author(s): {{ user.username | truncatechars:15}}
</h3>
</div>
</div>
</div>
</div>
{% endif %}
{% endif %}
{% endblock %}
{% block content %}
{% endblock %}
{% block corpusBannerBottom %}
{% endblock %}
<hr>
<footer>
<p>
Gargantext
<span class="glyphicon glyphicon-registration-mark" aria-hidden="true"></span>
, version 3.0.8,
<a href="http://www.cnrs.fr" target="blank" title="Institution that enables this project.">
Copyrights
<span class="glyphicon glyphicon-copyright-mark" aria-hidden="true"></span>
CNRS {{ date.year }}
</a>
<a href="http://gitlab.iscpif.fr/humanities/gargantext/blob/stable/LICENSE" target="blank" title="Legal instructions of the project.">
, Licences aGPLV3 and CECILL variant Affero compliant
</a>
.
</p>
</footer>
<!-- Place at the end of the document so the pages load faster -->
{% load staticfiles %}
<!--
<script type="text/javascript" src="{% static "lib/jquery/pie-chart/jquery.easypiechart.js"%}"></script>
<script type="text/javascript">
$(function() {
$('.chart').easyPieChart({
//your configuration goes here
size : 50
});
});
</script>
-->
<script type="text/javascript" src="{% static "lib/bootstrap/3.2.0/bootstrap.min.js" %}"></script>
<script type="text/javascript">
// initializes the popover elements with jquery
$(function () { $("[data-toggle='popover']").popover({
html: true,
title: function() {
return $("#popover-head").html();
},
content: function() {
return $("#popover-content").html();
}
});});
</script>
<script type="text/javascript">
// constrains the graph request with startdate & enddate if present
// TODO move in another template (only for pages that have dynacharts with a start/end)
// and then in other pages replace all links like onclick='gotoexplorer(this) by normal links
function gotoexplorer(elem) {
var url_ = $(elem).data("url")
// undef or false
if (typeof TheBuffer == "undefined" || !TheBuffer) {
return window.open(url_,'_blank');
}
var current_timerange = TheBuffer
var time_limits = [new Date(oldest[0],oldest[1]-1,oldest[2]), new Date(latest[0],latest[1]-1,latest[2] ) ];
time_limits[0] = new Date(time_limits[0].setDate(time_limits[0].getDate()-1) );
time_limits[1] = new Date(time_limits[1].setDate(time_limits[1].getDate()+1) );
if( ( +current_timerange[0]===+time_limits[0] ) && ( +current_timerange[1]===+time_limits[1] ) ) {
url_ = url_ // rien
} else {
var start__ = new Date(current_timerange[0].setDate(current_timerange[0].getDate()+1) );
var end__ = new Date(current_timerange[1].setDate(current_timerange[1].getDate()-1) );
var start_ = start__.getFullYear()+"-"+(start__.getMonth()+1)+"-"+(start__.getDay()+1)
var end_ = end__.getFullYear()+"-"+(end__.getMonth()+1)+"-"+(end__.getDay()+1)
url_ += "&start=" + start_ + "&end="+end_;
// url_ += "&start=" + start__.getFullYear() + "&end="+end__.getFullYear();
}
return window.open(url_,'_blank');
}
</script>
{% if view == "graph" %}
<!-- garganrest could be used here to update node's names if we add POST -->
<script type="text/javascript" src="{% static "lib/gargantext/garganrest.js" %}"></script>
<!-- Graph renaming (load after garganrest)-->
<script type="text/javascript" src="{% static "lib/gargantext/graph_renamer.js" %}"></script>
<!-- <script type="text/javascript" src="{% static "lib/gargantext/help.js" %}"></script> -->
{% endif %}
<script type="text/javascript" src="{% static "lib/gargantext/help.js" %}"></script>
{% if debug == False %}
<!-- Piwik -->
<script type="text/javascript">
var _paq = _paq || [];
_paq.push(['trackPageView']);
_paq.push(['enableLinkTracking']);
(function() {
var u="//piwik.iscpif.fr/";
_paq.push(['setTrackerUrl', u+'piwik.php']);
_paq.push(['setSiteId', 2]);
var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0];
g.type='text/javascript'; g.async=true; g.defer=true; g.src=u+'piwik.js'; s.parentNode.insertBefore(g,s);
})();
</script>
<noscript>
<p>
<img src="//piwik.iscpif.fr/piwik.php?idsite=2" style="border:0;" alt="" />
</p>
</noscript>
<!-- End Piwik Code -->
{% endif %}
</body>
</html>
<div class ="container">
<div id="addform" class="row collapse">
<div class="col-md-3"></div>
<div class="col-md-6">
<center>
<div class="panel panel-info">
<div class="panel-heading">Add a corpus</div>
<div class="panel-body">
<form id="form" class="add" role="form" action="/project/{{ project_id }}/" method="post" enctype="multipart/form-data">
{% csrf_token %}
<div id="radioBtn" class="btn-group">
<a id="parse" class="btn btn-info active" data-toggle="method" data-title="parse">
<span class="glyphicon glyphicon-download-alt" aria-hidden="true" > UPLOAD</span>
</a>
<div class="btn">
OR
</div>
<a id="scan" class="btn btn-info notActive" data-toggle="method" data-title="scan">
<span class="glyphicon glyphicon-search" aria-hidden="true" > SEARCH</span>
</a>
</div>
<br />
<br />
<div class="form-group" for="corpus_name">
<label for="name">Name:</label>
<input type="text" id="name"/>
<span class="help-block collapse" for="name">This field is required.</span>
</div>
<div id="source-group">
<label for="source">Select a database</label>
<select id="source" name="source" required>
<option value=""> Select a database &dArr; </option>
{% for element in ressources %}
{% if element.parser != None and element.crawler != None %}
<option value="{{element.type}}" data-parser ="true" data-crawler="true" data-format={{element.file_formats|join:","}}>{{element.name}}</option>
{% elif element.parser != None and element.crawler == None %}
<option value="{{element.type}}" data-parser ="true" data-crawler="false" data-format ={{element.file_formats| join:","}}>{{element.name}}</option>
{% elif element.parser == None and element.crawler != None %}
<option value="{{element.type}}" data-parser ="false" data-crawler="true" data-format ={{element.file_formats|join:","}}>{{element.name}}</option>
{%else%}
<option value="{{element.type}}" data-parser ="false" data-crawler="false" data-format ={{element.file_formats|join:","}}>{{element.name}}</option>
{% endif %}
{% endfor %}
</select>
<span class="help-block collapse" for="source">This field is required</span>
</div>
<br />
<div id="parser" class="form-group">
<input type="file" id="file" data-validation="mime size" data-validation-allowing="csv, txt, xml, zip" data-validation-max-size="1M" name="file" class="form-control-file" accept="text/*,application/xml, application/zip">
<span class="help-block collapse" for="file" class="danger">This field is required</span>
</div>
<br />
<div id="crawler" class="form-group">
<label for="query">Query:</label>
<textarea id="query" type="input" name="query" class="form-control col-xs-12"></textarea>
<span class="help-block collapse" for="id_query" class="danger">This field is required</span>
<br>
</div>
<br />
<div class="form-group" id="btnsubmit">
<button type="button" id="create" class="btn btn-info" >
Add corpus
</button>
</div>
</form>
<span id="simpleloader"></span>
</div>
</div>
</center>
</div>
<div class="col-md-3"></div>
</div>
</div>
{% if list_corpora %}
{% for key, corpora in list_corpora.items %}
<h2>
<div class="row">
<div class="col-md-1 content"></div>
<span class="glyphicon glyphicon-cd" aria-hidden="true"></span>
{{ key }}
</h2>
{% for corpus in corpora %}
<div id="corpus_{{corpus.id}}">
<div class="row">
<h4>
<div class="col-md-1 content"></div>
<div class="col-md-5 content">
<a href="/projects/{{project.id}}/corpora/{{corpus.id}}">
<span class="glyphicon glyphicon-file" aria-hidden="true"></span>
{{corpus.name}}, {{ corpus.count }} documents {{ corpus.status_message }}
</a>
</div>
<div class="col-md-3 content">
<!-- -->
{% for state in corpus.hyperdata.statuses %}
{% ifequal state.action "Workflow" %}
{% if state.complete %}
<a href="/projects/{{project.id}}/corpora/{{corpus.id}}" title="View the corpus">
<button type="button" class="btn btn-default" aria-label="Left Align">
<span class="glyphicon glyphicon-eye-open" aria-hidden="true"></span>
</button>
</a>
<button type="button" class="btn btn-default yopla" data-container="body" data-toggle="popover" data-placement="bottom" data-trigger="focus"
data-content="
<ul>
<li
onclick=&quot;
garganrest.metrics.update({{corpus.id}}, function(){alert('The corpus ({{corpus.name|escapejs}}) was updated')});
&quot;>
<a href='#'>Recalculate ngram metrics</a> <br/> (can take a little while)
</li>
</ul>
">
<span class="glyphicon glyphicon-repeat" aria-hidden="true"
title='Recalculate ngram scores and similarities'></span>
</button>
{% endif %}
<!-- TODO: delete non seulement si state.complete mais aussi si state.error -->
<button type="button" class="btn btn-default" data-container="body" data-toggle="popover" data-placement="bottom"
data-content="
<ul>
<li
onclick=&quot;
garganrest.nodes.delete({{corpus.id}}, function(){$('#corpus_'+{{corpus.id}}).remove()});
$(this).parent().parent().remove();
&quot;>
<a href='#'>Delete this</a>
</li>
</ul>
">
<span class="glyphicon glyphicon-trash" aria-hidden="true"
title='Delete this corpus'></span>
</button>
{% endifequal %}
{% endfor %}
</div>
<div class="col-md-3 content">
{% for state in corpus.hyperdata.statuses %}
{% ifequal state.action "Workflow" %}
{% if state.complete %}
<span class="glyphicon glyphicon-ok" aria-hidden="true"></span>
{% else %}
{% if state.error %}
<span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true"></span>
{{ state.error }}
{% else %}
<div class="progress">
<div class=" progress-bar progress-bar-striped
progress-bar-success
"
role="progressbar" aria-valuenow="45" aria-valuemin="0" aria-valuemax="100" style="width: 20%">
<span>
Upload
</span>
</div>
{% for state in corpus.hyperdata.statuses %}
<div class=" progress-bar progress-bar-striped
{% if state.complete %}
progress-bar-success
{% else %}
active
{% endif %}
"
role="progressbar" aria-valuenow="45" aria-valuemin="0" aria-valuemax="100" style="width: 20%">
<span>
{{ state.action }}
{% if not state.complete %}
Processing
{% endif %}
</span>
</div>
{% endfor %}
</div>
{% endif %}
{% endif %}
{% endifequal %}
{% endfor %}
</div>
<div class="col-md-1 content"></div>
</h4>
</div>
</div>
{% endfor %}
{% endfor %}
{% endif %}
<div class="modal fade" id="stack1" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h3>Query to PubMed</h3>
</div>
<div class="modal-body">
<p>One fine body…</p>
<input id="daquery" type="text" class="input-lg" data-tabindex="2">
<a onclick="getGlobalResults();" class="btn">Scan</a>
<div id="results"></div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
<button onclick="doTheQuery();" disabled id="id_thebutton" type="button" class="btn btn-primary">Explore a sample!</button>
</div>
</div><!-- /.modal-content -->
</div><!-- /.modal-dialog -->
</div><!-- /.modal -->
<!-- Modal -->
<div class="modal fade" id="addcorpus" tabindex="-1" role="dialog" aria-labelledby="myModalLabel2" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h3>Add a Corpus <a href="https://gogs.iscpif.fr/humanities/faq_gargantext/wiki/FAQ#import--export-a-dataset">
<span class="glyphicon glyphicon-question-sign" aria-hidden="true"></span>
</a>
</h3>
</div>
<div class="modal-body">
<!-- FAQ -->
<form id="id_form" enctype="multipart/form-data" action="/projects/{{project.id}}/" method="post">
{% csrf_token %}
<table cellpadding="5">
{% for field in form %}
<tr>
<th>{{field.label_tag}}</th>
<td>
{{ field.errors }}
{{ field }}
{% if field.name == 'name' %}
<span onclick="getGlobalResults(this);" id="scanpubmed"></span>
<div id="theresults"></div>
{% endif %}
</td>
</tr>
{% endfor %}
<tr>
<th></th>
<td>
<div id="pubmedcrawl" style="visibility: hidden;">
Do you have a file already? &nbsp;
<input type="radio" id="file_yes" name="file1" onclick="FileOrNotFile(this.value);" class="file1" value="true" checked> Yes </input>
<input type="radio" id="file_no" name="file1" onclick="FileOrNotFile(this.value);" class="file1" value="false"> No </input>
</div>
</td>
</tr>
</table>
</form>
<div class="modal-footer">
<!-- <div id="pubmedcrawl" align="right" style="visibility: hidden;"><a data-toggle="modal" href="#stack1">&#10142; Query directly in PubMed</a></div> -->
<button type="button" class="btn btn-default" data-dismiss="modal">
<span class="glyphicon glyphicon-remove" aria-hidden="true" ></span>
Close
</button>
<button onclick='bringDaNoise();' id="submit_thing" disabled class="btn btn-primary" >
<span class="glyphicon glyphicon-ok" aria-hidden="true" ></span>
Process this!
</button><span id="simpleloader"></span>
</div>
</div>
</div><!-- /.modal-content -->
</div><!-- /.modal-dialog -->
</div><!-- /.modal -->
<!-- Modal -->
<div id="wait" class="modal fade">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
<h2 class="modal-title"><h2><span class="glyphicon glyphicon-info-sign" aria-hidden="true"></span>Building corpus...</h2>
</div>
<div class="modal-body">
<h5>
Gargantext is gathering your texts
and need some time to eat it.
Duration depends on the size of the dish.
</h5>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Continue on Gargantext</button>
</div>
</div><!-- /.modal-content -->
</div><!-- /.modal-dialog -->
</div><!-- /.modal -->
<script>
var thequeries = [] ;
// load the template's value for N scan size
var querySize = parseInt({{query_size}}) ;
// TODO if is_admin
function doTheQuery() {
if ( $('#submit_thing').prop('disabled') ) return;
console.log("in doTheQuery:");
var origQuery = $("#id_name").val()
var pubmedifiedQuery = {
query : JSON.stringify(thequeries) ,
string: origQuery ,
N : querySize
} ;
console.log(pubmedifiedQuery)
var projectid = window.location.href.split("projects")[1].replace(/\//g, '')//replace all the slashes
$.ajax({
// contentType: "application/json",
url: window.location.origin+"/moissonneurs/pubmed/save/"+projectid,
data: pubmedifiedQuery,
type: 'POST',
beforeSend: function(xhr) {
xhr.setRequestHeader("X-CSRFToken", getCookie("csrftoken"));
},
success: function(data) {
console.log("in doTheQuery() Ajax.Success:")
// console.log(data)
setTimeout(
function() {
location.reload();
}, 3000);
},
error: function(result) {
console.log("in doTheQuery(). Data not found");
}
});
}
function bringDaNoise() {
var theresults = $("#theresults").html()
if( theresults && theresults.search("No results")==-1 ) {
console.log("we've in dynamic mode")
$("#simpleloader").html('<img width="30px" src="{% static "img/loading-bar.gif" %}"></img>')
$("#submit_thing").prop('onclick',null);
var theType = $("#id_type option:selected").html();
console.log("consoling the type: ")
console.log(theType)
if(theType=="Pubmed (XML format)") doTheQuery();
if(theType=="ISTex") {
var origQuery = $("#id_name").val()
console.log("printing the results:")
console.log(origQuery)
testISTEX(origQuery.replace(" ","+"), querySize)
}
}
else {
console.log("we dont have nothing inside results div")
if ( $("#id_file").is(':visible') ) {
console.log("we're in upload-file mode")
var namefield = $("#id_name").val()!=""
var typefield = $("#id_type").val()!=""
var filefield = $("#id_file").val()!=""
if( namefield && typefield && filefield ) {
$("#simpleloader").html('<img width="30px" src="{% static "img/loading-bar.gif" %}"></img>')
$("#submit_thing").prop('onclick',null);
$( "#id_form" ).submit();
}
}
}
}
function getGlobalResults(value){
console.log("in getGlobalResults()")
// AJAX to django
var pubmedquery = $("#id_name").val()
// var Npubs = $("#id_N").val();
if(pubmedquery=="") return;
var formData = {query:pubmedquery , N:querySize}
$("#theresults").html('<img width="30px" src="{% static "img/loading-bar.gif" %}"></img>')
console.log("disabling "+"#"+value.id)
$("#"+value.id).prop('onclick',null);
var theType = $("#id_type option:selected").html();
if(theType=="Pubmed (XML format)") {
$.ajax({
// contentType: "application/json",
url: window.location.origin+"/moissonneurs/pubmed/query",
data: formData,
type: 'POST',
beforeSend: function(xhr) {
xhr.setRequestHeader("X-CSRFToken", getCookie("csrftoken"));
},
success: function(data) {
console.log("SUCCESS")
console.log("in getGlobalResults")
// console.log(data)
console.log("enabling "+"#"+value.id)
$("#"+value.id).attr('onclick','getGlobalResults(this);');
// $("#submit_thing").prop('disabled' , false)
$("#submit_thing").html("Process a {{ query_size }} sample!")
thequeries = data
var N=0,k=0;
for(var i in thequeries) N += thequeries[i].count
if( N>0) {
$("#theresults").html("<i> <b>"+pubmedquery+"</b>: "+N+" publications in the last 5 years</i><br>")
$('#submit_thing').prop('disabled', false);
} else {
$("#theresults").html("<i> <b>"+pubmedquery+"</b>: No results!.</i><br>")
if(data[0]==false)
$("#theresults").html("Pubmed connection error!</i><br>")
$('#submit_thing').prop('disabled', true);
}
},
error: function(result) {
$("#theresults").html("Pubmed connection error!</i><br>")
$('#submit_thing').prop('disabled', true);
}
});
}
if(theType=="ISTex") {
console.log(window.location.origin+"moissonneurs/istex/query")
$.ajax({
// contentType: "application/json",
url: window.location.origin+"/moissonneurs/istex/query",
data: formData,
type: 'POST',
beforeSend: function(xhr) {
xhr.setRequestHeader("X-CSRFToken", getCookie("csrftoken"));
},
success: function(data) {
console.log("in getGlobalResults: Ajax(ISTex)")
console.log("enabling "+"#"+value.id)
$("#"+value.id).attr('onclick','getGlobalResults(this);');
// $("#submit_thing").prop('disabled' , false)
$("#submit_thing").html("Process a {{ query_size }} sample!")
thequeries = data
var N=data.length,k=0;
// for(var i in thequeries) N += thequeries[i].count
if( N>1) {
var total = JSON.parse(data).total
console.log("N: "+total)
$("#theresults").html("<i> <b>"+pubmedquery+"</b>: "+total+" publications.</i><br>")
$('#submit_thing').prop('disabled', false);
} else {
$("#theresults").html("<i> <b>"+data[0]+"</b></i><br>")
$('#submit_thing').prop('disabled', true);
}
},
error: function(result) {
console.log("Data not found");
}
});
}
}
// CSS events for selecting one Radio-Input
function FileOrNotFile( value ) {
var showfile = JSON.parse(value)
var theType = $("#id_type option:selected").html();
// @upload-file events
if (showfile) {
console.log("You've clicked the YES")
$("#id_file").show()
$('label[for=id_file]').show();
$("#id_name").attr("placeholder", "");
$("#scanpubmed").html("")
$("#theresults").html("")
$('#submit_thing').prop('disabled', false);
$( "#id_name" ).on('input',null);
$("#submit_thing").html('<span class="glyphicon glyphicon-ok" aria-hidden="true" ></span> Process this!')
}
// @dynamic-query events
else {
console.log("You've clicked the NO")
$("#id_file").hide()
$('label[for=id_file]').hide();
$("#id_name").attr("placeholder", " [ Enter your query here ] ");
$("#id_name").focus();
$("#scanpubmed").html('<a class="btn btn-primary">Scan</a>')//+'Get: <input id="id_N" size="2" type="text"></input>')
$("#theresults").html("")
$("#submit_thing").prop('disabled' , true)
$( "#id_name" ).on('input',function(e){
console.log($(this).val())
if(theType=="Pubmed (XML format)")
testPUBMED( $(this).val() )
});
}
}
//CSS events for changing the Select element
function CustomForSelect( selected ) {
// show Radio-Inputs and trigger FileOrNotFile>@upload-file events
selected = selected.toLowerCase()
var is_pubmed = (selected.indexOf('pubmed') != -1);
var is_istex = (selected.indexOf('istex' ) != -1);
var is_repec = (selected.indexOf('repec' ) != -1);
if (is_pubmed || is_istex || is_repec) {
// if(selected=="pubmed") {
console.log("show the button for: " + selected)
$("#pubmedcrawl").css("visibility", "visible");
$("#pubmedcrawl").show();
$("#file_yes").click();
$("#submit_thing").html("Process this!")
}
// hide Radio-Inputs and trigger @upload-file events
else {
console.log("hide the button")
$("#pubmedcrawl").css("visibility", "hidden");
$("#id_file").show()
$('label[for=id_file]').show();
FileOrNotFile( "true" )
}
}
var LastData = []
function NSuggest_CreateData(q, data) {
console.log("in the new NSuggest_CreateData:")
LastData = data;
// console.log(LastData)
console.log("adding class ui-widget")
$("#id_name").removeClass( "ui-widget" ).addClass( "ui-widget" )
$( "#id_name" ).autocomplete({
source: LastData
});
return data;
}
function testPUBMED( query ) {
LastData = []
if(!query || query=="") return;
var pubmedquery = encodeURIComponent(query)
$.ajax({
type: 'GET',
url: "http://www.ncbi.nlm.nih.gov/portal/utils/autocomp.fcgi?dict=pm_related_queries_2&q="+pubmedquery,
// data:"db="+db+"&query="+query,
contentType: "application/json",
dataType: 'jsonp'
});
return false;
}
function testISTEX(query,N) {
console.log("in testISTEX:");
if(!query || query=="") return;
var origQuery = query
var postQuery = { query : query , N: N }
var projectid = window.location.href.split("projects")[1].replace(/\//g, '')//replace all the slashes
$.ajax({
// contentType: "application/json",
url: window.location.origin+"/moissonneurs/istex/save/"+projectid,
data: postQuery,
type: 'POST',
beforeSend: function(xhr) {
xhr.setRequestHeader("X-CSRFToken", getCookie("csrftoken"));
},
success: function(data) {
console.log("ajax_success: in testISTEX()")
// console.log(data)
setTimeout(
function() {
location.reload();
}, 5000);
},
error: function(result) {
console.log("in testISTEX(). Data not found");
}
});
}
</script>
# all the corpus of this project
corpora = project.children('CORPUS', order=True).all()
if len(corpora) == 0:
return render(
template_name = 'pages/projects/project.html',
request = request,
context = {
'user': request.user,
'date': datetime.now(),
'project': project,
'resources': RESOURCETYPES,
'list_corpora': None,
'whitelists': [],
'blacklists': [],
'cooclists': [],
'number': 0,
'query_size': QUERY_SIZE_N_DEFAULT,
},
)
total_docs = sum([corpus.children('DOCUMENT').count() for corpus in corpora])
#all the possible resources
sources = [resource["name"] for resource in RESOURCETYPES]
sources_count = defaultdict.fromkeys(sources, 0)
sourcename2corpora = defaultdict.fromkeys(sources, [])
sourcename2corpora["default"] = []
for corpus in corpora:
resource = corpus.children('RESOURCE', order=True).first()
if resource is not None:
#print(resource["name"])
#counting docs by resource
sources_count[resource["name"]]=+ corpus.children('DOCUMENT').count()
#corpus.sources = corpus.children('RESOURCE', order=True).all()
else:
# if len(corpus.sources) < 1:
print("(WARNING) PROJECT view: no resources found for this corpus")
#GET DOCS
#One corpus has multiples docs
corpus.count = corpus.children('DOCUMENT').count()
# if len(corpus.count) < 1:
# print("(WARNING) PROJECT view: no documents found for this corpus")
#GET STATUS
#One corpus has a current status
#TO DO a method to get current status of the corpus
status = corpus.status()
if status is not None and not status['complete']:
if not status['error']:
corpus.status_message = '(in progress: %s, %d complete)' % (
status['action'].replace('_', ' '),
status['progress'],
)
else:
corpus.status_message = '(aborted: "%s" after %i docs)' % (
status['error'][-1],
status['progress']
)
else:
corpus.status_message = ''
#
try:
sourcename2corpora[resource["name"]].append(corpus)
except:
sourcename2corpora["default"].append(corpus)
#calculate repartition
donut = []
for name, count in sources_count.items():
if not count == 0:
donut.append({"source": name.strip().split("[")[0], "count": count, "part": round(count*100.0 /total_docs)})
corpus_list = {}
for name, corpora in sourcename2corpora.items():
if not len(corpora) == 0:
corpus_list[name] = corpora
#TO DO all the resources of this project
# One project has multiple resource that has multiple corpus that has multiple documents
#sources = project.children('RESOURCE', order=True).all()
#total_docs = 0
#for source in resources:
# source.docs_nb = 0
#corpora = source.children('CORPUS', order=True).all()s
#for corpus in corpora:
#docs = corpus.children('DOCUMENT').count()
# total_docs=+ docs
# source.docs_nb =+docs
return render(
template_name = 'pages/projects/project.html',
request = request,
context = {
'user': request.user,
'date': datetime.now(),
'project': project,
'resources': RESOURCETYPES,
'donut': donut,
'list_corpora' : corpora,
#'list_corpora': dict(corpus_list),
'whitelists': [],
'blacklists': [],
'cooclists': [],
'number': len(corpora),
'query_size': QUERY_SIZE_N_DEFAULT,
},
)
</div>
<!-- {% if list_corpora != None %}
{% for key, corpora in list_corpora.items %}
<h2>
<div class="row">
<div class="col-md-1 content"></div>
<span class="glyphicon glyphicon-cd" aria-hidden="true"></span>
{{ key }}
</h2>
{% for corpus in corpora %}
<div id="corpus_{{corpus.id}}">
<div class="row">
<h4>
<div class="col-md-1 content"></div>
<div class="col-md-5 content">
<a href="/projects/{{project.id}}/corpora/{{corpus.id}}">
<span class="glyphicon glyphicon-file" aria-hidden="true"></span>
{{corpus.name}}, {{ corpus.count }} documents {{ corpus.status_message }}
</a>
</div>
<div class="col-md-3 content">
<a href="/projects/{{project.id}}/corpora/{{corpus.id}}"
title="View the corpus">
<button type="button" class="btn btn-default" aria-label="Left Align">
<span class="glyphicon glyphicon-eye-open" aria-hidden="true"></span>
</button>
</a>
{% for state in corpus.hyperdata.statuses %}
{% ifequal state.action "Workflow" %}
{% if state.complete %}
<button type="button" class="btn btn-default yopla" data-container="body" data-toggle="popover" data-placement="bottom" data-trigger="focus"
data-content="
<ul>
<li
onclick=&quot;
garganrest.metrics.update({{corpus.id}}, function(){alert('The corpus ({{corpus.name|escapejs}}) was updated')});
&quot;>
<a href='#'>Recalculate ngram metrics</a> <br/> (can take a little while)
</li>
</ul>
">
<span class="glyphicon glyphicon-repeat" aria-hidden="true"
title='Recalculate ngram scores and similarities'></span>
</button>
{% endif %}
-->
<!-- TODO: delete non seulement si state.complete mais aussi si state.error -->
<!-- <button type="button" class="btn btn-default" data-container="body" data-toggle="popover" data-placement="bottom"
data-content="
<ul>
<li
onclick=&quot;
garganrest.nodes.delete({{corpus.id}}, function(){$('#corpus_'+{{corpus.id}}).remove()});
$(this).parent().parent().remove();
&quot;>
<a href='#'>Delete this</a>
</li>
</ul>
">
<span class="glyphicon glyphicon-trash" aria-hidden="true"
title='Delete this corpus'></span>
</button>
{% endifequal %}
{% endfor %}
</div>
<div class="col-md-3 content">
{% for state in corpus.hyperdata.statuses %}
{% ifequal state.action "Workflow" %}
{% if state.complete %}
<span class="glyphicon glyphicon-ok" aria-hidden="true"></span>
{% else %}
{% if state.error %}
<span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true"></span>
{{ state.error }}
{% else %}
<div class="progress">
{% for state in corpus.hyperdata.statuses %}
{% if state.action != "Workflow" %}
<div class=" progress-bar progress-bar-striped
{% if state.complete %}
progress-bar-success
{% else %}
active
{% endif %}
"
role="progressbar" aria-valuenow="45" aria-valuemin="0" aria-valuemax="100" style="width: 25%">
<span>
{{ state.action }}
{% if state.complete %}
Ok
{% else %}
Processing
{% endif %}
</span>
</div>
{% endif %}
{% endfor %}
</div>
{% endif %}
{% endif %}
{% endifequal %}
{% endfor %}
</div>
<div class="col-md-1 content"></div>
</h4>
</div>
</div>
{% endfor %}
{% endfor %}
{% endif %} -->
<!-- Modal -->
<!-- <div class="modal fade" id="stack1" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h3>Query to PubMed</h3>
</div>
<div class="modal-body">
<p>One fine body…</p>
<input id="daquery" type="text" class="input-lg" data-tabindex="2">
<a onclick="getGlobalResults();" class="btn">Scan</a>
<div id="results"></div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
<button onclick="doTheQuery();" disabled id="id_thebutton" type="button" class="btn btn-primary">Explore a sample!</button>
</div>
</div> /.modal-content -->
<!-- </div><!-- /.modal-dialog -->
<!-- </div> -->
<!-- /.modal -->
<!-- Modal -->
<div class="modal fade" id="addcorpus" tabindex="-1" role="dialog" aria-labelledby="myModalLabel2" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h3>Add a Corpus <a href="https://gogs.iscpif.fr/humanities/faq_gargantext/wiki/FAQ#import--export-a-dataset">
<span class="glyphicon glyphicon-question-sign" aria-hidden="true"></span>
</a>
</h3>
</div>
<div class="modal-body">
<form id="id_form" enctype="multipart/form-data" action="/projects/{{project.id}}/" method="post">
{% csrf_token %}
<table cellpadding="5">
{% for field in form %}
<tr>
<th>{{field.label_tag}}</th>
<td>
{{ field.errors }}
{{ field }}
{% if field.name == 'name' %}
<span onclick="getGlobalResults(this);" id="scanpubmed"></span>
<div id="theresults"></div>
{% endif %}
</td>
</tr>
{% endfor %}
<tr>
<th></th>
<td>
<div id="pubmedcrawl" style="visibility: hidden;">
Do you have a file already? &nbsp;
<input type="radio" id="file_yes" name="file1" onclick="FileOrNotFile(this.value);" class="file1" value="true" checked>Yes </input>
<input type="radio" id="file_no" name="file1" onclick="FileOrNotFile(this.value);" class="file1" value="false">No </input>
</div>
</td>
</tr>
</table>
</form>
<div class="modal-footer">
<!-- <div id="pubmedcrawl" align="right" style="visibility: hidden;"><a data-toggle="modal" href="#stack1">&#10142; Query directly in PubMed</a></div> -->
<button type="button" class="btn btn-default" data-dismiss="modal">
<span class="glyphicon glyphicon-remove" aria-hidden="true" ></span>
Close
</button>
<button onclick='bringDaNoise();' id="submit_thing" disabled class="btn btn-primary" >
<span class="glyphicon glyphicon-ok" aria-hidden="true" ></span>
Process this!
</button><span id="simpleloader"></span>
</div>
</div>
</div><!-- /.modal-content -->
</div><!-- /.modal-dialog -->
</div><!-- /.modal --> -->
{% extends "pages/menu.html" %}
{% block css %}
{% load staticfiles %}
<link rel="stylesheet" href="{% static "lib/bootstrap/3.0.2/bootstrap.css" %}">
<script type="text/javascript" src="{% static "lib/jquery/1.11.1/jquery.min.js" %}"></script>
<script type="text/javascript" src="{% static "lib/gargantext/garganrest.js" %}"></script>
<link rel="stylesheet" href="{% static "lib/jquery/1.11.2/jquery-ui.css" %}">
<script type="text/javascript" src="{% static "lib/morris/morris.min.js" %}"></script>
<link rel="stylesheet" href="{% static "lib/morris/morris.css" %}">
<script src="{% static "lib/raphael/raphael-min.js"%}"></script>
<style type="text/css">
.ui-autocomplete {
z-index: 5000;
}
.ui-autocomplete .ui-menu-item {
font-size:x-small;
}
/* for wait gif in buttons */
.wait-img-active {
margin-left: .5em;
}
/* hover red like btn_danger */
.btn.delete:hover {
color: #fff;
background-color: #c9302c;
border-color: #ac2925;
}
</style>
{% endblock %}
{% block content %}
<div class="container theme-showcase" role="main">
<div class="jumbotron">
<div class="row">
<div class="col-md-4">
<h1>
<span class="glyphicon glyphicon-home" aria-hidden="true"></span>
Projects
</h1>
</div>
<div class="col-md-3"></div>
<div class="col-md-5">
<p id="project" class="help">
<br>
<button id="add" type="button" class="btn btn-primary btn-lg help" data-container="body" data-toggle="popover" data-placement="bottom">
<span class="glyphicon glyphicon-plus" aria-hidden="true"></span>
Add a new project
</button>
<div id="popover-content" class="hide">
<form>
<div id="createForm" class="form-group">
{% csrf_token %}
<div id="status-form" class="collapse"></div>
<div class="row inline">
<label class="col-lg-3" for="inputName" ><span class="pull-right">Name:</span></label>
<input class="col-lg-8" type="text" id="inputName" class="form-control">
</div>
<div class="row inline">
<div class="col-lg-3"></div>
<button id="createProject" class="btn btn-primary btn-sm col-lg-8 push-left">Add Project</button>
<div class="col-lg-2"></div>
</div>
</div>
</form>
</div>
</p>
</div>
</div>
</div>
<div class="container">
<!-- GENERIC STATUS INFO -->
<div id="status" class="row col-lg-12 collapse">
<div id="status-msg" class="alert">
</div>
</div>
<!-- CHECKBOX EDITION -->
<!--
<div class="row collapse" id="editor">
<button title="delete selected project" type="button" class="btn btn-danger" id="delete">
<span class="glyphicon glyphicon-trash " aria-hidden="true" ></span>
</button>
<button title="edit selected project" type="button" class="btn btn-warning" id="edit">
<span class="glyphicon glyphicon-pencil " aria-hidden="true" onclick="editProjects()"></span>
</button> -->
<!-- <button type="button" class="btn btn-info" id="recalculate">
<span class="glyphicon glyphicon-refresh " aria-hidden="true" onclick="recalculateProjects()"></span>
</button>
</div>
-->
<br />
<div class="row container" id="projects">
<!--here loading projectlist from GET /projects-->
</div>
<img id="wait-img" width="90%" style="display:none" src="{% static "img/ajax-loader.gif"%}"></img>
<script type="html/tpl" id="project_item">
<div id="{url}" class="item row">
<h3>
<div class="col-md-6 content">
<!--
<input type="checkbox" value="{url}" data-id="{id}">
-->
<a href="{url}">
<span class="glyphicon glyphicon-book" aria-hidden="true"></span>
<span class="item_name">{name}</span>
</a>
</div>
</h3>
<div id="project_detail" class="col-md-4 content">
<div id="item-editor">
<!-- DELETE PROJECT -->
<button type="button" class="btn btn-default delete pull-right" data-url="{url}" >
<span class="glyphicon glyphicon-trash" aria-hidden="true"></span>
</button>
<!-- EDIT PROJECT-->
<button class="btn btn-default edit pull-right" data-id="{id}" data-url="{url}" data-toggle="collapse">
<span class="glyphicon glyphicon-pencil" aria-hidden="true"></span>
</button>
<!-- REFRESH PROJECT -->
<!--
<button type="button" class="btn btn-default refresh pull-right" data-id="{id}">
<span class="glyphicon glyphicon-refresh pull-right" aria-hidden="true"></span>
</button>
-->
<!-- GET Project -->
<a href="{url}">
<button type="button" title="see project" class="btn btn-default show pull-right" aria-label="Left Align">
<span class="glyphicon glyphicon-eye-open" aria-hidden="true"></span>
</button>
</a>
</div>
<div id="project_status">
<!-- Here add nb of the corpus? -->
</div>
</div>
</div>
<div id="editForm-{id}" class="collapse ">
<!-- status of the form -->
<div id="status-form" class="collapse"></div>
<b>Name:</b><input type="text" id="name-{id}" />
<button id="edit-submit-{id}" class="btn btn-success btn-sm"><span class="glyphicon glyphicon-ok" aria-hidden="true"></span></button>
<button id="edit-cancel-{id}" class="btn btn-danger btn-sm" ><span class="glyphicon glyphicon-remove" aria-hidden="true"></span></button>
</div>
</script>
<style type="text/css">
label {
padding:10px;
margin:0 0 10px;
display:block;
}
label:hover {
background:#eee;
cursor:pointer;
}
</style>
<script type="text/javascript" src="{% static "lib/gargantext/garganrest_projects.js" %}"></script>
<!-- <script type="text/javascript" src="{% static "lib/gargantext/help.js" %}"></script> -->
<script type="text/javascript">
getProjects();
// $(document).on("input#inoutName").bind('keypress', function(e) {
// if(e.keyCode==13){
// $('#createProject').trigger('click');
// }
// });
$(document).on("click","#createProject", function(e){
//alert("clicked");
//
//resetStatusForm("#createForm");
//$('input#inputName').val("");
createProject();
$('#add').on('hidden.bs.popover', function () {
// do something…
resetStatusForm("#createForm");
})
return false;
})
</script>
{% endblock %}
{% extends "pages/menu.html" %}
{% block css %}
{% load staticfiles %}
<link rel="stylesheet" href="{% static "lib/bootstrap/3.0.2/bootstrap.css" %}">
<script type="text/javascript" src="{% static "lib/jquery/1.11.1/jquery.min.js" %}"></script>
<script type="text/javascript" src="{% static "lib/gargantext/garganrest.js" %}"></script>
<link rel="stylesheet" href="{% static "lib/jquery/1.11.2/jquery-ui.css" %}">
<script type="text/javascript" src="{% static "lib/morris/morris.min.js" %}"></script>
<link rel="stylesheet" href="{% static "lib/morris/morris.css" %}">
<script src="{% static "lib/raphael/raphael-min.js"%}"></script>
<style type="text/css">
.ui-autocomplete {
z-index: 5000;
}
.ui-autocomplete .ui-menu-item {
font-size:x-small;
}
.statusinfo {
margin-top: .3em;
color: grey ;
}
ul.inside-popover {
padding: .5em ;
list-style-type: none ;
}
</style>
{% endblock %}
{% block content %}
<div class="container theme-showcase" role="main">
<div class="jumbotron">
<div class="row">
<div class="col-md-6">
{% if project %}
<h1>
<span class="glyphicon glyphicon-book" aria-hidden="true"></span>
{{ project.name | truncatechars:25 }}</h1>
<!--<h3> {{number}} corpora </h3>-->
{% endif %}
</div>
<div class="col-md-4">
<p>
{% if donut %}
<div id="hero-donut" style="height: 200px;"></div>
{% endif %}
<center id="corpus" class="help">
<a data-toggle="modal" href="#addcorpus" >
<button
type="button"
class="btn btn-primary btn-lg"
data-container="body"
data-toggle="popover"
data-placement="bottom"
>
<span class="glyphicon glyphicon-plus" aria-hidden="true" ></span>
Add a corpus
</button>
</a>
</center>
</p>
</div>
</div>
</div>
<!-- Add jumbotron container for each type of corpus (presse, science etc.) -->
<div id="semLoader" style="position:absolute; top:50%; left:40%; width:80px; visibility: hidden;">
<img src="{% static "img/loading-bar.gif" %}"></img>
</div>
<div class="container">
{% if list_corpora %}
{% for key, corpora in list_corpora.items %}
<h2>
<div class="row">
<div class="col-md-1 content"></div>
<span class="glyphicon glyphicon-cd" aria-hidden="true"></span>
{{ key }}
</h2>
{% for corpus in corpora %}
<div id="corpus_{{corpus.id}}" class="corpusElt">
<div class="row">
<h4>
<div class="col-md-1 content"></div>
<div class="col-md-5 content">
<a href="/projects/{{project.id}}/corpora/{{corpus.id}}">
<span class="glyphicon glyphicon-file" aria-hidden="true"></span>
{{corpus.name}}, <span id="corpus_{{corpus.id}}_ndocs">{{ corpus.count }} documents </span>
<span id="corpus_{{corpus.id}}_msg">{{ corpus.status_message }}</span>
</a>
</div>
<div class="col-md-3 content" id="corpus_{{corpus.id}}_tools">
{% if corpus.hyperdata.statuses %}
{% for state in corpus.hyperdata.statuses %}
{% ifequal state.action "Workflow" %}
<a class="{% if not state.complete %}hidden{% endif %}"
href="/projects/{{project.id}}/corpora/{{corpus.id}}" title="View the corpus">
<button type="button" class="btn btn-default" aria-label="Left Align">
<span class="glyphicon glyphicon-eye-open" aria-hidden="true"></span>
</button>
</a>
<button type="button" class="btn btn-default {% if not state.complete %}hidden{% endif %}" data-container="body" data-toggle="popover" data-placement="bottom" data-trigger="focus"
data-content="
<ul class=&quot;inside-popover&quot;>
<li
onclick=&quot;updateCorpus(event, {{corpus.id}})&quot;>
<a href='#'>Recalculate ngram metrics</a> <br/> (can take a little while)
</li>
</ul>
">
<span class="glyphicon glyphicon-repeat" aria-hidden="true"
title='Recalculate ngram scores and similarities'></span>
</button>
<!-- TODO: delete non seulement si state.complete mais aussi si state.error -->
<button type="button" class="btn btn-default" data-container="body" data-toggle="popover" data-placement="bottom"
data-content="
<ul id=&quot;{{corpus.id}}_trash_msg&quot; class=&quot;inside-popover&quot;>
<li
onclick=&quot;deleteCorpus(event, {{corpus.id}})&quot;>
<a href='#'>Delete this</a>
</li>
</ul>
">
<span class="glyphicon glyphicon-trash" aria-hidden="true"
title='Delete this corpus'></span>
</button>
{% endifequal %}
{% endfor %}
{% else %}
<button type="button" class="btn btn-default" data-container="body" data-toggle="popover" data-placement="bottom"
data-content="
<ul id=&quot;{{corpus.id}}_trash_msg&quot; class=&quot;inside-popover&quot;>
<li
onclick=&quot;deleteCorpus(event, {{corpus.id}})&quot;>
<a href='#'>Delete this</a>
</li>
</ul>
">
<span class="glyphicon glyphicon-trash" aria-hidden="true"
title='Delete this corpus'></span>
</button>
{% endif %}
</div>
<div class="col-md-3 content" id="corpus_{{corpus.id}}_status">
{% if corpus.hyperdata.statuses %}
{% for state in corpus.hyperdata.statuses %}
{% ifequal state.action "Workflow" %}
{% if state.complete %}
<span id="corpus_{{corpus.id}}_status_ok"
class="glyphicon glyphicon-ok"
aria-hidden="true"></span>
{% else %}
{% if state.error %}
<span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true"></span>
{{ state.error }}
{% else %}
<div class="progress">
<div class=" progress-bar progress-bar-striped
progress-bar-success
"
role="progressbar" aria-valuenow="45" aria-valuemin="0" aria-valuemax="100" style="width: 20%">
<span>
Upload
</span>
</div>
{% for state in corpus.hyperdata.statuses %}
<!-- {% if state.action != "Workflow" %} -->
<div class=" progress-bar progress-bar-striped
{% if state.complete %}
progress-bar-success
{% else %}
active
{% endif %}
"
role="progressbar" aria-valuenow="45" aria-valuemin="0" aria-valuemax="100"
id="corpus_{{corpus.id}}_status_{{state.action}}" style="width: 20%">
<span>
{{ state.action }}
{% if not state.complete %}
Processing
{% endif %}
</span>
</div>
<!-- {% endif %} -->
{% endfor %}
</div>
{% endif %}
{% endif %}
{% endifequal %}
{% endfor %}
{% else %}
<span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true"></span>
Error at parsing. Please create a new corpus. If this error persists then <a href="https://iscpif.fr/gargantext-feedback-and-bug-report/" target="blank">report</a> the bug with this id: {{ corpus.id }}.
{% endif %}
</div>
<div class="col-md-1 content"></div>
</h4>
</div>
</div>
{% endfor %}
{% endfor %}
{% endif %}
<div class="modal fade" id="stack1" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h3>Query to PubMed</h3>
</div>
<div class="modal-body">
<p>One fine body…</p>
<input id="daquery" type="text" class="input-lg" data-tabindex="2">
<a onclick="getGlobalResults();" class="btn">Scan</a>
<div id="results"></div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
<button onclick="doTheQuery();" disabled id="id_thebutton" type="button" class="btn btn-primary">Explore a sample!</button>
</div>
</div><!-- /.modal-content -->
</div><!-- /.modal-dialog -->
</div><!-- /.modal -->
<!-- Modal -->
<div class="modal fade" id="addcorpus" tabindex="-1" role="dialog" aria-labelledby="myModalLabel2" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h3 id="corpus" class="help">Add a Corpus
</a>
</h3>
</div>
<div class="modal-body">
<!-- FAQ -->
<form id="id_form" enctype="multipart/form-data" action="/projects/{{project.id}}/" method="post">
{% csrf_token %}
<table cellpadding="5">
{% for field in form %}
<tr>
<th>{{field.label_tag}}</th>
<td>
{{ field.errors }}
{{ field }}
{% if field.name == 'name' %}
<span onclick="getGlobalResults(this);" id="scanpubmed"></span>
<div id="theresults"></div>
{% endif %}
</td>
</tr>
{% endfor %}
<tr>
<th></th>
<td>
<div id="div-fileornot" style="visibility: hidden;">
Do you have a file already? &nbsp;
<input type="radio" id="file_yes" name="file1" onclick="FileOrNotFile(this.value);checkReady()" class="file1" value="true" checked> Yes </input>
<input type="radio" id="file_no" name="file1" onclick="FileOrNotFile(this.value);checkReady()" class="file1" value="false"> No </input>
</div>
</td>
</tr>
</table>
</form>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">
<span class="glyphicon glyphicon-remove" aria-hidden="true" ></span>
Close
</button>
<button onclick='bringDaNoise();' id="submit_thing" disabled class="btn btn-primary" >
<span class="glyphicon glyphicon-ok" aria-hidden="true" ></span>
Process this!
</button><span id="simpleloader"></span>
</div>
</div>
</div><!-- /.modal-content -->
</div><!-- /.modal-dialog -->
</div><!-- /.modal -->
<!-- Modal -->
<div id="wait" class="modal fade">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
<h2 class="modal-title"><h2><span class="glyphicon glyphicon-info-sign" aria-hidden="true"></span> Building the corpus...</h2>
</div>
<div class="modal-body">
<center>
<p>
Gargantext is gathering your texts <br>
and need some time to eat it. <br>
Duration depends on the size of the dish.
</p>
</center>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Continue on Gargantext</button>
</div>
</div><!-- /.modal-content -->
</div><!-- /.modal-dialog -->
</div><!-- /.modal -->
<script type="text/javascript" src="{% static "lib/jquery/1.11.2/jquery-ui.js" %}"></script>
<!-- <script type="text/javascript" src="{% static "lib/gargantext/help.js" %}"></script> -->
<script type="text/javascript">
var corporaDivs = document.getElementsByClassName('corpusElt')
// all corpora ids ======================================
var corporaIds = []
// for corpora ids whose delete is pending
var trashedIds = {}
for (var i = 0 ; i < corporaDivs.length ; i++) {
// ex: corpus_1198
divId = corporaDivs[i].id
if (divId) {
var corpusId = divId.match(/[0-9]+$/).pop()
corporaIds.push(corpusId)
}
}
var activeCorporaIds = testActiveCorpora()
if (activeCorporaIds.length) {
// initial checks if page reloaded with active corpora
keepCheckingProjectStatus()
}
// cookie ajax helper ==================================
function getCookie(name) {
var cookieValue = null;
if (document.cookie && document.cookie != '') {
var cookies = document.cookie.split(';');
for (var i = 0; i < cookies.length; i++) {
var cookie = jQuery.trim(cookies[i]);
// Does this cookie string begin with the name we want?
if (cookie.substring(0, name.length + 1) == (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
// =====================================================
// search queries and crawling =========================
// =====================================================
var thequeries = [] ;
// load the template's value for N scan size
var querySize = parseInt({{query_size}}) ;
// TODO if is_admin
function doTheQuery() {
if ( $('#submit_thing').prop('disabled') ) return;
console.log("in doTheQuery:");
var origQuery = $("#id_name").val()
var pubmedifiedQuery = {
query : JSON.stringify(thequeries) ,
string: origQuery ,
N : querySize
} ;
console.log(pubmedifiedQuery)
var projectid = window.location.href.split("projects")[1].replace(/\//g, '')//replace all the slashes
$.ajax({
// contentType: "application/json",
url: window.location.origin+"/moissonneurs/pubmed/save/"+projectid,
data: pubmedifiedQuery,
type: 'POST',
beforeSend: function(xhr) {
xhr.setRequestHeader("X-CSRFToken", getCookie("csrftoken"));
},
success: function(data) {
console.log("in doTheQuery() Ajax.Success:")
// console.log(data)
setTimeout(
function() {
$('#addcorpus').modal('hide');
$("#wait").modal("show");
}, 600);
},
error: function(result) {
console.log("in doTheQuery(). Data not found");
}
});
}
function checkReady() {
// checks if we allow [submit]
// *after* any modification
// in the form "Add a corpus"
var type = $("#id_type").val()
var file = $("#id_file").val()
// 5 booleans
var nameField = $("#id_name").val() != ""
var typeField = (type != "") && (type != "0")
var fileField = file != ""
var wantfileField = $("#file_yes").prop("checked")
var crawling = ((type==3)||(type==8)||(type==9)) && ! wantfileField
// console.warn("bool nameField",nameField)
// console.warn("bool typeField",typeField)
// console.warn("bool fileField",fileField)
// console.warn("bool wantfileField",wantfileField)
// console.warn("bool crawling",crawling)
if (! crawling) {
$("#submit_thing").prop('disabled' , !(nameField && typeField && fileField))
}
// Automatically select CSV when type is undefined
// and we have a .csv file
if (!typeField && file && file.match(/.csv$/i)) {
// Get CSV type id
var csv = $('#id_type > option')
.filter(function() {
return $(this).text() === 'CSV'
})
.attr('value')
// Select CSV type
$('#id_type').val(csv)
// Focus on name field
setTimeout(function() {
$("#id_name").focus()
})
}
}
function bringDaNoise() {
var theresults = $("#theresults").html()
if( theresults && theresults.search("No results")==-1 ) {
console.log("we've in dynamic mode")
$("#simpleloader").html('<img width="30px" src="{% static "img/loading-bar.gif" %}"></img>')
$("#submit_thing").prop('onclick',null);
var theType = $("#id_type option:selected").html();
console.log("consoling the type: ")
console.log(theType)
if(theType=="Pubmed [XML]") doTheQuery();
if(theType=="ISTex") {
var origQuery = $("#id_name").val()
console.log("printing the results:")
console.log(origQuery)
testISTEX(origQuery.replace(" ","+"), querySize)
}
}
else {
console.log("we dont have nothing inside results div")
if ( $("#id_file").is(':visible') ) {
console.log("we're in upload-file mode")
var namefield = $("#id_name").val()!=""
var typefield = $("#id_type").val()!=""
var filefield = $("#id_file").val()!=""
if( namefield && typefield && filefield ) {
$("#simpleloader").html('<img width="30px" src="{% static "img/loading-bar.gif" %}"></img>')
$("#submit_thing").prop('onclick',null);
$( "#id_form" ).submit();
}
}
}
// schedule periodic checks of status of active corpora
keepCheckingProjectStatus()
}
function getGlobalResults(value){
console.log("in getGlobalResults()")
// AJAX to django
var pubmedquery = $("#id_name").val()
// var Npubs = $("#id_N").val();
if(pubmedquery=="") return;
var formData = {query:pubmedquery , N:querySize}
$("#theresults").html('<img width="30px" src="{% static "img/loading-bar.gif" %}"></img>')
console.log("disabling "+"#"+value.id)
$("#"+value.id).prop('onclick',null);
var theType = $("#id_type option:selected").html();
var SourceTypeId = $("#id_type").val()
//alert(SourceTypeId);
//PUBMED = 3
if(SourceTypeId == "3") {
$.ajax({
// contentType: "application/json",
url: window.location.origin+"/moissonneurs/pubmed/query",
data: formData,
type: 'POST',
beforeSend: function(xhr) {
xhr.setRequestHeader("X-CSRFToken", getCookie("csrftoken"));
},
success: function(data) {
console.log("SUCCESS")
console.log("in getGlobalResults")
console.log(data)
console.log("enabling "+"#"+value.id)
$("#"+value.id).attr('onclick','getGlobalResults(this);');
// $("#submit_thing").prop('disabled' , false)
$("#submit_thing").html("Process a {{ query_size }} sample!")
thequeries = data
var N=0;
for(var i in thequeries) N += thequeries[i].count
if( N>0) {
$("#theresults").html("<i> <b>"+pubmedquery+"</b>: "+N+" publications in the last 5 years</i><br>")
$('#submit_thing').prop('disabled', false);
} else {
$("#theresults").html("<i> <b>"+pubmedquery+"</b>: No results!.</i><br>")
if(data[0]==false)
$("#theresults").html("Pubmed connection error!</i><br>")
$('#submit_thing').prop('disabled', true);
}
},
error: function(result) {
$("#theresults").html("Pubmed connection error.</i><br>")
$('#submit_thing').prop('disabled', true);
}
});
}
if(SourceTypeId == "8") {
console.log(window.location.origin+"moissonneurs/istex/query")
$.ajax({
// contentType: "application/json",
url: window.location.origin+"/moissonneurs/istex/query",
data: formData,
type: 'POST',
beforeSend: function(xhr) {
xhr.setRequestHeader("X-CSRFToken", getCookie("csrftoken"));
},
success: function(data) {
console.log("in getGlobalResults: Ajax(ISTex)")
console.log("enabling "+"#"+value.id)
$("#"+value.id).attr('onclick','getGlobalResults(this);');
// $("#submit_thing").prop('disabled' , false)
$("#submit_thing").html("Process a {{ query_size }} sample!")
thequeries = data
var N = data.total;
if (N > 0) {
console.log("N: "+N)
$("#theresults").html("<i> <b>"+pubmedquery+"</b>: "+N+" publications.</i><br>")
$('#submit_thing').prop('disabled', false);
} else {
$("#theresults").html("<i> <b>"+data[0]+"</b></i><br>")
$('#submit_thing').prop('disabled', true);
}
},
error: function(result) {
console.log("Data not found");
}
});
}
//<option value="9">SCOAP [XML]</option>
if (SourceTypeId == "9"){
$.ajax({
// contentType: "application/json",
url: window.location.origin+"/moissonneurs/cern/query",
data: formData,
type: 'POST',
beforeSend: function(xhr) {
xhr.setRequestHeader("X-CSRFToken", getCookie("csrftoken"));
},
success: function(data) {
console.log("SUCCESS")
console.log("enabling "+"#"+value.id)
$("#"+value.id).attr('onclick','getGlobalResults(this);');
$("#submit_thing").prop('disabled' , false)
//$("#submit_thing").html("Process a {{ query_size }} sample!")
N = data["results_nb"]
if(N > 0) {
if (N <= {{query_size}}){
$("#theresults").html("<i> <b>"+pubmedquery+"</b>: "+N+" publications </i><br>")
$("#submit_thing").html("Download!")
$("#submit_thing").prop('disabled' , false)
//$("#submit_thing").attr('onclick', testCERN(query, N));
$("#submit_thing").on("click", function(){
testCERN(pubmedquery, N);
//$("#submit_thing").onclick()
})}
//(N > {{query_size}})
else {
$("#theresults").html("<i> <b>"+pubmedquery+"</b>: "+N+" publications </i><br>")
$('#submit_thing').prop('disabled', false);
$("#submit_thing").html("Processing a sample file")
$("#submit_thing").on("click", function(){
testCERN(pubmedquery, N);
//$("#submit_thing").onclick()
})}
}
else {
$("#theresults").html("<i> <b>"+pubmedquery+"</b>: No results!.</i><br>")
if(data[0]==false)
$("#theresults").html(theType +" connection error!</i><br>")
$('#submit_thing').prop('disabled', true);
}
},
error: function(result) {
$("#theresults").html(theType +" connection error!</i><br>")
$('#submit_thing').prop('disabled', true);
}
});
}
//MULTIVAC = 10
if (SourceTypeId == "10"){
$.ajax({
// contentType: "application/json",
url: window.location.origin+"/moissonneurs/multivac/query",
data: formData,
type: 'POST',
beforeSend: function(xhr) {
xhr.setRequestHeader("X-CSRFToken", getCookie("csrftoken"));
},
success: function(data) {
console.log(data)
console.log("SUCCESS")
console.log("enabling "+"#"+value.id)
// $("#"+value.id).attr('onclick','getGlobalResults(this);');
$("#submit_thing").prop('disabled' , false)
//$("#submit_thing").html("Process a {{ query_size }} sample!")
N = data["results_nb"]
if(N > 0) {
if (N <= {{query_size}}){
$("#theresults").html("<i> <b>"+pubmedquery+"</b>: "+N+" publications </i><br>")
$("#submit_thing").html("Download!")
$("#submit_thing").prop('disabled' , false)
//$("#submit_thing").attr('onclick', testCERN(query, N));
$("#submit_thing").on("click", function(){
saveMultivac(pubmedquery, N, "/moissonneurs/multivac/save/");
//$("#submit_thing").onclick()
})}
//(N > {{query_size}})
else {
$("#theresults").html("<i> <b>"+pubmedquery+"</b>: "+N+" publications </i><br>")
$('#submit_thing').prop('disabled', false);
$("#submit_thing").html("Processing a sample file")
$("#submit_thing").on("click", function(){
saveMultivac(pubmedquery, N,"/moissonneurs/multivac/save/" );
//$("#submit_thing").onclick()
})}
}
else {
$("#theresults").html("<i> <b>"+pubmedquery+"</b>: No results!.</i><br>")
if(data[0]==false)
$("#theresults").html(theType +" connection error!</i><br>")
$('#submit_thing').prop('disabled', true);
}
},
error: function(result) {
$("#theresults").html(theType +" connection error</i><br>")
$('#submit_thing').prop('disabled', true);
}
});
}
//HAL = 11
if (SourceTypeId == "11"){
$.ajax({
// contentType: "application/json",
url: window.location.origin+"/moissonneurs/hal/query",
data: formData,
type: 'POST',
beforeSend: function(xhr) {
xhr.setRequestHeader("X-CSRFToken", getCookie("csrftoken"));
},
success: function(data) {
console.log(data)
console.log("SUCCESS")
console.log("enabling "+"#"+value.id)
// $("#"+value.id).attr('onclick','getGlobalResults(this);');
$("#submit_thing").prop('disabled' , false)
//$("#submit_thing").html("Process a {{ query_size }} sample!")
N = data["results_nb"]
if(N > 0) {
if (N <= {{query_size}}){
$("#theresults").html("<i> <b>"+pubmedquery+"</b>: "+N+" publications </i><br>")
$("#submit_thing").html("Download!")
$("#submit_thing").prop('disabled' , false)
//$("#submit_thing").attr('onclick', testCERN(query, N));
$("#submit_thing").on("click", function(){
save(pubmedquery, N, "/moissonneurs/hal/save/");
//$("#submit_thing").onclick()
})}
//(N > {{query_size}})
else {
$("#theresults").html("<i> <b>"+pubmedquery+"</b>: "+N+" publications </i><br>")
$('#submit_thing').prop('disabled', false);
$("#submit_thing").html("Processing a sample file")
$("#submit_thing").on("click", function(){
save(pubmedquery, N, "/moissonneurs/hal/save/");
//$("#submit_thing").onclick()
})}
}
else {
$("#theresults").html("<i> <b>"+pubmedquery+"</b>: No results!.</i><br>")
if(data[0]==false)
$("#theresults").html(theType +" connection error!</i><br>")
$('#submit_thing').prop('disabled', true);
}
},
error: function(result) {
$("#theresults").html(theType +" connection error</i><br>")
$('#submit_thing').prop('disabled', true);
}
});
}
//HAL = 12
if (SourceTypeId == "12"){
$.ajax({
// contentType: "application/json",
url: window.location.origin+"/moissonneurs/isidore/query",
data: formData,
type: 'POST',
beforeSend: function(xhr) {
xhr.setRequestHeader("X-CSRFToken", getCookie("csrftoken"));
},
success: function(data) {
console.log(data)
console.log("SUCCESS")
console.log("enabling "+"#"+value.id)
// $("#"+value.id).attr('onclick','getGlobalResults(this);');
$("#submit_thing").prop('disabled' , false)
//$("#submit_thing").html("Process a {{ query_size }} sample!")
N = data["results_nb"]
if(N > 0) {
if (N <= {{query_size}}){
$("#theresults").html("<i> <b>"+pubmedquery+"</b>: "+N+" publications </i><br>")
$("#submit_thing").html("Download!")
$("#submit_thing").prop('disabled' , false)
//$("#submit_thing").attr('onclick', testCERN(query, N));
$("#submit_thing").on("click", function(){
save(pubmedquery, N, "/moissonneurs/isidore/save/");
//$("#submit_thing").onclick()
})}
//(N > {{query_size}})
else {
$("#theresults").html("<i> <b>"+pubmedquery+"</b>: "+N+" publications </i><br>")
$('#submit_thing').prop('disabled', false);
$("#submit_thing").html("Processing a sample file")
$("#submit_thing").on("click", function(){
save(pubmedquery, N, "/moissonneurs/isidore/save/");
//$("#submit_thing").onclick()
})}
}
else {
$("#theresults").html("<i> <b>"+pubmedquery+"</b>: No results!.</i><br>")
if(data[0]==false)
$("#theresults").html(theType +" connection error!</i><br>")
$('#submit_thing').prop('disabled', true);
}
},
error: function(result) {
$("#theresults").html(theType +" connection error</i><br>")
$('#submit_thing').prop('disabled', true);
}
});
}
}
// CSS events for selecting one Radio-Input
function FileOrNotFile( value ) {
var showfile = JSON.parse(value)
var theType = $("#id_type option:selected").html();
// @upload-file events
if (showfile) {
console.log("You've clicked the YES")
$("#id_file").show()
$('label[for=id_file]').show();
$("#id_name").attr("placeholder", "");
$("#scanpubmed").html("")
$("#theresults").html("")
// $('#submit_thing').prop('disabled', false); // cf. checkReady
$( "#id_name" ).on('input',null);
$("#submit_thing").html('<span class="glyphicon glyphicon-ok" aria-hidden="true" ></span> Process this!')
}
// @dynamic-query events
else {
console.log("You've clicked the NO")
$("#id_file").hide()
$('label[for=id_file]').hide();
$("#id_name").attr("placeholder", " [ Enter your query here ] ");
$("#id_name").focus();
$("#scanpubmed").html('<a class="btn btn-primary">Scan</a>')//+'Get: <input id="id_N" size="2" type="text"></input>')
$("#theresults").html("")
$("#submit_thing").prop('disabled' , true)
$( "#id_name" ).on('input',function(e){
console.log($(this).val())
if(theType=="Pubmed [XML]")
testPUBMED( $(this).val() )
});
}
}
//CSS events for changing the Select element
function CustomForSelect( selectedId ) {
// show Radio-Inputs and trigger FileOrNotFile>@upload-file events
// selectedId = $("#id_type").val()
console.log("selected:", selectedId);
// by typeID: 3 = PUBMED, 8 = ISTEX, 9 = CERN
if ( selectedId == "3"
|| selectedId == "8"
|| selectedId == "9"
|| selectedId == "10"
|| selectedId == "11"
|| selectedId == "12"
) {
console.log("show the button for: " + selectedId)
$("#div-fileornot").css("visibility", "visible");
$("#div-fileornot").show();
//$("#file_yes").click();
$("#submit_thing").html("Process this!")
// (todo factorize)
// if not crawling, the submit_thing
// will be enabled by checkReady()
// if crawling, submit_thing
// will be enabled by getGlobalResults()
}
// hide Radio-Inputs and trigger @upload-file events
else {
console.log("hide the button")
$("#div-fileornot").css("visibility", "hidden");
$("#id_file").show()
$('label[for=id_file]').show();
FileOrNotFile( "true" )
}
}
var LastData = []
function NSuggest_CreateData(q, data) {
console.log("in the new NSuggest_CreateData:")
LastData = data;
// console.log(LastData)
console.log("adding class ui-widget")
$("#id_name").removeClass( "ui-widget" ).addClass( "ui-widget" )
$( "#id_name" ).autocomplete({
source: LastData
});
return data;
}
function testPUBMED( query ) {
LastData = []
if(!query || query=="") return;
var pubmedquery = encodeURIComponent(query)
$.ajax({
type: 'GET',
url: "http://www.ncbi.nlm.nih.gov/portal/utils/autocomp.fcgi?dict=pm_related_queries_2&q="+pubmedquery,
// data:"db="+db+"&query="+query,
contentType: "application/json",
dataType: 'jsonp'
});
return false;
}
function testCERN(query, N){
//alert("CERN!")
console.log("In testCern")
if(!query || query=="") return;
//var origQuery = query
var data = { "query" : query , "N": N };
var projectid = window.location.href.split("projects")[1].replace(/\//g, '')//replace all the slashes
console.log(data)
$.ajax({
dataType: 'json',
url: window.location.origin+"/moissonneurs/cern/save/"+projectid,
data: data,
type: 'POST',
beforeSend: function(xhr) {
xhr.setRequestHeader("X-CSRFToken", getCookie("csrftoken"));
},
success: function(data) {
console.log("ajax_success: in testCERN()")
console.log(data)
alert("OK")
setTimeout(
function() {
$('#addcorpus').modal('hide')
$("#wait").modal("show");
// setTimeout(
// function(){
// location.reload();
//
// }, 600);
// )
//setTimeout(, 300)
//location.reload();
}, 600);
},
error: function(data) {
console.log(data)
setTimeout(
function() {
$('#addcorpus').modal('hide')
$("#wait").modal("show")
//setTimeout(, 300)
//location.reload();
}, 600);
},
});
}
function testISTEX(query,N) {
console.log("in testISTEX:");
if(!query || query=="") return;
var origQuery = query
var postQuery = { query : query , N: N }
var projectid = window.location.href.split("projects")[1].replace(/\//g, '')//replace all the slashes
$.ajax({
// contentType: "application/json",
url: window.location.origin+"/moissonneurs/istex/save/"+projectid,
data: postQuery,
type: 'POST',
beforeSend: function(xhr) {
xhr.setRequestHeader("X-CSRFToken", getCookie("csrftoken"));
},
success: function(data) {
console.log("ajax_success: in testISTEX()")
// console.log(data)
setTimeout(
function() {
$('#addcorpus').modal('hide');
$("#wait").modal("show");
//location.reload();
}, 600);
},
error: function(result) {
console.log("in testISTEX(). Data not found");
}
});
}
function saveMultivac(query, N){
console.log("In Multivac")
if(!query || query=="") return;
console.log(query)
//var origQuery = query
var data = { "query" : query , "N": N };
// Replace all the slashes
var projectid = window.location.href.split("projects")[1].replace(/\//g, '')
console.log(data)
$.ajax({
dataType: 'json',
url: window.location.origin+"/moissonneurs/multivac/save/"+projectid,
data: data,
type: 'POST',
beforeSend: function(xhr) {
xhr.setRequestHeader("X-CSRFToken", getCookie("csrftoken"));
},
success: function(data) {
console.log("ajax_success: in saveMultivac()")
console.log(data)
alert("OK")
setTimeout(
function() {
$('#addcorpus').modal('hide')
$("#wait").modal("show");
}, 600);
},
error: function(data) {
console.log(data)
setTimeout(
function() {
$('#addcorpus').modal('hide')
$("#wait").modal("show")
//setTimeout(, 300)
//location.reload();
}, 600);
},
});
}
function save(query, N, urlGarg){
console.log("In Gargantext")
if(!query || query=="") return;
console.log(query)
//var origQuery = query
var data = { "query" : query , "N": N };
// Replace all the slashes
var projectid = window.location.href.split("projects")[1].replace(/\//g, '')
console.log(data)
$.ajax({
dataType: 'json',
url: window.location.origin + urlGarg + projectid,
data: data,
type: 'POST',
beforeSend: function(xhr) {
xhr.setRequestHeader("X-CSRFToken", getCookie("csrftoken"));
},
success: function(data) {
console.log("ajax_success: in Gargantext()")
console.log(data)
alert("OK")
setTimeout(
function() {
$('#addcorpus').modal('hide')
$("#wait").modal("show");
}, 600);
},
error: function(data) {
console.log(data)
setTimeout(
function() {
$('#addcorpus').modal('hide')
$("#wait").modal("show")
//setTimeout(, 300)
//location.reload();
}, 600);
},
});
}
function deleteCorpus(e, corpusId) {
// prevents scroll back to top of page
e.preventDefault()
// register pending operation
trashedIds[corpusId] = true ;
// visual loader wheel
var statusDiv = document.getElementById("corpus_"+corpusId+"_status")
statusDiv.innerHTML = '<img width="10%" src="{% static "img/ajax-loader.gif"%}"></img>'
var trashMsgDiv = document.getElementById(corpusId+"_trash_msg")
trashMsgDiv.innerHTML = '<h5>Deleting corpus, please wait</h5>'
// REST and callback
garganrest.nodes.delete(
corpusId,
function(){
$('#corpus_'+corpusId).remove()
delete trashedIds[corpusId]
// remove any popover too
$('.popover').remove();
}
);
}
function updateCorpus(e, corpusId) {
// prevents scroll back to top of page
e.preventDefault()
// show 'waiting'
var statusDiv = document.getElementById("corpus_"+corpusId+"_status")
var previousStatus = statusDiv.innerHTML
statusDiv.innerHTML = '<img width="10%" src="{% static "img/ajax-loader.gif"%}"></img>'
// REST and callback
garganrest.metrics.update(corpusId, function(){
statusDiv.innerHTML = '<div class="statusinfo">Recount is started, please wait, you will be sent a notification email.</div>'
// revert visual
//setTimeout(function(){ statusDiv.innerHTML = previousStatus }, 2000);
})
}
{% if donut %}
// Morris Donut Chart
Morris.Donut({
element: 'hero-donut',
data: [
{% for part in donut %}
{label: '{{ part.source }}', value: {{ part.part }} },
{% endfor %}
],
colors: ["@white", "@white"],
//colors: ["#30a1ec", "#76bdee"],
formatter: function (y) { return y + "%" }
});
{% endif %}
// =====================================================
$('#wait').on('hidden.bs.modal', function (e) {
// reload page when dismiss the info box
window.location.reload()
})
// =====================================================
// corpus-status checking ==============================
// =====================================================
// ------------------------------
// 1) helper progressbar function
// -------------------------------
function updateCorpusProgressbar(crid, statuses, the_status_url) {
if (statuses && statuses[0]) {
// 0 is status of whole WORKFLOW
var statusW = statuses[0]
if (statusW.complete) {
// show checkbox
$('#corpus_'+crid+'_status').html(
'<span id="corpus_'+crid+'_status_ok" '
+ ' class="glyphicon glyphicon-ok"></span>'
)
// show all tools
var cTools = document.getElementById('corpus_'+crid+'_tools').children
for (var i in cTools) {
var elt = cTools[i]
if (elt.classList) {
elt.classList.remove("hidden")
}
}
}
// workflow incomplete: we check each action in [1,4]
else {
var subStatuses = statuses.slice(1,5)
// console.warn(subStatuses)
for (var j in subStatuses) {
var stepOk = subStatuses[j]['complete']
var stepError = subStatuses[j]['error']
// stepName parmi 'Docs','Ngrams','Index','Lists'
var stepName = subStatuses[j]['action']
// debug
// console.warn(stepName)
var pgbarId = 'corpus_'+crid+'_status_'+stepName
// if error
if (stepError && stepError != 'null') {
$('#corpus_'+crid+'_status').html(
'<p class="workflow_error">'
+ 'Error in corpus parsing at step '
+ j +' (' + stepName + ')'
+ JSON.stringify(stepError) +
+ ' <a href="https://www.iscpif.fr/gargantext-feedback-and-bug-report/">'
+'(bug report here)'
+'</a></p>'
)
}
// normal cases: update progressbar ------------
else {
var progressbar = document.getElementById(pgbarId)
if (progressbar) {
console.log('updating '+pgbarId, "stepOk:", stepOk)
// A: done
if (stepOk || stepOk == "true") {
// make progressbar segment green
if (progressbar.className
&& progressbar.className.match('active')) {
progressbar.classList.remove("active")
progressbar.classList.add("progress-bar-success")
}
// remove message if any
document.getElementById('corpus_'+crid+'_msg').innerHTML = ""
// for docs parsing, also update nDocs
if (stepName == "Docs" && stepOk) {
var stepProgress = subStatuses[j]['progress']
document.getElementById('corpus_'+crid+'_ndocs')
.innerHTML = (stepProgress-1) + " documents"
}
}
// B: active
else {
progressbar.classList.add("active")
}
}
// C: new action => new bar segment
else {
console.log('creating '+pgbarId)
barSegmentHtml = '<div class="progress-bar progress-bar-striped'
barSegmentHtml += (stepOk ? ' progress-bar-success' : ' active') + '"'
barSegmentHtml += 'role="progressbar" aria-valuenow="45" aria-valuemin="0" aria-valuemax="100"'
barSegmentHtml += 'id="corpus_'+crid+'_status_'+stepName+'" style="width: 20%">'
barSegmentHtml += '<span>'+stepName
barSegmentHtml += '</span></div>'
$('#corpus_'+crid+'_status > .progress')
.append(barSegmentHtml)
}
}
// ---------------------------------------------
} // end detailed check
}
} // end if statuses array
else {
console.error("Wrong status API return format "
+ "for url" + the_status_url)
}
return null
} // end function
// ---------------------------------------------------
// 2 - main status check function on activeCorporaIds
// ---------------------------------------------------
function updateCorporaStates(someCorporaIds) {
for (var i in someCorporaIds) {
// !careful with closure, async function & loop on i
// cf stackoverflow.com/a/21819961/2489184
(function(i) {
var myCrid = someCorporaIds[i]
var the_status_url = "/api/nodes/"+myCrid+"/status?format=json"
// iterate ajax checks
$.ajax({
type: 'GET',
url: the_status_url,
success: function(data) {
var statuses = data['statuses']
// console.warn("running callback for corpus id:" + myCrid)
updateCorpusProgressbar(myCrid, statuses, the_status_url)
},
error: function(data, s) {
if (trashedIds[myCrid]) {
return null
}
else {
console.warn("status GET: ajax err (s="+s+")")
console.log(data)
}
},
beforeSend: function(xhr) {
xhr.setRequestHeader("X-CSRFToken", getCookie("csrftoken"));
}
}) // ajax: did 1 corpus
})(i)
} // did all corpora
}
// -----------------------------------------------------
// 3 - for testing on client side which need refresh
// -----------------------------------------------------
function testActiveCorpora() {
var activeCorporaIds = []
for (var i in corporaIds) {
var crid = corporaIds[i]
if ((! document.getElementById('corpus_'+crid+'_status_ok'))
&& (! trashedIds[crid])) {
activeCorporaIds.push(crid)
}
}
return activeCorporaIds
}
// -----------------------------------------------------
// 4 - running the check at regular intervals until done
// -----------------------------------------------------
var nChecks = 0
var currentJob = null
function keepCheckingProjectStatus() {
console.log("checking status", nChecks)
nChecks ++
// local check for active corpora
var newActiveCorporaIds = testActiveCorpora()
if (newActiveCorporaIds.length) {
// start remote calls
updateCorporaStates(newActiveCorporaIds)
if (nChecks > {{status_refresh_max_attempts}}) {
// we abandon after 5 checks
console.warn("stopping status checks for corpora:",
newActiveCorporaIds)
nChecks = 0
return null
}
else {
// decreasing intervals (preserving DB while "loosing interest")
var nextTime = nChecks * {{status_refresh_initial_interval}}
// schedule next check
currentJob = setTimeout(keepCheckingProjectStatus, nextTime)
console.log("next status check in", nextTime/1000, "s" )
return false
}
}
else {
console.info("OK, all corpora ingestion complete")
nChecks = 0
return true
}
}
function stopCheckingProjectStatus() {
clearTimeout(currentJob)
}
</script>
{% endblock %}
{% for state in corpus.hyperdata.statuses %}
{% ifequal state.action "Workflow" %}
{% if state.complete %}
<span class="glyphicon glyphicon-ok" aria-hidden="true"></span>
{% else %}
{% if state.error %}
<span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true"></span>
{{ state.error }}
{% else %}
<div class="progress">
{% for state in corpus.hyperdata.statuses %}
{% if state.action != "Workflow" %}
<div class=" progress-bar progress-bar-striped
{% if state.complete %}
progress-bar-success
{% else %}
active
{% endif %}
"
role="progressbar" aria-valuenow="45" aria-valuemin="0" aria-valuemax="100" style="width: 25%">
<span>
{{ state.action }}
{% if state.complete %}
Ok
{% else %}
Processing
{% endif %}
</span>
</div>
{% endif %}
{% endfor %}
</div>
{% endif %}
{% endif %}
{% endifequal %}
{% endfor %}
function manageStatus(statuses){
status_bar = ""
status_bar += '<div class="progress">'
statuses.forEach(function (status){
if (status["action"] == "Workflow"){
if (status["complete"]){
status_bar += '<span class="glyphicon glyphicon-ok pull-right" aria-hidden="true"></span></div>'
return status_bar;
};
else if (status["error"]) {
status_bar += '<span class="glyphicon glyphicon-exclamation-sign pull-right" aria-hidden="true"></span></div>'
return status_bar;
};
else{
};
};
else{
status_bar +='<div class=" progress-bar progress-bar-striped'
if (status["complete"]){
status_bar +='progress-bar-sucess'
};
else{
status_bar +='active'
};
status_bar+= '" role="progressbar" aria-valuenow="45" aria-valuemin="0" aria-valuemax="100" style="width: 25%"> <span>'
if (status["action"]){
if (status["complete"]){
status_bar+= " OK </span></div>"
};
else{
status_bar+= " Processing </span>"
};
}
});
}
}
})
status_bar+="</div>"
return status_bar
};
console.log(errors)
errors.forEach(function(err) {
div = err[0].split(" ")
logs = []
logs.push(div[0])
if (err[1] == false)
{
alert(div[0])
//$(div[0]).parent().addClass("alert danger error");
$(div[0]).next(div[1]).collapse("show");
//$(div[0]).find(div[1]).collapse("show")
}
else
{
$("<span class='glyphicon glyphicon-ok' aria-hidden='true'>").appendTo(div[0])
}
});
return errors
};
function checkInput(source){
if (source.val().length > 0){
return true
}
else {
return false
}
}
function checkSourceFormat(){
source = $("select#source").find(':selected')
if (source.val() != '') {
console.log(source)
source_data = source.data("format")
alert(source_data)
formats = source_data.split(',');
alert(formats);
extension = $("#file").val().substr( (filename.lastIndexOf('.') +1) );
if ($.inArray(extension, formats) == -1){
//$("span.format").collapse("show");
return false;
}
else{
//$("span.format").collapse("hide");
return true;
}
}
return true
}
function checkFileSize(filesize, max_size){
if (filesize > max_size){
return true
}
else{
return false
}
};
//ADD CORPUS FORM
// //source
// $('#source').change(function() {
// $("#source").next("span.required").collapse("hide");
// source_type = $('#source').find(":selected");
// var formats = source_type.data("format").split(',');
// if (formats.length == 0){
// $("#source").next("span.required").collapse("show");
//
// }
// else{
// $("#source").next("span.required").collapse("hide");
// }
// });
// //file
// var max_size = parseInt($('#file').data("max-size"));
// $('#file').change(function() {
// var filesize = parseInt(this.files[0].size);
// if( filesize > max_size){
// alert("Upload file can't exceed 1 Mo because Gargantext would have an indigestion. Consult the special diet of Gargantext in our FAQ")
// $("#file").empty();
// };
// });
//
//
// });
$("#create").bind("click",function(){
var method = $('#radioBtn').find('a.active').data("title");
errors = checkForm()
if (has_error == "true"){
alert("Invalid Form");
}
else{
alert("OK")
//if (checkFileExtension() == true){
//preparePost(method, form)
//}
}
});
/////////////////FORM VALIDATION
function checkFilename(filename){
if (filename == ""){
$("#filename").next("span.required").collapse("show");
return false;
}
else{
$("#file").next("span.required").collapse("hide");
return true;
}
};
function checkFileSize(filesize, max_size){
if (filesize > max_size){
$("span.size").collapse("show");
}
else{
$("span.size").collapse("hide");
}
};
function checkFileExtension(){
filename = $('#file').val()
source_type = $('#source').find(":selected");
if (filename != "" && source_type.val() !== "0"){
fextension = filename.substr( (filename.lastIndexOf('.') +1) );
var formats = source_type.data("format").split(',');
if ($.inArray(extension, formats) == -1){
$("span.format").collapse("show");
return false;
}
else{
$("span.format").collapse("hide");
return true;
}
}
};
//name
$("span.error").collapse("hide");
$('#name').on('input', function() {
var input=$(this);
var is_name=input.val();
if ( is_name.length < 0){
$("#name").next("span.required").collapse("show");
$("form-group#name").addClass("error");
}
else {
$("#name").next("span").collapse("hide");
}
});
//source
$('#source').change(function() {
$("#source").next("span.required").collapse("hide");
source_type = $('#source').find(":selected");
var formats = source_type.data("format").split(',');
if (formats.length == 0){
$("#source").next("span.required").collapse("show");
}
else{
$("#source").next("span.required").collapse("hide");
}
});
//file
var max_size = parseInt($('#file').data("max-size"));
$('#file').change(function() {
$('#name span').collapse("hide");
var input=$(this);
var filename= input.val()
var filesize = parseInt(this.files[0].size);
checkFileSize(filesize, max_size);
});
//console.log("ERRORS?,)
$("#create").bind("click",function(){
var method = $('#radioBtn').find('a.active').data("title");
has_error = $("span.error").hasClass("collapse in");
if (has_error == "true"){
alert("Invalid Form");
}
else{
if (checkFileExtension() == true){
//preparePost(method, form)
}
}
});
{% extends "pages/menu.html" %}
{% block css %}
{% load staticfiles %}
<link rel="stylesheet" href="{% static "lib/bootstrap/3.0.2/bootstrap.css" %}">
<script src="{% static "lib/jquery/1.11.1/jquery.min.js" %}" type="text/javascript"></script>
{% endblock %}
{% block content %}
<!--
<div class="container theme-showcase" role="main">
<div class="jumbotron">
<h2>Your file has been uploaded ! </h2>
<h2>Gargantext need some time to eat it.</h2>
<h2>Duration depends on the size of the dish.</h2>
<a class="btn btn-primary btn-lg" href="/projects/{{ project.id }}" title="Click and test by yourself">Continue on Gargantext</a>
</div> -->
<div class="container theme-showcase" role="main">
<div class="jumbotron">
<div class="row">
<div class="col-md-6">
{% if project %}
<h1>
<span class="glyphicon glyphicon-book" aria-hidden="true"></span>
{{ project.name | truncatechars:25 }}</h1>
<!--<h3> {{number}} corpora </h3>-->
{% endif %}
</div>
<div class="col-md-4">
<p>
{% if donut %}
<div id="hero-donut" style="height: 200px;"></div>
{% endif %}
<center>
<a data-toggle="modal" href="#addcorpus">
<button
type="button"
class="btn btn-primary btn-lg"
data-container="body"
data-toggle="popover"
data-placement="bottom"
>
<span class="glyphicon glyphicon-plus" aria-hidden="true" ></span>
Add a corpus
</button>
</a>
</center>
</p>
</div>
</div>
</div>
<!-- Add jumbotron container for each type of corpus (presse, science etc.) -->
<div id="semLoader" style="position:absolute; top:50%; left:40%; width:80px; visibility: hidden;">
<img src="{% static "img/loading-bar.gif" %}"></img>
</div>
<div class="container">
{% if list_corpora %}
{% for key, corpora in list_corpora.items %}
<h2>
<div class="row">
<div class="col-md-1 content"></div>
<span class="glyphicon glyphicon-cd" aria-hidden="true"></span>
{{ key }}
</h2>
{% for corpus in corpora %}
<div id="corpus_{{corpus.id}}">
<div class="row">
<h4>
<div class="col-md-1 content"></div>
<div class="col-md-5 content">
<a href="/projects/{{project.id}}/corpora/{{corpus.id}}">
<span class="glyphicon glyphicon-file" aria-hidden="true"></span>
{{corpus.name}}, {{ corpus.count }} documents {{ corpus.status_message }}
</a>
</div>
<div class="col-md-3 content">
<!-- -->
{% for state in corpus.hyperdata.statuses %}
{% ifequal state.action "Workflow" %}
{% if state.complete %}
<a href="/projects/{{project.id}}/corpora/{{corpus.id}}" title="View the corpus">
<button type="button" class="btn btn-default" aria-label="Left Align">
<span class="glyphicon glyphicon-eye-open" aria-hidden="true"></span>
</button>
</a>
<button type="button" class="btn btn-default yopla" data-container="body" data-toggle="popover" data-placement="bottom" data-trigger="focus"
data-content="
<ul>
<li
onclick=&quot;
garganrest.metrics.update({{corpus.id}}, function(){alert('The corpus ({{corpus.name|escapejs}}) was updated')});
&quot;>
<a href='#'>Recalculate ngram metrics</a> <br/> (can take a little while)
</li>
</ul>
">
<span class="glyphicon glyphicon-repeat" aria-hidden="true"
title='Recalculate ngram scores and similarities'></span>
</button>
{% endif %}
<!-- TODO: delete non seulement si state.complete mais aussi si state.error -->
<button type="button" class="btn btn-default" data-container="body" data-toggle="popover" data-placement="bottom"
data-content="
<ul>
<li
onclick=&quot;
garganrest.nodes.delete({{corpus.id}}, function(){$('#corpus_'+{{corpus.id}}).remove()});
$(this).parent().parent().remove();
&quot;>
<a href='#'>Delete this</a>
</li>
</ul>
">
<span class="glyphicon glyphicon-trash" aria-hidden="true"
title='Delete this corpus'></span>
</button>
{% endifequal %}
{% endfor %}
</div>
<div class="col-md-3 content">
{% for state in corpus.hyperdata.statuses %}
{% ifequal state.action "Workflow" %}
{% if state.complete %}
<span class="glyphicon glyphicon-ok" aria-hidden="true"></span>
{% else %}
{% if state.error %}
<span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true"></span>
{{ state.error }}
{% else %}
<div class="progress">
<div class=" progress-bar progress-bar-striped
progress-bar-success
"
role="progressbar" aria-valuenow="45" aria-valuemin="0" aria-valuemax="100" style="width: 20%">
<span>
Upload
</span>
</div>
{% for state in corpus.hyperdata.statuses %}
<!-- {% if state.action != "Workflow" %} --!>
<div class=" progress-bar progress-bar-striped
{% if state.complete %}
progress-bar-success
{% else %}
active
{% endif %}
"
role="progressbar" aria-valuenow="45" aria-valuemin="0" aria-valuemax="100" style="width: 20%">
<span>
{{ state.action }}
{% if not state.complete %}
Processing
{% endif %}
</span>
</div>
<!-- {% endif %} --!>
{% endfor %}
</div>
{% endif %}
{% endif %}
{% endifequal %}
{% endfor %}
</div>
<div class="col-md-1 content"></div>
</h4>
</div>
</div>
{% endfor %}
{% endfor %}
{% endif %}
<!-- Modal -->
<div id="wait" class="modal fade">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
<h2 class="modal-title"><h2><span class="glyphicon glyphicon-info-sign" aria-hidden="true"></span>Building the corpus...</h2>
</div>
<div class="modal-body">
<p>
Gargantext is gathering your texts
and need some time to eat it.
Duration depends on the size of the dish.
</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Continue on Gargantext</button>
</div>
</div><!-- /.modal-content -->
</div><!-- /.modal-dialog -->
</div><!-- /.modal -->
<script type="text/javascript" src="{% static "lib/jquery/1.11.2/jquery-ui.js" %}"></script>
<script type="text/javascript">
$(window).load(function() {
var projectid = window.location.href.split("projects")[1].replace(/\//g, '')//replace all the slashes
$('#wait').modal({ show: false})
$("#wait").modal("show");
$('#wait').on('hidden.bs.modal', function (e) {
// reload page when dismiss the info box
$(location).attr('href', window.location.origin+'/projects/'+projectid)
})
});
</script>
{% endblock %}
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