diff --git a/gargantext_web/api.py b/gargantext_web/api.py index 198aa10513fa5b50e1a05df8580a09dbb0d1075f..9bbc4d2d6f9a303769f058582647362d060bfd87 100644 --- a/gargantext_web/api.py +++ b/gargantext_web/api.py @@ -277,20 +277,23 @@ class NodesChildrenDuplicates(APIView): # get the minimum ID for each of the nodes sharing the same metadata kept_node_ids_query = self._fetch_duplicates(request, node_id, [func.min(Node.id).label('id')], 0) kept_node_ids = [kept_node.id for kept_node in kept_node_ids_query] - # delete the stuff - delete_query = (session - .query(Node) - .filter(Node.parent_id == node_id) - .filter(~Node.id.in_(kept_node_ids)) - ) - count = delete_query.count() - delete_query.delete(synchronize_session=False) - session.flush() - # return the result + duplicate_nodes = models.Node.objects.filter( parent_id=node_id ).exclude(id__in=kept_node_ids) + # # delete the stuff + # delete_query = (session + # .query(Node) + # .filter(Node.parent_id == node_id) + # .filter(~Node.id.in_(kept_node_ids)) + # ) + count = len(duplicate_nodes) + for node in duplicate_nodes: + print("deleting node ",node.id) + node.delete() + # print(delete_query) + # # delete_query.delete(synchronize_session=True) + # session.flush() return JsonHttpResponse({ - 'deleted': count, + 'deleted': count }) - # return duplicates_query @@ -663,6 +666,17 @@ class Nodes(APIView): 'metadata': dict(node.metadata), }) + # deleting node by id + # currently, very dangerous + def delete(self, request, node_id): + session = get_session() + node = models.Node.objects.filter(id = node_id) + msgres = "" + try: + node.delete() + msgres = node_id+" deleted!" + except: + msgres ="error deleting: "+node_id class CorpusController: diff --git a/gargantext_web/team.py b/gargantext_web/team.py new file mode 100644 index 0000000000000000000000000000000000000000..9da8a08def066ed3f9a01c74aa4a26cc6766a1cf --- /dev/null +++ b/gargantext_web/team.py @@ -0,0 +1,44 @@ +# -*- coding: utf-8 -*- + +# Order in script: Alphabetical order (first_name, name, mail, website) +# Order in public: Shuffled order + +import random + +def get_team(): + ''' + Function to get list of each member as dict of personal informations. + + You are free to fill the form which is verbose indeed but clear enough for + manual entries (I could zip lists but not clear enough). + + For your picture, please ask Alexandre to take your picture with his camera + in order to follow the design shape of the website. + + ''' + team = [ + { 'first_name' : 'Alexandre', 'last_name' : 'Delanoë', 'mail' : 'alexandre+gargantextATdelanoe.org', 'website' : 'http://alexandre.delanoe.org', 'picture' : 'alexandre.jpg'}, + { 'first_name' : 'David', 'last_name' : 'Chavalarias', 'mail' : '', 'website' : 'http://chavalarias.com', 'picture' : 'david.jpg'}, + { 'first_name' : 'Mathieu', 'last_name' : 'Rodic', 'mail' : '', 'website' : 'http://rodic.fr', 'picture' : 'mathieu.jpg'}, + { 'first_name' : 'Samuel', 'last_name' : 'Castillo J.', 'mail' : 'kaisleanATgmail.com', 'website' : 'http://www.pksm3.droppages.com', 'picture' : 'samuel.jpg'}, + { 'first_name' : 'Elias', 'last_name' : 'Showk', 'mail' : '', 'website' : 'https://github.com/elishowk', 'picture' : ''}, + #{ 'first_name' : '', 'name' : '', 'mail' : '', 'website' : '', 'picture' : ''}, + # copy paste the line above and write your informations please + ] + + random.shuffle(team) + return(team) + +def get_sponsors(): + ''' + Function to get list of each sponsor as dict of institutional informations. + + ''' + sponsors = [ + { 'name' : 'Mines ParisTech', 'website' : 'http://mines-paristech.fr', 'picture' : 'logo.png'}, + # copy paste the line above and write your informations please + ] + + random.shuffle(sponsors) + return(sponsors) + diff --git a/gargantext_web/urls.py b/gargantext_web/urls.py index 81785c07b2f60a74de317cef46406ba4999252ec..73268e4f175cb77128f0949e08b7215b1eeee3ce 100644 --- a/gargantext_web/urls.py +++ b/gargantext_web/urls.py @@ -22,6 +22,7 @@ urlpatterns = patterns('', # User Home view url(r'^$', views.home), + url(r'^about/', views.about), # Project Management url(r'^projects/$', views.projects), @@ -49,9 +50,11 @@ urlpatterns = patterns('', # Data management url(r'^api$', gargantext_web.api.Root), + url(r'^api/nodes/(\d+)/children/ngrams$', gargantext_web.api.NodesChildrenNgrams.as_view()), url(r'^api/nodes/(\d+)/children/metadata$', gargantext_web.api.NodesChildrenMetatadata.as_view()), url(r'^api/nodes/(\d+)/children/queries$', gargantext_web.api.NodesChildrenQueries.as_view()), url(r'^api/nodes/(\d+)/children/duplicates$', gargantext_web.api.NodesChildrenDuplicates.as_view()), + # url(r'^api/nodes/(\d+)/children/duplicates/delete$', gargantext_web.api.NodesChildrenDuplicates.delete ), url(r'^api/nodes/(\d+)$', gargantext_web.api.Nodes.as_view()), url(r'^api/nodes$', gargantext_web.api.NodesList.as_view()), @@ -62,7 +65,7 @@ urlpatterns = patterns('', url(r'^ngrams$', views.ngrams), url(r'^nodeinfo/(\d+)$', views.nodeinfo), url(r'^tests/mvc$', views.tests_mvc), - url(r'^tests/mvc-listdocuments$', views.tests_mvc_listdocuments), + url(r'^tests/mvc-listdocuments$', views.tests_mvc_listdocuments) ) diff --git a/gargantext_web/views.py b/gargantext_web/views.py index 5cecebcd2acc18b49962f47e60155ebe1958c9c7..9fc300b58857ec5a605120da06f58dac93405e07 100644 --- a/gargantext_web/views.py +++ b/gargantext_web/views.py @@ -9,7 +9,7 @@ from node.models import Language, ResourceType, Resource, \ Node, NodeType, Node_Resource, Project, Corpus, \ Ngram, Node_Ngram, NodeNgramNgram, NodeNodeNgram -from node.admin import CorpusForm, ProjectForm, ResourceForm +from node.admin import CorpusForm, ProjectForm, ResourceForm, CustomForm from django.contrib.auth.models import User @@ -97,6 +97,25 @@ def date_range(start_dt, end_dt = None, format=None): # SOME VIEWS +from gargantext_web import team +def about(request): + ''' + About Gargantext, the team and sponsors + ''' + template = get_template('about.html') + user = request.user + date = datetime.datetime.now() + members = team.get_team() + + html = template.render(Context({\ + 'user': user,\ + 'date': date,\ + 'team': members,\ + })) + + return HttpResponse(html) + + def home(request): ''' Home describes the platform. @@ -150,6 +169,7 @@ def projects(request): 'projects': projects }) + def project(request, project_id): ''' This view represents all corpora in a panoramic way. @@ -215,81 +235,172 @@ def project(request, project_id): if request.method == 'POST': - #form = CorpusForm(request.POST, request.FILES) - #print(str(request.POST)) - name = str(request.POST['name']) - try: - resource_type = ResourceType.objects.get(id=str(request.POST['type'])) - except Exception as error: - print(error) - resource_type = None - - try: - file = request.FILES['file'] - except Exception as error: - print(error) - file = None - - #if name != "" and resource_type is not None and file is not None: - try: - parent = Node.objects.get(id=project_id) - node_type = NodeType.objects.get(name='Corpus') - - if resource_type.name == "europress_french": - language = Language.objects.get(iso2='fr') - elif resource_type.name == "europress_english": - language = Language.objects.get(iso2='en') + print("original file:") + print(request.FILES) + + form = CustomForm(request.POST, request.FILES) + if form.is_valid(): + + + name = form.cleaned_data['name'] + thefile = form.cleaned_data['file'] + resource_type = ResourceType.objects.get(id=str( form.cleaned_data['type'] )) + + print("-------------") + print(name,"|",resource_type,"|",thefile) + print("-------------") + print("new file:") + print(thefile) + try: - corpus = Node( + parent = Node.objects.get(id=project_id) + node_type = NodeType.objects.get(name='Corpus') + + if resource_type.name == "europress_french": + language = Language.objects.get(iso2='fr') + elif resource_type.name == "europress_english": + language = Language.objects.get(iso2='en') + + try: + corpus = Node( + user=request.user, + parent=parent, + type=node_type, + language=language, + name=name, + ) + except: + corpus = Node( + user=request.user, + parent=parent, + type=node_type, + name=name, + ) + + corpus.save() + + print(request.user, resource_type , thefile ) + + corpus.add_resource( user=request.user, - parent=parent, - type=node_type, - language=language, - name=name, - ) - except: - corpus = Node( - user=request.user, - parent=parent, - type=node_type, - name=name, + type=resource_type, + file=thefile ) - corpus.save() + try: + #corpus.parse_and_extract_ngrams() + #corpus.parse_and_extract_ngrams.apply_async((), countdown=3) + if DEBUG is True: + corpus.workflow() + else: + corpus.workflow.apply_async((), countdown=3) - print(request.user, resource_type , file ) - print(corpus.language) - corpus.add_resource( - user=request.user, - type=resource_type, - file=file - ) + except Exception as error: + print(error) - try: - #corpus.parse_and_extract_ngrams() - #corpus.parse_and_extract_ngrams.apply_async((), countdown=3) - if DEBUG is True: - corpus.workflow() - else: - corpus.workflow.apply_async((), countdown=3) + return HttpResponseRedirect('/project/' + str(project_id)) + except Exception as error: - print(error) - - return HttpResponseRedirect('/project/' + str(project_id)) - except Exception as error: - print('ee', error) - form = CorpusForm(request=request) - formResource = ResourceForm() - + print('ee', error) + form = CorpusForm(request=request) + formResource = ResourceForm() + + + else: + print("bad form, bad form") + return render(request, 'project.html', { + 'form' : form, + 'user' : user, + 'date' : date, + 'project' : project, + 'donut' : donut, + 'list_corpora' : list_corpora, + 'whitelists' : whitelists, + 'blacklists' : blacklists, + 'cooclists' : cooclists, + 'number' : number, + }) else: - form = CorpusForm(request=request) - formResource = ResourceForm() + form = CustomForm() + + + # if request.method == 'POST': + # #form = CorpusForm(request.POST, request.FILES) + # #print(str(request.POST)) + # name = str(request.POST['name']) + # try: + # resource_type = ResourceType.objects.get(id=str(request.POST['type'])) + # except Exception as error: + # print(error) + # resource_type = None + + # try: + # file = request.FILES['file'] + # except Exception as error: + # print(error) + # file = None + + # #if name != "" and resource_type is not None and file is not None: + # try: + # parent = Node.objects.get(id=project_id) + # node_type = NodeType.objects.get(name='Corpus') + + # if resource_type.name == "europress_french": + # language = Language.objects.get(iso2='fr') + # elif resource_type.name == "europress_english": + # language = Language.objects.get(iso2='en') + + # try: + # corpus = Node( + # user=request.user, + # parent=parent, + # type=node_type, + # language=language, + # name=name, + # ) + # except: + # corpus = Node( + # user=request.user, + # parent=parent, + # type=node_type, + # name=name, + # ) + + # corpus.save() + + # print(request.user, resource_type , file ) + # print(corpus.language) + # corpus.add_resource( + # user=request.user, + # type=resource_type, + # file=file + # ) + + # try: + # #corpus.parse_and_extract_ngrams() + # #corpus.parse_and_extract_ngrams.apply_async((), countdown=3) + # if DEBUG is True: + # corpus.workflow() + # else: + # corpus.workflow.apply_async((), countdown=3) + + # except Exception as error: + # print(error) + + # return HttpResponseRedirect('/project/' + str(project_id)) + # except Exception as error: + # print('ee', error) + # form = CorpusForm(request=request) + # formResource = ResourceForm() + + # else: + # form = CorpusForm(request=request) + # formResource = ResourceForm() return render(request, 'project.html', { 'form' : form, - 'formResource' : formResource, 'user' : user, 'date' : date, 'project' : project, @@ -398,8 +509,6 @@ def corpus(request, project_id, corpus_id): return HttpResponse(html) - - from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger def subcorpus(request, project_id, corpus_id, start , end ): if not request.user.is_authenticated(): diff --git a/init/graph.pdf b/init/graph.pdf index 5d66bd2ed1d11c68c88ccad8f84dc86a81d68c75..cf305c237d6d8000427203e58d8aadce1477bbff 100644 Binary files a/init/graph.pdf and b/init/graph.pdf differ diff --git a/node/admin.py b/node/admin.py index 6fa30e98648ea26b62ccd4453eff02fd84d22a4a..3fe445a8b5c8f47cbc0ebd390b97d1172bd648aa 100644 --- a/node/admin.py +++ b/node/admin.py @@ -92,6 +92,49 @@ class ResourceForm(ModelForm): model = Resource exclude = ['user', 'guid', 'digest'] + +# for formexample.html +from django import forms + +from django.utils.translation import ugettext_lazy as _ +class CustomForm(forms.Form): + name = forms.CharField( label='Name', max_length=199 , required=True) + parsing_options = ResourceType.objects.all().values_list('id', 'name') + type = forms.IntegerField( widget=forms.Select( choices= parsing_options) , required=True ) + file = forms.FileField() + + + + # Description: clean_file() + """ + * file_.content_type - Example: ['application/pdf', 'image/jpeg'] + * len(file_) - file size. + 2.5MB - 2621440 + 5MB - 5242880 + 10MB - 10485760 + 20MB - 20971520 + 50MB - 5242880 + 100MB 104857600 + 250MB - 214958080 + 500MB - 429916160 + """ + def clean_file(self): + file_ = self.cleaned_data.get('file') + #Filename length + if len(file_.name)>30: + from datetime import datetime + file_.name = str(datetime.now().microsecond) + # raise forms.ValidationError(_('Come on dude, name too long. Now is:'+file_.name)) + #File size + if len(file_)>104857600: + raise forms.ValidationError(_('File to heavy! (<100MB).')) + ## File type: + # if file_.content_type == "application/zip": + # raise forms.ValidationError(_('We need a zip pls.')) + return file_ + + + class CorpusForm(ModelForm): #parent = ModelChoiceField(EmptyQuerySet) def __init__(self, *args, **kwargs): @@ -99,12 +142,6 @@ class CorpusForm(ModelForm): self.request = kwargs.pop('request', None) super(CorpusForm, self).__init__(*args, **kwargs) parent_type = NodeType.objects.get(name="Project") - #parent_type = NodeType.objects.get(name=self._parent_nodetype_name) -# self.fields['parent'].queryset = Node.objects.filter( -# user_id=self.request.user.id, -# type_id=parent_type.id -# ) - #self.fields['language'].queryset = Language.objects.filter(implemented=1) except Exception as error: print("Error with", error) diff --git a/node/models.py b/node/models.py index cf972d379eb8e0ab1d6f02bfd7205c94f2c6fa70..44ef6227bc87561b0a50a603c904fb561a4185ca 100644 --- a/node/models.py +++ b/node/models.py @@ -129,33 +129,10 @@ class Node(CTENode): return Resource.objects.select_related('node_resource').filter(node_resource__node = self) def add_resource(self, **kwargs): - - # print("printing arguments for add_resource():") - # print(kwargs) - - # from django.core.files.storage import default_storage - # from django.core.files.base import ContentFile - # import os - # thefile = kwargs["file"] - # path = default_storage.save('tmp/somename.zip', ContentFile(thefile.read())) - # tmp_file = os.path.join(MEDIA_ROOT, path) - # print(tmp_file) - # kwargs["file"] = tmp_file - # print("final kwargs:") - # print(kwargs) - - # only for tests resource = Resource(guid=str(time()), digest=str(time()), **kwargs ) - - #resource = Resource(**kwargs) resource.save() - print("printing rresource.file:") - print(resource.file) - # print("printing the resource 01____:") - # print(resource.file) - # print("printing the resource 02____: asdasdasd") # User if 'user' not in kwargs and 'user_id' not in kwargs: @@ -193,8 +170,6 @@ class Node(CTENode): 'europress_french' : EuropressFileParser, 'europress_english' : EuropressFileParser, })[resource.type.name]() - print("parse_resources:") - print(resource.file) metadata_list += parser.parse(str(resource.file)) # retrieve info from the database type_id = NodeType.objects.get(name='Document').id diff --git a/static/css/bootstrap.css b/static/css/bootstrap.css index 914c74443f903391f7be75c76165999be9de6870..18930d4b5c10ac148aaf7697f4219f17a88c0464 100644 --- a/static/css/bootstrap.css +++ b/static/css/bootstrap.css @@ -743,6 +743,7 @@ pre code { min-height: 1px; padding-left: 15px; padding-right: 15px; + padding-bottom: 15px; } .col-xs-1, .col-xs-2, diff --git a/static/css/ng-tags-input.min.css b/static/css/ng-tags-input.min.css new file mode 100644 index 0000000000000000000000000000000000000000..02d687fec394dd641cbdde34e2e37898f3aeb754 --- /dev/null +++ b/static/css/ng-tags-input.min.css @@ -0,0 +1 @@ +:after,:before,tags-input *{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}tags-input .host{position:relative;margin-top:5px;margin-bottom:5px}tags-input .host:active{outline:0}tags-input .tags{-moz-appearance:textfield;-webkit-appearance:textfield;padding:1px;overflow:hidden;word-wrap:break-word;cursor:text;background-color:#fff;border:1px solid #a9a9a9;box-shadow:1px 1px 1px 0 #d3d3d3 inset}tags-input .tags.focused{outline:0;-webkit-box-shadow:0 0 3px 1px rgba(5,139,242,.6);-moz-box-shadow:0 0 3px 1px rgba(5,139,242,.6);box-shadow:0 0 3px 1px rgba(5,139,242,.6)}tags-input .tags .tag-list{margin:0;padding:0;list-style-type:none}tags-input .tags .tag-item{margin:2px;padding:0 5px;display:inline-block;float:left;font:14px "Helvetica Neue",Helvetica,Arial,sans-serif;height:26px;line-height:25px;border:1px solid #acacac;border-radius:3px;background:-webkit-linear-gradient(top,#f0f9ff 0,#cbebff 47%,#a1dbff 100%);background:linear-gradient(to bottom,#f0f9ff 0,#cbebff 47%,#a1dbff 100%)}tags-input .tags .tag-item.selected{background:-webkit-linear-gradient(top,#febbbb 0,#fe9090 45%,#ff5c5c 100%);background:linear-gradient(to bottom,#febbbb 0,#fe9090 45%,#ff5c5c 100%)}tags-input .tags .tag-item .remove-button{margin:0 0 0 5px;padding:0;border:none;background:0 0;cursor:pointer;vertical-align:middle;font:700 16px Arial,sans-serif;color:#585858}tags-input .tags .tag-item .remove-button:active{color:red}tags-input .tags .input{border:0;outline:0;margin:2px;padding:0;padding-left:5px;float:left;height:26px;font:14px "Helvetica Neue",Helvetica,Arial,sans-serif}tags-input .tags .input.invalid-tag{color:red}tags-input .tags .input::-ms-clear{display:none}tags-input.ng-invalid .tags{-webkit-box-shadow:0 0 3px 1px rgba(255,0,0,.6);-moz-box-shadow:0 0 3px 1px rgba(255,0,0,.6);box-shadow:0 0 3px 1px rgba(255,0,0,.6)}tags-input .autocomplete{margin-top:5px;position:absolute;padding:5px 0;z-index:999;width:100%;background-color:#fff;border:1px solid rgba(0,0,0,.2);-webkit-box-shadow:0 5px 10px rgba(0,0,0,.2);-moz-box-shadow:0 5px 10px rgba(0,0,0,.2);box-shadow:0 5px 10px rgba(0,0,0,.2)}tags-input .autocomplete .suggestion-list{margin:0;padding:0;list-style-type:none}tags-input .autocomplete .suggestion-item{padding:5px 10px;cursor:pointer;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;font:16px "Helvetica Neue",Helvetica,Arial,sans-serif;color:#000;background-color:#fff}tags-input .autocomplete .suggestion-item.selected,tags-input .autocomplete .suggestion-item.selected em{color:#fff;background-color:#0097cf}tags-input .autocomplete .suggestion-item em{font:normal bold 16px "Helvetica Neue",Helvetica,Arial,sans-serif;color:#000;background-color:#fff} \ No newline at end of file diff --git a/static/img/logo.png b/static/img/logo.png index f680289482df96ccf166445ce11a782383442103..7dad58ffa9f4f9198456ce92b43048ca8de734cc 100644 Binary files a/static/img/logo.png and b/static/img/logo.png differ diff --git a/static/img/logo.svg b/static/img/logo.svg index 46c4b0cb9086b42f237b1e644a8cb064b0d30eca..5465b193960d0875d508f856bcf88685f3a12883 100644 --- a/static/img/logo.svg +++ b/static/img/logo.svg @@ -31,7 +31,7 @@ showgrid="true" inkscape:grid-bbox="true" inkscape:document-units="px" - inkscape:window-width="1360" + inkscape:window-width="881" inkscape:window-height="762" inkscape:window-x="0" inkscape:window-y="0" @@ -60,11 +60,11 @@ x="0" y="-0.1566938" inkscape:export-filename="/srv/gargantext/static/img/logo.png" - inkscape:export-xdpi="53" - inkscape:export-ydpi="53" /> + inkscape:export-xdpi="454.50735" + inkscape:export-ydpi="454.50735" /> <g - inkscape:export-ydpi="53.799999" - inkscape:export-xdpi="53.799999" + inkscape:export-ydpi="454.50735" + inkscape:export-xdpi="454.50735" inkscape:export-filename="/srv/gargantext/static/img/logo.png" style="fill:#ff8080;fill-opacity:0.82014388" id="g3835" diff --git a/static/img/team/alexandre.jpg b/static/img/team/alexandre.jpg new file mode 100644 index 0000000000000000000000000000000000000000..bfc035e99e7364dd00382bd22f416c7a82d9cb9b Binary files /dev/null and b/static/img/team/alexandre.jpg differ diff --git a/static/img/team/david.jpg b/static/img/team/david.jpg new file mode 100644 index 0000000000000000000000000000000000000000..a729c9e98d68666f050494942d64d6ac3561a6de Binary files /dev/null and b/static/img/team/david.jpg differ diff --git a/static/img/team/elias.jpg b/static/img/team/elias.jpg new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/static/img/team/logo.svg b/static/img/team/logo.svg new file mode 100644 index 0000000000000000000000000000000000000000..46c4b0cb9086b42f237b1e644a8cb064b0d30eca --- /dev/null +++ b/static/img/team/logo.svg @@ -0,0 +1,97 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="48px" + height="48px" + id="svg4362" + version="1.1" + inkscape:version="0.48.5 r10040" + sodipodi:docname="logo.svg"> + <defs + id="defs4364" /> + <sodipodi:namedview + id="base" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageopacity="0.0" + inkscape:pageshadow="2" + inkscape:zoom="5.6897594" + inkscape:cx="-11.235831" + inkscape:cy="3.8560006" + inkscape:current-layer="layer1" + showgrid="true" + inkscape:grid-bbox="true" + inkscape:document-units="px" + inkscape:window-width="1360" + inkscape:window-height="762" + inkscape:window-x="0" + inkscape:window-y="0" + inkscape:window-maximized="0" /> + <metadata + id="metadata4367"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title></dc:title> + </cc:Work> + </rdf:RDF> + </metadata> + <g + id="layer1" + inkscape:label="Layer 1" + inkscape:groupmode="layer"> + <rect + style="fill:#fffcfc;fill-opacity:1;stroke:none" + id="rect3755" + width="29.70249" + height="31.108515" + x="0" + y="-0.1566938" + inkscape:export-filename="/srv/gargantext/static/img/logo.png" + inkscape:export-xdpi="53" + inkscape:export-ydpi="53" /> + <g + inkscape:export-ydpi="53.799999" + inkscape:export-xdpi="53.799999" + inkscape:export-filename="/srv/gargantext/static/img/logo.png" + style="fill:#ff8080;fill-opacity:0.82014388" + id="g3835" + transform="matrix(0.2422549,0,0,0.23374214,-49.789462,-7.9055988)"> + <path + inkscape:export-ydpi="100" + inkscape:export-xdpi="100" + inkscape:export-filename="/home/alexandre/projets/gargantext.py/gargantext_core/shared/LogoSimple.png" + id="path3837" + d="m 206.24721,35.28586 0,129.5 67.78125,0 0,-8.625 c -9.86526,-0.47262 -18.57934,-2.63259 -25.5625,-6.28125 -18.65918,-9.74237 -29.875,-28.26535 -29.875,-49.1875 0,-31.71741 21.11877,-52.8149 55.4375,-55.1875 l 0,-10.21875 -67.78125,0 z m 67.78125,10.21875 0,8.5 c 1.74191,-0.16369 3.53543,-0.28125 5.37499,-0.28125 6.91081,0 13.295,1.44116 19.6875,4.15625 l 2.40625,2.875 2.59375,14.53125 9.6875,0 0,-25.375 c -11.40283,-3.03451 -22.61727,-4.65625 -33.15625,-4.65625 -2.24526,0 -4.44959,0.10177 -6.59374,0.25 z m 0,8.5 c -23.28864,2.18852 -37.65625,18.81513 -37.65625,45.562503 0,27.600037 14.44681,45.025437 37.65625,47.812497 l 0,-93.375 z m 0,93.375 0,8.78125 c 1.36224,0.0653 2.75177,0.0937 4.15624,0.0937 10.19344,0 22.1324,-1.88915 35.78125,-5.5625 l 0,-38.1875 2.9375,-2.21875 9.5,-0.8125 0,-6.5625 -43.21875,0 0,6.5625 12.28125,0.8125 2.9375,2.21875 0,33.21875 c -6.73804,1.4374 -12.61466,2.09375 -17.625,2.09375 -2.32322,0 -4.57592,-0.17643 -6.74999,-0.4375 z" + style="font-size:166.11251831px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:center;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:middle;fill:#ff8080;fill-opacity:0.82014388;stroke:none;font-family:Bitstream Charter;-inkscape-font-specification:Bitstream Charter" + inkscape:connector-curvature="0" /> + <path + inkscape:export-ydpi="100" + inkscape:export-xdpi="100" + transform="translate(611.62306,-400.10238)" + sodipodi:open="true" + sodipodi:end="6.1660663" + sodipodi:start="0" + d="m -312.87112,480.17926 c 0,4.97881 -4.03612,9.01493 -9.01493,9.01493 -4.97881,0 -9.01493,-4.03612 -9.01493,-9.01493 0,-4.97881 4.03612,-9.01493 9.01493,-9.01493 4.57131,0 8.41901,3.42153 8.95317,7.96152" + sodipodi:ry="9.0149298" + sodipodi:rx="9.0149298" + sodipodi:cy="480.17926" + sodipodi:cx="-321.88605" + id="path3839" + style="fill:#ff8080;fill-opacity:0.82014388;stroke:none" + sodipodi:type="arc" /> + </g> + </g> +</svg> diff --git a/static/img/team/mathieu.jpg b/static/img/team/mathieu.jpg new file mode 100644 index 0000000000000000000000000000000000000000..1d1f0cae882d81e8a4e801b9a1ee13ed63efcce5 Binary files /dev/null and b/static/img/team/mathieu.jpg differ diff --git a/static/img/team/samuel.jpg b/static/img/team/samuel.jpg new file mode 100644 index 0000000000000000000000000000000000000000..01742a7c06b84360c9c74c01595e21e6b83baaee Binary files /dev/null and b/static/img/team/samuel.jpg differ diff --git a/static/js/gargantext.angular.js b/static/js/gargantext.angular.js index 06307b2a549f0a3fe7b24a5c3d602cb024f2cc09..e797b6ce3769e24cdff48e61c82546e7bca69878 100644 --- a/static/js/gargantext.angular.js +++ b/static/js/gargantext.angular.js @@ -108,7 +108,7 @@ var groupings = { // Define the application -var gargantext = angular.module('Gargantext', ['n3-charts.linechart', 'ngCookies']); +var gargantext = angular.module('Gargantext', ['n3-charts.linechart', 'ngCookies', 'ngTagsInput']); // Customize the application's scope @@ -272,16 +272,36 @@ gargantext.controller("DatasetController", function($scope, $http) { $scope.entities = undefined; $scope.filters = []; $http.get(url, {cache: true}).success(function(response){ - $scope.entities = { - metadata: response.data, - ngrams: [ - {key:'terms', type:'string'}, - {key:'terms count', type:'integer'} - ] - }; + $scope.entities = [ + { + key: 'metadata', + columns: response.data + }, + { + key: 'ngrams', + columns: [ + {key:'terms', type:'string'}, + {key:'terms count', type:'integer'} + ], + } + ]; }); $scope.updateQuery(); }; + // query ngrams + $scope.getNgrams = function(query) { + var url = '/api/nodes/' + $scope.corpusId + '/children/ngrams?limit=10&contain=' + encodeURI(query); + var appendTransform = function(defaults, transform) { + defaults = angular.isArray(defaults) ? defaults : [defaults]; + return defaults.concat(transform); + } + return $http.get(url, { + transformResponse: appendTransform($http.defaults.transformResponse, function(value) { + console.log(value.data) + return value.data; + }) + }); + }; // filtering informations retrieval $scope.operators = operators; // add a filter @@ -308,11 +328,25 @@ gargantext.controller("DatasetController", function($scope, $http) { continue; } } - filters.push({ - field: filter.entity + '.' + filter.column, - operator: filter.operator, - value: filter.value - }); + if (filter.entity.key == 'ngrams') { + var termsList = []; + angular.forEach(filter.value, function(ngram) { + termsList.push(ngram.terms); + }); + if (termsList.length) { + filters.push({ + field: 'ngrams.terms', + operator: 'in', + value: termsList + }); + } + } else { + filters.push({ + field: filter.entity.key + '.' + filter.column.key, + operator: filter.operator, + value: filter.value + }); + } } // event firing to parent(s) $scope.$emit('updateDataset', { diff --git a/static/js/ng-tags-input.min.js b/static/js/ng-tags-input.min.js new file mode 100644 index 0000000000000000000000000000000000000000..6748ef34f0ade1b5eba98d7d1ce9b667e2881363 --- /dev/null +++ b/static/js/ng-tags-input.min.js @@ -0,0 +1 @@ +/*! ngTagsInput v2.0.1 License: MIT */!function(){"use strict";function a(){var a={};return{on:function(b,c){return b.split(" ").forEach(function(b){a[b]||(a[b]=[]),a[b].push(c)}),this},trigger:function(b,c){return angular.forEach(a[b],function(a){a.call(null,c)}),this}}}function b(a,b){return a=a||[],a.length>0&&!angular.isObject(a[0])&&a.forEach(function(c,d){a[d]={},a[d][b]=c}),a}function c(a,b,c){for(var d=null,e=0;e<a.length;e++)if(a[e][c].toLowerCase()===b[c].toLowerCase()){d=a[e];break}return d}function d(a,b,c){var d=b.replace(/([.?*+^$[\]\\(){}|-])/g,"\\$1");return a.replace(new RegExp(d,"gi"),c)}var e={backspace:8,tab:9,enter:13,escape:27,space:32,up:38,down:40,comma:188},f=angular.module("ngTagsInput",[]);f.directive("tagsInput",["$timeout","$document","tagsInputConfig",function(d,f,g){function h(a,b){var d,e,f,g={};return d=function(b){return b[a.displayProperty]},e=function(b,c){b[a.displayProperty]=c},f=function(b){var e=d(b);return e.length>=a.minLength&&e.length<=(a.maxLength||e.length)&&a.allowedTagsPattern.test(e)&&!c(g.items,b,a.displayProperty)},g.items=[],g.addText=function(a){var b={};return e(b,a),g.add(b)},g.add=function(c){var h=d(c).trim();return a.replaceSpacesWithDashes&&(h=h.replace(/\s/g,"-")),e(c,h),f(c)?(g.items.push(c),b.trigger("tag-added",{$tag:c})):b.trigger("invalid-tag",{$tag:c}),c},g.remove=function(a){var c=g.items.splice(a,1)[0];return b.trigger("tag-removed",{$tag:c}),c},g.removeLast=function(){var b,c=g.items.length-1;return a.enableEditingLastTag||g.selected?(g.selected=null,b=g.remove(c)):g.selected||(g.selected=g.items[c]),b},g}return{restrict:"E",require:"ngModel",scope:{tags:"=ngModel",onTagAdded:"&",onTagRemoved:"&"},replace:!1,transclude:!0,templateUrl:"ngTagsInput/tags-input.html",controller:["$scope","$attrs","$element",function(b,c,d){g.load("tagsInput",b,c,{placeholder:[String,"Add a tag"],tabindex:[Number],removeTagSymbol:[String,String.fromCharCode(215)],replaceSpacesWithDashes:[Boolean,!0],minLength:[Number,3],maxLength:[Number],addOnEnter:[Boolean,!0],addOnSpace:[Boolean,!1],addOnComma:[Boolean,!0],addOnBlur:[Boolean,!0],allowedTagsPattern:[RegExp,/.+/],enableEditingLastTag:[Boolean,!1],minTags:[Number],maxTags:[Number],displayProperty:[String,"text"],allowLeftoverText:[Boolean,!1],addFromAutocompleteOnly:[Boolean,!1]}),b.events=new a,b.tagList=new h(b.options,b.events),this.registerAutocomplete=function(){var a=d.find("input");return a.on("keydown",function(a){b.events.trigger("input-keydown",a)}),{addTag:function(a){return b.tagList.add(a)},focusInput:function(){a[0].focus()},getTags:function(){return b.tags},getOptions:function(){return b.options},on:function(a,c){return b.events.on(a,c),this}}}}],link:function(a,c,g,h){var i=[e.enter,e.comma,e.space,e.backspace],j=a.tagList,k=a.events,l=a.options,m=c.find("input");k.on("tag-added",a.onTagAdded).on("tag-removed",a.onTagRemoved).on("tag-added",function(){a.newTag.text=""}).on("tag-added tag-removed",function(){h.$setViewValue(a.tags)}).on("invalid-tag",function(){a.newTag.invalid=!0}).on("input-change",function(){j.selected=null,a.newTag.invalid=null}).on("input-focus",function(){h.$setValidity("leftoverText",!0)}).on("input-blur",function(){l.addFromAutocompleteOnly||(l.addOnBlur&&j.addText(a.newTag.text),h.$setValidity("leftoverText",l.allowLeftoverText?!0:!a.newTag.text))}),a.newTag={text:"",invalid:null},a.getDisplayText=function(a){return a[l.displayProperty].trim()},a.track=function(a){return a[l.displayProperty]},a.newTagChange=function(){k.trigger("input-change",a.newTag.text)},a.$watch("tags",function(c){a.tags=b(c,l.displayProperty),j.items=a.tags}),a.$watch("tags.length",function(a){h.$setValidity("maxTags",angular.isUndefined(l.maxTags)||a<=l.maxTags),h.$setValidity("minTags",angular.isUndefined(l.minTags)||a>=l.minTags)}),m.on("keydown",function(b){if(!b.isImmediatePropagationStopped||!b.isImmediatePropagationStopped()){var c,d,f=b.keyCode,g=b.shiftKey||b.altKey||b.ctrlKey||b.metaKey,h={};if(!g&&-1!==i.indexOf(f))if(h[e.enter]=l.addOnEnter,h[e.comma]=l.addOnComma,h[e.space]=l.addOnSpace,c=!l.addFromAutocompleteOnly&&h[f],d=!c&&f===e.backspace&&0===a.newTag.text.length,c)j.addText(a.newTag.text),a.$apply(),b.preventDefault();else if(d){var k=j.removeLast();k&&l.enableEditingLastTag&&(a.newTag.text=k[l.displayProperty]),a.$apply(),b.preventDefault()}}}).on("focus",function(){a.hasFocus||(a.hasFocus=!0,k.trigger("input-focus"),a.$apply())}).on("blur",function(){d(function(){var b=f.prop("activeElement"),d=b===m[0],e=c[0].contains(b);(d||!e)&&(a.hasFocus=!1,k.trigger("input-blur"))})}),c.find("div").on("click",function(){m[0].focus()})}}}]),f.directive("autoComplete",["$document","$timeout","$sce","tagsInputConfig",function(a,f,g,h){function i(a,d){var e,g,h,i={};return g=function(a,b){return a.filter(function(a){return!c(b,a,d.tagsInput.displayProperty)})},i.reset=function(){h=null,i.items=[],i.visible=!1,i.index=-1,i.selected=null,i.query=null,f.cancel(e)},i.show=function(){i.selected=null,i.visible=!0},i.load=function(c,j){return c.length<d.minLength?void i.reset():(f.cancel(e),void(e=f(function(){i.query=c;var e=a({$query:c});h=e,e.then(function(a){e===h&&(a=b(a.data||a,d.tagsInput.displayProperty),a=g(a,j),i.items=a.slice(0,d.maxResultsToShow),i.items.length>0?i.show():i.reset())})},d.debounceDelay,!1)))},i.selectNext=function(){i.select(++i.index)},i.selectPrior=function(){i.select(--i.index)},i.select=function(a){0>a?a=i.items.length-1:a>=i.items.length&&(a=0),i.index=a,i.selected=i.items[a]},i.reset(),i}function j(a){return a.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">")}return{restrict:"E",require:"^tagsInput",scope:{source:"&"},templateUrl:"ngTagsInput/auto-complete.html",link:function(b,c,f,k){var l,m,n,o,p,q=[e.enter,e.tab,e.escape,e.up,e.down];h.load("autoComplete",b,f,{debounceDelay:[Number,100],minLength:[Number,3],highlightMatchedText:[Boolean,!0],maxResultsToShow:[Number,10]}),n=b.options,m=k.registerAutocomplete(),n.tagsInput=m.getOptions(),l=new i(b.source,n),o=function(a){return a[n.tagsInput.displayProperty]},b.suggestionList=l,b.addSuggestion=function(){var a=!1;return l.selected&&(m.addTag(l.selected),l.reset(),m.focusInput(),a=!0),a},b.highlight=function(a){var b=o(a);return b=j(b),n.highlightMatchedText&&(b=d(b,j(l.query),"<em>$&</em>")),g.trustAsHtml(b)},b.track=function(a){return o(a)},m.on("tag-added invalid-tag",function(){l.reset()}).on("input-change",function(a){a?l.load(a,m.getTags()):l.reset()}).on("input-keydown",function(a){var c,d;if(-1!==q.indexOf(a.keyCode)){var f=!1;a.stopImmediatePropagation=function(){f=!0,a.stopPropagation()},a.isImmediatePropagationStopped=function(){return f},l.visible&&(c=a.keyCode,d=!1,c===e.down?(l.selectNext(),d=!0):c===e.up?(l.selectPrior(),d=!0):c===e.escape?(l.reset(),d=!0):(c===e.enter||c===e.tab)&&(d=b.addSuggestion()),d&&(a.preventDefault(),a.stopImmediatePropagation(),b.$apply()))}}).on("input-blur",function(){l.reset()}),p=function(){l.visible&&(l.reset(),b.$apply())},a.on("click",p),b.$on("$destroy",function(){a.off("click",p)})}}}]),f.directive("tiTranscludeAppend",function(){return function(a,b,c,d,e){e(function(a){b.append(a)})}}),f.directive("tiAutosize",function(){return{restrict:"A",require:"ngModel",link:function(a,b,c,d){var e,f,g=3;e=angular.element('<span class="input"></span>'),e.css("display","none").css("visibility","hidden").css("width","auto").css("white-space","pre"),b.parent().append(e),f=function(a){var d,f=a;return angular.isString(f)&&0===f.length&&(f=c.placeholder),f&&(e.text(f),e.css("display",""),d=e.prop("offsetWidth"),e.css("display","none")),b.css("width",d?d+g+"px":""),a},d.$parsers.unshift(f),d.$formatters.unshift(f),c.$observe("placeholder",function(a){d.$modelValue||f(a)})}}}),f.provider("tagsInputConfig",function(){var a={},b={};this.setDefaults=function(b,c){return a[b]=c,this},this.setActiveInterpolation=function(a,c){return b[a]=c,this},this.$get=["$interpolate",function(c){var d={};return d[String]=function(a){return a},d[Number]=function(a){return parseInt(a,10)},d[Boolean]=function(a){return"true"===a.toLowerCase()},d[RegExp]=function(a){return new RegExp(a)},{load:function(e,f,g,h){f.options={},angular.forEach(h,function(h,i){var j,k,l,m,n;j=h[0],k=h[1],l=d[j],m=function(){var b=a[e]&&a[e][i];return angular.isDefined(b)?b:k},n=function(a){f.options[i]=a?l(a):m()},b[e]&&b[e][i]?g.$observe(i,function(a){n(a)}):n(g[i]&&c(g[i])(f.$parent))})}}}]}),f.run(["$templateCache",function(a){a.put("ngTagsInput/tags-input.html",'<div class="host" tabindex="-1" ti-transclude-append=""><div class="tags" ng-class="{focused: hasFocus}"><ul class="tag-list"><li class="tag-item" ng-repeat="tag in tagList.items track by track(tag)" ng-class="{ selected: tag == tagList.selected }"><span>{{getDisplayText(tag)}}</span> <a class="remove-button" ng-click="tagList.remove($index)">{{options.removeTagSymbol}}</a></li></ul><input class="input" placeholder="{{options.placeholder}}" tabindex="{{options.tabindex}}" ng-model="newTag.text" ng-change="newTagChange()" ng-trim="false" ng-class="{\'invalid-tag\': newTag.invalid}" ti-autosize=""></div></div>'),a.put("ngTagsInput/auto-complete.html",'<div class="autocomplete" ng-show="suggestionList.visible"><ul class="suggestion-list"><li class="suggestion-item" ng-repeat="item in suggestionList.items track by track(item)" ng-class="{selected: item == suggestionList.selected}" ng-click="addSuggestion()" ng-mouseenter="suggestionList.select($index)" ng-bind-html="highlight(item)"></li></ul></div>')}])}(); \ No newline at end of file diff --git a/templates/about.html b/templates/about.html new file mode 100644 index 0000000000000000000000000000000000000000..01a0bbc99e716d026fe32c1163b24ad0b79828bf --- /dev/null +++ b/templates/about.html @@ -0,0 +1,143 @@ + +{% extends "menu.html" %} + +{% block css %} +{% load staticfiles %} +<link rel="stylesheet" href="{% static "css/bootstrap.css" %}"> + +<script src="{% static "js/jquery/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"> + <h2>Versions</h2> + </a> + </h2> + </div> + <div id="collapseVersions" class="panel-collapse collapse" role="tabpanel"> + <div class="panel-body"> + <div class="container"> + <ul> + <li>Version 1.0</li> + <ul> + <li>Beta Version </li> + <li>Licence of Gargantext is GPL v3+ </li> + </ul> + <li>Version 1.0.5</li> + <ul> + <li>Bug resolution: xml zipped from Mac</li> + <li>Bug resolution: french accents in filenames</li> + <li>New features: [Advanced chart] ngrams completion</li> + <li>New features: button to delete all duplicates</li> + </ul> + </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"> + <h2>Community</h2> + </a> + </h2> + </div> + <div id="collapseCommunity" class="panel-collapse collapse" role="tabpanel"> + <div class="panel-body"> + <div class="container"> + <ul> + <li>Mailing-lists</li> + <ul> + <li>User mailing-list: soon</li> + <li>Devel mailing-list: soon</li> + </ul> + <li>Code and repository access</li> + <ul> + <li>You are free to participate. Present yourself on mailing-lists or irc.</li> + </ul> + <li>IRC</li> + <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> + </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"> + <h2>Core team</h2> + </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-3 "> + <div class="thumbnail"> + {% if member.picture %} + <img src="{% static "img/team/"%}{{ member.picture }}" style="100px; height:150px"> + {% else %} + <img src="{% static "img/logo.png" %}" style="100px; height:150px"> + {% endif %} + <div class="caption"> + <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 %} + </div> + </div> + </div> + {% endfor %} + </div> + </div> + </div> + </div> + +{% endif %} + + </div> +</div> + + + +</div> + +{% endblock %} diff --git a/templates/chart.html b/templates/chart.html index bdf82c10a96e37f40b9efde69b0fc8a6c6341a39..a57c1f46cf0d0eea8a76062204155df3ac11cfd9 100644 --- a/templates/chart.html +++ b/templates/chart.html @@ -13,7 +13,8 @@ <div class="container theme-showcase" role="main"> <div class="jumbotron"> - <h1>Advanced charts</h1> + <h1>Advanced chart</h1> + <p>Custom, test, interpret</p> </div> </div> @@ -21,7 +22,7 @@ <div id="test-container"></div> </div> - <!-- All the templates used by the Javascript framework --> + <!-- All the templates used by the Javascript framework --> {% verbatim %} <!-- <script type="text/template" id="filter-template"> @@ -217,12 +218,15 @@ </div> --> - <div ng-app="Gargantext" ng-controller="GraphController"> + + + <div ng-app="Gargantext" ng-controller="GraphController"> + <ul class="datasets"> <button class="add" ng-click="addDataset()">Add a dataset...</button> <li class="dataset" ng-controller="DatasetController" ng-repeat="dataset in datasets"> - <hr/> + <hr/> <div class="corpus"> <button ng-click="removeDataset($index)" title="remove this dataset">X</button> <select ng-model="mesured" style="background-color:{{ getColor($index, datasets.length) }}" ng-options="value as key for (key, value) in {'Documents count': 'nodes.count', 'Ngrams count': 'ngrams.count'}" ng-change="updateQuery()"></select> @@ -236,21 +240,17 @@ <li ng-repeat="filter in filters"> <button ng-click="removeFilter($index)" title="remove this filter">x</button> <span>...where the </span> - <select ng-model="filter.entity"> - <option ng-repeat="(entityName, entityColumns) in entities" value="{{entityName}}">{{entityName}}</option> - </select> - <span ng-if="filter.entity"> - <select ng-model="filter.column"> - <option ng-repeat="column in entities[filter.entity] | orderBy:'key'" value="{{column.key}}">{{column.key}}</option> - </select> - <span ng-if="filter.column" ng-repeat="column in entities[filter.entity]"> - <span ng-if="column.key == filter.column"> - <select ng-model="filter.operator"> - <option ng-repeat="operator in operators[column.type]" value="{{operator.key}}">{{operator.label}}</option> - </select> - <input type="text" ng-model="filter.value" ng-change="updateQuery()"> - </span> - </span> + <select ng-model="filter.entity" ng-options="entity as entity.key for entity in entities"></select> + <span ng-if="filter.entity.key != 'ngrams'"> + <select ng-if="filter.entity" ng-model="filter.column" ng-options="column as column.key for column in filter.entity.columns | orderBy:'key'"></select> + <select ng-if="filter.column" ng-model="filter.operator" ng-options="operator.key as operator.label for operator in operators[filter.column.type]"></select> + <input ng-if="filter.operator" type="text" ng-model="filter.value" ng-change="updateQuery()"> + </span> + <span ng-if="filter.entity.key == 'ngrams'"> + are in this list: + <tags-input ng-model="filter.value" display-property="terms" placeholder="Add an ngram" on-tag-added="updateQuery()" on-tag-removed="updateQuery()" add-from-autocomplete-only="true"> + <auto-complete source="getNgrams($query)"></auto-complete> + </tags-input ng-model="tags"> </span> </li> </ul> @@ -333,7 +333,9 @@ <script type="text/javascript" src="{% static "js/angular-cookies.min.js" %}"></script> <script type="text/javascript" src="{% static "js/d3/d3.v2.min.js" %}"></script> <script type="text/javascript" src="{% static "js/d3/n3.line-chart.min.js" %}"></script> - <!-- <script type="text/javascript" src="{% static "js/d3/angular-charts.js" %}"></script> --> + + <script type="text/javascript" src="{% static "js/ng-tags-input.min.js" %}"></script> + <link rel="stylesheet" href="{% static "css/ng-tags-input.min.css" %}"> <script type="text/javascript" src="{% static "js/gargantext.angular.js" %}"></script> @@ -358,3 +360,4 @@ + diff --git a/templates/corpus.html b/templates/corpus.html index eb46c107a4b3d7e89e728065deafc73155309897..b3f3d1a228e63a0bc71201e1fab90fdbad2453e0 100644 --- a/templates/corpus.html +++ b/templates/corpus.html @@ -240,6 +240,7 @@ $.ajax({ BIS_dict[untitlebis[0]] = [bisarray[i].count , 0];// [ total amount , removed ] } pr(BIS_dict) + if(Object.keys(BIS_dict).length>0) $("#delAll").css("visibility", "visible"); $("#delAll").show(); } }); diff --git a/templates/home.html b/templates/home.html index 18b91d94626005f0c5daa31e86fd1a6d9d143209..7bddd0b152d17ae9a51ae5dc7a280a3407b3dfb2 100644 --- a/templates/home.html +++ b/templates/home.html @@ -24,7 +24,7 @@ <div class="row"> <div class="content"> <center> - <img src="http://s3.lprs1.fr/images/2015/01/08/4429565_je-suis-charlie_545x460_autocrop.jpg" alt="Je suis Charlie" style="100px; height:150px"> + <img src="{% static "img/logo.png"%}" alt="Logo Gargantext" style="100px; height:150px"> <!-- <h2>Introduction Video</h2> @@ -43,25 +43,62 @@ <div class="container"> - <div class="row"> - <div class="col-md-4 content"> - <h3>Presentation</h3> + + +<div class="row"> + +<div class="col-md-4 content"> + <h3><a href="#">Historic</a></h3> <p> - Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. + + Chapter 1.VI. -- How Gargantua was born in a strange manner. + Chapter 2.XXIII. -- How Pantagruel departed from Paris, hearing + news that the Dipsodes had invaded the land of the Amaurots; and + the cause wherefore the leagues are so short in France. Chapter + 3.XLVI. -- How Pantagruel and Panurge diversely interpret the + words of Triboulet. Chapter 4.LV. -- How Pantagruel, being at sea, + heard various unfrozen words. Chapter 5.IX. -- How we arrived at + the island of Tools. + </p> </div> - + <div class="col-md-4 content"> - <h3>Historic</h3> +<h3><a href="#">Presentation</a></h3> <p> - Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. + + Lorem ipsum dolor sit amet, consectetur adipiscing elit, + sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. + Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris + nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in + reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla + pariatur. Excepteur sint occaecat cupidatat non proident, sunt in + culpa qui officia deserunt mollit anim id est laborum. + </p> </div> - + + <div class="col-md-4 content"> - <h3>Tutorials</h3> +<h3><a href="#">Tutoreil</a></h3> <p> - Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. + <!-- Why not French ? --> + <!-- find Cambridge source which inspired this --!> + + Il praaît que l'odrre des ltetres dnas un mot n'a pas + d'iprnorotncae. La pmeirère et la drenèire letrte diovent + êrte à la bnnoe pclae. Le rsete peut êrte dnas un dsérorde + ttoal et on puet tujoruos lrie snas poribême. On ne lit + donc pas chuaqe ltetre en elle-mmêe, mias le mot cmome un + tuot. Un chnagmnet de réfretniel et nuos tarnsposns ce + rselutat au txete lui-mmêe: l'odrre des mtos est faiblement + imoprtnat copmraé au cnotxete du txete qui, lui, est copmté: + comptexter avec Gargantext. + + + + + </p> </div> diff --git a/templates/menu.html b/templates/menu.html index d222a93ef0cb03ab4c4c3f959950ee237bfe03aa..77d306c9e7a380e8581458fd4f5c78a6f6ea8e73 100644 --- a/templates/menu.html +++ b/templates/menu.html @@ -23,7 +23,11 @@ <div class="navbar-collapse collapse"> <ul class="nav navbar-nav"> <!-- <li><a href="/admin/">Admin/</a></li> --!> + <li><a href="/about/">About</a> + </li> + {% if user.is_authenticated %} <li><a href="/projects/">Projects</a></li> + {% endif %} {% if project %} <li><a href="/project/{{project.id}}">{{project.name}}</a></li> {% endif %} @@ -61,7 +65,7 @@ <hr> <footer> - <p>Gargantext v.1.0 (Copyrights CNRS {{ date.year }})</p> + <p>Gargantext, version 1.0.5, Copyrights CNRS {{ date.year }}.</p> </footer> diff --git a/templates/project.html b/templates/project.html index 7eb641ce0bc02ff09931392ce648fe9c8f6a863b..6d4bfaab7389c310f1baa7e9546fb1a27de4d97c 100644 --- a/templates/project.html +++ b/templates/project.html @@ -90,8 +90,8 @@ <button type="button" class="btn btn-xs btn-default" data-container="body" data-toggle="popover" data-placement="bottom" data-content=' <ul> - <li> Add documents </li> <li> Rename </li> + <li> Add new documents </li> <li><a href="/project/{{ project.id }}/corpus/{{ corpus.id}}/delete">Delete</a></li> </ul> '>Manage</button> diff --git a/templates/projects.html b/templates/projects.html index ca25560ab3bf491245a8fb970ef2ea7f1f17a211..d4a805d6369adfda516a77ac641e2384c3613f48 100644 --- a/templates/projects.html +++ b/templates/projects.html @@ -38,7 +38,16 @@ <!--<div class="col-md-offset-7 col-md-4 content" style="background-color:grey">!--> <div class="col-md-3 content"> <h3><a href="/project/{{ project.id }}">{{ project.name }}</a> - <button type="button" class="btn btn-xs btn-default" data-container="body" data-toggle="popover" data-placement="bottom" data-content='<a href="/project/{{ project.id }}/delete">Yes, I am sure!</a>'>Delete</button> + + <button type="button" class="btn btn-xs btn-default" data-container="body" data-toggle="popover" data-placement="bottom" + data-content=' + <ul> + <li> Rename </li> + <li> Add new corpus </li> + <li><a href="/project/{{ project.id }}/delete">Delete</a></li> + </ul> + '>Manage</button> + </h3> <h4>{{ project.subtitle }}<h4> diff --git a/templates/subcorpus.html b/templates/subcorpus.html index b56cf95b2818ff2b1e16f33116147cebd40f1baf..57745770122ad755e070d78c1b02c3161d7f240c 100644 --- a/templates/subcorpus.html +++ b/templates/subcorpus.html @@ -19,6 +19,12 @@ {% if documents %} + + <div id="delAll" style="visibility: hidden;"> + <button onclick="deleteDuplicates(theurl);">Delete Duplicates</button> + </div> + + <ul> {% for doc in documents %} {% if doc.date %} @@ -45,6 +51,26 @@ function getCookie(name) { return cookieValue; } +function deleteDuplicates(url) { + console.log("hello world") + console.log(url) + $.ajax({ + url: url, + type: 'DELETE', + beforeSend: function(xhr) { + xhr.setRequestHeader("X-CSRFToken", getCookie("csrftoken")); + }, + success: function(data) { + console.log("in DeleteDuplicates") + console.log(data) + $("#delAll").remove(); + }, + error: function(result) { + console.log("Data not found"); + console.log(result) + } + }); +} function deleteNode(node_id) { $.ajax({ @@ -111,6 +137,11 @@ function deleteNode(node_id) { //'+"{{doc.id}}"+',\"'+title+'\" current_docs = {} +if(Object.keys(BIS_dict).length>0) { + $("#delAll").css("visibility", "visible"); + $("#delAll").show(); +} else $("#delAll").remove() + {% for doc in documents %} id = "doc_{{doc.id}}" title = $("<div/>").html("{{doc.name}}").text() diff --git a/templates/tests/formexample.html b/templates/tests/formexample.html new file mode 100644 index 0000000000000000000000000000000000000000..aa7dc8a91631bb3509e562fb7e6eb5ff68ceabc7 --- /dev/null +++ b/templates/tests/formexample.html @@ -0,0 +1,15 @@ +<html> +<body> + +<form action="/formexample/" enctype="multipart/form-data" method="post"> + {% csrf_token %} + {{ form.as_p }} + <input type="submit" value="OK"> +</form> + +{% if msg %} +<p>Response: {{msg}}</p> +{% endif %} + +</body> +</html> \ No newline at end of file diff --git a/templates/tests/mvc.html b/templates/tests/mvc.html index f23bf25aebf397fa722d1e502dd7c417c50a6c6f..9e44d2909710d6f8fd6fa77654e3b86b6626ee2b 100644 --- a/templates/tests/mvc.html +++ b/templates/tests/mvc.html @@ -218,12 +218,15 @@ </div> --> - <div ng-app="Gargantext" ng-controller="GraphController"> + + + <div ng-app="Gargantext" ng-controller="GraphController"> + <ul class="datasets"> <button class="add" ng-click="addDataset()">Add a dataset...</button> <li class="dataset" ng-controller="DatasetController" ng-repeat="dataset in datasets"> - <hr/> + <hr/> <div class="corpus"> <button ng-click="removeDataset($index)" title="remove this dataset">X</button> <select ng-model="mesured" style="background-color:{{ getColor($index, datasets.length) }}" ng-options="value as key for (key, value) in {'Documents count': 'nodes.count', 'Ngrams count': 'ngrams.count'}" ng-change="updateQuery()"></select> @@ -237,21 +240,17 @@ <li ng-repeat="filter in filters"> <button ng-click="removeFilter($index)" title="remove this filter">x</button> <span>...where the </span> - <select ng-model="filter.entity"> - <option ng-repeat="(entityName, entityColumns) in entities" value="{{entityName}}">{{entityName}}</option> - </select> - <span ng-if="filter.entity"> - <select ng-model="filter.column"> - <option ng-repeat="column in entities[filter.entity] | orderBy:'key'" value="{{column.key}}">{{column.key}}</option> - </select> - <span ng-if="filter.column" ng-repeat="column in entities[filter.entity]"> - <span ng-if="column.key == filter.column"> - <select ng-model="filter.operator"> - <option ng-repeat="operator in operators[column.type]" value="{{operator.key}}">{{operator.label}}</option> - </select> - <input type="text" ng-model="filter.value" ng-change="updateQuery()"> - </span> - </span> + <select ng-model="filter.entity" ng-options="entity as entity.key for entity in entities"></select> + <span ng-if="filter.entity.key != 'ngrams'"> + <select ng-if="filter.entity" ng-model="filter.column" ng-options="column as column.key for column in filter.entity.columns | orderBy:'key'"></select> + <select ng-if="filter.column" ng-model="filter.operator" ng-options="operator.key as operator.label for operator in operators[filter.column.type]"></select> + <input ng-if="filter.operator" type="text" ng-model="filter.value" ng-change="updateQuery()"> + </span> + <span ng-if="filter.entity.key == 'ngrams'"> + are in this list: + <tags-input ng-model="filter.value" display-property="terms" placeholder="Add an ngram" on-tag-added="updateQuery()" on-tag-removed="updateQuery()" add-from-autocomplete-only="true"> + <auto-complete source="getNgrams($query)"></auto-complete> + </tags-input ng-model="tags"> </span> </li> </ul> @@ -334,7 +333,9 @@ <script type="text/javascript" src="{% static "js/angular-cookies.min.js" %}"></script> <script type="text/javascript" src="{% static "js/d3/d3.v2.min.js" %}"></script> <script type="text/javascript" src="{% static "js/d3/n3.line-chart.min.js" %}"></script> - <!-- <script type="text/javascript" src="{% static "js/d3/angular-charts.js" %}"></script> --> + + <script type="text/javascript" src="{% static "js/ng-tags-input.min.js" %}"></script> + <link rel="stylesheet" href="{% static "css/ng-tags-input.min.css" %}"> <script type="text/javascript" src="{% static "js/gargantext.angular.js" %}"></script>