├── libreqda
├── __init__.py
├── templatetags
│ ├── __init__.py
│ └── filters.py
├── static
│ ├── imgs
│ │ ├── logo.png
│ │ ├── github.png
│ │ └── tryolabs-logo.png
│ ├── lib
│ │ ├── jquery.contextMenu
│ │ │ ├── images
│ │ │ │ ├── cut.png
│ │ │ │ ├── door.png
│ │ │ │ ├── page_white_add.png
│ │ │ │ ├── page_white_copy.png
│ │ │ │ ├── page_white_edit.png
│ │ │ │ ├── page_white_delete.png
│ │ │ │ └── page_white_paste.png
│ │ │ ├── jquery.contextMenu.css
│ │ │ └── jquery.ui.position.js
│ │ ├── bootstrap
│ │ │ ├── img
│ │ │ │ ├── glyphicons-halflings.png
│ │ │ │ └── glyphicons-halflings-white.png
│ │ │ └── css
│ │ │ │ ├── bootstrap-responsive.min.css
│ │ │ │ └── bootstrap-responsive.css
│ │ ├── collisioncheck
│ │ │ └── jquery.collisioncheck-1.1.min.js
│ │ └── annotator
│ │ │ └── annotator.store-1.2.6.js
│ ├── js
│ │ └── simplemodal.js
│ └── css
│ │ └── base.css
├── locale
│ ├── en
│ │ └── LC_MESSAGES
│ │ │ ├── django.mo
│ │ │ └── django.po
│ ├── es
│ │ └── LC_MESSAGES
│ │ │ └── django.po
│ └── pt
│ │ └── LC_MESSAGES
│ │ └── django.po
├── reports.py
├── http_handlers.py
├── admin.py
├── templates
│ ├── new_document.html
│ ├── new_code.html
│ ├── new_annotation.html
│ ├── new_category.html
│ ├── new_set_query.html
│ ├── upload_document.html
│ ├── copy_project.html
│ ├── new_boolean_query.html
│ ├── new_project.html
│ ├── new_proximity_query.html
│ ├── new_semantic_query.html
│ ├── 404.html
│ ├── error.html
│ ├── browse_annotations_general_tab.html
│ ├── view_document_documents_tab.html
│ ├── modal.html
│ ├── form.html
│ ├── browse_annotations_citations_tab.html
│ ├── registration
│ │ └── login.html
│ ├── browse_projects_general_tab.html
│ ├── browse_projects_documents_tab.html
│ ├── browse_annotations_codes_tab.html
│ ├── base.html
│ ├── browse_projects_users_tab.html
│ ├── about.html
│ ├── browse_query_results.html
│ ├── browse_categories.html
│ ├── browse_annotations.html
│ ├── browse_codes.html
│ ├── citation_details.html
│ ├── browse_projects.html
│ ├── browse_queries.html
│ └── view_document.html
├── validators.py
├── utils.py
├── local_settings.py.template
├── wsgi.py
├── text_extraction.py
├── forms.py
├── annotations_views.py
├── settings.py
├── urls.py
└── models.py
├── .gitignore
├── manage.py
├── requirements.txt
└── README.md
/libreqda/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/libreqda/templatetags/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/libreqda/static/imgs/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tryolabs/libreQDA/HEAD/libreqda/static/imgs/logo.png
--------------------------------------------------------------------------------
/libreqda/static/imgs/github.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tryolabs/libreQDA/HEAD/libreqda/static/imgs/github.png
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.log
2 | *.pot
3 | *.pyc
4 | .metadata/
5 | .project
6 | .pydevproject
7 | .settings/
8 | local_settings.py
9 |
--------------------------------------------------------------------------------
/libreqda/locale/en/LC_MESSAGES/django.mo:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tryolabs/libreQDA/HEAD/libreqda/locale/en/LC_MESSAGES/django.mo
--------------------------------------------------------------------------------
/libreqda/static/imgs/tryolabs-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tryolabs/libreQDA/HEAD/libreqda/static/imgs/tryolabs-logo.png
--------------------------------------------------------------------------------
/libreqda/reports.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from libreqda.models import Project
3 |
4 | from model_report.report import reports, ReportAdmin
--------------------------------------------------------------------------------
/libreqda/static/lib/jquery.contextMenu/images/cut.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tryolabs/libreQDA/HEAD/libreqda/static/lib/jquery.contextMenu/images/cut.png
--------------------------------------------------------------------------------
/libreqda/static/lib/jquery.contextMenu/images/door.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tryolabs/libreQDA/HEAD/libreqda/static/lib/jquery.contextMenu/images/door.png
--------------------------------------------------------------------------------
/libreqda/static/lib/bootstrap/img/glyphicons-halflings.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tryolabs/libreQDA/HEAD/libreqda/static/lib/bootstrap/img/glyphicons-halflings.png
--------------------------------------------------------------------------------
/libreqda/static/lib/bootstrap/img/glyphicons-halflings-white.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tryolabs/libreQDA/HEAD/libreqda/static/lib/bootstrap/img/glyphicons-halflings-white.png
--------------------------------------------------------------------------------
/libreqda/static/lib/jquery.contextMenu/images/page_white_add.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tryolabs/libreQDA/HEAD/libreqda/static/lib/jquery.contextMenu/images/page_white_add.png
--------------------------------------------------------------------------------
/libreqda/static/lib/jquery.contextMenu/images/page_white_copy.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tryolabs/libreQDA/HEAD/libreqda/static/lib/jquery.contextMenu/images/page_white_copy.png
--------------------------------------------------------------------------------
/libreqda/static/lib/jquery.contextMenu/images/page_white_edit.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tryolabs/libreQDA/HEAD/libreqda/static/lib/jquery.contextMenu/images/page_white_edit.png
--------------------------------------------------------------------------------
/libreqda/static/lib/jquery.contextMenu/images/page_white_delete.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tryolabs/libreQDA/HEAD/libreqda/static/lib/jquery.contextMenu/images/page_white_delete.png
--------------------------------------------------------------------------------
/libreqda/static/lib/jquery.contextMenu/images/page_white_paste.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tryolabs/libreQDA/HEAD/libreqda/static/lib/jquery.contextMenu/images/page_white_paste.png
--------------------------------------------------------------------------------
/libreqda/http_handlers.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from django.shortcuts import render
3 |
4 |
5 | def handle_404(request, template='404.html'):
6 | return render(request, template, {})
7 |
--------------------------------------------------------------------------------
/manage.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | import os
3 | import sys
4 |
5 | if __name__ == "__main__":
6 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "libreqda.settings")
7 |
8 | from django.core.management import execute_from_command_line
9 |
10 | execute_from_command_line(sys.argv)
11 |
--------------------------------------------------------------------------------
/libreqda/admin.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from django.contrib import admin
3 |
4 | from models import Code, Document, Project, DocumentInstance, Citation
5 |
6 | admin.site.register(Code)
7 | admin.site.register(Project)
8 | admin.site.register(Citation)
9 | admin.site.register(Document)
10 | admin.site.register(DocumentInstance)
11 |
--------------------------------------------------------------------------------
/libreqda/templates/new_document.html:
--------------------------------------------------------------------------------
1 | {% extends "base.html" %}
2 |
3 | {% block head %}
4 | {{ block.super }}
5 | {% endblock head %}
6 |
7 | {% block topbar_extra %}
8 | {% endblock topbar_extra %}
9 |
10 | {% block body %}
11 |
12 |
13 | {% include "form.html" with form=form form_action=form_action back_url=""%}
14 |
15 |
16 | {% endblock %}
--------------------------------------------------------------------------------
/libreqda/templates/new_code.html:
--------------------------------------------------------------------------------
1 | {% extends "base.html" %}
2 |
3 | {% block head %}
4 | {{ block.super }}
5 | {% endblock head %}
6 |
7 | {% block topbar_extra %}
8 | {% endblock topbar_extra %}
9 |
10 | {% block body %}
11 |
12 |
13 | {% include "form.html" with form=form form_action=form_action back_url=back_url %}
14 |
15 |
16 | {% endblock %}
--------------------------------------------------------------------------------
/libreqda/templates/new_annotation.html:
--------------------------------------------------------------------------------
1 | {% extends "base.html" %}
2 |
3 | {% block head %}
4 | {{ block.super }}
5 | {% endblock head %}
6 |
7 | {% block topbar_extra %}
8 | {% endblock topbar_extra %}
9 |
10 | {% block body %}
11 |
12 |
13 | {% include "form.html" with form=form form_action=form_action back_url=back_url %}
14 |
15 |
16 | {% endblock %}
--------------------------------------------------------------------------------
/libreqda/templates/new_category.html:
--------------------------------------------------------------------------------
1 | {% extends "base.html" %}
2 |
3 | {% block head %}
4 | {{ block.super }}
5 | {% endblock head %}
6 |
7 | {% block topbar_extra %}
8 | {% endblock topbar_extra %}
9 |
10 | {% block body %}
11 |
12 |
13 | {% include "form.html" with form=form form_action=form_action back_url=back_url %}
14 |
15 |
16 | {% endblock %}
--------------------------------------------------------------------------------
/libreqda/templates/new_set_query.html:
--------------------------------------------------------------------------------
1 | {% extends "base.html" %}
2 |
3 | {% block head %}
4 | {{ block.super }}
5 | {% endblock head %}
6 |
7 | {% block topbar_extra %}
8 | {% endblock topbar_extra %}
9 |
10 | {% block body %}
11 |
12 |
13 | {% include "form.html" with form=form form_action=form_action back_url=back_url%}
14 |
15 |
16 | {% endblock %}
--------------------------------------------------------------------------------
/libreqda/templates/upload_document.html:
--------------------------------------------------------------------------------
1 | {% extends "base.html" %}
2 |
3 | {% block head %}
4 | {{ block.super }}
5 | {% endblock head %}
6 |
7 | {% block topbar_extra %}
8 | {% endblock topbar_extra %}
9 |
10 | {% block body %}
11 |
12 |
13 | {% include "form.html" with form=form form_action=form_action back_url=back_url %}
14 |
15 |
16 | {% endblock %}
--------------------------------------------------------------------------------
/libreqda/templates/copy_project.html:
--------------------------------------------------------------------------------
1 | {% extends "base.html" %}
2 |
3 | {% block head %}
4 | {{ block.super }}
5 | {% endblock head %}
6 |
7 | {% block topbar_extra %}
8 | {% endblock topbar_extra %}
9 |
10 | {% block body %}
11 |
12 |
13 | {% include "form.html" with form=project_form form_action=form_action back_url=back_url%}
14 |
15 |
16 | {% endblock %}
--------------------------------------------------------------------------------
/libreqda/templates/new_boolean_query.html:
--------------------------------------------------------------------------------
1 | {% extends "base.html" %}
2 |
3 | {% block head %}
4 | {{ block.super }}
5 | {% endblock head %}
6 |
7 | {% block topbar_extra %}
8 | {% endblock topbar_extra %}
9 |
10 | {% block body %}
11 |
12 |
13 | {% include "form.html" with form=form form_action=form_action back_url=back_url%}
14 |
15 |
16 | {% endblock %}
--------------------------------------------------------------------------------
/libreqda/templates/new_project.html:
--------------------------------------------------------------------------------
1 | {% extends "base.html" %}
2 |
3 | {% block head %}
4 | {{ block.super }}
5 | {% endblock head %}
6 |
7 | {% block topbar_extra %}
8 | {% endblock topbar_extra %}
9 |
10 | {% block body %}
11 |
12 |
13 | {% include "form.html" with form=project_form form_action=form_action back_url=back_url%}
14 |
15 |
16 | {% endblock %}
--------------------------------------------------------------------------------
/libreqda/templates/new_proximity_query.html:
--------------------------------------------------------------------------------
1 | {% extends "base.html" %}
2 |
3 | {% block head %}
4 | {{ block.super }}
5 | {% endblock head %}
6 |
7 | {% block topbar_extra %}
8 | {% endblock topbar_extra %}
9 |
10 | {% block body %}
11 |
12 |
13 | {% include "form.html" with form=form form_action=form_action back_url=back_url%}
14 |
15 |
16 | {% endblock %}
--------------------------------------------------------------------------------
/libreqda/templates/new_semantic_query.html:
--------------------------------------------------------------------------------
1 | {% extends "base.html" %}
2 |
3 | {% block head %}
4 | {{ block.super }}
5 | {% endblock head %}
6 |
7 | {% block topbar_extra %}
8 | {% endblock topbar_extra %}
9 |
10 | {% block body %}
11 |
12 |
13 | {% include "form.html" with form=form form_action=form_action back_url=back_url%}
14 |
15 |
16 | {% endblock %}
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | BeautifulSoup==3.2.1
2 | Django==1.4.3
3 | MySQL-python==1.2.4c1
4 | PIL==1.1.7
5 | argparse==1.2.1
6 | distribute==0.6.32
7 | django-model-report==0.1.4
8 | django-rosetta==0.6.8
9 | -e git+https://github.com/mikemaccana/python-docx.git@0c4379c6b89a7c745890e940a9be88b04147dfc2#egg=docx-dev
10 | html5lib==0.95
11 | ipython==0.13.1
12 | lxml==3.1.0
13 | pdfminer==20110515
14 | pisa==3.0.33
15 | pyth==0.5.6
16 | python-dateutil==2.1
17 | reportlab==2.6
18 | six==1.2.0
19 | slate==0.3
20 | wsgiref==0.1.2
21 |
--------------------------------------------------------------------------------
/libreqda/validators.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from os.path import splitext
3 |
4 | from django.core.exceptions import ValidationError
5 | from django.utils.translation import ugettext as _
6 |
7 |
8 | class DocumentValidator():
9 | SUPPORTED_FILETYPES = ('.doc', '.docx', '.pdf', '.rtf', '.txt')
10 |
11 | def __call__(self, f):
12 | #TODO: python-magic
13 | if splitext(f.name)[1].lower() not in self.SUPPORTED_FILETYPES:
14 | raise ValidationError(_("Tipo de archivo no soportado."))
15 |
--------------------------------------------------------------------------------
/libreqda/utils.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from django.utils import simplejson
3 | from django.http import HttpResponse
4 |
5 |
6 | class JsonResponse(HttpResponse):
7 | def __init__(self, data, **kwargs):
8 | content = simplejson.dumps(
9 | data,
10 | indent=2,
11 | ensure_ascii=False)
12 | super(JsonResponse, self).__init__(
13 | content=content,
14 | mimetype='application/json; charset=utf8',
15 | **kwargs)
16 |
--------------------------------------------------------------------------------
/libreqda/local_settings.py.template:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | DEBUG = True
3 |
4 | DATABASES = {
5 | 'default': {
6 | 'ENGINE': 'django.db.backends.mysql',
7 | 'NAME': 'libreqda',
8 | 'USER': '***',
9 | 'PASSWORD': '***',
10 | 'HOST': 'localhost',
11 | 'PORT': '5432',
12 | }
13 | }
14 |
15 | SECRET_KEY = 'type your secret key here'
16 |
17 | # Absolute path for file uploads.
18 | # Warning: the web server must have write perms over this directory.
19 | MEDIA_ROOT = ''
20 |
21 | # Absolute path to the directory static files should be collected to.
22 | STATIC_ROOT = ''
23 |
--------------------------------------------------------------------------------
/libreqda/templates/404.html:
--------------------------------------------------------------------------------
1 | {% extends "base.html" %}
2 |
3 | {% load i18n %}
4 | {% load filters %}
5 |
6 | {% block head %}
7 | {{ block.super }}
8 | {% endblock head %}
9 |
10 | {% block topbar_extra %}
11 | {% endblock topbar_extra %}
12 |
13 | {% block body %}
14 |
23 | {% endblock %}
--------------------------------------------------------------------------------
/libreqda/templates/error.html:
--------------------------------------------------------------------------------
1 | {% extends "base.html" %}
2 |
3 | {% load i18n %}
4 | {% load filters %}
5 |
6 | {% block head %}
7 | {{ block.super }}
8 | {% endblock head %}
9 |
10 | {% block topbar_extra %}
11 | {% endblock topbar_extra %}
12 |
13 | {% block body %}
14 |
15 |
16 |
17 | {% if title %}
18 |
{{ title }}
19 | {% endif %}
20 |
21 | {{ message }}
22 |
23 | {% if backlink and backtext %}
24 |
{{ backtext }}
25 | {% endif %}
26 |
27 |
28 |
29 | {% endblock %}
--------------------------------------------------------------------------------
/libreqda/static/lib/collisioncheck/jquery.collisioncheck-1.1.min.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Collision Check Plugin v1.1
3 | * Copyright (c) Constantin Groß, 48design.de
4 | * v1.2 rewrite with thanks to Daniel
5 | *
6 | * @requires jQuery v1.3.2
7 | *
8 | * Dual licensed under the MIT and GPL licenses:
9 | * http://www.opensource.org/licenses/mit-license.php
10 | * http://www.gnu.org/licenses/gpl.html
11 | *
12 | */
13 | (function(a){a.fn.collidesWith=function(e){var b=this;var d=a(e);var f=a([]);if(!b||!d){return false}b.each(function(){var i=a(this);var g=i.offset();var h=g.left;var c=g.top;var k=h+i.outerWidth();var j=c+i.outerHeight();d.not(i).each(function(){var o=a(this);var l=o.offset();var q=l.left;var p=l.top;var n=q+o.outerWidth();var m=p+o.outerHeight();if(h>=n||k<=q||c>=m||j<=p){return true}else{if(f.length==f.not(this).length){f.push(this)}}})});return f}})(jQuery);
--------------------------------------------------------------------------------
/libreqda/templates/browse_annotations_general_tab.html:
--------------------------------------------------------------------------------
1 | {% load i18n %}
2 |
3 |
4 |
5 |
6 | | {% trans "Fecha de creación" %} |
7 | {{ annotation.creation_date }} |
8 |
9 |
10 | | {% trans "Creador" %} |
11 | {{ annotation.created_by }} |
12 |
13 |
14 | | {% trans "Número de documentos" %} |
15 | TODO |
16 |
17 |
18 | | {% trans "Número total de códigos" %} |
19 | {{ annotation.codes.count }} |
20 |
21 |
22 | | {% trans "Número total de citas" %} |
23 | {{ annotation.citations.count }} |
24 |
25 |
26 |
27 |
28 |
29 | {{ annotation.text|linebreaks }}
30 |
--------------------------------------------------------------------------------
/libreqda/templates/view_document_documents_tab.html:
--------------------------------------------------------------------------------
1 | {% load i18n %}
2 |
3 |
4 | {% for doc in project.documents.all %}
5 |
6 |
11 |
12 |
13 | {% if doc.comment %}
14 | {{ doc.comment|linebreaks }}
15 | {% else %}
16 | {% trans "El documento no tiene descripción." %}
17 | {% endif %}
18 |
19 |
20 |
21 |
22 | {% endfor %}
23 |
--------------------------------------------------------------------------------
/libreqda/templates/modal.html:
--------------------------------------------------------------------------------
1 |
5 |
6 |
27 |
--------------------------------------------------------------------------------
/libreqda/static/js/simplemodal.js:
--------------------------------------------------------------------------------
1 | function simpleModal(buttonId, modalId) {
2 | $(document).ready(function() {
3 | $('#' + buttonId).click(function(ev) {
4 | ev.preventDefault(); // prevent navigation
5 | var url = $(this).data("url"); // get the form url
6 | $.getJSON(url, function(data) { // load the url into the modal
7 | $('#' + modalId).html(data.html);
8 | $('#' + modalId).modal('show');
9 | });
10 | return false; // prevent the click propagation
11 | });
12 | $('#' + modalId).on('submit', 'form', function() {
13 | $.ajax({
14 | type : $(this).attr('method'),
15 | url : this.action,
16 | data : $(this).serialize(),
17 | context : this,
18 | success : function(data, status) {
19 | if (data.redirect) {
20 | window.location.replace(data.redirect);
21 | }
22 | $('#' + modalId).html(data.html);
23 | }
24 | });
25 | return false;
26 | });
27 | });
28 | }
29 |
--------------------------------------------------------------------------------
/libreqda/wsgi.py:
--------------------------------------------------------------------------------
1 | """
2 | WSGI config for libreqda project.
3 |
4 | This module contains the WSGI application used by Django's development server
5 | and any production WSGI deployments. It should expose a module-level variable
6 | named ``application``. Django's ``runserver`` and ``runfcgi`` commands discover
7 | this application via the ``WSGI_APPLICATION`` setting.
8 |
9 | Usually you will have the standard Django WSGI application here, but it also
10 | might make sense to replace the whole Django WSGI application with a custom one
11 | that later delegates to the Django one. For example, you could introduce WSGI
12 | middleware here, or combine a Django application with an application of another
13 | framework.
14 |
15 | """
16 | import os
17 |
18 | os.environ.setdefault("DJANGO_SETTINGS_MODULE", "libreqda.settings")
19 |
20 | # This application object is used by any WSGI server configured to use this
21 | # file. This includes Django's development server, if the WSGI_APPLICATION
22 | # setting points here.
23 | from django.core.wsgi import get_wsgi_application
24 | application = get_wsgi_application()
25 |
26 | # Apply WSGI middleware here.
27 | # from helloworld.wsgi import HelloWorldApplication
28 | # application = HelloWorldApplication(application)
29 |
--------------------------------------------------------------------------------
/libreqda/templates/form.html:
--------------------------------------------------------------------------------
1 |
34 |
--------------------------------------------------------------------------------
/libreqda/templates/browse_annotations_citations_tab.html:
--------------------------------------------------------------------------------
1 | {% load i18n %}
2 | {% load filters %}
3 |
4 | {% if annotation.citations.all %}
5 |
6 |
7 |
8 | | # |
9 | {% trans "Códigos" %} |
10 | {% trans "Documento" %} |
11 | |
12 |
13 |
14 |
15 | {% for citation in annotation.citations.all %}
16 |
17 | | {{ forloop.counter }} |
18 |
19 | {% for code in citation.codes.all %}
20 | {{ code|pretty_print_code_name|safe }}
21 | {% endfor %}
22 | |
23 | {{ citation.document.name }} |
24 |
25 | {% trans "Ver documento" %}
26 | |
27 |
28 |
29 | |
30 | {{ citation.text }}
31 | |
32 | |
33 | {% endfor %}
34 |
35 |
36 | {% else %}
37 |
38 |
{% trans "¡La anotación no fue asignada a ninguna cita!" %}
39 |
40 | {% endif %}
--------------------------------------------------------------------------------
/libreqda/text_extraction.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | import cStringIO
3 | from pdfminer.pdfinterp import PDFResourceManager, process_pdf
4 | from pdfminer.converter import TextConverter
5 | from pdfminer.layout import LAParams
6 |
7 | from docx import opendocx, getdocumenttext
8 | from pyth.plugins.rtf15.reader import Rtf15Reader
9 |
10 |
11 | def txt(f):
12 | with open(f, 'r') as f:
13 | return '\r\n'.join(f.readlines())
14 |
15 |
16 | def pdf(f):
17 | rsrcmgr = PDFResourceManager()
18 | retstr = cStringIO.StringIO()
19 | codec = 'utf-8'
20 |
21 | laparams = LAParams()
22 | laparams.all_texts = True
23 |
24 | device = TextConverter(
25 | rsrcmgr, retstr, codec=codec, laparams=laparams
26 | )
27 |
28 | fp = file(f, 'rb')
29 | process_pdf(rsrcmgr, device, fp)
30 | fp.close()
31 | device.close()
32 |
33 | str = retstr.getvalue()
34 | retstr.close()
35 | return str
36 |
37 |
38 | def docx(f):
39 | doc = opendocx(f)
40 | return '\r\n'.join(getdocumenttext(doc))
41 |
42 |
43 | def rtf(f):
44 | with open(f, "rb") as f:
45 | doc = Rtf15Reader.read(f)
46 | result = []
47 | for element in doc.content:
48 | for text in element.content:
49 | result.append(''.join(text.content))
50 | return '\r\n'.join(result)
51 |
52 |
--------------------------------------------------------------------------------
/libreqda/templates/registration/login.html:
--------------------------------------------------------------------------------
1 | {% extends "base.html" %}
2 |
3 | {% block body %}
4 |
5 |
6 |

7 |
8 |
34 |
35 | {% endblock %}
--------------------------------------------------------------------------------
/libreqda/templates/browse_projects_general_tab.html:
--------------------------------------------------------------------------------
1 | {% load i18n %}
2 | {% load filters %}
3 |
4 |
5 |
6 |
7 | | {% trans "Versión" %} |
8 | {{ project.version }} |
9 |
10 |
11 | | {% trans "Fecha de creación" %} |
12 | {{ project.creation_date }} |
13 |
14 |
15 | | {% trans "Fecha de modificación" %} |
16 | {{ project.modified_date }} |
17 |
18 |
19 | | {% trans "Creador" %} |
20 | {{ project.owner }} |
21 |
22 |
23 | | {% trans "Comentario" %} |
24 |
25 | {% if project.comment %}
26 | {{ project.comment|linebreaks }}
27 | {% else %}
28 | {% trans "El proyecto no tiene un comentario." %}
29 | {% endif %}
30 | |
31 |
32 |
33 | | {% trans "Número de documentos" %} |
34 | {{ project.documents.count }} |
35 |
36 |
37 | | {% trans "Número total de códigos" %} |
38 | {{ project.codes.count }} |
39 |
40 |
41 | | {% trans "Número total de citas" %} |
42 | {{ project|project_citation_count }} |
43 |
44 |
45 |
--------------------------------------------------------------------------------
/libreqda/templatetags/filters.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from django import template
3 | from django.utils.translation import ugettext as _
4 |
5 | from libreqda.models import Citation
6 |
7 | register = template.Library()
8 |
9 |
10 | @register.filter
11 | def get_permission_text(user_permission):
12 | key_map = {'a': _('Administrador'),
13 | 'e': _('Editor'),
14 | 'g': _('Invitado')}
15 |
16 | return key_map[user_permission.permissions]
17 |
18 |
19 | @register.filter
20 | def pretty_print_code_name(code):
21 | class_map = {'i': 'badge-info',
22 | 's': 'badge-success',
23 | 'w': 'badge-warning',
24 | 'e': 'badge-important',
25 | 'b': 'badge-inverse',
26 | 'd': ''}
27 |
28 | if code.color:
29 | return '%s' % (class_map[code.color],
30 | code.name)
31 | else:
32 | return code.name
33 |
34 |
35 | @register.filter
36 | def pretty_print_category_name(c):
37 | class_map = {'i': 'label-info',
38 | 's': 'label-success',
39 | 'w': 'label-warning',
40 | 'e': 'label-important',
41 | 'b': 'label-inverse',
42 | 'd': ''}
43 |
44 | if c.color:
45 | return '%s' % (class_map[c.color],
46 | c.name)
47 | else:
48 | return c.name
49 |
50 |
51 | @register.filter
52 | def project_citation_count(project):
53 | return Citation.objects.filter(document__project=project).count()
54 |
--------------------------------------------------------------------------------
/libreqda/templates/browse_projects_documents_tab.html:
--------------------------------------------------------------------------------
1 | {% load i18n %}
2 |
5 | {% if project.documents.all %}
6 |
7 |
8 |
9 | | # |
10 | {% trans "Nombre" %} |
11 | {% trans "Tipo" %} |
12 | {% trans "Fecha" %} |
13 | {% trans "Añadido por" %} |
14 | |
15 |
16 |
17 |
18 | {% for doc in project.documents.all %}
19 |
20 | | {{ forloop.counter }} |
21 | {{ doc.name }} |
22 | {{ doc.type }} |
23 | {{ doc.creation_date }} |
24 | {{ doc.uploaded_by }} |
25 |
26 | {% trans "Ver" %}
27 | {% trans "Eliminar" %}
28 | |
29 |
30 |
31 | |
32 | {% if doc.comment %}
33 | {{ doc.comment|linebreaks }} |
34 | {% else %}
35 | {% trans "El documento no tiene descripción." %} |
36 | {% endif %}
37 |
38 | {% endfor %}
39 |
40 |
41 | {% else %}
42 |
43 | ¡{% trans "No hay documentos!" %}
44 |
45 | {% endif %}
--------------------------------------------------------------------------------
/libreqda/templates/browse_annotations_codes_tab.html:
--------------------------------------------------------------------------------
1 | {% load i18n %}
2 | {% load filters %}
3 |
4 |
5 |
6 |
7 |
10 |
11 | {% if annotation.codes.all %}
12 |
13 |
14 |
15 | | # |
16 | {% trans "Etiqueta" %} |
17 | {% trans "Citas" %} |
18 | {% trans "Códigos" %} |
19 | {% trans "Peso" %} |
20 | {% trans "Añadido por" %} |
21 | {% trans "Fecha" %} |
22 | |
23 |
24 |
25 |
26 | {% for code in annotation.codes.all %}
27 |
28 | | {{ forloop.counter}} |
29 | {{ code|pretty_print_code_name|safe }} |
30 | {{ code.citations.count }} |
31 | TODO |
32 | {{ code.weight }} |
33 | {{ code.created_by }} |
34 | {{ code.creation_date }} |
35 | {% trans "Eliminar" %} |
36 |
37 |
38 | {% if code.comment %}
39 | | {{ code.comment }} |
40 | {% else %}
41 | {% trans "El código no tiene descripción." %} |
42 | {% endif %}
43 |
44 | {% endfor %}
45 |
46 |
47 | {% else %}
48 |
49 |
{% trans "¡No hay códigos asignados!" %}
50 |
51 | {% endif %}
52 |
53 |
--------------------------------------------------------------------------------
/libreqda/templates/base.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | {% load i18n %}
4 |
5 |
6 |
7 | {% block head %}
8 |
9 | {% block title %}{% trans "LibreQDA" %}{% endblock%}
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 | {% endblock head %}
18 |
19 |
20 |
21 | {% block topbar %}
22 |
47 | {% endblock topbar %}
48 |
49 | {% block body %}
50 | {% endblock body %}
51 |
52 | {% block footer %}
53 | {% endblock footer %}
54 |
55 |
--------------------------------------------------------------------------------
/libreqda/templates/browse_projects_users_tab.html:
--------------------------------------------------------------------------------
1 | {% load filters %}
2 |
3 |
32 |
33 |
34 |
39 |
40 |
41 |
42 | | # |
43 | Nombre |
44 | Rol |
45 | Fecha |
46 | |
47 |
48 |
49 |
50 |
51 | | - |
52 | {{ project.owner }} |
53 | Dueño |
54 | {{ project.creation_date }} |
55 | |
56 |
57 | {% for user_perm in project.permissions.all %}
58 |
59 | | {{ forloop.counter }} |
60 | {{ user_perm.user.username }} |
61 | {{ user_perm|get_permission_text }} |
62 | {{ user_perm.creation_date }} |
63 |
64 | {% if user in project.admin_users and user_perm.user != project.owner %}
65 | Eliminar
66 | {% endif %}
67 | |
68 |
69 |
70 | {% endfor %}
71 |
72 |
--------------------------------------------------------------------------------
/libreqda/templates/about.html:
--------------------------------------------------------------------------------
1 | {% extends "base.html" %}
2 |
3 | {% load i18n %}
4 | {% load filters %}
5 |
6 | {% block head %}
7 | {{ block.super }}
8 | {% endblock head %}
9 |
10 | {% block topbar_extra %}
11 | {% endblock topbar_extra %}
12 |
13 | {% block body %}
14 |
15 |
16 |
17 |
18 |

19 |
20 |
21 |
Líderes de proyecto
22 |
23 | - Juan Muñoz (Universitat Autònoma de Barcelona)
24 | - Paribanú Freitas (Universidad de la República)
25 | - Luis Alonzo Fulchi (DATA-CSE - Universidad de la República)
26 | - Marc Bria (Universitat Autònoma de Barcelona)
27 |
28 |
29 |
Desarrollo
30 |
31 |
36 |
37 |
38 | - Alejandro Martínez

39 | - Ernesto Rodríguez

40 | - Mauro de Carvalho

41 |
42 |
43 |
Financiación
44 |
45 | - Agencia Española de Cooperación Internacional para el Desarrollo (AECID)
46 | - Programa de Cooperación Interuniversitaria e Investigación Científica
47 |
48 |
49 |
Logo
50 |
51 | - Carlos Silva
52 |
53 |
54 |
55 |
56 |
57 |
58 | {% endblock body%}
59 |
--------------------------------------------------------------------------------
/libreqda/locale/es/LC_MESSAGES/django.po:
--------------------------------------------------------------------------------
1 | # SOME DESCRIPTIVE TITLE.
2 | # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
3 | # This file is distributed under the same license as the PACKAGE package.
4 | # FIRST AUTHOR , YEAR.
5 | #
6 | #, fuzzy
7 | msgid ""
8 | msgstr ""
9 | "Project-Id-Version: PACKAGE VERSION\n"
10 | "Report-Msgid-Bugs-To: \n"
11 | "POT-Creation-Date: 2013-02-18 16:39-0200\n"
12 | "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
13 | "Last-Translator: FULL NAME \n"
14 | "Language-Team: LANGUAGE \n"
15 | "Language: \n"
16 | "MIME-Version: 1.0\n"
17 | "Content-Type: text/plain; charset=UTF-8\n"
18 | "Content-Transfer-Encoding: 8bit\n"
19 | "Plural-Forms: nplurals=2; plural=(n != 1)\n"
20 |
21 | #: forms.py:17
22 | msgid "Usuarios"
23 | msgstr ""
24 |
25 | #: models.py:7
26 | msgid "Nombre"
27 | msgstr ""
28 |
29 | #: models.py:10
30 | msgid "Comentario"
31 | msgstr ""
32 |
33 | #: models.py:105
34 | msgid "Administrator"
35 | msgstr ""
36 |
37 | #: models.py:106 templatetags/filters.py:10
38 | msgid "Editor"
39 | msgstr ""
40 |
41 | #: models.py:107
42 | msgid "Guest"
43 | msgstr ""
44 |
45 | #: settings.py:171
46 | msgid "Inglés"
47 | msgstr ""
48 |
49 | #: settings.py:172
50 | msgid "Español"
51 | msgstr ""
52 |
53 | #: settings.py:173
54 | msgid "Portugués"
55 | msgstr ""
56 |
57 | #: views.py:95
58 | msgid "Asignar usuarios al proyecto"
59 | msgstr ""
60 |
61 | #: views.py:114
62 | msgid "No se puede remover del projecto a su propietario."
63 | msgstr ""
64 |
65 | #: views.py:120
66 | msgid "Permisos insuficientes."
67 | msgstr ""
68 |
69 | #: templates/base.html:7 templates/base.html.py:25
70 | msgid "LibreQDA"
71 | msgstr ""
72 |
73 | #: templates/base.html:35
74 | #, python-format
75 | msgid "Bienvenido, %(user.username)s"
76 | msgstr ""
77 |
78 | #: templates/view_document.html:19
79 | msgid "Categorías"
80 | msgstr ""
81 |
82 | #: templates/view_document.html:20
83 | msgid "Informes"
84 | msgstr ""
85 |
86 | #: templates/view_document.html:21
87 | msgid "Consultas"
88 | msgstr ""
89 |
90 | #: templates/view_document.html:22
91 | msgid "Filtros"
92 | msgstr ""
93 |
94 | #: templates/view_document.html:23
95 | msgid "Anotaciones"
96 | msgstr ""
97 |
98 | #: templates/view_document.html:24
99 | msgid "Códigos"
100 | msgstr ""
101 |
102 | #: templates/view_document.html:25
103 | msgid "Citas"
104 | msgstr ""
105 |
106 | #: templatetags/filters.py:9
107 | msgid "Administrador"
108 | msgstr ""
109 |
110 | #: templatetags/filters.py:11
111 | msgid "Invitado"
112 | msgstr ""
113 |
--------------------------------------------------------------------------------
/libreqda/locale/pt/LC_MESSAGES/django.po:
--------------------------------------------------------------------------------
1 | # SOME DESCRIPTIVE TITLE.
2 | # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
3 | # This file is distributed under the same license as the PACKAGE package.
4 | # FIRST AUTHOR , YEAR.
5 | #
6 | #, fuzzy
7 | msgid ""
8 | msgstr ""
9 | "Project-Id-Version: PACKAGE VERSION\n"
10 | "Report-Msgid-Bugs-To: \n"
11 | "POT-Creation-Date: 2013-02-18 16:39-0200\n"
12 | "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
13 | "Last-Translator: FULL NAME \n"
14 | "Language-Team: LANGUAGE \n"
15 | "Language: \n"
16 | "MIME-Version: 1.0\n"
17 | "Content-Type: text/plain; charset=UTF-8\n"
18 | "Content-Transfer-Encoding: 8bit\n"
19 | "Plural-Forms: nplurals=2; plural=(n != 1)\n"
20 |
21 | #: forms.py:17
22 | msgid "Usuarios"
23 | msgstr ""
24 |
25 | #: models.py:7
26 | msgid "Nombre"
27 | msgstr ""
28 |
29 | #: models.py:10
30 | msgid "Comentario"
31 | msgstr ""
32 |
33 | #: models.py:105
34 | msgid "Administrator"
35 | msgstr ""
36 |
37 | #: models.py:106 templatetags/filters.py:10
38 | msgid "Editor"
39 | msgstr ""
40 |
41 | #: models.py:107
42 | msgid "Guest"
43 | msgstr ""
44 |
45 | #: settings.py:171
46 | msgid "Inglés"
47 | msgstr ""
48 |
49 | #: settings.py:172
50 | msgid "Español"
51 | msgstr ""
52 |
53 | #: settings.py:173
54 | msgid "Portugués"
55 | msgstr ""
56 |
57 | #: views.py:95
58 | msgid "Asignar usuarios al proyecto"
59 | msgstr ""
60 |
61 | #: views.py:114
62 | msgid "No se puede remover del projecto a su propietario."
63 | msgstr ""
64 |
65 | #: views.py:120
66 | msgid "Permisos insuficientes."
67 | msgstr ""
68 |
69 | #: templates/base.html:7 templates/base.html.py:25
70 | msgid "LibreQDA"
71 | msgstr ""
72 |
73 | #: templates/base.html:35
74 | #, python-format
75 | msgid "Bienvenido, %(user.username)s"
76 | msgstr ""
77 |
78 | #: templates/view_document.html:19
79 | msgid "Categorías"
80 | msgstr ""
81 |
82 | #: templates/view_document.html:20
83 | msgid "Informes"
84 | msgstr ""
85 |
86 | #: templates/view_document.html:21
87 | msgid "Consultas"
88 | msgstr ""
89 |
90 | #: templates/view_document.html:22
91 | msgid "Filtros"
92 | msgstr ""
93 |
94 | #: templates/view_document.html:23
95 | msgid "Anotaciones"
96 | msgstr ""
97 |
98 | #: templates/view_document.html:24
99 | msgid "Códigos"
100 | msgstr ""
101 |
102 | #: templates/view_document.html:25
103 | msgid "Citas"
104 | msgstr ""
105 |
106 | #: templatetags/filters.py:9
107 | msgid "Administrador"
108 | msgstr ""
109 |
110 | #: templatetags/filters.py:11
111 | msgid "Invitado"
112 | msgstr ""
113 |
--------------------------------------------------------------------------------
/libreqda/locale/en/LC_MESSAGES/django.po:
--------------------------------------------------------------------------------
1 | # SOME DESCRIPTIVE TITLE.
2 | # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
3 | # This file is distributed under the same license as the PACKAGE package.
4 | # FIRST AUTHOR , YEAR.
5 | #
6 | #, fuzzy
7 | msgid ""
8 | msgstr ""
9 | "Project-Id-Version: PACKAGE VERSION\n"
10 | "Report-Msgid-Bugs-To: \n"
11 | "POT-Creation-Date: 2013-02-18 16:39-0200\n"
12 | "PO-Revision-Date: 2013-02-22 12:33\n"
13 | "Last-Translator: \n"
14 | "Language-Team: LANGUAGE \n"
15 | "MIME-Version: 1.0\n"
16 | "Content-Type: text/plain; charset=UTF-8\n"
17 | "Content-Transfer-Encoding: 8bit\n"
18 | "Language: \n"
19 | "X-Translated-Using: django-rosetta 0.6.8\n"
20 |
21 | #: forms.py:17
22 | msgid "Usuarios"
23 | msgstr "Users"
24 |
25 | #: models.py:7
26 | msgid "Nombre"
27 | msgstr "Name"
28 |
29 | #: models.py:10
30 | msgid "Comentario"
31 | msgstr "Comment"
32 |
33 | #: models.py:105
34 | msgid "Administrator"
35 | msgstr ""
36 |
37 | #: models.py:106 templatetags/filters.py:10
38 | msgid "Editor"
39 | msgstr ""
40 |
41 | #: models.py:107
42 | msgid "Guest"
43 | msgstr ""
44 |
45 | #: settings.py:171
46 | msgid "Inglés"
47 | msgstr "English"
48 |
49 | #: settings.py:172
50 | msgid "Español"
51 | msgstr "Spanish "
52 |
53 | #: settings.py:173
54 | msgid "Portugués"
55 | msgstr "Portuguese "
56 |
57 | #: views.py:95
58 | msgid "Asignar usuarios al proyecto"
59 | msgstr ""
60 |
61 | #: views.py:114
62 | msgid "No se puede remover del projecto a su propietario."
63 | msgstr ""
64 |
65 | #: views.py:120
66 | msgid "Permisos insuficientes."
67 | msgstr ""
68 |
69 | #: templates/base.html:7 templates/base.html.py:25
70 | msgid "LibreQDA"
71 | msgstr ""
72 |
73 | #: templates/base.html:35
74 | #, python-format
75 | msgid "Bienvenido, %(user.username)s"
76 | msgstr ""
77 |
78 | #: templates/view_document.html:19
79 | msgid "Categorías"
80 | msgstr ""
81 |
82 | #: templates/view_document.html:20
83 | msgid "Informes"
84 | msgstr ""
85 |
86 | #: templates/view_document.html:21
87 | msgid "Consultas"
88 | msgstr ""
89 |
90 | #: templates/view_document.html:22
91 | msgid "Filtros"
92 | msgstr ""
93 |
94 | #: templates/view_document.html:23
95 | msgid "Anotaciones"
96 | msgstr ""
97 |
98 | #: templates/view_document.html:24
99 | msgid "Códigos"
100 | msgstr ""
101 |
102 | #: templates/view_document.html:25
103 | msgid "Citas"
104 | msgstr ""
105 |
106 | #: templatetags/filters.py:9
107 | msgid "Administrador"
108 | msgstr ""
109 |
110 | #: templatetags/filters.py:11
111 | msgid "Invitado"
112 | msgstr ""
113 |
--------------------------------------------------------------------------------
/libreqda/templates/browse_query_results.html:
--------------------------------------------------------------------------------
1 | {% extends "base.html" %}
2 |
3 | {% load i18n %}
4 | {% load filters %}
5 |
6 | {% block head %}
7 | {{ block.super }}
8 | {% endblock head %}
9 |
10 | {% block topbar_extra %}
11 | {% endblock topbar_extra %}
12 |
13 | {% block body %}
14 |
15 |
16 | {% if results %}
17 |
18 | {% for code in results %}
19 |
20 |
25 |
26 |
27 |
28 |
29 |
30 | | # |
31 | {% trans "Códigos" %} |
32 | |
33 |
34 |
35 |
36 | {% for citation in code.citations %}
37 |
38 | | {{ forloop.counter }} |
39 |
40 | {% for code in citation.codes.all %}
41 | {{ code|pretty_print_code_name|safe }}
42 | {% endfor %}
43 | |
44 |
45 | {{citation.document.name}}
46 | {% trans "Ver documento" %}
47 | |
48 |
49 |
50 | |
51 | {{ citation.text }}
52 | |
53 |
54 | {% endfor %}
55 |
56 |
57 |
58 |
59 |
60 | {% endfor %}
61 |
62 | {% else %}
63 |
66 | {% endif %}
67 |
68 |
69 | {% endblock %}
--------------------------------------------------------------------------------
/libreqda/templates/browse_categories.html:
--------------------------------------------------------------------------------
1 | {% extends "base.html" %}
2 |
3 | {% load i18n %}
4 | {% load filters %}
5 |
6 | {% block head %}
7 | {{ block.super }}
8 | {% endblock head %}
9 |
10 | {% block topbar_extra %}
11 | {% endblock topbar_extra %}
12 |
13 | {% block body %}
14 |
15 |
16 |
19 |
20 | {% if project.categories.all %}
21 |
22 |
23 |
24 | | # |
25 | {% trans "Etiqueta" %} |
26 | {% trans "Citas" %} |
27 | {% trans "Códigos" %} |
28 | {% trans "Anotaciones" %} |
29 | {% trans "Documentos" %} |
30 | {% trans "Añadido por" %} |
31 | {% trans "Fecha" %} |
32 | |
33 |
34 |
35 |
36 | {% for category in project.categories.all %}
37 |
38 | | {{ forloop.counter}} |
39 | {{ category|pretty_print_category_name|safe }} |
40 | {{ category.citations.count }} |
41 | {{ category.codes.count }} |
42 | {{ category.annotations.count }} |
43 | {{ category.documents.count }} |
44 | {{ category.created_by }} |
45 | {{ category.creation_date }} |
46 | {% trans "Eliminar" %} |
47 |
48 |
49 | {% if category.comment %}
50 | | {{ category.comment }} |
51 | {% else %}
52 | {% trans "La categoría no tiene descripción." %} |
53 | {% endif %}
54 |
55 | {% endfor %}
56 |
57 |
58 | {% else %}
59 |
60 |
{% trans "¡No hay categorías!" %}
61 |
{% trans "No hay categorías para el proyecto. Puede " %}{% trans "agregar una" %}.
62 |
63 | {% endif %}
64 |
65 |
66 |
67 | {% endblock %}
--------------------------------------------------------------------------------
/libreqda/templates/browse_annotations.html:
--------------------------------------------------------------------------------
1 | {% extends "base.html" %}
2 |
3 | {% load i18n %}
4 |
5 | {% block head %}
6 | {{ block.super }}
7 |
8 |
9 | {% endblock head %}
10 |
11 | {% block topbar_extra %}
12 | {% endblock topbar_extra %}
13 |
14 | {% load filters %}
15 |
16 | {% block body %}
17 |
18 |
19 |
22 | {% if project.annotations.all %}
23 |
24 | {% for annotation in project.annotations.all %}
25 |
26 |
31 |
32 |
33 |
36 |
41 |
42 |
43 | {% include "browse_annotations_general_tab.html" with annotation=annotation %}
44 |
45 |
46 | {% include "browse_annotations_citations_tab.html" with annotation=annotation %}
47 |
48 |
49 | {% include "browse_annotations_codes_tab.html" with annotation=annotation %}
50 |
51 |
52 |
53 |
54 |
55 | {% endfor %}
56 |
57 | {% else %}
58 |
59 |
{% trans "¡No hay Anotaciones!" %}
60 |
{% trans "No hay anotaciones para el proyecto. Puede " %}{% trans "agregar una" %}.
61 |
62 | {% endif %}
63 |
64 |
65 | {% endblock %}
--------------------------------------------------------------------------------
/libreqda/templates/browse_codes.html:
--------------------------------------------------------------------------------
1 | {% extends "base.html" %}
2 |
3 | {% load i18n %}
4 | {% load filters %}
5 |
6 | {% block head %}
7 | {{ block.super }}
8 | {% endblock head %}
9 |
10 | {% block topbar_extra %}
11 | {% endblock topbar_extra %}
12 |
13 | {% block body %}
14 |
15 |
16 |
19 |
20 | {% if project.codes.all %}
21 |
22 |
23 |
24 | | # |
25 | {% trans "Etiqueta" %} |
26 | {% trans "Citas" %} |
27 | {% trans "Códigos" %} |
28 | {% trans "Padre" %} |
29 | {% trans "Peso" %} |
30 | {% trans "Añadido por" %} |
31 | {% trans "Fecha" %} |
32 | |
33 |
34 |
35 |
36 | {% for code in project.codes.all %}
37 |
38 | | {{ forloop.counter}} |
39 | {{ code|pretty_print_code_name|safe }} |
40 | {{ code.citations.count }} |
41 | TODO |
42 |
43 | {% if code.parent_codes.all %}
44 | {% for parent in code.parent_codes.all %}
45 | {% if forloop.last %}
46 | {{ parent|pretty_print_code_name|safe }}
47 | {% else %}
48 | {{ parent|pretty_print_code_name|safe }}
49 | {% endif %}
50 | {% endfor %}
51 | {% else %}
52 | -
53 | {% endif %}
54 | |
55 | {{ code.weight }} |
56 | {{ code.created_by }} |
57 | {{ code.creation_date }} |
58 | {% trans "Eliminar" %} |
59 |
60 |
61 | {% if code.comment %}
62 | | {{ code.comment }} |
63 | {% else %}
64 | {% trans "El código no tiene descripción." %} |
65 | {% endif %}
66 |
67 | {% endfor %}
68 |
69 |
70 | {% else %}
71 |
72 |
{% trans "¡No hay códigos!" %}
73 |
{% trans "No hay códigos para el proyecto. Puede " %}{% trans "agregar uno" %}.
74 |
75 | {% endif %}
76 |
77 |
78 |
79 | {% endblock %}
--------------------------------------------------------------------------------
/libreqda/templates/citation_details.html:
--------------------------------------------------------------------------------
1 | {% load i18n %}
2 | {% load filters %}
3 |
4 |
8 |
9 |
10 |
{% trans "Datos de la cita" %}
11 |
12 |
13 |
14 | | {% trans "Fecha de creación" %} |
15 | {{ citation.creation_date }} |
16 |
17 |
18 | | {% trans "Fecha de modificación" %} |
19 | {{ citation.modified_date }} |
20 |
21 |
22 |
23 | | {% trans "Creador" %} |
24 | {{ citation.created_by }} |
25 |
26 |
27 | | {% trans "Comentario" %} |
28 | {{ citation.comment }} |
29 |
30 |
31 | | {% trans "Texto" %} |
32 | {{ citation.text }} |
33 |
34 |
35 |
36 |
37 |
{% trans "Códigos de la cita" %}
38 |
39 |
40 |
41 | {% if citation.codes.all %}
42 |
43 |
44 |
45 | | # |
46 | {% trans "Etiqueta" %} |
47 | {% trans "Padre" %} |
48 | | {% trans "Peso" %} |
49 | {% trans "Añadido por" %} |
50 | |
51 |
52 |
53 |
54 | {% for code in citation.codes.all %}
55 |
56 | | {{ forloop.counter}} |
57 | {{ code|pretty_print_code_name|safe }} |
58 |
59 | {% if code.parent_code %}
60 | {{ code.parent_code|pretty_print_code_name|safe }}
61 | {% else %}
62 | -
63 | {% endif %}
64 | |
65 | {{ code.weight }} |
66 | {{ code.created_by }} |
67 | {% trans "Remover" %} |
68 |
69 |
70 | {% if code.comment %}
71 | | {{ code.comment }} |
72 | {% else %}
73 | {% trans "El código no tiene descripción." %} |
74 | {% endif %}
75 |
76 | {% endfor %}
77 |
78 |
79 | {% else %}
80 |
81 |
{% trans "No hay códigos asignados a esta cita." %}
82 |
83 | {% endif %}
84 |
85 |
86 |
87 |
88 |
89 |
92 |
--------------------------------------------------------------------------------
/libreqda/templates/browse_projects.html:
--------------------------------------------------------------------------------
1 | {% extends "base.html" %}
2 | {% load i18n %}
3 |
4 | {% block head %}
5 | {{ block.super }}
6 | {% endblock head %}
7 |
8 | {% block topbar_extra %}
9 | {% endblock topbar_extra %}
10 |
11 | {% load filters %}
12 |
13 | {% block body %}
14 |
15 |
16 |
17 |
18 |
19 |
22 | {% if projects %}
23 |
24 | {% for project in projects %}
25 |
26 |
31 |
32 |
33 |
45 |
50 |
51 |
52 | {% include "browse_projects_general_tab.html" %}
53 |
54 |
55 | {% include "browse_projects_documents_tab.html" %}
56 |
57 |
58 | {% include "browse_projects_users_tab.html" %}
59 |
60 |
61 |
62 |
63 |
64 | {% endfor %}
65 |
66 | {% else %}
67 |
68 |
¡No hay proyectos!
69 |
No hay proyectos asignados a este usuario. Puede agregar uno.
70 |
71 | {% endif %}
72 |
73 |
74 | {% endblock %}
--------------------------------------------------------------------------------
/libreqda/forms.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from django import forms
3 | from django.contrib.auth.models import User
4 | from django.utils.translation import ugettext_lazy as _
5 |
6 | from libreqda.models import Annotation, BooleanQuery, Category, Code, \
7 | Document, Project, SemanticQuery, SetQuery, ProximityQuery
8 | from libreqda.validators import DocumentValidator
9 |
10 |
11 | class ProjectForm(forms.ModelForm):
12 | class Meta:
13 | model = Project
14 | exclude = ('owner', 'version', 'creation_date', 'modified_date')
15 |
16 |
17 | class AddUserToProjectForm(forms.Form):
18 | users = forms.ModelMultipleChoiceField(
19 | queryset=User.objects.all(),
20 | label=_('Usuarios'))
21 |
22 |
23 | class AddCodeToCitationForm(forms.Form):
24 | codes = forms.ModelMultipleChoiceField(
25 | queryset=Code.objects.all(),
26 | label=_(u'Códigos'))
27 |
28 |
29 | class AddAnnotationToCitationForm(forms.Form):
30 | annotations = forms.ModelMultipleChoiceField(
31 | queryset=Annotation.objects.all(),
32 | label=_('Anotaciones'))
33 |
34 |
35 | class NewDocumentForm(forms.Form):
36 | document = forms.ModelChoiceField(
37 | queryset=Document.objects.all(),
38 | label="Documento")
39 | name = forms.CharField(max_length=250, label='Nombre')
40 | comment = forms.CharField(required=False,
41 | widget=forms.Textarea,
42 | label='Comentario')
43 |
44 |
45 | class UploadDocumentForm(forms.Form):
46 | document = forms.FileField(label="Documento",
47 | validators=[DocumentValidator()])
48 | name = forms.CharField(max_length=250, label='Nombre')
49 | comment = forms.CharField(required=False,
50 | widget=forms.Textarea,
51 | label='Comentario')
52 |
53 |
54 | class CodeForm(forms.ModelForm):
55 | class Meta:
56 | WEIGHTS = [(i, i) for i in range(-100, 101)][::-1]
57 |
58 | model = Code
59 | exclude = ('citations', 'created_by', 'creation_date',
60 | 'modified_date', 'project')
61 | widgets = {'name': forms.TextInput(),
62 | 'weight': forms.Select(choices=WEIGHTS)}
63 |
64 |
65 | class AnnotationForm(forms.ModelForm):
66 | class Meta:
67 | model = Annotation
68 | exclude = ('codes', 'created_by', 'creation_date',
69 | 'modified_date', 'project')
70 |
71 |
72 | class AddCodeToAnnotation(forms.Form):
73 | codes = forms.ModelMultipleChoiceField(queryset=Code.objects.none(),
74 | label=_(u'Códigos'))
75 |
76 |
77 | class BooleanQueryForm(forms.ModelForm):
78 | class Meta:
79 | model = BooleanQuery
80 | exclude = ('project')
81 |
82 |
83 | class SetQueryForm(forms.ModelForm):
84 | class Meta:
85 | model = SetQuery
86 | exclude = ('project')
87 |
88 | def clean(self):
89 | cleaned_data = super(SetQueryForm, self).clean()
90 |
91 | if not (cleaned_data['boolean_queries'] or
92 | cleaned_data['proximity_queries'] or
93 | cleaned_data['semantic_queries']):
94 | raise forms.ValidationError(
95 | _('* Se debe seleccionar al menos una consulta.'))
96 |
97 | return cleaned_data
98 |
99 |
100 | class SemanticQueryForm(forms.ModelForm):
101 | class Meta:
102 | model = SemanticQuery
103 | exclude = ('project')
104 |
105 |
106 | class ProximityQueryForm(forms.ModelForm):
107 | class Meta:
108 | model = ProximityQuery
109 | exclude = ('project')
110 |
111 |
112 | class CategoryForm(forms.ModelForm):
113 | class Meta:
114 | model = Category
115 | exclude = ('annotations', 'citations', 'codes', 'documents',
116 | 'created_by', 'creation_date', 'modified_date', 'project')
117 | widgets = {'name': forms.TextInput()}
118 |
--------------------------------------------------------------------------------
/libreqda/annotations_views.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | import re
3 | from datetime import datetime
4 |
5 | from django.http import HttpResponse
6 | from django.utils import simplejson as json
7 | from django.shortcuts import get_object_or_404
8 | from django.views.decorators.csrf import csrf_exempt
9 | from django.contrib.auth.decorators import login_required
10 |
11 | from libreqda.utils import JsonResponse
12 | from libreqda.models import DocumentInstance, Citation
13 |
14 |
15 | # ##TODO:Resolver temas de permisos en todas las vistas.
16 |
17 | @csrf_exempt # TODO: Fix this to include csrf token in Annotations post
18 | @login_required
19 | def create(request, pid, did):
20 | user = request.user
21 | doc = get_object_or_404(DocumentInstance, pk=did)
22 | serialized_annotation = request.body
23 |
24 | c = populate_citation(Citation(), serialized_annotation, doc, user)
25 |
26 | return HttpResponse(c.serialized,
27 | mimetype='application/json; charset=utf8')
28 |
29 | @login_required
30 | def read(request, pid, did, aid=None):
31 | doc = get_object_or_404(DocumentInstance, pk=did)
32 |
33 | citations = [cit.serialized for cit in doc.citations.all()]
34 | if not citations:
35 | return JsonResponse([])
36 |
37 | content = '[%s]' % (','.join(citations),)
38 | return HttpResponse(content, mimetype='application/json; charset=utf8')
39 |
40 | @csrf_exempt # TODO: Fix this to include csrf token in Annotations post
41 | @login_required
42 | def update(request, pid, did, aid):
43 | user = request.user
44 | doc = get_object_or_404(DocumentInstance, pk=did)
45 | citation = doc.citations.get(pk=aid)
46 |
47 | serialized_annotation = request.body
48 | citation = populate_citation(citation, serialized_annotation,
49 | doc, user, citation_id=aid)
50 |
51 | return HttpResponse(citation.serialized,
52 | mimetype='application/json; charset=utf8')
53 |
54 | @csrf_exempt # TODO: Fix this to include csrf token in Annotations post
55 | @login_required
56 | def destroy(request, pid, did, aid):
57 | doc = get_object_or_404(DocumentInstance, pk=did)
58 | citation = doc.citations.get(pk=aid)
59 | citation.delete()
60 |
61 | return JsonResponse('', status=204)
62 |
63 | #### Helper functions for annotations views
64 |
65 | def populate_citation(citation, serialized_annotation,
66 | document, user, citation_id=None):
67 | '''
68 | Populates a freshly created Citation object or updates an
69 | already created one from a serialized annotation.
70 |
71 | Returns the citation with updated fields.
72 | '''
73 |
74 | c = citation
75 | annotation = json.loads(serialized_annotation)
76 |
77 | c.created_by = user
78 | c.document = document
79 | c.comment = annotation['text']
80 |
81 | a_range = get_range_from_annotation(annotation['ranges'][0])
82 | c.start_paragraph = a_range['start_p']
83 | c.end_paragraph = a_range['end_p']
84 | c.start = a_range['start']
85 | c.end = a_range['end']
86 | c.text = annotation['quote']
87 |
88 | if not citation_id:
89 | # Freshly created citation.
90 | c.creation_date = datetime.now()
91 | c.modified_date = c.creation_date
92 | c.serialized = serialized_annotation
93 | c.save()
94 |
95 | annotation['id'] = c.id
96 | c.serialized = json.dumps(annotation)
97 | c.save()
98 | else:
99 | annotation['id'] = citation_id
100 | c.serialized = json.dumps(annotation)
101 | c.modified_date = datetime.now()
102 | c.save()
103 |
104 | return c
105 |
106 | def get_range_from_annotation(range_dict):
107 | '''
108 | Given an annotation range dictionary it returns a dic with
109 | the following keys:
110 | start_p : Start paragraph, end_p : End paragraph,
111 | start : Start offset in paragraph, end : End offset in paragraph
112 | '''
113 | range_RE = r'/p\[(\d+)\]'
114 |
115 | start = range_dict['startOffset']
116 | end = range_dict['endOffset']
117 | start_p = re.findall(range_RE, range_dict['start'])[0]
118 | end_p = re.findall(range_RE, range_dict['end'])[0]
119 |
120 | return {
121 | 'start_p' : int(start_p),
122 | 'end_p' : int(end_p),
123 | 'start' : start,
124 | 'end' : end,
125 | }
126 |
--------------------------------------------------------------------------------
/libreqda/static/lib/jquery.contextMenu/jquery.contextMenu.css:
--------------------------------------------------------------------------------
1 | /*!
2 | * jQuery contextMenu - Plugin for simple contextMenu handling
3 | *
4 | * Version: git-master
5 | *
6 | * Authors: Rodney Rehm, Addy Osmani (patches for FF)
7 | * Web: http://medialize.github.com/jQuery-contextMenu/
8 | *
9 | * Licensed under
10 | * MIT License http://www.opensource.org/licenses/mit-license
11 | * GPL v3 http://opensource.org/licenses/GPL-3.0
12 | *
13 | */
14 |
15 | .context-menu-list {
16 | margin:0;
17 | padding:0;
18 |
19 | min-width: 120px;
20 | max-width: 250px;
21 | display: inline-block;
22 | position: absolute;
23 | list-style-type: none;
24 |
25 | border: 1px solid #DDD;
26 | background: #EEE;
27 |
28 | -webkit-box-shadow: 0 2px 5px rgba(0, 0, 0, 0.5);
29 | -moz-box-shadow: 0 2px 5px rgba(0, 0, 0, 0.5);
30 | -ms-box-shadow: 0 2px 5px rgba(0, 0, 0, 0.5);
31 | -o-box-shadow: 0 2px 5px rgba(0, 0, 0, 0.5);
32 | box-shadow: 0 2px 5px rgba(0, 0, 0, 0.5);
33 |
34 | font-family: Verdana, Arial, Helvetica, sans-serif;
35 | font-size: 11px;
36 | }
37 |
38 | .context-menu-item {
39 | padding: 2px 2px 2px 24px;
40 | background-color: #EEE;
41 | position: relative;
42 | -webkit-user-select: none;
43 | -moz-user-select: -moz-none;
44 | -ms-user-select: none;
45 | user-select: none;
46 | }
47 |
48 | .context-menu-separator {
49 | padding-bottom:0;
50 | border-bottom: 1px solid #DDD;
51 | }
52 |
53 | .context-menu-item > label > input,
54 | .context-menu-item > label > textarea {
55 | -webkit-user-select: text;
56 | -moz-user-select: text;
57 | -ms-user-select: text;
58 | user-select: text;
59 | }
60 |
61 | .context-menu-item.hover {
62 | cursor: pointer;
63 | background-color: #39F;
64 | }
65 |
66 | .context-menu-item.disabled {
67 | color: #666;
68 | }
69 |
70 | .context-menu-input.hover,
71 | .context-menu-item.disabled.hover {
72 | cursor: default;
73 | background-color: #EEE;
74 | }
75 |
76 | .context-menu-submenu:after {
77 | content: ">";
78 | color: #666;
79 | position: absolute;
80 | top: 0;
81 | right: 3px;
82 | z-index: 1;
83 | }
84 |
85 | /* icons
86 | #protip:
87 | In case you want to use sprites for icons (which I would suggest you do) have a look at
88 | http://css-tricks.com/13224-pseudo-spriting/ to get an idea of how to implement
89 | .context-menu-item.icon:before {}
90 | */
91 | .context-menu-item.context-menu-icon { min-height: 18px; background-repeat: no-repeat; background-position: 4px 2px; }
92 | .context-menu-item.context-menu-icon-edit { background-image: url(images/page_white_edit.png); }
93 | .context-menu-item.context-menu-icon-cut { background-image: url(images/cut.png); }
94 | .context-menu-item.context-menu-icon-copy { background-image: url(images/page_white_copy.png); }
95 | .context-menu-item.context-menu-icon-paste { background-image: url(images/page_white_paste.png); }
96 | .context-menu-item.context-menu-icon-delete { background-image: url(images/page_white_delete.png); }
97 | .context-menu-item.context-menu-icon-add { background-image: url(images/page_white_add.png); }
98 | .context-menu-item.context-menu-icon-quit { background-image: url(images/door.png); }
99 |
100 | /* vertically align inside labels */
101 | .context-menu-input > label > * { vertical-align: top; }
102 |
103 | /* position checkboxes and radios as icons */
104 | .context-menu-input > label > input[type="checkbox"],
105 | .context-menu-input > label > input[type="radio"] {
106 | margin-left: -17px;
107 | }
108 | .context-menu-input > label > span {
109 | margin-left: 5px;
110 | }
111 |
112 | .context-menu-input > label,
113 | .context-menu-input > label > input[type="text"],
114 | .context-menu-input > label > textarea,
115 | .context-menu-input > label > select {
116 | display: block;
117 | width: 100%;
118 |
119 | -webkit-box-sizing: border-box;
120 | -moz-box-sizing: border-box;
121 | -ms-box-sizing: border-box;
122 | -o-box-sizing: border-box;
123 | box-sizing: border-box;
124 | }
125 |
126 | .context-menu-input > label > textarea {
127 | height: 100px;
128 | }
129 | .context-menu-item > .context-menu-list {
130 | display: none;
131 | /* re-positioned by js */
132 | right: -5px;
133 | top: 5px;
134 | }
135 |
136 | .context-menu-item.hover > .context-menu-list {
137 | display: block;
138 | }
139 |
140 | .context-menu-accesskey {
141 | text-decoration: underline;
142 | }
143 |
--------------------------------------------------------------------------------
/libreqda/static/css/base.css:
--------------------------------------------------------------------------------
1 | body {
2 | background-color: #F6F6F6;
3 | }
4 |
5 | .navbar-inner {
6 | -webkit-border-radius: 0;
7 | -moz-border-radius: 0;
8 | border-radius: 0;
9 | }
10 |
11 | .logo-container {
12 | text-align: center;
13 | }
14 |
15 | .separate {
16 | margin-top: 20px;
17 | margin-bottom: 20px;
18 | }
19 |
20 | .credits {
21 | margin-left: 10%;
22 | }
23 | .login-container {
24 | top: 45%;
25 | left: 50%;
26 | width: 500px;
27 | height: 335px;
28 | margin: -150px 0px 0px -250px;
29 | position: absolute;
30 | padding-top: 20px !important;
31 | }
32 |
33 | #login-form {
34 | margin: 40px 0 20px;
35 | }
36 |
37 | .with-border {
38 | padding: 4px;
39 | border-radius: 5px 5px 5px 5px;
40 | -webkit-border-radius: 5px 5px 5px 5px;
41 | border: 1px solid #DDD;
42 | }
43 |
44 | .grey-background {
45 | background-color: #E8E8E8;
46 | }
47 |
48 | .white-background {
49 | background-color: White;
50 | }
51 |
52 | .lone-container {
53 | padding-top: 20px;
54 | padding-left: 10px;
55 | padding-right: 10px;
56 | padding-bottom: 20px;
57 | }
58 | .acordion-project-name {
59 | font-size: 17.5px
60 | }
61 |
62 | .tight-tab-content {
63 | padding-left: 1%;
64 | padding-right: 1%;
65 | }
66 |
67 | .key-value-table {
68 | table-layout: fixed;
69 | width:98%;
70 | }
71 |
72 | .key-value-table .key {
73 | width: 24%
74 | }
75 |
76 | .key-value-table .value {
77 | width: 74%
78 | }
79 |
80 | .toolbar {
81 | width: 100%;
82 | display: table;
83 | margin-bottom: 20px;
84 | }
85 |
86 | .move-up {
87 | margin-top: -10px;
88 | }
89 |
90 | .toolbar-small {
91 | width: 100%;
92 | display: table;
93 | margin-bottom: 9px;
94 | }
95 |
96 | .right-button {
97 | margin-left: 25px;
98 | }
99 |
100 | .left-group-button {
101 | margin-left: 4px;
102 | }
103 |
104 | .menu-document-button {
105 | padding-left: 20px;
106 | padding-right: 20px;
107 | margin-top: 10px;
108 | margin-bottom: 5px;
109 | }
110 |
111 | .menu {
112 | transition: all 0.4s;
113 | -o-transition: all 0.4s;
114 | -moz-transition: all 0.4s;
115 | -webkit-transition: all 0.4s;
116 | }
117 |
118 | .menu {
119 | top: 42px;
120 | height: 100%;
121 | background: #FFFFFF;
122 | width: 400px;
123 | padding: 30px;
124 | position: fixed;
125 | z-index: 100000;
126 | box-shadow: 4px 0 10px rgba(0,0,0,0.25);
127 | -moz-box-shadow: 4px 0 10px rgba(0,0,0,0.25);
128 | -webkit-box-shadow: 4px 0 10px rgba(0,0,0,0.25);
129 | }
130 |
131 |
132 | .left {
133 | left: 0;
134 | border-right: 3px solid #000000;
135 | }
136 |
137 | .left:hover, .left:focus {
138 | left: 0 !important;
139 | }
140 |
141 | /*
142 | .right {
143 | right: 0;
144 | border-left: 3px solid #000000;
145 | }
146 |
147 | .right:hover, .right:focus {
148 | right: 0 !important;
149 | }
150 | */
151 |
152 |
153 | .document-container {
154 | top: 90px;
155 | left: 0;
156 | right: 0;
157 | bottom: 0;
158 | position: absolute;
159 | width: auto;
160 | height: auto;
161 | margin-bottom: 10px;
162 | margin-right: 10px;
163 | margin-left: 50px;
164 | padding: 0px;
165 | overflow: auto;
166 | }
167 |
168 | .document-container div {
169 | padding-top: 5px;
170 | }
171 |
172 | .document-text {
173 | height: 100%;
174 | text-align: justify;
175 | padding-left: 15px;
176 | padding-right: 15px;
177 | padding-bottom: 15px;
178 | border-right: 1px solid #CCC;
179 | }
180 |
181 | .document-citations {
182 | height: 100%;
183 | padding-left: 5px;
184 | }
185 |
186 | .document-citations .citation-bar {
187 | width: 10px;
188 | height: 5px;
189 | background-color: burlywood;
190 | display: block;
191 | margin: 1px;
192 | position: relative;
193 | border-radius: 5px;
194 | }
195 |
196 | .citation-bar.cit-grey { background-color: grey; }
197 | .citation-bar.cit-red { background-color: #E30022; }
198 | .citation-bar.cit-yellow { background-color: #FFEF00; }
199 | .citation-bar.cit-green { background-color: #008000; }
200 | .citation-bar.cit-blue { background-color: #00308F; }
201 | .citation-bar.cit-black { background-color: black; }
202 |
203 | .document-citations .citation-bar:hover {
204 | background-color: khaki;
205 | cursor: hand;
206 | cursor: pointer;
207 | }
208 |
209 | .citation-bar.cit-grey:hover { background-color: lightgrey; }
210 | .citation-bar.cit-red:hover { background-color: #FF5349; }
211 | .citation-bar.cit-yellow:hover { background-color: #FADA5E; }
212 | .citation-bar.cit-green:hover { background-color: #8DB600; }
213 | .citation-bar.cit-blue:hover { background-color: #72A0C1; }
214 | .citation-bar.cit-black:hover { background-color: #635147; }
215 |
216 | #userModal form {
217 | margin: 0;
218 | }
219 |
220 | #citationModal {
221 | width: 1075px;
222 | left: 415px;
223 | }
224 |
225 | #doc-text-area {
226 | word-wrap: break-word;
227 | }
228 |
229 | .github-badge {
230 | width: 32px;
231 | left: 32px;
232 | }
233 |
234 | .tooltip {
235 | z-index: 1;
236 | pointer-events: none;
237 | }
238 |
239 | .tooltip.in {
240 | opacity: .6;
241 | }
242 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | 
2 | [LibreQDA](https://github.com/tryolabs/libreQDA)
3 | ================================================
4 |
5 | Copyright (C) 2013 [Tryolabs](http://www.tryolabs.com)
6 |
7 | This program is free software: you can redistribute it and/or modify
8 | it under the terms of the GNU Affero General Public License as published by
9 | the Free Software Foundation, either version 3 of the License, or
10 | (at your option) any later version.
11 |
12 | This program is distributed in the hope that it will be useful,
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | GNU General Public License for more details.
16 |
17 | You should have received a copy of the GNU General Public License
18 | along with this program. If not, see [](http://www.gnu.org/licenses/).
19 |
20 | Instalación
21 | ===========
22 |
23 | [Virtualenv](https://pypi.python.org/pypi/virtualenv)
24 | ------------------------------------------------------
25 | Para mayor comodidad se recomienda utilizar un virtualenv.
26 |
27 | 1. Instalar Virtualenv: (`sudo apt-get install python-virtualenv` en Debian/Ubuntu).
28 | 2. Una vez instalado, crear un Virtualenv: `virtualenv libreqda`.
29 | 3. Activar el Virtualenv: `cd libreqda` y luego `source bin/activate`.
30 |
31 | Obtener el código
32 | -----------------
33 | Probablemente tengas que instalar git: `sudo apt-get install git`
34 |
35 | Luego debes obtener el código de LibreQDA: `git clone https://github.com/tryolabs/libreQDA.git`.
36 |
37 |
38 | Dependencias
39 | ------------
40 | Antes de poder comenzar es necesario instalar algunas dependencias.
41 |
42 | 1. Instalar `build-essential`: `sudo apt-get install build-essential`.
43 | 2. Instalar MySQL: `sudo apt-get install mysql-server libmysqlclient-dev libevent-dev libxml2-dev libxslt1-dev`.
44 | 3. El archivo `requirements.txt` contiene una lista de dependencias a instalar. Es posible instalar todas de forma automática con el comando `pip install -r requirements.txt`.
45 |
46 | ~~Python-docx~~
47 | -----------
48 | ~~Para poder extraer el texto de archivos ``docx` es necesario instalar `python-docx`.~~
49 |
50 | 1. ~~Obtener el código desde su [repositorio en Github](https://github.com/mikemaccana/python-docx): `git clone https://github.com/mikemaccana/python-docx.git`.~~
51 | 2. ~~Ir al directorio con el código: `cd python-docx`.~~
52 | 3. ~~Instalar con: `python setup.py install`.~~
53 |
54 | Configurar y ejecutar
55 | ---------------------
56 | 1. Crear una base de datos para LibreQDA. El encoding de la base de datos debe ser **UTF-8** para evitar problemas al subir documentos.
57 | `CREATE DATABASE libreqda CHARACTER SET utf8 COLLATE utf8_general_ci;`
58 | 2. Copiar el archivo `local_settings.py.template` que se encuentra junto al código a `local_settings.py`.
59 | 3. Abrir el nuevo archivo, `local_settings.py` y editar según sea necesario.
60 | 4. Crear la base de datos con django: `python manage.py syncdb`.
61 | 5. Ejecutar con: `python manage.py runserver`
62 |
63 | Actualizar
64 | ----------
65 | Para actualizar LibreQDA simplemente es necesario hacer un pull del repositorio con `git pull` y luego actualizar la base de datos con `python manage.py reset libreqda`.
66 |
67 | También es necesario actualziar las dependencias con: `pip install -r requirements.txt`.
68 |
69 | NOTA: Los datos son eliminados de la base de datos cuando se hace un `reset`. Es posible utilizar
70 | [`dumpdata`](https://docs.djangoproject.com/en/dev/ref/django-admin/#dumpdata-appname-appname-appname-model) y
71 | [`loaddata`](https://docs.djangoproject.com/en/dev/ref/django-admin/#loaddata-fixture-fixture) para exportar e importar datos fácilmente.
72 |
73 | FIXME: Ojo, hice un dumpdata y un loaddata y me da error: `Problem installing fixture 'proyectos': dump is not a known serialization format.`
74 |
75 | Cómo agregar soporte para otros tipos de archivos
76 | =================================================
77 | Agregar soporte para otros tipos de archivos es relativamente simple. Existen dos archivos a modificar:
78 | * `validators.py`: Contiene código para permitir o no la subida de un tipo de archivo en particular.
79 | * `text_extraction.py`: Contiene el código para extraer el texto de cada uno de los distintos tipos de archivo permitidos.
80 |
81 | 1. Abrir el archivo `validators.py`.
82 | 2. En la tupla `SUPPORTED_FILETYPES` agregar un `string` con el tipo de archivo. Por ejemplo, para archivos Postscript, agregar `'.ps'` a la tupla.
83 | 3. Abrir el archivo `tex_extraction.py.
84 | 4. Agregar una nueva función con la extensión de archivo como nombre. Por ejemplo, para procesar archivos Postscript, agregar una función llamada `ps`.
85 |
86 | La nueva función va a recibir un solo parámetro, siendo éste el path al nuevo archivo subido.
87 | La función debe abrir el archivo y extraer el texto, para finalmente retornar un objeto del tipo `string` con el contenido de archivo. Éste valor será el que se guarde en la base de datos.
88 |
89 | TODO
90 | ----
91 | Actualmente para determinar el tipo de archivo, LibreQDA se basa en la extensión. La dentificación de tipos de archivos debería realizarse utilizando [`python-magic`](https://github.com/ahupp/python-magic).
92 |
--------------------------------------------------------------------------------
/libreqda/settings.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | # Django settings for libreqda project.
3 |
4 | import os
5 |
6 |
7 | BASE_PATH = os.path.abspath(os.path.dirname(__file__))
8 |
9 | DEBUG = False
10 | TEMPLATE_DEBUG = DEBUG
11 |
12 | ADMINS = (
13 | # ('Your Name', 'your_email@example.com'),
14 | )
15 |
16 | MANAGERS = ADMINS
17 |
18 | DATABASES = {}
19 |
20 | # Local time zone for this installation. Choices can be found here:
21 | # http://en.wikipedia.org/wiki/List_of_tz_zones_by_name
22 | # although not all choices may be available on all operating systems.
23 | # In a Windows environment this must be set to your system time zone.
24 | TIME_ZONE = 'America/Montevideo'
25 |
26 | # Language code for this installation. All choices can be found here:
27 | # http://www.i18nguy.com/unicode/language-identifiers.html
28 | LANGUAGE_CODE = 'es-UY'
29 |
30 | SITE_ID = 1
31 |
32 | # If you set this to False, Django will make some optimizations so as not
33 | # to load the internationalization machinery.
34 | USE_I18N = True
35 |
36 | # If you set this to False, Django will not format dates, numbers and
37 | # calendars according to the current locale.
38 | USE_L10N = True
39 |
40 | # If you set this to False, Django will not use timezone-aware datetimes.
41 | USE_TZ = True
42 |
43 | # Absolute filesystem path to the directory that will hold user-uploaded files.
44 | # Example: "/home/media/media.lawrence.com/media/"
45 | MEDIA_ROOT = ''
46 |
47 | # URL that handles the media served from MEDIA_ROOT. Make sure to use a
48 | # trailing slash.
49 | # Examples: "http://media.lawrence.com/media/", "http://example.com/media/"
50 | MEDIA_URL = ''
51 |
52 | # Absolute path to the directory static files should be collected to.
53 | # Don't put anything in this directory yourself; store your static files
54 | # in apps' "static/" subdirectories and in STATICFILES_DIRS.
55 | # Example: "/home/media/media.lawrence.com/static/"
56 | STATIC_ROOT = ''
57 |
58 | # URL prefix for static files.
59 | # Example: "http://media.lawrence.com/static/"
60 | STATIC_URL = '/static/'
61 |
62 | # Additional locations of static files
63 | STATICFILES_DIRS = (
64 | # Put strings here, like "/home/html/static" or "C:/www/django/static".
65 | # Always use forward slashes, even on Windows.
66 | # Don't forget to use absolute paths, not relative paths.
67 | )
68 |
69 | # List of finder classes that know how to find static files in
70 | # various locations.
71 | STATICFILES_FINDERS = (
72 | 'django.contrib.staticfiles.finders.FileSystemFinder',
73 | 'django.contrib.staticfiles.finders.AppDirectoriesFinder',
74 | # 'django.contrib.staticfiles.finders.DefaultStorageFinder',
75 | )
76 |
77 | # Make this unique, and don't share it with anybody.
78 | SECRET_KEY = ''
79 |
80 | # List of callables that know how to import templates from various sources.
81 | TEMPLATE_LOADERS = (
82 | 'django.template.loaders.filesystem.Loader',
83 | 'django.template.loaders.app_directories.Loader',
84 | 'django.template.loaders.eggs.Loader',
85 | )
86 |
87 | TEMPLATE_CONTEXT_PROCESSORS = (
88 | 'django.contrib.auth.context_processors.auth',
89 | 'django.core.context_processors.debug',
90 | 'django.core.context_processors.i18n',
91 | 'django.core.context_processors.media',
92 | 'django.core.context_processors.static',
93 | 'django.core.context_processors.request',
94 | 'django.contrib.messages.context_processors.messages'
95 | )
96 |
97 | MIDDLEWARE_CLASSES = (
98 | 'django.contrib.sessions.middleware.SessionMiddleware',
99 | 'django.middleware.locale.LocaleMiddleware', # Translations
100 | 'django.middleware.common.CommonMiddleware',
101 | 'django.middleware.csrf.CsrfViewMiddleware',
102 | 'django.contrib.auth.middleware.AuthenticationMiddleware',
103 | 'django.contrib.messages.middleware.MessageMiddleware',
104 | # Uncomment the next line for simple clickjacking protection:
105 | # 'django.middleware.clickjacking.XFrameOptionsMiddleware',
106 | )
107 |
108 | ROOT_URLCONF = 'libreqda.urls'
109 |
110 | # Python dotted path to the WSGI application used by Django's runserver.
111 | WSGI_APPLICATION = 'libreqda.wsgi.application'
112 |
113 | TEMPLATE_DIRS = (
114 | os.path.join(BASE_PATH, 'templates')
115 | # Put strings here, like "/home/html/django_templates" or "C:/www/django/templates".
116 | # Always use forward slashes, even on Windows.
117 | # Don't forget to use absolute paths, not relative paths.
118 | )
119 |
120 | INSTALLED_APPS = (
121 | 'django.contrib.auth',
122 | 'django.contrib.contenttypes',
123 | 'django.contrib.sessions',
124 | 'django.contrib.sites',
125 | 'django.contrib.messages',
126 | 'django.contrib.staticfiles',
127 | 'django.contrib.admin',
128 | # 'django.contrib.admindocs', # admin documentation
129 | # 3rd party
130 | 'rosetta',
131 | 'model_report',
132 | # Ours
133 | 'libreqda',
134 | )
135 |
136 | # A sample logging configuration. The only tangible logging
137 | # performed by this configuration is to send an email to
138 | # the site admins on every HTTP 500 error when DEBUG=False.
139 | # See http://docs.djangoproject.com/en/dev/topics/logging for
140 | # more details on how to customize your logging configuration.
141 | LOGGING = {
142 | 'version': 1,
143 | 'disable_existing_loggers': False,
144 | 'filters': {
145 | 'require_debug_false': {
146 | '()': 'django.utils.log.RequireDebugFalse'
147 | }
148 | },
149 | 'handlers': {
150 | 'mail_admins': {
151 | 'level': 'ERROR',
152 | 'filters': ['require_debug_false'],
153 | 'class': 'django.utils.log.AdminEmailHandler'
154 | }
155 | },
156 | 'loggers': {
157 | 'django.request': {
158 | 'handlers': ['mail_admins'],
159 | 'level': 'ERROR',
160 | 'propagate': True,
161 | },
162 | }
163 | }
164 |
165 | LOGIN_URL = '/accounts/login'
166 | LOGIN_REDIRECT_URL = '/project/'
167 | LOGOUT_REDIRECT_URL = '/accounts/login'
168 |
169 | # Localization
170 | ugettext = lambda s: s
171 | LANGUAGES = (
172 | ('en', ugettext(u'Inglés')),
173 | ('es', ugettext(u'Español')),
174 | ('pt', ugettext(u'Portugués')),
175 | )
176 |
177 | try:
178 | from local_settings import *
179 | except:
180 | pass
181 |
--------------------------------------------------------------------------------
/libreqda/urls.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | from django.contrib import admin
3 | from django.conf import settings
4 | from django.conf.urls import patterns, include, url
5 |
6 | admin.autodiscover()
7 |
8 | handler404 = 'libreqda.http_handlers.handle_404'
9 |
10 | urlpatterns = patterns('',
11 | # admin
12 | url(r'^admin/', include(admin.site.urls)),
13 | # about
14 | url(r'about/$',
15 | 'libreqda.views.about',
16 | name='about'),
17 | # projects
18 | url(r'^$',
19 | 'libreqda.views.home',
20 | name='home'),
21 | url(r'^project/$',
22 | 'libreqda.views.browse_projects',
23 | name='browse_projects'),
24 | url(r'^project/new/$',
25 | 'libreqda.views.new_project',
26 | name='new_project'),
27 | url(r'^project/(?P\d+)/delete/$',
28 | 'libreqda.views.delete_project',
29 | name='delete_project'),
30 | url(r'^project/(?P\d+)/copy/$',
31 | 'libreqda.views.copy_project',
32 | name='copy_project'),
33 | url(r'^project/(?P\d+)/user/add/$',
34 | 'libreqda.views.add_user_to_project',
35 | name='add_user_to_project'),
36 | url(r'^project/(?P\d+)/user/(?P\d+)/remove/$',
37 | 'libreqda.views.remove_user_from_project',
38 | name='remove_user_from_project'),
39 | # documents
40 | url(r'^project/(?P\d+)/document/(?P\d+)/$',
41 | 'libreqda.views.view_document',
42 | name='view_document'),
43 | url(r'^project/(?P\d+)/document/add/$',
44 | 'libreqda.views.upload_document',
45 | name='upload_document'),
46 | url(r'^project/(?P\d+)/document/(?P\d+)/delete/$',
47 | 'libreqda.views.delete_document',
48 | name='delete_document'),
49 | #codes
50 | url(r'^project/(?P\d+)/code/$',
51 | 'libreqda.views.browse_codes',
52 | name='browse_codes'),
53 | url(r'^project/(?P\d+)/code/new/$',
54 | 'libreqda.views.new_code',
55 | name='new_code'),
56 | url(r'^project/(?P\d+)/code/(?P\d+)/delete/$',
57 | 'libreqda.views.delete_code',
58 | name='delete_code'),
59 | #categories
60 | url(r'^project/(?P\d+)/category/$',
61 | 'libreqda.views.browse_categories',
62 | name='browse_categories'),
63 | url(r'^project/(?P\d+)/category/new/$',
64 | 'libreqda.views.new_category',
65 | name='new_category'),
66 | url(r'^project/(?P\d+)/category/(?P\d+)/delete/$',
67 | 'libreqda.views.delete_category',
68 | name='delete_category'),
69 | #annotations
70 | url(r'^project/(?P\d+)/annotation/$',
71 | 'libreqda.views.browse_annotations',
72 | name='browse_annotations'),
73 | url(r'^project/(?P\d+)/annotation/new/$',
74 | 'libreqda.views.new_annotation',
75 | name='new_annotation'),
76 | url(r'^project/(?P\d+)/annotation/(?P\d+)/delete/$',
77 | 'libreqda.views.delete_annotation',
78 | name='delete_annotation'),
79 | url(r'^project/(?P\d+)/annotation/(?P\d+)/code/add/$',
80 | 'libreqda.views.add_code_to_annotation',
81 | name='add_code_to_annotation'),
82 | url(r'^project/(?P\d+)/annotation/(?P\d+)/code/remove/(?P\d+)/$',
83 | 'libreqda.views.remove_code_from_annotation',
84 | name='remove_code_from_annotation'),
85 | #citations
86 | url(r'^project/(?P\d+)/citation/(?P.+)/code/assign/$',
87 | 'libreqda.views.add_code_to_citation',
88 | name='add_code_to_citation'),
89 | url(r'^project/(?P\d+)/citation/(?P.+)/details/$',
90 | 'libreqda.views.citation_details',
91 | name='citation_details'),
92 | url(r'^project/(?P\d+)/citation/(?P\d+)/code/(?P\d+)/remove/$',
93 | 'libreqda.views.remove_code_from_citation',
94 | name='remove_code_from_citation'),
95 | url(r'^project/(?P\d+)/citation/(?P.+)/annotation/assign/$',
96 | 'libreqda.views.add_annotation_to_citation',
97 | name='add_annotation_to_citation'),
98 | url(r'^project/(?P\d+)/citation/(?P\d+)/annotation/(?P\d+)/remove/$',
99 | 'libreqda.views.remove_annotation_from_citation',
100 | name='remove_annotation_from_citation'),
101 | # accounts
102 | url(r'^accounts/login/$',
103 | 'django.contrib.auth.views.login',
104 | name='login'),
105 | url(r'^accounts/logout/$',
106 | 'django.contrib.auth.views.logout',
107 | name='logout',
108 | kwargs={'next_page': '/accounts/login'}),
109 | #queries
110 | url(r'^project/(?P\d+)/query/$',
111 | 'libreqda.views.browse_queries',
112 | name='browse_queries'),
113 | url(r'^project/(?P\d+)/query/boolean/new/$',
114 | 'libreqda.views.new_boolean_query',
115 | name='new_boolean_query'),
116 | url(r'^project/(?P\d+)/query/boolean/delete/(?P\d+)/$',
117 | 'libreqda.views.delete_boolean_query',
118 | name='delete_boolean_query'),
119 | url(r'^project/(?P\d+)/query/set/new/$',
120 | 'libreqda.views.new_set_query',
121 | name='new_set_query'),
122 | url(r'^project/(?P\d+)/query/proximity/new/$',
123 | 'libreqda.views.new_proximity_query',
124 | name='new_proximity_query'),
125 | url(r'^project/(?P\d+)/query/proximity/delete/(?P\d+)/$',
126 | 'libreqda.views.delete_proximity_query',
127 | name='delete_proximity_query'),
128 | url(r'^project/(?P\d+)/query/semantic/new/$',
129 | 'libreqda.views.new_semantic_query',
130 | name='new_semantic_query'),
131 | url(r'^project/(?P\d+)/query/semantic/delete/(?P\d+)/$',
132 | 'libreqda.views.delete_semantic_query',
133 | name='delete_semantic_query'),
134 | url(r'^project/(?P\d+)/query/set/delete/(?P\d+)/$',
135 | 'libreqda.views.delete_set_query',
136 | name='delete_set_query'),
137 | url(r'^project/(?P\d+)/query/boolean/(?P\d+)/$',
138 | 'libreqda.views.do_boolean_query',
139 | name='do_boolean_query'),
140 | url(r'^project/(?P\d+)/query/proximity/(?P\d+)/$',
141 | 'libreqda.views.do_proximity_query',
142 | name='do_proximity_query'),
143 | url(r'^project/(?P\d+)/query/semantic/(?P\d+)/$',
144 | 'libreqda.views.do_semantic_query',
145 | name='do_semantic_query'),
146 | url(r'^project/(?P\d+)/query/set/(?P\d+)/$',
147 | 'libreqda.views.do_set_query',
148 | name='do_set_query'),
149 | # annotator
150 | url(r'^project/(?P\d+)/document/(?P\d+)/annotations/create/$',
151 | 'libreqda.annotations_views.create',
152 | name='annotations_create'),
153 | url(r'^project/(?P\d+)/document/(?P\d+)/annotations/read/$',
154 | 'libreqda.annotations_views.read',
155 | name='annotations_read'),
156 | url(r'^project/(?P\d+)/document/(?P\d+)/annotations/read/(?P\d+)$',
157 | 'libreqda.annotations_views.read',
158 | name='annotations_read'),
159 | url(r'^project/(?P\d+)/document/(?P\d+)/annotations/destroy/$',
160 | 'libreqda.annotations_views.destroy',
161 | name='annotations_destroy'),
162 | url(r'^project/(?P\d+)/document/(?P\d+)/annotations/destroy/(?P\d+)$',
163 | 'libreqda.annotations_views.destroy',
164 | name='annotations_destroy'),
165 | url(r'^project/(?P\d+)/document/(?P\d+)/annotations/update/$',
166 | 'libreqda.annotations_views.update',
167 | name='annotations_update'),
168 | url(r'^project/(?P\d+)/document/(?P\d+)/annotations/update/(?P\d+)$',
169 | 'libreqda.annotations_views.update',
170 | name='annotations_update'),
171 | )
172 |
173 | if 'rosetta' in settings.INSTALLED_APPS:
174 | urlpatterns += patterns('',
175 | url(r'^rosetta/', include('rosetta.urls')),
176 | )
177 |
--------------------------------------------------------------------------------
/libreqda/templates/browse_queries.html:
--------------------------------------------------------------------------------
1 | {% extends "base.html" %}
2 |
3 | {% load i18n %}
4 | {% load filters %}
5 |
6 | {% block head %}
7 | {{ block.super }}
8 | {% endblock head %}
9 |
10 | {% block topbar_extra %}
11 | {% endblock topbar_extra %}
12 |
13 | {% block body %}
14 |
15 |
16 |
17 |
18 |
21 |
{% trans "Consultas booleanas" %}
22 | {% if project.boolean_queries.all %}
23 |
24 |
25 |
26 | | # |
27 | {% trans "Nombre" %} |
28 | {% trans "Códigos" %} |
29 | {% trans "Operador" %} |
30 | |
31 |
32 |
33 |
34 | {% for query in project.boolean_queries.all %}
35 |
36 | | {{ forloop.counter }} |
37 | {{query.name}} |
38 |
39 | {% for code in query.codes.all %}
40 | {{ code|pretty_print_code_name|safe }}
41 | {% endfor %}
42 | |
43 | {{ query.operator }} |
44 |
45 | {% trans "Consultar" %}
46 | {% trans "Eliminar" %}
47 | |
48 |
49 | {% endfor %}
50 |
51 |
52 | {% else %}
53 |
54 |
{% trans "¡No hay consultas booleanas definidas!" %}
55 |
56 | {% endif %}
57 |
58 |
59 |
62 |
{% trans "Consultas semánticas" %}
63 | {% if project.semantic_queries.all %}
64 |
65 |
66 |
67 | | # |
68 | {% trans "Nombre" %} |
69 | {% trans "Código" %} |
70 | {% trans "Operador" %} |
71 | |
72 |
73 |
74 |
75 | {% for query in project.semantic_queries.all %}
76 |
77 | | {{ forloop.counter }} |
78 | {{ query.name }} |
79 | {{ query.code|pretty_print_code_name|safe }} |
80 | {{ query.operator }} |
81 |
82 | {% trans "Consultar" %}
83 | {% trans "Eliminar" %}
84 | |
85 |
86 | {% endfor %}
87 |
88 |
89 | {% else %}
90 |
91 |
{% trans "¡No hay consultas semánticas definidas!" %}
92 |
93 | {% endif %}
94 |
95 |
96 |
99 |
{% trans "Consultas de proximidad" %}
100 | {% if project.proximity_queries.all %}
101 |
102 |
103 |
104 | | # |
105 | {% trans "Nombre" %} |
106 | {% trans "Código 1" %} |
107 | {% trans "Código 2" %} |
108 | {% trans "Operador" %} |
109 | |
110 |
111 |
112 |
113 | {% for query in project.proximity_queries.all %}
114 |
115 | | {{ forloop.counter }} |
116 | {{ query.name }} |
117 | {{ query.code1|pretty_print_code_name|safe }} |
118 | {{ query.code2|pretty_print_code_name|safe }} |
119 | {{ query.operator }} |
120 |
121 | {% trans "Consultar" %}
122 | {% trans "Eliminar" %}
123 | |
124 |
125 | {% endfor %}
126 |
127 |
128 | {% else %}
129 |
130 |
{% trans "¡No hay consultas de proximidad definidas!" %}
131 |
132 | {% endif %}
133 |
134 |
135 |
138 |
{% trans "Consultas avanzadas" %}
139 | {% if project.set_queries.all %}
140 |
141 |
142 |
143 | | # |
144 | {% trans "Nombre" %} |
145 | {% trans "Consultas booleanas" %} |
146 | {% trans "Consultas de proximidad" %} |
147 | {% trans "Consultas semánticas" %} |
148 | {% trans "Operador" %} |
149 | |
150 |
151 |
152 |
153 | {% for query in project.set_queries.all %}
154 |
155 | | {{ forloop.counter }} |
156 | {{query.name}} |
157 |
158 | {% for qq in query.boolean_queries.all %}
159 | {% if forloop.last %}
160 | {{ qq.name }}
161 | {% else %}
162 | {{ qq.name }},
163 | {% endif %}
164 | {% endfor %}
165 | |
166 |
167 | {% for qq in query.proximity_queries.all %}
168 | {% if forloop.last %}
169 | {{ qq.name }}
170 | {% else %}
171 | {{ qq.name }},
172 | {% endif %}
173 | {% endfor %}
174 | |
175 |
176 | {% for qq in query.semantic_queries.all %}
177 | {% if forloop.last %}
178 | {{ qq.name }}
179 | {% else %}
180 | {{ qq.name }},
181 | {% endif %}
182 | {% endfor %}
183 | |
184 | {{ query.operator }} |
185 |
186 | {% trans "Consultar" %}
187 | {% trans "Eliminar" %}
188 | |
189 |
190 | {% endfor %}
191 |
192 |
193 | {% else %}
194 |
195 |
{% trans "¡No hay consultas avazadas definidas!" %}
196 |
197 | {% endif %}
198 |
199 |
200 |
201 | {% endblock %}
--------------------------------------------------------------------------------
/libreqda/static/lib/annotator/annotator.store-1.2.6.js:
--------------------------------------------------------------------------------
1 | /*
2 | ** Annotator v1.2.6
3 | ** https://github.com/okfn/annotator/
4 | **
5 | ** Copyright 2012 Aron Carroll, Rufus Pollock, and Nick Stenning.
6 | ** Dual licensed under the MIT and GPLv3 licenses.
7 | ** https://github.com/okfn/annotator/blob/master/LICENSE
8 | **
9 | ** Built at: 2013-01-21 09:43:51Z
10 | */
11 |
12 | (function() {
13 | var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
14 | __hasProp = Object.prototype.hasOwnProperty,
15 | __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor; child.__super__ = parent.prototype; return child; },
16 | __indexOf = Array.prototype.indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
17 |
18 | Annotator.Plugin.Store = (function(_super) {
19 |
20 | __extends(Store, _super);
21 |
22 | Store.prototype.events = {
23 | 'annotationCreated': 'annotationCreated',
24 | 'annotationDeleted': 'annotationDeleted',
25 | 'annotationUpdated': 'annotationUpdated'
26 | };
27 |
28 | Store.prototype.options = {
29 | prefix: '/store',
30 | autoFetch: true,
31 | annotationData: {},
32 | loadFromSearch: false,
33 | urls: {
34 | create: '/annotations',
35 | read: '/annotations/:id',
36 | update: '/annotations/:id',
37 | destroy: '/annotations/:id',
38 | search: '/search'
39 | }
40 | };
41 |
42 | function Store(element, options) {
43 | this._onError = __bind(this._onError, this);
44 | this._onLoadAnnotationsFromSearch = __bind(this._onLoadAnnotationsFromSearch, this);
45 | this._onLoadAnnotations = __bind(this._onLoadAnnotations, this);
46 | this._getAnnotations = __bind(this._getAnnotations, this); Store.__super__.constructor.apply(this, arguments);
47 | this.annotations = [];
48 | }
49 |
50 | Store.prototype.pluginInit = function() {
51 | if (!Annotator.supported()) return;
52 | if (this.annotator.plugins.Auth) {
53 | return this.annotator.plugins.Auth.withToken(this._getAnnotations);
54 | } else {
55 | return this._getAnnotations();
56 | }
57 | };
58 |
59 | Store.prototype._getAnnotations = function() {
60 | if (this.options.loadFromSearch) {
61 | return this.loadAnnotationsFromSearch(this.options.loadFromSearch);
62 | } else {
63 | return this.loadAnnotations();
64 | }
65 | };
66 |
67 | Store.prototype.annotationCreated = function(annotation) {
68 | var _this = this;
69 | if (__indexOf.call(this.annotations, annotation) < 0) {
70 | this.registerAnnotation(annotation);
71 | return this._apiRequest('create', annotation, function(data) {
72 | if (!(data.id != null)) {
73 | console.warn(Annotator._t("Warning: No ID returned from server for annotation "), annotation);
74 | }
75 | return _this.updateAnnotation(annotation, data);
76 | });
77 | } else {
78 | return this.updateAnnotation(annotation, {});
79 | }
80 | };
81 |
82 | Store.prototype.annotationUpdated = function(annotation) {
83 | var _this = this;
84 | if (__indexOf.call(this.annotations, annotation) >= 0) {
85 | return this._apiRequest('update', annotation, (function(data) {
86 | return _this.updateAnnotation(annotation, data);
87 | }));
88 | }
89 | };
90 |
91 | Store.prototype.annotationDeleted = function(annotation) {
92 | var _this = this;
93 | if (__indexOf.call(this.annotations, annotation) >= 0) {
94 | return this._apiRequest('destroy', annotation, (function() {
95 | return _this.unregisterAnnotation(annotation);
96 | }));
97 | }
98 | };
99 |
100 | Store.prototype.registerAnnotation = function(annotation) {
101 | return this.annotations.push(annotation);
102 | };
103 |
104 | Store.prototype.unregisterAnnotation = function(annotation) {
105 | return this.annotations.splice(this.annotations.indexOf(annotation), 1);
106 | };
107 |
108 | Store.prototype.updateAnnotation = function(annotation, data) {
109 | if (__indexOf.call(this.annotations, annotation) < 0) {
110 | console.error(Annotator._t("Trying to update unregistered annotation!"));
111 | } else {
112 | $.extend(annotation, data);
113 | }
114 | annotation.highlights[0].name = this.annotator.citationIdStr + annotation.id;
115 | this.annotator.publish('annotationSaved', [annotation]);//TODO:pass
116 | return $(annotation.highlights).data('annotation', annotation);
117 | };
118 |
119 | Store.prototype.loadAnnotations = function() {
120 | return this._apiRequest('read', null, this._onLoadAnnotations);
121 | };
122 |
123 | Store.prototype._onLoadAnnotations = function(data) {
124 | if (data == null) data = [];
125 | this.annotations = data;
126 | var result = this.annotator.loadAnnotations(data.slice());
127 | this.annotator.publish('annotationsLoadedFromStore');//TODO:pass
128 | return result;
129 | };
130 |
131 | Store.prototype.loadAnnotationsFromSearch = function(searchOptions) {
132 | return this._apiRequest('search', searchOptions, this._onLoadAnnotationsFromSearch);
133 | };
134 |
135 | Store.prototype._onLoadAnnotationsFromSearch = function(data) {
136 | if (data == null) data = {};
137 | return this._onLoadAnnotations(data.rows || []);
138 | };
139 |
140 | Store.prototype.dumpAnnotations = function() {
141 | var ann, _i, _len, _ref, _results;
142 | _ref = this.annotations;
143 | _results = [];
144 | for (_i = 0, _len = _ref.length; _i < _len; _i++) {
145 | ann = _ref[_i];
146 | _results.push(JSON.parse(this._dataFor(ann)));
147 | }
148 | return _results;
149 | };
150 |
151 | Store.prototype._apiRequest = function(action, obj, onSuccess) {
152 | var id, options, request, url;
153 | id = obj && obj.id;
154 | url = this._urlFor(action, id);
155 | options = this._apiRequestOptions(action, obj, onSuccess);
156 | request = $.ajax(url, options);
157 | request._id = id;
158 | request._action = action;
159 | return request;
160 | };
161 |
162 | Store.prototype._apiRequestOptions = function(action, obj, onSuccess) {
163 | var opts;
164 | opts = {
165 | type: this._methodFor(action),
166 | headers: this.element.data('annotator:headers'),
167 | dataType: "json",
168 | success: onSuccess || function() {},
169 | error: this._onError
170 | };
171 | if (action === "search") {
172 | opts = $.extend(opts, {
173 | data: obj
174 | });
175 | } else {
176 | opts = $.extend(opts, {
177 | data: obj && this._dataFor(obj),
178 | contentType: "application/json; charset=utf-8"
179 | });
180 | }
181 | return opts;
182 | };
183 |
184 | Store.prototype._urlFor = function(action, id) {
185 | var replaceWith, url;
186 | replaceWith = id != null ? '/' + id : '';
187 | url = this.options.prefix != null ? this.options.prefix : '';
188 | url += this.options.urls[action];
189 | url = url.replace(/\/:id/, replaceWith);
190 | return url;
191 | };
192 |
193 | Store.prototype._methodFor = function(action) {
194 | var table;
195 | table = {
196 | 'create': 'POST',
197 | 'read': 'GET',
198 | 'update': 'PUT',
199 | 'destroy': 'DELETE',
200 | 'search': 'GET'
201 | };
202 | return table[action];
203 | };
204 |
205 | Store.prototype._dataFor = function(annotation) {
206 | var data, highlights;
207 | highlights = annotation.highlights;
208 | delete annotation.highlights;
209 | $.extend(annotation, this.options.annotationData);
210 | data = JSON.stringify(annotation);
211 | if (highlights) annotation.highlights = highlights;
212 | return data;
213 | };
214 |
215 | Store.prototype._onError = function(xhr) {
216 | var action, message;
217 | action = xhr._action;
218 | message = Annotator._t("Sorry we could not ") + action + Annotator._t(" this annotation");
219 | if (xhr._action === 'search') {
220 | message = Annotator._t("Sorry we could not search the store for annotations");
221 | } else if (xhr._action === 'read' && !xhr._id) {
222 | message = Annotator._t("Sorry we could not ") + action + Annotator._t(" the annotations from the store");
223 | }
224 | switch (xhr.status) {
225 | case 401:
226 | message = Annotator._t("Sorry you are not allowed to ") + action + Annotator._t(" this annotation");
227 | break;
228 | case 404:
229 | message = Annotator._t("Sorry we could not connect to the annotations store");
230 | break;
231 | case 500:
232 | message = Annotator._t("Sorry something went wrong with the annotation store");
233 | }
234 | Annotator.showNotification(message, Annotator.Notification.ERROR);
235 | return console.error(Annotator._t("API request failed:") + (" '" + xhr.status + "'"));
236 | };
237 |
238 | return Store;
239 |
240 | })(Annotator.Plugin);
241 |
242 | }).call(this);
243 |
--------------------------------------------------------------------------------
/libreqda/templates/view_document.html:
--------------------------------------------------------------------------------
1 | {% extends "base.html" %}
2 | {% load i18n %}
3 |
4 | {% block head %}
5 | {{ block.super }}
6 |
7 |
8 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 | {% endblock head %}
21 |
22 | {% block topbar_extra %}
23 | {% endblock topbar_extra %}
24 |
25 | {% block body %}
26 |
27 |
28 |
29 |
30 |
31 |
32 |
35 |
36 |
49 |
50 |
51 |
52 |
{{ document.name }}
53 |
54 | {{ document.document.text|linebreaks }}
55 |
56 |
57 |
58 | {% for cit in citations %}
59 |
60 | {% endfor %}
61 |
62 |
63 |
64 |
298 | {% endblock %}
299 |
--------------------------------------------------------------------------------
/libreqda/static/lib/bootstrap/css/bootstrap-responsive.min.css:
--------------------------------------------------------------------------------
1 | /*!
2 | * Bootstrap Responsive v2.2.2
3 | *
4 | * Copyright 2012 Twitter, Inc
5 | * Licensed under the Apache License v2.0
6 | * http://www.apache.org/licenses/LICENSE-2.0
7 | *
8 | * Designed and built with all the love in the world @twitter by @mdo and @fat.
9 | */@-ms-viewport{width:device-width}.clearfix{*zoom:1}.clearfix:before,.clearfix:after{display:table;line-height:0;content:""}.clearfix:after{clear:both}.hide-text{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.input-block-level{display:block;width:100%;min-height:30px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.hidden{display:none;visibility:hidden}.visible-phone{display:none!important}.visible-tablet{display:none!important}.hidden-desktop{display:none!important}.visible-desktop{display:inherit!important}@media(min-width:768px) and (max-width:979px){.hidden-desktop{display:inherit!important}.visible-desktop{display:none!important}.visible-tablet{display:inherit!important}.hidden-tablet{display:none!important}}@media(max-width:767px){.hidden-desktop{display:inherit!important}.visible-desktop{display:none!important}.visible-phone{display:inherit!important}.hidden-phone{display:none!important}}@media(min-width:1200px){.row{margin-left:-30px;*zoom:1}.row:before,.row:after{display:table;line-height:0;content:""}.row:after{clear:both}[class*="span"]{float:left;min-height:1px;margin-left:30px}.container,.navbar-static-top .container,.navbar-fixed-top .container,.navbar-fixed-bottom .container{width:1170px}.span12{width:1170px}.span11{width:1070px}.span10{width:970px}.span9{width:870px}.span8{width:770px}.span7{width:670px}.span6{width:570px}.span5{width:470px}.span4{width:370px}.span3{width:270px}.span2{width:170px}.span1{width:70px}.offset12{margin-left:1230px}.offset11{margin-left:1130px}.offset10{margin-left:1030px}.offset9{margin-left:930px}.offset8{margin-left:830px}.offset7{margin-left:730px}.offset6{margin-left:630px}.offset5{margin-left:530px}.offset4{margin-left:430px}.offset3{margin-left:330px}.offset2{margin-left:230px}.offset1{margin-left:130px}.row-fluid{width:100%;*zoom:1}.row-fluid:before,.row-fluid:after{display:table;line-height:0;content:""}.row-fluid:after{clear:both}.row-fluid [class*="span"]{display:block;float:left;width:100%;min-height:30px;margin-left:2.564102564102564%;*margin-left:2.5109110747408616%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.row-fluid [class*="span"]:first-child{margin-left:0}.row-fluid .controls-row [class*="span"]+[class*="span"]{margin-left:2.564102564102564%}.row-fluid .span12{width:100%;*width:99.94680851063829%}.row-fluid .span11{width:91.45299145299145%;*width:91.39979996362975%}.row-fluid .span10{width:82.90598290598291%;*width:82.8527914166212%}.row-fluid .span9{width:74.35897435897436%;*width:74.30578286961266%}.row-fluid .span8{width:65.81196581196582%;*width:65.75877432260411%}.row-fluid .span7{width:57.26495726495726%;*width:57.21176577559556%}.row-fluid .span6{width:48.717948717948715%;*width:48.664757228587014%}.row-fluid .span5{width:40.17094017094017%;*width:40.11774868157847%}.row-fluid .span4{width:31.623931623931625%;*width:31.570740134569924%}.row-fluid .span3{width:23.076923076923077%;*width:23.023731587561375%}.row-fluid .span2{width:14.52991452991453%;*width:14.476723040552828%}.row-fluid .span1{width:5.982905982905983%;*width:5.929714493544281%}.row-fluid .offset12{margin-left:105.12820512820512%;*margin-left:105.02182214948171%}.row-fluid .offset12:first-child{margin-left:102.56410256410257%;*margin-left:102.45771958537915%}.row-fluid .offset11{margin-left:96.58119658119658%;*margin-left:96.47481360247316%}.row-fluid .offset11:first-child{margin-left:94.01709401709402%;*margin-left:93.91071103837061%}.row-fluid .offset10{margin-left:88.03418803418803%;*margin-left:87.92780505546462%}.row-fluid .offset10:first-child{margin-left:85.47008547008548%;*margin-left:85.36370249136206%}.row-fluid .offset9{margin-left:79.48717948717949%;*margin-left:79.38079650845607%}.row-fluid .offset9:first-child{margin-left:76.92307692307693%;*margin-left:76.81669394435352%}.row-fluid .offset8{margin-left:70.94017094017094%;*margin-left:70.83378796144753%}.row-fluid .offset8:first-child{margin-left:68.37606837606839%;*margin-left:68.26968539734497%}.row-fluid .offset7{margin-left:62.393162393162385%;*margin-left:62.28677941443899%}.row-fluid .offset7:first-child{margin-left:59.82905982905982%;*margin-left:59.72267685033642%}.row-fluid .offset6{margin-left:53.84615384615384%;*margin-left:53.739770867430444%}.row-fluid .offset6:first-child{margin-left:51.28205128205128%;*margin-left:51.175668303327875%}.row-fluid .offset5{margin-left:45.299145299145295%;*margin-left:45.1927623204219%}.row-fluid .offset5:first-child{margin-left:42.73504273504273%;*margin-left:42.62865975631933%}.row-fluid .offset4{margin-left:36.75213675213675%;*margin-left:36.645753773413354%}.row-fluid .offset4:first-child{margin-left:34.18803418803419%;*margin-left:34.081651209310785%}.row-fluid .offset3{margin-left:28.205128205128204%;*margin-left:28.0987452264048%}.row-fluid .offset3:first-child{margin-left:25.641025641025642%;*margin-left:25.53464266230224%}.row-fluid .offset2{margin-left:19.65811965811966%;*margin-left:19.551736679396257%}.row-fluid .offset2:first-child{margin-left:17.094017094017094%;*margin-left:16.98763411529369%}.row-fluid .offset1{margin-left:11.11111111111111%;*margin-left:11.004728132387708%}.row-fluid .offset1:first-child{margin-left:8.547008547008547%;*margin-left:8.440625568285142%}input,textarea,.uneditable-input{margin-left:0}.controls-row [class*="span"]+[class*="span"]{margin-left:30px}input.span12,textarea.span12,.uneditable-input.span12{width:1156px}input.span11,textarea.span11,.uneditable-input.span11{width:1056px}input.span10,textarea.span10,.uneditable-input.span10{width:956px}input.span9,textarea.span9,.uneditable-input.span9{width:856px}input.span8,textarea.span8,.uneditable-input.span8{width:756px}input.span7,textarea.span7,.uneditable-input.span7{width:656px}input.span6,textarea.span6,.uneditable-input.span6{width:556px}input.span5,textarea.span5,.uneditable-input.span5{width:456px}input.span4,textarea.span4,.uneditable-input.span4{width:356px}input.span3,textarea.span3,.uneditable-input.span3{width:256px}input.span2,textarea.span2,.uneditable-input.span2{width:156px}input.span1,textarea.span1,.uneditable-input.span1{width:56px}.thumbnails{margin-left:-30px}.thumbnails>li{margin-left:30px}.row-fluid .thumbnails{margin-left:0}}@media(min-width:768px) and (max-width:979px){.row{margin-left:-20px;*zoom:1}.row:before,.row:after{display:table;line-height:0;content:""}.row:after{clear:both}[class*="span"]{float:left;min-height:1px;margin-left:20px}.container,.navbar-static-top .container,.navbar-fixed-top .container,.navbar-fixed-bottom .container{width:724px}.span12{width:724px}.span11{width:662px}.span10{width:600px}.span9{width:538px}.span8{width:476px}.span7{width:414px}.span6{width:352px}.span5{width:290px}.span4{width:228px}.span3{width:166px}.span2{width:104px}.span1{width:42px}.offset12{margin-left:764px}.offset11{margin-left:702px}.offset10{margin-left:640px}.offset9{margin-left:578px}.offset8{margin-left:516px}.offset7{margin-left:454px}.offset6{margin-left:392px}.offset5{margin-left:330px}.offset4{margin-left:268px}.offset3{margin-left:206px}.offset2{margin-left:144px}.offset1{margin-left:82px}.row-fluid{width:100%;*zoom:1}.row-fluid:before,.row-fluid:after{display:table;line-height:0;content:""}.row-fluid:after{clear:both}.row-fluid [class*="span"]{display:block;float:left;width:100%;min-height:30px;margin-left:2.7624309392265194%;*margin-left:2.709239449864817%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.row-fluid [class*="span"]:first-child{margin-left:0}.row-fluid .controls-row [class*="span"]+[class*="span"]{margin-left:2.7624309392265194%}.row-fluid .span12{width:100%;*width:99.94680851063829%}.row-fluid .span11{width:91.43646408839778%;*width:91.38327259903608%}.row-fluid .span10{width:82.87292817679558%;*width:82.81973668743387%}.row-fluid .span9{width:74.30939226519337%;*width:74.25620077583166%}.row-fluid .span8{width:65.74585635359117%;*width:65.69266486422946%}.row-fluid .span7{width:57.18232044198895%;*width:57.12912895262725%}.row-fluid .span6{width:48.61878453038674%;*width:48.56559304102504%}.row-fluid .span5{width:40.05524861878453%;*width:40.00205712942283%}.row-fluid .span4{width:31.491712707182323%;*width:31.43852121782062%}.row-fluid .span3{width:22.92817679558011%;*width:22.87498530621841%}.row-fluid .span2{width:14.3646408839779%;*width:14.311449394616199%}.row-fluid .span1{width:5.801104972375691%;*width:5.747913483013988%}.row-fluid .offset12{margin-left:105.52486187845304%;*margin-left:105.41847889972962%}.row-fluid .offset12:first-child{margin-left:102.76243093922652%;*margin-left:102.6560479605031%}.row-fluid .offset11{margin-left:96.96132596685082%;*margin-left:96.8549429881274%}.row-fluid .offset11:first-child{margin-left:94.1988950276243%;*margin-left:94.09251204890089%}.row-fluid .offset10{margin-left:88.39779005524862%;*margin-left:88.2914070765252%}.row-fluid .offset10:first-child{margin-left:85.6353591160221%;*margin-left:85.52897613729868%}.row-fluid .offset9{margin-left:79.8342541436464%;*margin-left:79.72787116492299%}.row-fluid .offset9:first-child{margin-left:77.07182320441989%;*margin-left:76.96544022569647%}.row-fluid .offset8{margin-left:71.2707182320442%;*margin-left:71.16433525332079%}.row-fluid .offset8:first-child{margin-left:68.50828729281768%;*margin-left:68.40190431409427%}.row-fluid .offset7{margin-left:62.70718232044199%;*margin-left:62.600799341718584%}.row-fluid .offset7:first-child{margin-left:59.94475138121547%;*margin-left:59.838368402492065%}.row-fluid .offset6{margin-left:54.14364640883978%;*margin-left:54.037263430116376%}.row-fluid .offset6:first-child{margin-left:51.38121546961326%;*margin-left:51.27483249088986%}.row-fluid .offset5{margin-left:45.58011049723757%;*margin-left:45.47372751851417%}.row-fluid .offset5:first-child{margin-left:42.81767955801105%;*margin-left:42.71129657928765%}.row-fluid .offset4{margin-left:37.01657458563536%;*margin-left:36.91019160691196%}.row-fluid .offset4:first-child{margin-left:34.25414364640884%;*margin-left:34.14776066768544%}.row-fluid .offset3{margin-left:28.45303867403315%;*margin-left:28.346655695309746%}.row-fluid .offset3:first-child{margin-left:25.69060773480663%;*margin-left:25.584224756083227%}.row-fluid .offset2{margin-left:19.88950276243094%;*margin-left:19.783119783707537%}.row-fluid .offset2:first-child{margin-left:17.12707182320442%;*margin-left:17.02068884448102%}.row-fluid .offset1{margin-left:11.32596685082873%;*margin-left:11.219583872105325%}.row-fluid .offset1:first-child{margin-left:8.56353591160221%;*margin-left:8.457152932878806%}input,textarea,.uneditable-input{margin-left:0}.controls-row [class*="span"]+[class*="span"]{margin-left:20px}input.span12,textarea.span12,.uneditable-input.span12{width:710px}input.span11,textarea.span11,.uneditable-input.span11{width:648px}input.span10,textarea.span10,.uneditable-input.span10{width:586px}input.span9,textarea.span9,.uneditable-input.span9{width:524px}input.span8,textarea.span8,.uneditable-input.span8{width:462px}input.span7,textarea.span7,.uneditable-input.span7{width:400px}input.span6,textarea.span6,.uneditable-input.span6{width:338px}input.span5,textarea.span5,.uneditable-input.span5{width:276px}input.span4,textarea.span4,.uneditable-input.span4{width:214px}input.span3,textarea.span3,.uneditable-input.span3{width:152px}input.span2,textarea.span2,.uneditable-input.span2{width:90px}input.span1,textarea.span1,.uneditable-input.span1{width:28px}}@media(max-width:767px){body{padding-right:20px;padding-left:20px}.navbar-fixed-top,.navbar-fixed-bottom,.navbar-static-top{margin-right:-20px;margin-left:-20px}.container-fluid{padding:0}.dl-horizontal dt{float:none;width:auto;clear:none;text-align:left}.dl-horizontal dd{margin-left:0}.container{width:auto}.row-fluid{width:100%}.row,.thumbnails{margin-left:0}.thumbnails>li{float:none;margin-left:0}[class*="span"],.uneditable-input[class*="span"],.row-fluid [class*="span"]{display:block;float:none;width:100%;margin-left:0;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.span12,.row-fluid .span12{width:100%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.row-fluid [class*="offset"]:first-child{margin-left:0}.input-large,.input-xlarge,.input-xxlarge,input[class*="span"],select[class*="span"],textarea[class*="span"],.uneditable-input{display:block;width:100%;min-height:30px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.input-prepend input,.input-append input,.input-prepend input[class*="span"],.input-append input[class*="span"]{display:inline-block;width:auto}.controls-row [class*="span"]+[class*="span"]{margin-left:0}.modal{position:fixed;top:20px;right:20px;left:20px;width:auto;margin:0}.modal.fade{top:-100px}.modal.fade.in{top:20px}}@media(max-width:480px){.nav-collapse{-webkit-transform:translate3d(0,0,0)}.page-header h1 small{display:block;line-height:20px}input[type="checkbox"],input[type="radio"]{border:1px solid #ccc}.form-horizontal .control-label{float:none;width:auto;padding-top:0;text-align:left}.form-horizontal .controls{margin-left:0}.form-horizontal .control-list{padding-top:0}.form-horizontal .form-actions{padding-right:10px;padding-left:10px}.media .pull-left,.media .pull-right{display:block;float:none;margin-bottom:10px}.media-object{margin-right:0;margin-left:0}.modal{top:10px;right:10px;left:10px}.modal-header .close{padding:10px;margin:-10px}.carousel-caption{position:static}}@media(max-width:979px){body{padding-top:0}.navbar-fixed-top,.navbar-fixed-bottom{position:static}.navbar-fixed-top{margin-bottom:20px}.navbar-fixed-bottom{margin-top:20px}.navbar-fixed-top .navbar-inner,.navbar-fixed-bottom .navbar-inner{padding:5px}.navbar .container{width:auto;padding:0}.navbar .brand{padding-right:10px;padding-left:10px;margin:0 0 0 -5px}.nav-collapse{clear:both}.nav-collapse .nav{float:none;margin:0 0 10px}.nav-collapse .nav>li{float:none}.nav-collapse .nav>li>a{margin-bottom:2px}.nav-collapse .nav>.divider-vertical{display:none}.nav-collapse .nav .nav-header{color:#777;text-shadow:none}.nav-collapse .nav>li>a,.nav-collapse .dropdown-menu a{padding:9px 15px;font-weight:bold;color:#777;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.nav-collapse .btn{padding:4px 10px 4px;font-weight:normal;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.nav-collapse .dropdown-menu li+li a{margin-bottom:2px}.nav-collapse .nav>li>a:hover,.nav-collapse .dropdown-menu a:hover{background-color:#f2f2f2}.navbar-inverse .nav-collapse .nav>li>a,.navbar-inverse .nav-collapse .dropdown-menu a{color:#999}.navbar-inverse .nav-collapse .nav>li>a:hover,.navbar-inverse .nav-collapse .dropdown-menu a:hover{background-color:#111}.nav-collapse.in .btn-group{padding:0;margin-top:5px}.nav-collapse .dropdown-menu{position:static;top:auto;left:auto;display:none;float:none;max-width:none;padding:0;margin:0 15px;background-color:transparent;border:0;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none}.nav-collapse .open>.dropdown-menu{display:block}.nav-collapse .dropdown-menu:before,.nav-collapse .dropdown-menu:after{display:none}.nav-collapse .dropdown-menu .divider{display:none}.nav-collapse .nav>li>.dropdown-menu:before,.nav-collapse .nav>li>.dropdown-menu:after{display:none}.nav-collapse .navbar-form,.nav-collapse .navbar-search{float:none;padding:10px 15px;margin:10px 0;border-top:1px solid #f2f2f2;border-bottom:1px solid #f2f2f2;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.1);-moz-box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.1);box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.1)}.navbar-inverse .nav-collapse .navbar-form,.navbar-inverse .nav-collapse .navbar-search{border-top-color:#111;border-bottom-color:#111}.navbar .nav-collapse .nav.pull-right{float:none;margin-left:0}.nav-collapse,.nav-collapse.collapse{height:0;overflow:hidden}.navbar .btn-navbar{display:block}.navbar-static .navbar-inner{padding-right:10px;padding-left:10px}}@media(min-width:980px){.nav-collapse.collapse{height:auto!important;overflow:visible!important}}
10 |
--------------------------------------------------------------------------------
/libreqda/models.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | import os
3 | import uuid
4 | from sets import Set
5 | from itertools import chain
6 |
7 | from django.db import models
8 | from django.core.validators import MinValueValidator, MaxValueValidator
9 | from django.utils.translation import ugettext_lazy as _
10 | from django.contrib.auth.models import User
11 |
12 |
13 | class Project(models.Model):
14 | name = models.CharField(max_length=250, blank=False, verbose_name=_("Nombre"))
15 | owner = models.ForeignKey(User, related_name='projects')
16 | version = models.PositiveIntegerField(default=1)
17 | comment = models.TextField(null=True, blank=True, verbose_name=_("Comentario"))
18 | modified_date = models.DateTimeField(auto_now=True)
19 | creation_date = models.DateTimeField(auto_now_add=True)
20 |
21 | def __unicode__(self):
22 | return "Project %d-%s" % (self.id, self.name)
23 |
24 | def admin_users(self):
25 | '''
26 | Return a list of users that have administration
27 | privileges for the project.
28 | '''
29 | admin_perms = self.permissions.filter(permissions='a')
30 | admins = User.objects.filter(permissions__in=admin_perms)
31 | return set(list(admins) + [self.owner])
32 |
33 |
34 | def get_new_document_path(instance, filename):
35 | doc_uuid = uuid.uuid4().hex
36 | return os.path.join(
37 | 'documents',
38 | doc_uuid,
39 | filename)
40 |
41 |
42 | class Document(models.Model):
43 | name = models.CharField(max_length=250)
44 | type = models.CharField(max_length=250)
45 | text = models.TextField(blank=True)
46 | comment = models.TextField(blank=True, null=True)
47 | file = models.FileField(upload_to=get_new_document_path)
48 | uploaded_by = models.ForeignKey(User)
49 | creation_date = models.DateTimeField(auto_now_add=True)
50 |
51 | def __unicode__(self):
52 | return "Document: %s" % (self.name)
53 |
54 |
55 | class DocumentInstance(models.Model):
56 | document = models.ForeignKey(Document, related_name='instances')
57 | project = models.ForeignKey(Project, related_name='documents')
58 | name = models.CharField(max_length=250)
59 | type = models.CharField(max_length=250)
60 | comment = models.TextField(blank=True, null=True)
61 | modified_date = models.DateTimeField(auto_now=True)
62 | uploaded_by = models.ForeignKey(User)
63 | creation_date = models.DateTimeField(auto_now_add=True)
64 | annotations = models.ManyToManyField('Annotation', related_name='documents')
65 |
66 | def __unicode__(self):
67 | return "DocumentInstance: %s" % (self.name)
68 |
69 |
70 | class Annotation(models.Model):
71 | project = models.ForeignKey(Project, related_name='annotations')
72 | creation_date = models.DateTimeField(auto_now_add=True)
73 | modified_date = models.DateTimeField(auto_now=True)
74 | created_by = models.ForeignKey(User)
75 | text = models.TextField()
76 | codes = models.ManyToManyField('Code',
77 | blank=True,
78 | related_name=_('annotations'))
79 |
80 | def __unicode__(self):
81 | return self.text
82 |
83 |
84 | class Citation(models.Model):
85 | # TODO: Document instances are no longer needed, should we remove them ?
86 | document = models.ForeignKey(DocumentInstance, related_name='citations')
87 | created_by = models.ForeignKey(User)
88 | creation_date = models.DateTimeField(auto_now_add=True)
89 | modified_date = models.DateTimeField(auto_now=True)
90 | comment = models.TextField(null=True, blank=True)
91 | start_paragraph = models.PositiveIntegerField()
92 | end_paragraph = models.PositiveIntegerField()
93 | start = models.PositiveIntegerField()
94 | end = models.PositiveIntegerField()
95 | text = models.TextField(blank=True, null=True)
96 | serialized = models.TextField(null=True, blank=True)
97 | annotations = models.ManyToManyField(Annotation,
98 | null=True,
99 | blank=True,
100 | related_name='citations')
101 |
102 | def __unicode__(self):
103 | return self.comment
104 |
105 | def touches(self, other):
106 | tlen = len(self.document.document.text) + 1
107 | ss = self.start_paragraph * tlen + self.start
108 | se = self.end_paragraph * tlen + self.end
109 | os = other.start_paragraph * tlen + other.start
110 | oe = other.end_paragraph * tlen + other.end
111 |
112 | return ss < os < se or ss < oe < ss
113 |
114 | def codes_str(self):
115 | return ', '.join(self.codes.all().values_list('name', flat=True))
116 |
117 | def html_color(self):
118 | if not self.codes.all():
119 | return 'blank'
120 | return self.codes.all()[0].html_color()
121 |
122 | return ', '.join(self.codes.all().values_list('name', flat=True))
123 |
124 |
125 | class Code(models.Model):
126 | CODE_COLORS = (('d', _('Grey')),
127 | ('e', _('Red')),
128 | ('w', _('Yellow')),
129 | ('s', _('Green')),
130 | ('i', _('Blue')),
131 | ('b', _('Black')),)
132 | project = models.ForeignKey(Project, related_name='codes')
133 | name = models.TextField(max_length=250, verbose_name=_('Nombre'))
134 | weight = models.IntegerField(validators=[MinValueValidator(-100),
135 | MaxValueValidator(100)],
136 | verbose_name=_('Peso'))
137 | created_by = models.ForeignKey(User)
138 | color = models.CharField(max_length=1,
139 | blank=True,
140 | null=True,
141 | choices=CODE_COLORS,
142 | verbose_name=_('Color'))
143 | comment = models.TextField(null=True,
144 | blank=True,
145 | verbose_name=_('Comentario'))
146 | modified_date = models.DateTimeField(auto_now=True)
147 | creation_date = models.DateTimeField(auto_now_add=True)
148 | citations = models.ManyToManyField(Citation, related_name='codes')
149 | parent_codes = models.ManyToManyField('self',
150 | null=True,
151 | blank=True,
152 | symmetrical=False,
153 | related_name='sub_codes',
154 | verbose_name=_(u'Códigos padre'))
155 |
156 | def __unicode__(self):
157 | return self.name
158 |
159 | def html_color(self):
160 | return {
161 | 'd': 'grey',
162 | 'e': 'red',
163 | 'w': 'yellow',
164 | 's': 'green',
165 | 'i': 'blue',
166 | 'b': 'black',
167 | }.get(self.color)
168 |
169 |
170 | class Category(models.Model):
171 | CODE_COLORS = (('d', _('Grey')),
172 | ('e', _('Red')),
173 | ('w', _('Yellow')),
174 | ('s', _('Green')),
175 | ('i', _('Blue')),
176 | ('b', _('Black')),)
177 | name = models.TextField(max_length=250)
178 | color = models.CharField(max_length=1,
179 | blank=True,
180 | null=True,
181 | choices=CODE_COLORS,
182 | verbose_name=_('Color'))
183 | creation_date = models.DateTimeField(auto_now_add=True)
184 | modified_date = models.DateTimeField(auto_now=True)
185 | created_by = models.ForeignKey(User)
186 | comment = models.TextField(null=True, blank=True)
187 | project = models.ForeignKey(Project, related_name='categories')
188 | codes = models.ManyToManyField(Code, related_name='categories')
189 | citations = models.ManyToManyField(Citation, related_name='categories')
190 | documents = models.ManyToManyField(Document, related_name='categories')
191 | annotations = models.ManyToManyField(Annotation, related_name='categories')
192 |
193 |
194 | class UserProjectPermission(models.Model):
195 | PROJECT_PERMISSIONS = (('a', _('Administrator')),
196 | ('e', _('Editor')),
197 | ('g', _('Guest')),)
198 | user = models.ForeignKey(User, related_name='permissions')
199 | project = models.ForeignKey(Project, related_name='permissions')
200 | modified_date = models.DateTimeField(auto_now=True)
201 | creation_date = models.DateTimeField(auto_now_add=True)
202 | permissions = models.CharField(max_length=1, choices=PROJECT_PERMISSIONS)
203 |
204 | class Meta:
205 | unique_together = ('user', 'project')
206 |
207 | def is_admin_permission(self):
208 | return self.permissions == 'a'
209 |
210 |
211 | class BooleanQuery(models.Model):
212 | OPERATORS = (('|', _('or')),
213 | ('&', _('and')))
214 | project = models.ForeignKey(Project, related_name=_('boolean_queries'))
215 | codes = models.ManyToManyField(Code,
216 | related_name='boolean_queries',
217 | verbose_name=_(u'Códigos'))
218 | operator = models.CharField(max_length=1,
219 | choices=OPERATORS,
220 | verbose_name=_('Operadores'))
221 | name = models.CharField(max_length=250, verbose_name=_('Nombre'))
222 |
223 | def __unicode__(self):
224 | return self.name
225 |
226 | def execute(self):
227 | result_set = Set()
228 | codes = self.codes.all()
229 |
230 | for citation in Citation.objects.filter(document__project=self.project):
231 | ccodes = citation.codes.all()
232 | if self.operator == '|':
233 | tests = False
234 | for c in codes:
235 | if c in ccodes:
236 | tests = True
237 | break
238 | elif self.operator == '&':
239 | tests = True
240 | for c in codes:
241 | if c not in ccodes:
242 | tests = False
243 | break
244 | else:
245 | raise ValueError(_('Unknown operator.'))
246 |
247 | if tests:
248 | result_set.add(citation)
249 |
250 | return result_set
251 |
252 |
253 | class SemanticQuery(models.Model):
254 | OPERATORS = (('u', _('up')),
255 | ('d', _('down')),)
256 | project = models.ForeignKey(Project, related_name=_('semantic_queries'))
257 | code = models.ForeignKey(Code,
258 | related_name='semantic_operand',
259 | verbose_name=_(u'Código'))
260 | operator = models.CharField(max_length=1,
261 | choices=OPERATORS,
262 | verbose_name=_('Operador'))
263 | name = models.CharField(max_length=250, verbose_name=_('Nombre'))
264 |
265 | def __unicode__(self):
266 | return self.name
267 |
268 | def execute(self):
269 | if self.operator == 'd':
270 | return self.__execute_down()
271 | elif self.operator == 'u':
272 | return self.__execute_up()
273 | else:
274 | raise ValueError(_('Unknown operator.'))
275 |
276 | def __execute_up(self):
277 | result_set = Set()
278 |
279 | for citation in self.code.citations.all():
280 | result_set.add(citation)
281 | for parent in self.code.parent_codes.all():
282 | for citation in parent.citations.all():
283 | result_set.add(citation)
284 |
285 | return result_set
286 |
287 | def __execute_down(self):
288 | hierarchy = Set()
289 | result_set = Set()
290 |
291 | def traverse_hierarchy(code):
292 | hierarchy.add(code)
293 | for sub_code in code.sub_codes.all():
294 | if sub_code not in hierarchy:
295 | traverse_hierarchy(sub_code)
296 | traverse_hierarchy(self.code)
297 |
298 | for code in hierarchy:
299 | for citation in code.citations.all():
300 | result_set.add(citation)
301 |
302 | return result_set
303 |
304 |
305 | class ProximityQuery(models.Model):
306 | OPERATORS = (('c', _('coocurrencia')),)
307 | project = models.ForeignKey(Project, related_name=_('proximity_queries'))
308 | code1 = models.ForeignKey(Code,
309 | related_name='proximity_operand1',
310 | verbose_name=_(u'Código 1'))
311 | code2 = models.ForeignKey(Code,
312 | related_name='proximity_operand2',
313 | verbose_name=_(u'Código 2'))
314 | operator = models.CharField(max_length=1,
315 | choices=OPERATORS,
316 | verbose_name=_('Operador'))
317 | name = models.CharField(max_length=250, verbose_name=_('Nombre'))
318 |
319 | def __unicode__(self):
320 | return self.name
321 |
322 | def execute(self):
323 | if self.operator == 'c':
324 | return self.__execute_cooccurrence()
325 | else:
326 | raise ValueError(_('Unknown operator.'))
327 |
328 | def __execute_cooccurrence(self):
329 | result_set = Set()
330 |
331 | for doc in self.project.documents.all():
332 | with_c1 = self.code1.citations.filter(document=doc)
333 | with_c2 = self.code2.citations.filter(document=doc)
334 |
335 | for c in with_c1:
336 | for cc in with_c2:
337 | if c != cc and c.touches(cc):
338 | result_set.add(c)
339 | result_set.add(cc)
340 |
341 | return result_set
342 |
343 |
344 | class SetQuery(models.Model):
345 | OPERATORS = (('+', _('union')),
346 | ('^', _('intersection')))
347 | project = models.ForeignKey(Project, related_name=_('set_queries'))
348 | boolean_queries = models.ManyToManyField(BooleanQuery,
349 | blank=True,
350 | related_name='containing_queries',
351 | verbose_name=_('Consultas booleanas'))
352 | proximity_queries = models.ManyToManyField(ProximityQuery,
353 | blank=True,
354 | related_name='containing_queries',
355 | verbose_name=_('Consultas de proximidad'))
356 | semantic_queries = models.ManyToManyField(SemanticQuery,
357 | blank=True,
358 | related_name='containing_queries',
359 | verbose_name=_(u'Consultas semánticas'))
360 | operator = models.CharField(max_length=1,
361 | choices=OPERATORS,
362 | verbose_name=_('Operador'))
363 | name = models.CharField(max_length=250, verbose_name=_('Nombre'))
364 |
365 | def __unicode__(self):
366 | return self.name
367 |
368 | def __queries(self):
369 | return list(chain(self.boolean_queries.all(),
370 | self.proximity_queries.all(),
371 | self.semantic_queries.all()))
372 |
373 | def execute(self):
374 | queries = self.__queries()
375 | result_set = queries[0].execute()
376 | for q in queries[1:]:
377 | if self.operator == '+':
378 | result_set = result_set.union(q.execute())
379 | elif self.operator == '^':
380 | result_set = result_set.intersection(q.execute())
381 | else:
382 | raise ValueError(_('Unknown operator.'))
383 | return result_set
384 |
--------------------------------------------------------------------------------
/libreqda/static/lib/jquery.contextMenu/jquery.ui.position.js:
--------------------------------------------------------------------------------
1 | /*!
2 | * jQuery UI Position v1.10.0
3 | * http://jqueryui.com
4 | *
5 | * Copyright 2013 jQuery Foundation and other contributors
6 | * Released under the MIT license.
7 | * http://jquery.org/license
8 | *
9 | * http://api.jqueryui.com/position/
10 | */
11 | (function( $, undefined ) {
12 |
13 | $.ui = $.ui || {};
14 |
15 | var cachedScrollbarWidth,
16 | max = Math.max,
17 | abs = Math.abs,
18 | round = Math.round,
19 | rhorizontal = /left|center|right/,
20 | rvertical = /top|center|bottom/,
21 | roffset = /[\+\-]\d+%?/,
22 | rposition = /^\w+/,
23 | rpercent = /%$/,
24 | _position = $.fn.position;
25 |
26 | function getOffsets( offsets, width, height ) {
27 | return [
28 | parseInt( offsets[ 0 ], 10 ) * ( rpercent.test( offsets[ 0 ] ) ? width / 100 : 1 ),
29 | parseInt( offsets[ 1 ], 10 ) * ( rpercent.test( offsets[ 1 ] ) ? height / 100 : 1 )
30 | ];
31 | }
32 |
33 | function parseCss( element, property ) {
34 | return parseInt( $.css( element, property ), 10 ) || 0;
35 | }
36 |
37 | function getDimensions( elem ) {
38 | var raw = elem[0];
39 | if ( raw.nodeType === 9 ) {
40 | return {
41 | width: elem.width(),
42 | height: elem.height(),
43 | offset: { top: 0, left: 0 }
44 | };
45 | }
46 | if ( $.isWindow( raw ) ) {
47 | return {
48 | width: elem.width(),
49 | height: elem.height(),
50 | offset: { top: elem.scrollTop(), left: elem.scrollLeft() }
51 | };
52 | }
53 | if ( raw.preventDefault ) {
54 | return {
55 | width: 0,
56 | height: 0,
57 | offset: { top: raw.pageY, left: raw.pageX }
58 | };
59 | }
60 | return {
61 | width: elem.outerWidth(),
62 | height: elem.outerHeight(),
63 | offset: elem.offset()
64 | };
65 | }
66 |
67 | $.position = {
68 | scrollbarWidth: function() {
69 | if ( cachedScrollbarWidth !== undefined ) {
70 | return cachedScrollbarWidth;
71 | }
72 | var w1, w2,
73 | div = $( "" ),
74 | innerDiv = div.children()[0];
75 |
76 | $( "body" ).append( div );
77 | w1 = innerDiv.offsetWidth;
78 | div.css( "overflow", "scroll" );
79 |
80 | w2 = innerDiv.offsetWidth;
81 |
82 | if ( w1 === w2 ) {
83 | w2 = div[0].clientWidth;
84 | }
85 |
86 | div.remove();
87 |
88 | return (cachedScrollbarWidth = w1 - w2);
89 | },
90 | getScrollInfo: function( within ) {
91 | var overflowX = within.isWindow ? "" : within.element.css( "overflow-x" ),
92 | overflowY = within.isWindow ? "" : within.element.css( "overflow-y" ),
93 | hasOverflowX = overflowX === "scroll" ||
94 | ( overflowX === "auto" && within.width < within.element[0].scrollWidth ),
95 | hasOverflowY = overflowY === "scroll" ||
96 | ( overflowY === "auto" && within.height < within.element[0].scrollHeight );
97 | return {
98 | width: hasOverflowX ? $.position.scrollbarWidth() : 0,
99 | height: hasOverflowY ? $.position.scrollbarWidth() : 0
100 | };
101 | },
102 | getWithinInfo: function( element ) {
103 | var withinElement = $( element || window ),
104 | isWindow = $.isWindow( withinElement[0] );
105 | return {
106 | element: withinElement,
107 | isWindow: isWindow,
108 | offset: withinElement.offset() || { left: 0, top: 0 },
109 | scrollLeft: withinElement.scrollLeft(),
110 | scrollTop: withinElement.scrollTop(),
111 | width: isWindow ? withinElement.width() : withinElement.outerWidth(),
112 | height: isWindow ? withinElement.height() : withinElement.outerHeight()
113 | };
114 | }
115 | };
116 |
117 | $.fn.position = function( options ) {
118 | if ( !options || !options.of ) {
119 | return _position.apply( this, arguments );
120 | }
121 |
122 | // make a copy, we don't want to modify arguments
123 | options = $.extend( {}, options );
124 |
125 | var atOffset, targetWidth, targetHeight, targetOffset, basePosition, dimensions,
126 | target = $( options.of ),
127 | within = $.position.getWithinInfo( options.within ),
128 | scrollInfo = $.position.getScrollInfo( within ),
129 | collision = ( options.collision || "flip" ).split( " " ),
130 | offsets = {};
131 |
132 | dimensions = getDimensions( target );
133 | if ( target[0].preventDefault ) {
134 | // force left top to allow flipping
135 | options.at = "left top";
136 | }
137 | targetWidth = dimensions.width;
138 | targetHeight = dimensions.height;
139 | targetOffset = dimensions.offset;
140 | // clone to reuse original targetOffset later
141 | basePosition = $.extend( {}, targetOffset );
142 |
143 | // force my and at to have valid horizontal and vertical positions
144 | // if a value is missing or invalid, it will be converted to center
145 | $.each( [ "my", "at" ], function() {
146 | var pos = ( options[ this ] || "" ).split( " " ),
147 | horizontalOffset,
148 | verticalOffset;
149 |
150 | if ( pos.length === 1) {
151 | pos = rhorizontal.test( pos[ 0 ] ) ?
152 | pos.concat( [ "center" ] ) :
153 | rvertical.test( pos[ 0 ] ) ?
154 | [ "center" ].concat( pos ) :
155 | [ "center", "center" ];
156 | }
157 | pos[ 0 ] = rhorizontal.test( pos[ 0 ] ) ? pos[ 0 ] : "center";
158 | pos[ 1 ] = rvertical.test( pos[ 1 ] ) ? pos[ 1 ] : "center";
159 |
160 | // calculate offsets
161 | horizontalOffset = roffset.exec( pos[ 0 ] );
162 | verticalOffset = roffset.exec( pos[ 1 ] );
163 | offsets[ this ] = [
164 | horizontalOffset ? horizontalOffset[ 0 ] : 0,
165 | verticalOffset ? verticalOffset[ 0 ] : 0
166 | ];
167 |
168 | // reduce to just the positions without the offsets
169 | options[ this ] = [
170 | rposition.exec( pos[ 0 ] )[ 0 ],
171 | rposition.exec( pos[ 1 ] )[ 0 ]
172 | ];
173 | });
174 |
175 | // normalize collision option
176 | if ( collision.length === 1 ) {
177 | collision[ 1 ] = collision[ 0 ];
178 | }
179 |
180 | if ( options.at[ 0 ] === "right" ) {
181 | basePosition.left += targetWidth;
182 | } else if ( options.at[ 0 ] === "center" ) {
183 | basePosition.left += targetWidth / 2;
184 | }
185 |
186 | if ( options.at[ 1 ] === "bottom" ) {
187 | basePosition.top += targetHeight;
188 | } else if ( options.at[ 1 ] === "center" ) {
189 | basePosition.top += targetHeight / 2;
190 | }
191 |
192 | atOffset = getOffsets( offsets.at, targetWidth, targetHeight );
193 | basePosition.left += atOffset[ 0 ];
194 | basePosition.top += atOffset[ 1 ];
195 |
196 | return this.each(function() {
197 | var collisionPosition, using,
198 | elem = $( this ),
199 | elemWidth = elem.outerWidth(),
200 | elemHeight = elem.outerHeight(),
201 | marginLeft = parseCss( this, "marginLeft" ),
202 | marginTop = parseCss( this, "marginTop" ),
203 | collisionWidth = elemWidth + marginLeft + parseCss( this, "marginRight" ) + scrollInfo.width,
204 | collisionHeight = elemHeight + marginTop + parseCss( this, "marginBottom" ) + scrollInfo.height,
205 | position = $.extend( {}, basePosition ),
206 | myOffset = getOffsets( offsets.my, elem.outerWidth(), elem.outerHeight() );
207 |
208 | if ( options.my[ 0 ] === "right" ) {
209 | position.left -= elemWidth;
210 | } else if ( options.my[ 0 ] === "center" ) {
211 | position.left -= elemWidth / 2;
212 | }
213 |
214 | if ( options.my[ 1 ] === "bottom" ) {
215 | position.top -= elemHeight;
216 | } else if ( options.my[ 1 ] === "center" ) {
217 | position.top -= elemHeight / 2;
218 | }
219 |
220 | position.left += myOffset[ 0 ];
221 | position.top += myOffset[ 1 ];
222 |
223 | // if the browser doesn't support fractions, then round for consistent results
224 | if ( !$.support.offsetFractions ) {
225 | position.left = round( position.left );
226 | position.top = round( position.top );
227 | }
228 |
229 | collisionPosition = {
230 | marginLeft: marginLeft,
231 | marginTop: marginTop
232 | };
233 |
234 | $.each( [ "left", "top" ], function( i, dir ) {
235 | if ( $.ui.position[ collision[ i ] ] ) {
236 | $.ui.position[ collision[ i ] ][ dir ]( position, {
237 | targetWidth: targetWidth,
238 | targetHeight: targetHeight,
239 | elemWidth: elemWidth,
240 | elemHeight: elemHeight,
241 | collisionPosition: collisionPosition,
242 | collisionWidth: collisionWidth,
243 | collisionHeight: collisionHeight,
244 | offset: [ atOffset[ 0 ] + myOffset[ 0 ], atOffset [ 1 ] + myOffset[ 1 ] ],
245 | my: options.my,
246 | at: options.at,
247 | within: within,
248 | elem : elem
249 | });
250 | }
251 | });
252 |
253 | if ( options.using ) {
254 | // adds feedback as second argument to using callback, if present
255 | using = function( props ) {
256 | var left = targetOffset.left - position.left,
257 | right = left + targetWidth - elemWidth,
258 | top = targetOffset.top - position.top,
259 | bottom = top + targetHeight - elemHeight,
260 | feedback = {
261 | target: {
262 | element: target,
263 | left: targetOffset.left,
264 | top: targetOffset.top,
265 | width: targetWidth,
266 | height: targetHeight
267 | },
268 | element: {
269 | element: elem,
270 | left: position.left,
271 | top: position.top,
272 | width: elemWidth,
273 | height: elemHeight
274 | },
275 | horizontal: right < 0 ? "left" : left > 0 ? "right" : "center",
276 | vertical: bottom < 0 ? "top" : top > 0 ? "bottom" : "middle"
277 | };
278 | if ( targetWidth < elemWidth && abs( left + right ) < targetWidth ) {
279 | feedback.horizontal = "center";
280 | }
281 | if ( targetHeight < elemHeight && abs( top + bottom ) < targetHeight ) {
282 | feedback.vertical = "middle";
283 | }
284 | if ( max( abs( left ), abs( right ) ) > max( abs( top ), abs( bottom ) ) ) {
285 | feedback.important = "horizontal";
286 | } else {
287 | feedback.important = "vertical";
288 | }
289 | options.using.call( this, props, feedback );
290 | };
291 | }
292 |
293 | elem.offset( $.extend( position, { using: using } ) );
294 | });
295 | };
296 |
297 | $.ui.position = {
298 | fit: {
299 | left: function( position, data ) {
300 | var within = data.within,
301 | withinOffset = within.isWindow ? within.scrollLeft : within.offset.left,
302 | outerWidth = within.width,
303 | collisionPosLeft = position.left - data.collisionPosition.marginLeft,
304 | overLeft = withinOffset - collisionPosLeft,
305 | overRight = collisionPosLeft + data.collisionWidth - outerWidth - withinOffset,
306 | newOverRight;
307 |
308 | // element is wider than within
309 | if ( data.collisionWidth > outerWidth ) {
310 | // element is initially over the left side of within
311 | if ( overLeft > 0 && overRight <= 0 ) {
312 | newOverRight = position.left + overLeft + data.collisionWidth - outerWidth - withinOffset;
313 | position.left += overLeft - newOverRight;
314 | // element is initially over right side of within
315 | } else if ( overRight > 0 && overLeft <= 0 ) {
316 | position.left = withinOffset;
317 | // element is initially over both left and right sides of within
318 | } else {
319 | if ( overLeft > overRight ) {
320 | position.left = withinOffset + outerWidth - data.collisionWidth;
321 | } else {
322 | position.left = withinOffset;
323 | }
324 | }
325 | // too far left -> align with left edge
326 | } else if ( overLeft > 0 ) {
327 | position.left += overLeft;
328 | // too far right -> align with right edge
329 | } else if ( overRight > 0 ) {
330 | position.left -= overRight;
331 | // adjust based on position and margin
332 | } else {
333 | position.left = max( position.left - collisionPosLeft, position.left );
334 | }
335 | },
336 | top: function( position, data ) {
337 | var within = data.within,
338 | withinOffset = within.isWindow ? within.scrollTop : within.offset.top,
339 | outerHeight = data.within.height,
340 | collisionPosTop = position.top - data.collisionPosition.marginTop,
341 | overTop = withinOffset - collisionPosTop,
342 | overBottom = collisionPosTop + data.collisionHeight - outerHeight - withinOffset,
343 | newOverBottom;
344 |
345 | // element is taller than within
346 | if ( data.collisionHeight > outerHeight ) {
347 | // element is initially over the top of within
348 | if ( overTop > 0 && overBottom <= 0 ) {
349 | newOverBottom = position.top + overTop + data.collisionHeight - outerHeight - withinOffset;
350 | position.top += overTop - newOverBottom;
351 | // element is initially over bottom of within
352 | } else if ( overBottom > 0 && overTop <= 0 ) {
353 | position.top = withinOffset;
354 | // element is initially over both top and bottom of within
355 | } else {
356 | if ( overTop > overBottom ) {
357 | position.top = withinOffset + outerHeight - data.collisionHeight;
358 | } else {
359 | position.top = withinOffset;
360 | }
361 | }
362 | // too far up -> align with top
363 | } else if ( overTop > 0 ) {
364 | position.top += overTop;
365 | // too far down -> align with bottom edge
366 | } else if ( overBottom > 0 ) {
367 | position.top -= overBottom;
368 | // adjust based on position and margin
369 | } else {
370 | position.top = max( position.top - collisionPosTop, position.top );
371 | }
372 | }
373 | },
374 | flip: {
375 | left: function( position, data ) {
376 | var within = data.within,
377 | withinOffset = within.offset.left + within.scrollLeft,
378 | outerWidth = within.width,
379 | offsetLeft = within.isWindow ? within.scrollLeft : within.offset.left,
380 | collisionPosLeft = position.left - data.collisionPosition.marginLeft,
381 | overLeft = collisionPosLeft - offsetLeft,
382 | overRight = collisionPosLeft + data.collisionWidth - outerWidth - offsetLeft,
383 | myOffset = data.my[ 0 ] === "left" ?
384 | -data.elemWidth :
385 | data.my[ 0 ] === "right" ?
386 | data.elemWidth :
387 | 0,
388 | atOffset = data.at[ 0 ] === "left" ?
389 | data.targetWidth :
390 | data.at[ 0 ] === "right" ?
391 | -data.targetWidth :
392 | 0,
393 | offset = -2 * data.offset[ 0 ],
394 | newOverRight,
395 | newOverLeft;
396 |
397 | if ( overLeft < 0 ) {
398 | newOverRight = position.left + myOffset + atOffset + offset + data.collisionWidth - outerWidth - withinOffset;
399 | if ( newOverRight < 0 || newOverRight < abs( overLeft ) ) {
400 | position.left += myOffset + atOffset + offset;
401 | }
402 | }
403 | else if ( overRight > 0 ) {
404 | newOverLeft = position.left - data.collisionPosition.marginLeft + myOffset + atOffset + offset - offsetLeft;
405 | if ( newOverLeft > 0 || abs( newOverLeft ) < overRight ) {
406 | position.left += myOffset + atOffset + offset;
407 | }
408 | }
409 | },
410 | top: function( position, data ) {
411 | var within = data.within,
412 | withinOffset = within.offset.top + within.scrollTop,
413 | outerHeight = within.height,
414 | offsetTop = within.isWindow ? within.scrollTop : within.offset.top,
415 | collisionPosTop = position.top - data.collisionPosition.marginTop,
416 | overTop = collisionPosTop - offsetTop,
417 | overBottom = collisionPosTop + data.collisionHeight - outerHeight - offsetTop,
418 | top = data.my[ 1 ] === "top",
419 | myOffset = top ?
420 | -data.elemHeight :
421 | data.my[ 1 ] === "bottom" ?
422 | data.elemHeight :
423 | 0,
424 | atOffset = data.at[ 1 ] === "top" ?
425 | data.targetHeight :
426 | data.at[ 1 ] === "bottom" ?
427 | -data.targetHeight :
428 | 0,
429 | offset = -2 * data.offset[ 1 ],
430 | newOverTop,
431 | newOverBottom;
432 | if ( overTop < 0 ) {
433 | newOverBottom = position.top + myOffset + atOffset + offset + data.collisionHeight - outerHeight - withinOffset;
434 | if ( ( position.top + myOffset + atOffset + offset) > overTop && ( newOverBottom < 0 || newOverBottom < abs( overTop ) ) ) {
435 | position.top += myOffset + atOffset + offset;
436 | }
437 | }
438 | else if ( overBottom > 0 ) {
439 | newOverTop = position.top - data.collisionPosition.marginTop + myOffset + atOffset + offset - offsetTop;
440 | if ( ( position.top + myOffset + atOffset + offset) > overBottom && ( newOverTop > 0 || abs( newOverTop ) < overBottom ) ) {
441 | position.top += myOffset + atOffset + offset;
442 | }
443 | }
444 | }
445 | },
446 | flipfit: {
447 | left: function() {
448 | $.ui.position.flip.left.apply( this, arguments );
449 | $.ui.position.fit.left.apply( this, arguments );
450 | },
451 | top: function() {
452 | $.ui.position.flip.top.apply( this, arguments );
453 | $.ui.position.fit.top.apply( this, arguments );
454 | }
455 | }
456 | };
457 |
458 | // fraction support test
459 | (function () {
460 | var testElement, testElementParent, testElementStyle, offsetLeft, i,
461 | body = document.getElementsByTagName( "body" )[ 0 ],
462 | div = document.createElement( "div" );
463 |
464 | //Create a "fake body" for testing based on method used in jQuery.support
465 | testElement = document.createElement( body ? "div" : "body" );
466 | testElementStyle = {
467 | visibility: "hidden",
468 | width: 0,
469 | height: 0,
470 | border: 0,
471 | margin: 0,
472 | background: "none"
473 | };
474 | if ( body ) {
475 | $.extend( testElementStyle, {
476 | position: "absolute",
477 | left: "-1000px",
478 | top: "-1000px"
479 | });
480 | }
481 | for ( i in testElementStyle ) {
482 | testElement.style[ i ] = testElementStyle[ i ];
483 | }
484 | testElement.appendChild( div );
485 | testElementParent = body || document.documentElement;
486 | testElementParent.insertBefore( testElement, testElementParent.firstChild );
487 |
488 | div.style.cssText = "position: absolute; left: 10.7432222px;";
489 |
490 | offsetLeft = $( div ).offset().left;
491 | $.support.offsetFractions = offsetLeft > 10 && offsetLeft < 11;
492 |
493 | testElement.innerHTML = "";
494 | testElementParent.removeChild( testElement );
495 | })();
496 |
497 | }( jQuery ) );
498 |
--------------------------------------------------------------------------------
/libreqda/static/lib/bootstrap/css/bootstrap-responsive.css:
--------------------------------------------------------------------------------
1 | /*!
2 | * Bootstrap Responsive v2.2.2
3 | *
4 | * Copyright 2012 Twitter, Inc
5 | * Licensed under the Apache License v2.0
6 | * http://www.apache.org/licenses/LICENSE-2.0
7 | *
8 | * Designed and built with all the love in the world @twitter by @mdo and @fat.
9 | */
10 |
11 | @-ms-viewport {
12 | width: device-width;
13 | }
14 |
15 | .clearfix {
16 | *zoom: 1;
17 | }
18 |
19 | .clearfix:before,
20 | .clearfix:after {
21 | display: table;
22 | line-height: 0;
23 | content: "";
24 | }
25 |
26 | .clearfix:after {
27 | clear: both;
28 | }
29 |
30 | .hide-text {
31 | font: 0/0 a;
32 | color: transparent;
33 | text-shadow: none;
34 | background-color: transparent;
35 | border: 0;
36 | }
37 |
38 | .input-block-level {
39 | display: block;
40 | width: 100%;
41 | min-height: 30px;
42 | -webkit-box-sizing: border-box;
43 | -moz-box-sizing: border-box;
44 | box-sizing: border-box;
45 | }
46 |
47 | .hidden {
48 | display: none;
49 | visibility: hidden;
50 | }
51 |
52 | .visible-phone {
53 | display: none !important;
54 | }
55 |
56 | .visible-tablet {
57 | display: none !important;
58 | }
59 |
60 | .hidden-desktop {
61 | display: none !important;
62 | }
63 |
64 | .visible-desktop {
65 | display: inherit !important;
66 | }
67 |
68 | @media (min-width: 768px) and (max-width: 979px) {
69 | .hidden-desktop {
70 | display: inherit !important;
71 | }
72 | .visible-desktop {
73 | display: none !important ;
74 | }
75 | .visible-tablet {
76 | display: inherit !important;
77 | }
78 | .hidden-tablet {
79 | display: none !important;
80 | }
81 | }
82 |
83 | @media (max-width: 767px) {
84 | .hidden-desktop {
85 | display: inherit !important;
86 | }
87 | .visible-desktop {
88 | display: none !important;
89 | }
90 | .visible-phone {
91 | display: inherit !important;
92 | }
93 | .hidden-phone {
94 | display: none !important;
95 | }
96 | }
97 |
98 | @media (min-width: 1200px) {
99 | .row {
100 | margin-left: -30px;
101 | *zoom: 1;
102 | }
103 | .row:before,
104 | .row:after {
105 | display: table;
106 | line-height: 0;
107 | content: "";
108 | }
109 | .row:after {
110 | clear: both;
111 | }
112 | [class*="span"] {
113 | float: left;
114 | min-height: 1px;
115 | margin-left: 30px;
116 | }
117 | .container,
118 | .navbar-static-top .container,
119 | .navbar-fixed-top .container,
120 | .navbar-fixed-bottom .container {
121 | width: 1170px;
122 | }
123 | .span12 {
124 | width: 1170px;
125 | }
126 | .span11 {
127 | width: 1070px;
128 | }
129 | .span10 {
130 | width: 970px;
131 | }
132 | .span9 {
133 | width: 870px;
134 | }
135 | .span8 {
136 | width: 770px;
137 | }
138 | .span7 {
139 | width: 670px;
140 | }
141 | .span6 {
142 | width: 570px;
143 | }
144 | .span5 {
145 | width: 470px;
146 | }
147 | .span4 {
148 | width: 370px;
149 | }
150 | .span3 {
151 | width: 270px;
152 | }
153 | .span2 {
154 | width: 170px;
155 | }
156 | .span1 {
157 | width: 70px;
158 | }
159 | .offset12 {
160 | margin-left: 1230px;
161 | }
162 | .offset11 {
163 | margin-left: 1130px;
164 | }
165 | .offset10 {
166 | margin-left: 1030px;
167 | }
168 | .offset9 {
169 | margin-left: 930px;
170 | }
171 | .offset8 {
172 | margin-left: 830px;
173 | }
174 | .offset7 {
175 | margin-left: 730px;
176 | }
177 | .offset6 {
178 | margin-left: 630px;
179 | }
180 | .offset5 {
181 | margin-left: 530px;
182 | }
183 | .offset4 {
184 | margin-left: 430px;
185 | }
186 | .offset3 {
187 | margin-left: 330px;
188 | }
189 | .offset2 {
190 | margin-left: 230px;
191 | }
192 | .offset1 {
193 | margin-left: 130px;
194 | }
195 | .row-fluid {
196 | width: 100%;
197 | *zoom: 1;
198 | }
199 | .row-fluid:before,
200 | .row-fluid:after {
201 | display: table;
202 | line-height: 0;
203 | content: "";
204 | }
205 | .row-fluid:after {
206 | clear: both;
207 | }
208 | .row-fluid [class*="span"] {
209 | display: block;
210 | float: left;
211 | width: 100%;
212 | min-height: 30px;
213 | margin-left: 2.564102564102564%;
214 | *margin-left: 2.5109110747408616%;
215 | -webkit-box-sizing: border-box;
216 | -moz-box-sizing: border-box;
217 | box-sizing: border-box;
218 | }
219 | .row-fluid [class*="span"]:first-child {
220 | margin-left: 0;
221 | }
222 | .row-fluid .controls-row [class*="span"] + [class*="span"] {
223 | margin-left: 2.564102564102564%;
224 | }
225 | .row-fluid .span12 {
226 | width: 100%;
227 | *width: 99.94680851063829%;
228 | }
229 | .row-fluid .span11 {
230 | width: 91.45299145299145%;
231 | *width: 91.39979996362975%;
232 | }
233 | .row-fluid .span10 {
234 | width: 82.90598290598291%;
235 | *width: 82.8527914166212%;
236 | }
237 | .row-fluid .span9 {
238 | width: 74.35897435897436%;
239 | *width: 74.30578286961266%;
240 | }
241 | .row-fluid .span8 {
242 | width: 65.81196581196582%;
243 | *width: 65.75877432260411%;
244 | }
245 | .row-fluid .span7 {
246 | width: 57.26495726495726%;
247 | *width: 57.21176577559556%;
248 | }
249 | .row-fluid .span6 {
250 | width: 48.717948717948715%;
251 | *width: 48.664757228587014%;
252 | }
253 | .row-fluid .span5 {
254 | width: 40.17094017094017%;
255 | *width: 40.11774868157847%;
256 | }
257 | .row-fluid .span4 {
258 | width: 31.623931623931625%;
259 | *width: 31.570740134569924%;
260 | }
261 | .row-fluid .span3 {
262 | width: 23.076923076923077%;
263 | *width: 23.023731587561375%;
264 | }
265 | .row-fluid .span2 {
266 | width: 14.52991452991453%;
267 | *width: 14.476723040552828%;
268 | }
269 | .row-fluid .span1 {
270 | width: 5.982905982905983%;
271 | *width: 5.929714493544281%;
272 | }
273 | .row-fluid .offset12 {
274 | margin-left: 105.12820512820512%;
275 | *margin-left: 105.02182214948171%;
276 | }
277 | .row-fluid .offset12:first-child {
278 | margin-left: 102.56410256410257%;
279 | *margin-left: 102.45771958537915%;
280 | }
281 | .row-fluid .offset11 {
282 | margin-left: 96.58119658119658%;
283 | *margin-left: 96.47481360247316%;
284 | }
285 | .row-fluid .offset11:first-child {
286 | margin-left: 94.01709401709402%;
287 | *margin-left: 93.91071103837061%;
288 | }
289 | .row-fluid .offset10 {
290 | margin-left: 88.03418803418803%;
291 | *margin-left: 87.92780505546462%;
292 | }
293 | .row-fluid .offset10:first-child {
294 | margin-left: 85.47008547008548%;
295 | *margin-left: 85.36370249136206%;
296 | }
297 | .row-fluid .offset9 {
298 | margin-left: 79.48717948717949%;
299 | *margin-left: 79.38079650845607%;
300 | }
301 | .row-fluid .offset9:first-child {
302 | margin-left: 76.92307692307693%;
303 | *margin-left: 76.81669394435352%;
304 | }
305 | .row-fluid .offset8 {
306 | margin-left: 70.94017094017094%;
307 | *margin-left: 70.83378796144753%;
308 | }
309 | .row-fluid .offset8:first-child {
310 | margin-left: 68.37606837606839%;
311 | *margin-left: 68.26968539734497%;
312 | }
313 | .row-fluid .offset7 {
314 | margin-left: 62.393162393162385%;
315 | *margin-left: 62.28677941443899%;
316 | }
317 | .row-fluid .offset7:first-child {
318 | margin-left: 59.82905982905982%;
319 | *margin-left: 59.72267685033642%;
320 | }
321 | .row-fluid .offset6 {
322 | margin-left: 53.84615384615384%;
323 | *margin-left: 53.739770867430444%;
324 | }
325 | .row-fluid .offset6:first-child {
326 | margin-left: 51.28205128205128%;
327 | *margin-left: 51.175668303327875%;
328 | }
329 | .row-fluid .offset5 {
330 | margin-left: 45.299145299145295%;
331 | *margin-left: 45.1927623204219%;
332 | }
333 | .row-fluid .offset5:first-child {
334 | margin-left: 42.73504273504273%;
335 | *margin-left: 42.62865975631933%;
336 | }
337 | .row-fluid .offset4 {
338 | margin-left: 36.75213675213675%;
339 | *margin-left: 36.645753773413354%;
340 | }
341 | .row-fluid .offset4:first-child {
342 | margin-left: 34.18803418803419%;
343 | *margin-left: 34.081651209310785%;
344 | }
345 | .row-fluid .offset3 {
346 | margin-left: 28.205128205128204%;
347 | *margin-left: 28.0987452264048%;
348 | }
349 | .row-fluid .offset3:first-child {
350 | margin-left: 25.641025641025642%;
351 | *margin-left: 25.53464266230224%;
352 | }
353 | .row-fluid .offset2 {
354 | margin-left: 19.65811965811966%;
355 | *margin-left: 19.551736679396257%;
356 | }
357 | .row-fluid .offset2:first-child {
358 | margin-left: 17.094017094017094%;
359 | *margin-left: 16.98763411529369%;
360 | }
361 | .row-fluid .offset1 {
362 | margin-left: 11.11111111111111%;
363 | *margin-left: 11.004728132387708%;
364 | }
365 | .row-fluid .offset1:first-child {
366 | margin-left: 8.547008547008547%;
367 | *margin-left: 8.440625568285142%;
368 | }
369 | input,
370 | textarea,
371 | .uneditable-input {
372 | margin-left: 0;
373 | }
374 | .controls-row [class*="span"] + [class*="span"] {
375 | margin-left: 30px;
376 | }
377 | input.span12,
378 | textarea.span12,
379 | .uneditable-input.span12 {
380 | width: 1156px;
381 | }
382 | input.span11,
383 | textarea.span11,
384 | .uneditable-input.span11 {
385 | width: 1056px;
386 | }
387 | input.span10,
388 | textarea.span10,
389 | .uneditable-input.span10 {
390 | width: 956px;
391 | }
392 | input.span9,
393 | textarea.span9,
394 | .uneditable-input.span9 {
395 | width: 856px;
396 | }
397 | input.span8,
398 | textarea.span8,
399 | .uneditable-input.span8 {
400 | width: 756px;
401 | }
402 | input.span7,
403 | textarea.span7,
404 | .uneditable-input.span7 {
405 | width: 656px;
406 | }
407 | input.span6,
408 | textarea.span6,
409 | .uneditable-input.span6 {
410 | width: 556px;
411 | }
412 | input.span5,
413 | textarea.span5,
414 | .uneditable-input.span5 {
415 | width: 456px;
416 | }
417 | input.span4,
418 | textarea.span4,
419 | .uneditable-input.span4 {
420 | width: 356px;
421 | }
422 | input.span3,
423 | textarea.span3,
424 | .uneditable-input.span3 {
425 | width: 256px;
426 | }
427 | input.span2,
428 | textarea.span2,
429 | .uneditable-input.span2 {
430 | width: 156px;
431 | }
432 | input.span1,
433 | textarea.span1,
434 | .uneditable-input.span1 {
435 | width: 56px;
436 | }
437 | .thumbnails {
438 | margin-left: -30px;
439 | }
440 | .thumbnails > li {
441 | margin-left: 30px;
442 | }
443 | .row-fluid .thumbnails {
444 | margin-left: 0;
445 | }
446 | }
447 |
448 | @media (min-width: 768px) and (max-width: 979px) {
449 | .row {
450 | margin-left: -20px;
451 | *zoom: 1;
452 | }
453 | .row:before,
454 | .row:after {
455 | display: table;
456 | line-height: 0;
457 | content: "";
458 | }
459 | .row:after {
460 | clear: both;
461 | }
462 | [class*="span"] {
463 | float: left;
464 | min-height: 1px;
465 | margin-left: 20px;
466 | }
467 | .container,
468 | .navbar-static-top .container,
469 | .navbar-fixed-top .container,
470 | .navbar-fixed-bottom .container {
471 | width: 724px;
472 | }
473 | .span12 {
474 | width: 724px;
475 | }
476 | .span11 {
477 | width: 662px;
478 | }
479 | .span10 {
480 | width: 600px;
481 | }
482 | .span9 {
483 | width: 538px;
484 | }
485 | .span8 {
486 | width: 476px;
487 | }
488 | .span7 {
489 | width: 414px;
490 | }
491 | .span6 {
492 | width: 352px;
493 | }
494 | .span5 {
495 | width: 290px;
496 | }
497 | .span4 {
498 | width: 228px;
499 | }
500 | .span3 {
501 | width: 166px;
502 | }
503 | .span2 {
504 | width: 104px;
505 | }
506 | .span1 {
507 | width: 42px;
508 | }
509 | .offset12 {
510 | margin-left: 764px;
511 | }
512 | .offset11 {
513 | margin-left: 702px;
514 | }
515 | .offset10 {
516 | margin-left: 640px;
517 | }
518 | .offset9 {
519 | margin-left: 578px;
520 | }
521 | .offset8 {
522 | margin-left: 516px;
523 | }
524 | .offset7 {
525 | margin-left: 454px;
526 | }
527 | .offset6 {
528 | margin-left: 392px;
529 | }
530 | .offset5 {
531 | margin-left: 330px;
532 | }
533 | .offset4 {
534 | margin-left: 268px;
535 | }
536 | .offset3 {
537 | margin-left: 206px;
538 | }
539 | .offset2 {
540 | margin-left: 144px;
541 | }
542 | .offset1 {
543 | margin-left: 82px;
544 | }
545 | .row-fluid {
546 | width: 100%;
547 | *zoom: 1;
548 | }
549 | .row-fluid:before,
550 | .row-fluid:after {
551 | display: table;
552 | line-height: 0;
553 | content: "";
554 | }
555 | .row-fluid:after {
556 | clear: both;
557 | }
558 | .row-fluid [class*="span"] {
559 | display: block;
560 | float: left;
561 | width: 100%;
562 | min-height: 30px;
563 | margin-left: 2.7624309392265194%;
564 | *margin-left: 2.709239449864817%;
565 | -webkit-box-sizing: border-box;
566 | -moz-box-sizing: border-box;
567 | box-sizing: border-box;
568 | }
569 | .row-fluid [class*="span"]:first-child {
570 | margin-left: 0;
571 | }
572 | .row-fluid .controls-row [class*="span"] + [class*="span"] {
573 | margin-left: 2.7624309392265194%;
574 | }
575 | .row-fluid .span12 {
576 | width: 100%;
577 | *width: 99.94680851063829%;
578 | }
579 | .row-fluid .span11 {
580 | width: 91.43646408839778%;
581 | *width: 91.38327259903608%;
582 | }
583 | .row-fluid .span10 {
584 | width: 82.87292817679558%;
585 | *width: 82.81973668743387%;
586 | }
587 | .row-fluid .span9 {
588 | width: 74.30939226519337%;
589 | *width: 74.25620077583166%;
590 | }
591 | .row-fluid .span8 {
592 | width: 65.74585635359117%;
593 | *width: 65.69266486422946%;
594 | }
595 | .row-fluid .span7 {
596 | width: 57.18232044198895%;
597 | *width: 57.12912895262725%;
598 | }
599 | .row-fluid .span6 {
600 | width: 48.61878453038674%;
601 | *width: 48.56559304102504%;
602 | }
603 | .row-fluid .span5 {
604 | width: 40.05524861878453%;
605 | *width: 40.00205712942283%;
606 | }
607 | .row-fluid .span4 {
608 | width: 31.491712707182323%;
609 | *width: 31.43852121782062%;
610 | }
611 | .row-fluid .span3 {
612 | width: 22.92817679558011%;
613 | *width: 22.87498530621841%;
614 | }
615 | .row-fluid .span2 {
616 | width: 14.3646408839779%;
617 | *width: 14.311449394616199%;
618 | }
619 | .row-fluid .span1 {
620 | width: 5.801104972375691%;
621 | *width: 5.747913483013988%;
622 | }
623 | .row-fluid .offset12 {
624 | margin-left: 105.52486187845304%;
625 | *margin-left: 105.41847889972962%;
626 | }
627 | .row-fluid .offset12:first-child {
628 | margin-left: 102.76243093922652%;
629 | *margin-left: 102.6560479605031%;
630 | }
631 | .row-fluid .offset11 {
632 | margin-left: 96.96132596685082%;
633 | *margin-left: 96.8549429881274%;
634 | }
635 | .row-fluid .offset11:first-child {
636 | margin-left: 94.1988950276243%;
637 | *margin-left: 94.09251204890089%;
638 | }
639 | .row-fluid .offset10 {
640 | margin-left: 88.39779005524862%;
641 | *margin-left: 88.2914070765252%;
642 | }
643 | .row-fluid .offset10:first-child {
644 | margin-left: 85.6353591160221%;
645 | *margin-left: 85.52897613729868%;
646 | }
647 | .row-fluid .offset9 {
648 | margin-left: 79.8342541436464%;
649 | *margin-left: 79.72787116492299%;
650 | }
651 | .row-fluid .offset9:first-child {
652 | margin-left: 77.07182320441989%;
653 | *margin-left: 76.96544022569647%;
654 | }
655 | .row-fluid .offset8 {
656 | margin-left: 71.2707182320442%;
657 | *margin-left: 71.16433525332079%;
658 | }
659 | .row-fluid .offset8:first-child {
660 | margin-left: 68.50828729281768%;
661 | *margin-left: 68.40190431409427%;
662 | }
663 | .row-fluid .offset7 {
664 | margin-left: 62.70718232044199%;
665 | *margin-left: 62.600799341718584%;
666 | }
667 | .row-fluid .offset7:first-child {
668 | margin-left: 59.94475138121547%;
669 | *margin-left: 59.838368402492065%;
670 | }
671 | .row-fluid .offset6 {
672 | margin-left: 54.14364640883978%;
673 | *margin-left: 54.037263430116376%;
674 | }
675 | .row-fluid .offset6:first-child {
676 | margin-left: 51.38121546961326%;
677 | *margin-left: 51.27483249088986%;
678 | }
679 | .row-fluid .offset5 {
680 | margin-left: 45.58011049723757%;
681 | *margin-left: 45.47372751851417%;
682 | }
683 | .row-fluid .offset5:first-child {
684 | margin-left: 42.81767955801105%;
685 | *margin-left: 42.71129657928765%;
686 | }
687 | .row-fluid .offset4 {
688 | margin-left: 37.01657458563536%;
689 | *margin-left: 36.91019160691196%;
690 | }
691 | .row-fluid .offset4:first-child {
692 | margin-left: 34.25414364640884%;
693 | *margin-left: 34.14776066768544%;
694 | }
695 | .row-fluid .offset3 {
696 | margin-left: 28.45303867403315%;
697 | *margin-left: 28.346655695309746%;
698 | }
699 | .row-fluid .offset3:first-child {
700 | margin-left: 25.69060773480663%;
701 | *margin-left: 25.584224756083227%;
702 | }
703 | .row-fluid .offset2 {
704 | margin-left: 19.88950276243094%;
705 | *margin-left: 19.783119783707537%;
706 | }
707 | .row-fluid .offset2:first-child {
708 | margin-left: 17.12707182320442%;
709 | *margin-left: 17.02068884448102%;
710 | }
711 | .row-fluid .offset1 {
712 | margin-left: 11.32596685082873%;
713 | *margin-left: 11.219583872105325%;
714 | }
715 | .row-fluid .offset1:first-child {
716 | margin-left: 8.56353591160221%;
717 | *margin-left: 8.457152932878806%;
718 | }
719 | input,
720 | textarea,
721 | .uneditable-input {
722 | margin-left: 0;
723 | }
724 | .controls-row [class*="span"] + [class*="span"] {
725 | margin-left: 20px;
726 | }
727 | input.span12,
728 | textarea.span12,
729 | .uneditable-input.span12 {
730 | width: 710px;
731 | }
732 | input.span11,
733 | textarea.span11,
734 | .uneditable-input.span11 {
735 | width: 648px;
736 | }
737 | input.span10,
738 | textarea.span10,
739 | .uneditable-input.span10 {
740 | width: 586px;
741 | }
742 | input.span9,
743 | textarea.span9,
744 | .uneditable-input.span9 {
745 | width: 524px;
746 | }
747 | input.span8,
748 | textarea.span8,
749 | .uneditable-input.span8 {
750 | width: 462px;
751 | }
752 | input.span7,
753 | textarea.span7,
754 | .uneditable-input.span7 {
755 | width: 400px;
756 | }
757 | input.span6,
758 | textarea.span6,
759 | .uneditable-input.span6 {
760 | width: 338px;
761 | }
762 | input.span5,
763 | textarea.span5,
764 | .uneditable-input.span5 {
765 | width: 276px;
766 | }
767 | input.span4,
768 | textarea.span4,
769 | .uneditable-input.span4 {
770 | width: 214px;
771 | }
772 | input.span3,
773 | textarea.span3,
774 | .uneditable-input.span3 {
775 | width: 152px;
776 | }
777 | input.span2,
778 | textarea.span2,
779 | .uneditable-input.span2 {
780 | width: 90px;
781 | }
782 | input.span1,
783 | textarea.span1,
784 | .uneditable-input.span1 {
785 | width: 28px;
786 | }
787 | }
788 |
789 | @media (max-width: 767px) {
790 | body {
791 | padding-right: 20px;
792 | padding-left: 20px;
793 | }
794 | .navbar-fixed-top,
795 | .navbar-fixed-bottom,
796 | .navbar-static-top {
797 | margin-right: -20px;
798 | margin-left: -20px;
799 | }
800 | .container-fluid {
801 | padding: 0;
802 | }
803 | .dl-horizontal dt {
804 | float: none;
805 | width: auto;
806 | clear: none;
807 | text-align: left;
808 | }
809 | .dl-horizontal dd {
810 | margin-left: 0;
811 | }
812 | .container {
813 | width: auto;
814 | }
815 | .row-fluid {
816 | width: 100%;
817 | }
818 | .row,
819 | .thumbnails {
820 | margin-left: 0;
821 | }
822 | .thumbnails > li {
823 | float: none;
824 | margin-left: 0;
825 | }
826 | [class*="span"],
827 | .uneditable-input[class*="span"],
828 | .row-fluid [class*="span"] {
829 | display: block;
830 | float: none;
831 | width: 100%;
832 | margin-left: 0;
833 | -webkit-box-sizing: border-box;
834 | -moz-box-sizing: border-box;
835 | box-sizing: border-box;
836 | }
837 | .span12,
838 | .row-fluid .span12 {
839 | width: 100%;
840 | -webkit-box-sizing: border-box;
841 | -moz-box-sizing: border-box;
842 | box-sizing: border-box;
843 | }
844 | .row-fluid [class*="offset"]:first-child {
845 | margin-left: 0;
846 | }
847 | .input-large,
848 | .input-xlarge,
849 | .input-xxlarge,
850 | input[class*="span"],
851 | select[class*="span"],
852 | textarea[class*="span"],
853 | .uneditable-input {
854 | display: block;
855 | width: 100%;
856 | min-height: 30px;
857 | -webkit-box-sizing: border-box;
858 | -moz-box-sizing: border-box;
859 | box-sizing: border-box;
860 | }
861 | .input-prepend input,
862 | .input-append input,
863 | .input-prepend input[class*="span"],
864 | .input-append input[class*="span"] {
865 | display: inline-block;
866 | width: auto;
867 | }
868 | .controls-row [class*="span"] + [class*="span"] {
869 | margin-left: 0;
870 | }
871 | .modal {
872 | position: fixed;
873 | top: 20px;
874 | right: 20px;
875 | left: 20px;
876 | width: auto;
877 | margin: 0;
878 | }
879 | .modal.fade {
880 | top: -100px;
881 | }
882 | .modal.fade.in {
883 | top: 20px;
884 | }
885 | }
886 |
887 | @media (max-width: 480px) {
888 | .nav-collapse {
889 | -webkit-transform: translate3d(0, 0, 0);
890 | }
891 | .page-header h1 small {
892 | display: block;
893 | line-height: 20px;
894 | }
895 | input[type="checkbox"],
896 | input[type="radio"] {
897 | border: 1px solid #ccc;
898 | }
899 | .form-horizontal .control-label {
900 | float: none;
901 | width: auto;
902 | padding-top: 0;
903 | text-align: left;
904 | }
905 | .form-horizontal .controls {
906 | margin-left: 0;
907 | }
908 | .form-horizontal .control-list {
909 | padding-top: 0;
910 | }
911 | .form-horizontal .form-actions {
912 | padding-right: 10px;
913 | padding-left: 10px;
914 | }
915 | .media .pull-left,
916 | .media .pull-right {
917 | display: block;
918 | float: none;
919 | margin-bottom: 10px;
920 | }
921 | .media-object {
922 | margin-right: 0;
923 | margin-left: 0;
924 | }
925 | .modal {
926 | top: 10px;
927 | right: 10px;
928 | left: 10px;
929 | }
930 | .modal-header .close {
931 | padding: 10px;
932 | margin: -10px;
933 | }
934 | .carousel-caption {
935 | position: static;
936 | }
937 | }
938 |
939 | @media (max-width: 979px) {
940 | body {
941 | padding-top: 0;
942 | }
943 | .navbar-fixed-top,
944 | .navbar-fixed-bottom {
945 | position: static;
946 | }
947 | .navbar-fixed-top {
948 | margin-bottom: 20px;
949 | }
950 | .navbar-fixed-bottom {
951 | margin-top: 20px;
952 | }
953 | .navbar-fixed-top .navbar-inner,
954 | .navbar-fixed-bottom .navbar-inner {
955 | padding: 5px;
956 | }
957 | .navbar .container {
958 | width: auto;
959 | padding: 0;
960 | }
961 | .navbar .brand {
962 | padding-right: 10px;
963 | padding-left: 10px;
964 | margin: 0 0 0 -5px;
965 | }
966 | .nav-collapse {
967 | clear: both;
968 | }
969 | .nav-collapse .nav {
970 | float: none;
971 | margin: 0 0 10px;
972 | }
973 | .nav-collapse .nav > li {
974 | float: none;
975 | }
976 | .nav-collapse .nav > li > a {
977 | margin-bottom: 2px;
978 | }
979 | .nav-collapse .nav > .divider-vertical {
980 | display: none;
981 | }
982 | .nav-collapse .nav .nav-header {
983 | color: #777777;
984 | text-shadow: none;
985 | }
986 | .nav-collapse .nav > li > a,
987 | .nav-collapse .dropdown-menu a {
988 | padding: 9px 15px;
989 | font-weight: bold;
990 | color: #777777;
991 | -webkit-border-radius: 3px;
992 | -moz-border-radius: 3px;
993 | border-radius: 3px;
994 | }
995 | .nav-collapse .btn {
996 | padding: 4px 10px 4px;
997 | font-weight: normal;
998 | -webkit-border-radius: 4px;
999 | -moz-border-radius: 4px;
1000 | border-radius: 4px;
1001 | }
1002 | .nav-collapse .dropdown-menu li + li a {
1003 | margin-bottom: 2px;
1004 | }
1005 | .nav-collapse .nav > li > a:hover,
1006 | .nav-collapse .dropdown-menu a:hover {
1007 | background-color: #f2f2f2;
1008 | }
1009 | .navbar-inverse .nav-collapse .nav > li > a,
1010 | .navbar-inverse .nav-collapse .dropdown-menu a {
1011 | color: #999999;
1012 | }
1013 | .navbar-inverse .nav-collapse .nav > li > a:hover,
1014 | .navbar-inverse .nav-collapse .dropdown-menu a:hover {
1015 | background-color: #111111;
1016 | }
1017 | .nav-collapse.in .btn-group {
1018 | padding: 0;
1019 | margin-top: 5px;
1020 | }
1021 | .nav-collapse .dropdown-menu {
1022 | position: static;
1023 | top: auto;
1024 | left: auto;
1025 | display: none;
1026 | float: none;
1027 | max-width: none;
1028 | padding: 0;
1029 | margin: 0 15px;
1030 | background-color: transparent;
1031 | border: none;
1032 | -webkit-border-radius: 0;
1033 | -moz-border-radius: 0;
1034 | border-radius: 0;
1035 | -webkit-box-shadow: none;
1036 | -moz-box-shadow: none;
1037 | box-shadow: none;
1038 | }
1039 | .nav-collapse .open > .dropdown-menu {
1040 | display: block;
1041 | }
1042 | .nav-collapse .dropdown-menu:before,
1043 | .nav-collapse .dropdown-menu:after {
1044 | display: none;
1045 | }
1046 | .nav-collapse .dropdown-menu .divider {
1047 | display: none;
1048 | }
1049 | .nav-collapse .nav > li > .dropdown-menu:before,
1050 | .nav-collapse .nav > li > .dropdown-menu:after {
1051 | display: none;
1052 | }
1053 | .nav-collapse .navbar-form,
1054 | .nav-collapse .navbar-search {
1055 | float: none;
1056 | padding: 10px 15px;
1057 | margin: 10px 0;
1058 | border-top: 1px solid #f2f2f2;
1059 | border-bottom: 1px solid #f2f2f2;
1060 | -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1);
1061 | -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1);
1062 | box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1);
1063 | }
1064 | .navbar-inverse .nav-collapse .navbar-form,
1065 | .navbar-inverse .nav-collapse .navbar-search {
1066 | border-top-color: #111111;
1067 | border-bottom-color: #111111;
1068 | }
1069 | .navbar .nav-collapse .nav.pull-right {
1070 | float: none;
1071 | margin-left: 0;
1072 | }
1073 | .nav-collapse,
1074 | .nav-collapse.collapse {
1075 | height: 0;
1076 | overflow: hidden;
1077 | }
1078 | .navbar .btn-navbar {
1079 | display: block;
1080 | }
1081 | .navbar-static .navbar-inner {
1082 | padding-right: 10px;
1083 | padding-left: 10px;
1084 | }
1085 | }
1086 |
1087 | @media (min-width: 980px) {
1088 | .nav-collapse.collapse {
1089 | height: auto !important;
1090 | overflow: visible !important;
1091 | }
1092 | }
1093 |
--------------------------------------------------------------------------------