# HG changeset patch # User ymh # Date 1381484778 -7200 # Node ID 7c6fe1dab2134edf95db900d89ac0497755751ec # Parent 8c32ea1310de679d3479a1aaf80b14a00afffb86 Add a screen in the admin to launch commands. Fix bug #4 (https://github.com/IRI-Research/plan4learning/issues/4). diff -r 8c32ea1310de -r 7c6fe1dab213 doc/administration.rst --- a/doc/administration.rst Tue Oct 08 17:25:39 2013 +0200 +++ b/doc/administration.rst Fri Oct 11 11:46:18 2013 +0200 @@ -27,7 +27,7 @@ Commande d'administration ========================= -Voici une liste des commandes ser vant à gérer l'import et l'export des notices (``Record``). +Voici une liste des commandes servant à gérer l'import et l'export des notices (``Record``). .. _admin-import-record: @@ -242,13 +242,16 @@ Cette commande est fournie par le module Django ``Haystack``. Sa documentation se trouve à l'adresse suivante : http://django-haystack.readthedocs.org/en/v2.1.0/management_commands.html -console d'administration / gestion des utilisateurs -=================================================== +console d'administration +======================== Le back-office offre une console d'administration donnant accès en particulier à la gestion des utilisateurs. On y accède par le lien ``admin`` dans l'en-tête des pages si on est connecté en tant qu'administrateur ou bien en allant directement à l'adresse ``/p4l/admin/``. +gestion des utilisateurs +------------------------ + L'administration des utilisateurs se fait à l'adresse suivante : ``/p4l/admin/p4l/user/``. L'administration des groupes d'utilisateurs se fait à l'adresse suivante: ``/p4l/admin/auth/group/``. @@ -263,4 +266,45 @@ Pour faciliter la gestion de ces permissions, le plus simple est de créer un groupe ``utilisateurs``. On affectera à ce groupe toutes les permissions sur les objects de l'application ``p4l``. il suffira ensuite de mettre les utilisateurs dans ce groupe (champ ``Groupes`` dans l'interface d'édition des utilisateurs). L'utilisateur héritera alors des parmissions du groupe. - + + +Lancement d'un script +--------------------- +Il est possible de lancer un script à partir de l'adresse suivante : ``/p4l/admin/confirm_script``. + +Le script qui est exécuté est configuré par la propriété ``ADMIN_SCRIPT`` dans la configuration de l'application (``src/p4l/config.py``). +Cette propriété est un dictionnaire dont les clés sont les arguments du constructeur de subprocess.Popen. +Tous les arguments et le fonctionnement de cet objet sont détaillés à l'adresse suivante : http://docs.python.org/2/library/subprocess.html#popen-constructor +Tous les arguments sont configurables sauf les suivants : ``stdout``, ``stderr``, ``bufsize``, ``close_fds``, ``preexec_fn``. +Cependant les quatres suivants seront les plus utiles: + * `args`: soit une séquence d'arguments de programme, soit une chaine de caractères + * `cwd`: le chemin du reepertoire de travail. Par défaut : ``None`` + * `env`: dictionnire donnant les variables d'evironement positinnées durant l'éxeecution du script. + +Il est recommandé que ``args`` soit une liste d'arguments et non une simple chaîne de caractères. + +L'example suivant démontre comment on peut configurer cette propriété pour lancer le dump des notices avec la commande ``dump_record``. + +.. code-block :: python + +ADMIN_SCRIPT = { + 'args' : [ sys.executable, "manage.py", "dump_record", "--newline", "-j", "/tmp/script_dump.rdf.bz2"], + 'cwd' : "/src", + 'env' : {'PYTHONPATH': '/lib/python2.7/site-packages'} +} + + +Plusieurs points sont à noter: + + * L'utilisation de cette fonctionnalité est à priori réservé pour une application installé sous Unix. (cela peut fonctionner sous Windows, mais cela n'a pas été testé) + * La fermeture de la fenêtre du navigateur ne stoppe pas la commande + * En particulier si la session de l'utilisateur expire ou bien que la fenêtre du browser est fermée, il n'y a plus possibilité de stopper le processus à partir d'un browser. + Le processus devra être interompu par les moyens habituels directement sur le serveur + * La commande est lancée dans le contexte du serveur web. Elle est donc executé par l'utilisateur du serveur web et hérite de ces droits d'accès. + * Tout démarrage du serveur web stoppe la commande. + * La commande partage les ressources du serveurs web. Attention donc à ne pas lancer des commandes trop gourmandes en ressources, cela peut avoir des conséquences sur la stabilité du serveur web et sa disponibilité. + * L'affichage de la sortie de la commande dans le browser se fait ligne par ligne. + Si la sortie de la commande ne comporte pas de caractère de retour à la ligne (``"\n"``) rien ne s'affichera avant la fin de la commande. + * Les sorties erreur et standard sont affichée ensemble sans différentiation. + + \ No newline at end of file diff -r 8c32ea1310de -r 7c6fe1dab213 src/p4l/admin.py --- a/src/p4l/admin.py Tue Oct 08 17:25:39 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,48 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright IRI (c) 2013 -# -# contact@iri.centrepompidou.fr -# -# This software is governed by the CeCILL-B license under French law and -# abiding by the rules of distribution of free software. You can use, -# modify and/ or redistribute the software under the terms of the CeCILL-B -# license as circulated by CEA, CNRS and INRIA at the following URL -# "http://www.cecill.info". -# -# As a counterpart to the access to the source code and rights to copy, -# modify and redistribute granted by the license, users are provided only -# with a limited warranty and the software's author, the holder of the -# economic rights, and the successive licensors have only limited -# liability. -# -# In this respect, the user's attention is drawn to the risks associated -# with loading, using, modifying and/or developing or reproducing the -# software by the user in light of its specific status of free software, -# that may mean that it is complicated to manipulate, and that also -# therefore means that it is reserved for developers and experienced -# professionals having in-depth computer knowledge. Users are therefore -# encouraged to load and test the software's suitability as regards their -# requirements in conditions enabling the security of their systems and/or -# data to be ensured and, more generally, to use and operate it in the -# same conditions as regards security. -# -# The fact that you are presently reading this means that you have had -# knowledge of the CeCILL-B license and that you accept its terms. -# - -from django.contrib import admin -from django.contrib.auth.admin import UserAdmin as AuthUserAdmin -from django.utils.translation import gettext_lazy as _ -from p4l.models import User -from p4l.forms import UserChangeForm, UserCreationform - -class UserAdmin(AuthUserAdmin): - form = UserChangeForm - add_form = UserCreationform - fieldsets = tuple(list(AuthUserAdmin.fieldsets) + [(_('language'), {'fields':('language',)})]) - - -admin.site.register(User, UserAdmin) - - diff -r 8c32ea1310de -r 7c6fe1dab213 src/p4l/admin/__init__.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/p4l/admin/__init__.py Fri Oct 11 11:46:18 2013 +0200 @@ -0,0 +1,46 @@ +# -*- coding: utf-8 -*- +# +# Copyright IRI (c) 2013 +# +# contact@iri.centrepompidou.fr +# +# This software is governed by the CeCILL-B license under French law and +# abiding by the rules of distribution of free software. You can use, +# modify and/ or redistribute the software under the terms of the CeCILL-B +# license as circulated by CEA, CNRS and INRIA at the following URL +# "http://www.cecill.info". +# +# As a counterpart to the access to the source code and rights to copy, +# modify and redistribute granted by the license, users are provided only +# with a limited warranty and the software's author, the holder of the +# economic rights, and the successive licensors have only limited +# liability. +# +# In this respect, the user's attention is drawn to the risks associated +# with loading, using, modifying and/or developing or reproducing the +# software by the user in light of its specific status of free software, +# that may mean that it is complicated to manipulate, and that also +# therefore means that it is reserved for developers and experienced +# professionals having in-depth computer knowledge. Users are therefore +# encouraged to load and test the software's suitability as regards their +# requirements in conditions enabling the security of their systems and/or +# data to be ensured and, more generally, to use and operate it in the +# same conditions as regards security. +# +# The fact that you are presently reading this means that you have had +# knowledge of the CeCILL-B license and that you accept its terms. +# + +__all__ = ['site'] + +from django.contrib.auth.admin import GroupAdmin +from django.contrib.auth.models import Group + +from p4l.admin.components import UserAdmin +from p4l.admin.sites import site +from p4l.models import User + + +site.register(User, UserAdmin) +site.register(Group, GroupAdmin) + diff -r 8c32ea1310de -r 7c6fe1dab213 src/p4l/admin/components.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/p4l/admin/components.py Fri Oct 11 11:46:18 2013 +0200 @@ -0,0 +1,50 @@ +# -*- coding: utf-8 -*- +# +# Copyright IRI (c) 2013 +# +# contact@iri.centrepompidou.fr +# +# This software is governed by the CeCILL-B license under French law and +# abiding by the rules of distribution of free software. You can use, +# modify and/ or redistribute the software under the terms of the CeCILL-B +# license as circulated by CEA, CNRS and INRIA at the following URL +# "http://www.cecill.info". +# +# As a counterpart to the access to the source code and rights to copy, +# modify and redistribute granted by the license, users are provided only +# with a limited warranty and the software's author, the holder of the +# economic rights, and the successive licensors have only limited +# liability. +# +# In this respect, the user's attention is drawn to the risks associated +# with loading, using, modifying and/or developing or reproducing the +# software by the user in light of its specific status of free software, +# that may mean that it is complicated to manipulate, and that also +# therefore means that it is reserved for developers and experienced +# professionals having in-depth computer knowledge. Users are therefore +# encouraged to load and test the software's suitability as regards their +# requirements in conditions enabling the security of their systems and/or +# data to be ensured and, more generally, to use and operate it in the +# same conditions as regards security. +# +# The fact that you are presently reading this means that you have had +# knowledge of the CeCILL-B license and that you accept its terms. +# + + +''' +Created on Oct 9, 2013 + +@author: ymh +''' + +from django.contrib.auth.admin import UserAdmin as AuthUserAdmin +from django.utils.translation import gettext_lazy as _ + +from p4l.admin.forms import UserChangeForm, UserCreationform + + +class UserAdmin(AuthUserAdmin): + form = UserChangeForm + add_form = UserCreationform + fieldsets = tuple(list(AuthUserAdmin.fieldsets) + [(_('language'), {'fields':('language',)})]) diff -r 8c32ea1310de -r 7c6fe1dab213 src/p4l/admin/forms.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/p4l/admin/forms.py Fri Oct 11 11:46:18 2013 +0200 @@ -0,0 +1,64 @@ +# -*- coding: utf-8 -*- +# +# Copyright IRI (c) 2013 +# +# contact@iri.centrepompidou.fr +# +# This software is governed by the CeCILL-B license under French law and +# abiding by the rules of distribution of free software. You can use, +# modify and/ or redistribute the software under the terms of the CeCILL-B +# license as circulated by CEA, CNRS and INRIA at the following URL +# "http://www.cecill.info". +# +# As a counterpart to the access to the source code and rights to copy, +# modify and redistribute granted by the license, users are provided only +# with a limited warranty and the software's author, the holder of the +# economic rights, and the successive licensors have only limited +# liability. +# +# In this respect, the user's attention is drawn to the risks associated +# with loading, using, modifying and/or developing or reproducing the +# software by the user in light of its specific status of free software, +# that may mean that it is complicated to manipulate, and that also +# therefore means that it is reserved for developers and experienced +# professionals having in-depth computer knowledge. Users are therefore +# encouraged to load and test the software's suitability as regards their +# requirements in conditions enabling the security of their systems and/or +# data to be ensured and, more generally, to use and operate it in the +# same conditions as regards security. +# +# The fact that you are presently reading this means that you have had +# knowledge of the CeCILL-B license and that you accept its terms. +# + + +from django.conf import settings +from django.contrib.auth import get_user_model +from django.contrib.auth.forms import (UserChangeForm as AuthUserChangeForm, + UserCreationForm as AuthUserCreationForm) +from django.core.exceptions import ValidationError +from django.forms.fields import ChoiceField +from django.utils.translation import ugettext as _ + + +User = get_user_model() + +class UserCreationform(AuthUserCreationForm): + class Meta: + model = User + + def clean_username(self): + # Since User.username is unique, this check is redundant, + # but it sets a nicer error message than the ORM. See #13147. + username = self.cleaned_data["username"] + try: + User.objects.get(username=username) + except User.DoesNotExist: + return username + raise ValidationError(self.error_messages['duplicate_username']) + + +class UserChangeForm(AuthUserChangeForm): + language = ChoiceField(label=_("language"), choices=[(k,_(v)) for k,v in settings.LANGUAGES], initial=settings.LANGUAGE_CODE[:2]) + class Meta: + model = User diff -r 8c32ea1310de -r 7c6fe1dab213 src/p4l/admin/sites.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/p4l/admin/sites.py Fri Oct 11 11:46:18 2013 +0200 @@ -0,0 +1,65 @@ +# -*- coding: utf-8 -*- +# +# Copyright IRI (c) 2013 +# +# contact@iri.centrepompidou.fr +# +# This software is governed by the CeCILL-B license under French law and +# abiding by the rules of distribution of free software. You can use, +# modify and/ or redistribute the software under the terms of the CeCILL-B +# license as circulated by CEA, CNRS and INRIA at the following URL +# "http://www.cecill.info". +# +# As a counterpart to the access to the source code and rights to copy, +# modify and redistribute granted by the license, users are provided only +# with a limited warranty and the software's author, the holder of the +# economic rights, and the successive licensors have only limited +# liability. +# +# In this respect, the user's attention is drawn to the risks associated +# with loading, using, modifying and/or developing or reproducing the +# software by the user in light of its specific status of free software, +# that may mean that it is complicated to manipulate, and that also +# therefore means that it is reserved for developers and experienced +# professionals having in-depth computer knowledge. Users are therefore +# encouraged to load and test the software's suitability as regards their +# requirements in conditions enabling the security of their systems and/or +# data to be ensured and, more generally, to use and operate it in the +# same conditions as regards security. +# +# The fact that you are presently reading this means that you have had +# knowledge of the CeCILL-B license and that you accept its terms. +# + + +''' +Created on Oct 9, 2013 + +@author: ymh +''' + +from django.conf.urls import patterns, url +from django.contrib.admin import AdminSite as DjangoAdminSite + +from p4l.admin.views import RunScriptView, ConfirmScriptView, KillScriptView +from p4l.decorators import is_staff + + +class AdminSite(DjangoAdminSite): + + login_template = "registration/login.html" + + + def get_urls(self): + urlpatterns = DjangoAdminSite.get_urls(self) + + urlpatterns += patterns('', + url(r'^confirm_script$', is_staff(ConfirmScriptView.as_view()), name='confirm_script'), + url(r'^run_script$', is_staff(RunScriptView.as_view()), name='run_script'), + url(r'^kill_script$', is_staff(KillScriptView.as_view()), name='kill_script') + ) + + return urlpatterns + +site = AdminSite() + diff -r 8c32ea1310de -r 7c6fe1dab213 src/p4l/admin/views.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/p4l/admin/views.py Fri Oct 11 11:46:18 2013 +0200 @@ -0,0 +1,156 @@ +# -*- coding: utf-8 -*- +# +# Copyright IRI (c) 2013 +# +# contact@iri.centrepompidou.fr +# +# This software is governed by the CeCILL-B license under French law and +# abiding by the rules of distribution of free software. You can use, +# modify and/ or redistribute the software under the terms of the CeCILL-B +# license as circulated by CEA, CNRS and INRIA at the following URL +# "http://www.cecill.info". +# +# As a counterpart to the access to the source code and rights to copy, +# modify and redistribute granted by the license, users are provided only +# with a limited warranty and the software's author, the holder of the +# economic rights, and the successive licensors have only limited +# liability. +# +# In this respect, the user's attention is drawn to the risks associated +# with loading, using, modifying and/or developing or reproducing the +# software by the user in light of its specific status of free software, +# that may mean that it is complicated to manipulate, and that also +# therefore means that it is reserved for developers and experienced +# professionals having in-depth computer knowledge. Users are therefore +# encouraged to load and test the software's suitability as regards their +# requirements in conditions enabling the security of their systems and/or +# data to be ensured and, more generally, to use and operate it in the +# same conditions as regards security. +# +# The fact that you are presently reading this means that you have had +# knowledge of the CeCILL-B license and that you accept its terms. +# +''' +Created on Oct 9, 2013 + +@author: ymh +''' + +import itertools +import os +import signal +from subprocess import PIPE, Popen, STDOUT +import time +import uuid + +from django.conf import settings +from django.http.response import StreamingHttpResponse, HttpResponse +from django.utils.translation import ugettext +from django.views.generic.base import TemplateView, View + + +class ConfirmScriptView(TemplateView): + template_name = "p4l/admin/confirm_run_script.html" + + def get_context_data(self, **kwargs): + return { + 'command_line' : " ".join(getattr(settings,"ADMIN_SCRIPT", {}).get('command',"")), + 'env' : repr(getattr(settings,"ADMIN_SCRIPT", {}).get('env',{})), + 'cwd' : repr(getattr(settings,"ADMIN_SCRIPT", {}).get('cwd',"")), + } + +class RunScriptView(View): + + def __init__(self, **kwargs): + View.__init__(self, **kwargs) + self.boundary = "--BOUNDARY--==--%s" % str(uuid.uuid4()) + + + def get(self, request): + resp = StreamingHttpResponse() + + command_kwargs = { + 'shell':False, + 'env':None, + 'cwd':None + } + admin_script = getattr(settings,"ADMIN_SCRIPT", {}) + command = admin_script.get('args',"") + + if not command: + return resp + + command_kwargs.update(admin_script, + stdout=PIPE, + stderr=STDOUT, + bufsize=0, + close_fds=True, + preexec_fn=os.setsid + ) + + resp['Connection'] = "Keep-Alive" + doc_start = [ + '', + '', + '', + '', + 'output', + '', + '', + '', + ] + + doc_end = [ + '', + '', + '' + ] + + scroll_to_bottom = '' + + process = Popen(**command_kwargs) + + # Save the pid in the user's session (a thread-safe place) + request.session['pid'] = process.pid + + def read_output(): + for line in iter(process.stdout.readline, b''): + yield "%s%s" %(line, scroll_to_bottom) + + resp.streaming_content = itertools.chain(doc_start, read_output(), doc_end) + + return resp + + +def check_pid(pid): + """ Check For the existence of a unix pid. """ + try: + os.kill(pid, 0) + except OSError: + return False + else: + return True + +class KillScriptView(View): + + def get(self, request): + + resp = HttpResponse() + + pid = request.session.get('pid', None) + + if not pid: + resp.content = ugettext("No active process to kill") + else: + os.kill(pid, signal.SIGINT) + i = 0 + while i <= settings.SCRIPT_MAX_WAIT and check_pid(pid): + time.sleep(settings.SCRIPT_WAIT) + i += 1 + + if check_pid(pid): + os.killpg(pid, signal.SIGKILL) + + resp.content = ugettext("Success: The process was killed successfully.") + + return resp diff -r 8c32ea1310de -r 7c6fe1dab213 src/p4l/config.py.tmpl --- a/src/p4l/config.py.tmpl Tue Oct 08 17:25:39 2013 +0200 +++ b/src/p4l/config.py.tmpl Fri Oct 11 11:46:18 2013 +0200 @@ -165,3 +165,5 @@ # url of the sesame repository containing all the rdf referentials SPARQL_QUERY_ENDPOINT = "http://localhost:8080/openrdf-sesame/repositories/plan4learning" +# cf http://docs.python.org/2/library/subprocess.html#popen-constructor +ADMIN_COMMAND_SCRIPT = {} diff -r 8c32ea1310de -r 7c6fe1dab213 src/p4l/decorators.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/p4l/decorators.py Fri Oct 11 11:46:18 2013 +0200 @@ -0,0 +1,55 @@ +# -*- coding: utf-8 -*- +# +# Copyright IRI (c) 2013 +# +# contact@iri.centrepompidou.fr +# +# This software is governed by the CeCILL-B license under French law and +# abiding by the rules of distribution of free software. You can use, +# modify and/ or redistribute the software under the terms of the CeCILL-B +# license as circulated by CEA, CNRS and INRIA at the following URL +# "http://www.cecill.info". +# +# As a counterpart to the access to the source code and rights to copy, +# modify and redistribute granted by the license, users are provided only +# with a limited warranty and the software's author, the holder of the +# economic rights, and the successive licensors have only limited +# liability. +# +# In this respect, the user's attention is drawn to the risks associated +# with loading, using, modifying and/or developing or reproducing the +# software by the user in light of its specific status of free software, +# that may mean that it is complicated to manipulate, and that also +# therefore means that it is reserved for developers and experienced +# professionals having in-depth computer knowledge. Users are therefore +# encouraged to load and test the software's suitability as regards their +# requirements in conditions enabling the security of their systems and/or +# data to be ensured and, more generally, to use and operate it in the +# same conditions as regards security. +# +# The fact that you are presently reading this means that you have had +# knowledge of the CeCILL-B license and that you accept its terms. +# +from django.contrib.auth import REDIRECT_FIELD_NAME + +''' +Created on Oct 10, 2013 + +@author: ymh +''' +from django.contrib.auth.decorators import user_passes_test + + +def is_staff(function=None, redirect_field_name=REDIRECT_FIELD_NAME, login_url=None): + """ + Decorator for views that checks that the user is logged in, redirecting + to the log-in page if necessary. + """ + actual_decorator = user_passes_test( + lambda u: u.is_staff, + login_url=login_url, + redirect_field_name=redirect_field_name + ) + if function: + return actual_decorator(function) + return actual_decorator diff -r 8c32ea1310de -r 7c6fe1dab213 src/p4l/forms.py --- a/src/p4l/forms.py Tue Oct 08 17:25:39 2013 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,65 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright IRI (c) 2013 -# -# contact@iri.centrepompidou.fr -# -# This software is governed by the CeCILL-B license under French law and -# abiding by the rules of distribution of free software. You can use, -# modify and/ or redistribute the software under the terms of the CeCILL-B -# license as circulated by CEA, CNRS and INRIA at the following URL -# "http://www.cecill.info". -# -# As a counterpart to the access to the source code and rights to copy, -# modify and redistribute granted by the license, users are provided only -# with a limited warranty and the software's author, the holder of the -# economic rights, and the successive licensors have only limited -# liability. -# -# In this respect, the user's attention is drawn to the risks associated -# with loading, using, modifying and/or developing or reproducing the -# software by the user in light of its specific status of free software, -# that may mean that it is complicated to manipulate, and that also -# therefore means that it is reserved for developers and experienced -# professionals having in-depth computer knowledge. Users are therefore -# encouraged to load and test the software's suitability as regards their -# requirements in conditions enabling the security of their systems and/or -# data to be ensured and, more generally, to use and operate it in the -# same conditions as regards security. -# -# The fact that you are presently reading this means that you have had -# knowledge of the CeCILL-B license and that you accept its terms. -# - - -from django.conf import settings -from django.contrib.auth import get_user_model -from django.contrib.auth.forms import (UserChangeForm as AuthUserChangeForm, - UserCreationForm as AuthUserCreationForm) -from django.core.exceptions import ValidationError -from django.forms.fields import ChoiceField -from django.utils.translation import ugettext as _ - - -User = get_user_model() - -class UserCreationform(AuthUserCreationForm): - class Meta: - model = User - - def clean_username(self): - # Since User.username is unique, this check is redundant, - # but it sets a nicer error message than the ORM. See #13147. - username = self.cleaned_data["username"] - try: - User.objects.get(username=username) - except User.DoesNotExist: - return username - raise ValidationError(self.error_messages['duplicate_username']) - - -class UserChangeForm(AuthUserChangeForm): - language = ChoiceField(label=_("language"), choices=[(k,_(v)) for k,v in settings.LANGUAGES], initial=settings.LANGUAGE_CODE[:2]) - class Meta: - model = User - diff -r 8c32ea1310de -r 7c6fe1dab213 src/p4l/locale/en/LC_MESSAGES/django.mo Binary file src/p4l/locale/en/LC_MESSAGES/django.mo has changed diff -r 8c32ea1310de -r 7c6fe1dab213 src/p4l/locale/en/LC_MESSAGES/django.po --- a/src/p4l/locale/en/LC_MESSAGES/django.po Tue Oct 08 17:25:39 2013 +0200 +++ b/src/p4l/locale/en/LC_MESSAGES/django.po Fri Oct 11 11:46:18 2013 +0200 @@ -7,7 +7,7 @@ msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2013-09-24 06:09-0500\n" +"POT-Creation-Date: 2013-10-11 10:22+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -16,27 +16,35 @@ "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -#: admin.py:10 forms.py:34 templates/p4l/record_view.html:56 -msgid "language" -msgstr "language" - -#: settings.py:42 +#: settings.py:76 msgid "French" msgstr "French" -#: settings.py:43 +#: settings.py:77 msgid "English" msgstr "English" -#: settings.py:44 +#: settings.py:78 msgid "Spanish" msgstr "Spanish" -#: semantictree/forms/widgets.py:39 +#: admin/components.py:50 admin/forms.py:62 templates/p4l/record_view.html:56 +msgid "language" +msgstr "language" + +#: admin/views.py:143 +msgid "No active process to kill" +msgstr "No active process to kill" + +#: admin/views.py:154 +msgid "Success: The process was killed successfully." +msgstr "Success: The process was killed successfully." + +#: semantictree/forms/widgets.py:68 msgid "Search" msgstr "Search" -#: semantictree/forms/widgets.py:43 semantictree/forms/widgets.py:80 +#: semantictree/forms/widgets.py:72 semantictree/forms/widgets.py:109 msgid "" "\"data-url\", \"data-query\", \"data-root-query\", \"data-childs-query\" and " "\"data-child-count-query\" must be set in CharField configuration" @@ -44,69 +52,91 @@ "\"data-url\", \"data-query\", \"data-root-query\", \"data-childs-query\" and " "\"data-child-count-query\" must be set in CharField configuration" -#: semantictree/forms/widgets.py:44 semantictree/forms/widgets.py:81 +#: semantictree/forms/widgets.py:73 semantictree/forms/widgets.py:110 msgid "Browse" msgstr "Browse" -#: semantictree/forms/widgets.py:49 semantictree/forms/widgets.py:86 +#: semantictree/forms/widgets.py:78 semantictree/forms/widgets.py:115 msgid "or" msgstr "or" -#: templates/p4l/base.html:35 +#: templates/admin/app_index.html:7 +#: templates/p4l/admin/confirm_run_script.html:13 +msgid "Home" +msgstr "Home" + +#: templates/admin/app_index.html:10 +#, python-format +msgid "%(name)s" +msgstr "%(name)s" + +#: templates/admin/index.html:10 +msgid "Commands" +msgstr "Commands" + +#: templates/admin/index.html:12 +msgid "Launch Script" +msgstr "Launch Script" + +#: templates/admin/index.html:13 +msgid "Launch" +msgstr "Launch" + +#: templates/p4l/base.html:36 msgid "logout" msgstr "logout" -#: templates/p4l/base.html:37 templates/registration/login.html:4 +#: templates/p4l/base.html:38 templates/registration/login.html:4 #: templates/registration/login.html:27 msgid "login" msgstr "login" -#: templates/p4l/home.html:6 templates/p4l/home.html.py:10 +#: templates/p4l/home.html:6 templates/p4l/home.html.py:15 msgid "Record List" msgstr "Record list" -#: templates/p4l/home.html:6 templates/p4l/home.html.py:30 -#: templates/p4l/home.html:70 +#: templates/p4l/home.html:6 templates/p4l/home.html.py:35 +#: templates/p4l/home.html:75 msgid "Page" msgstr "Page" -#: templates/p4l/home.html:14 +#: templates/p4l/home.html:19 msgid "Query" msgstr "Query" -#: templates/p4l/home.html:19 +#: templates/p4l/home.html:24 msgid "New record" msgstr "New record" -#: templates/p4l/home.html:27 templates/p4l/home.html.py:67 +#: templates/p4l/home.html:32 templates/p4l/home.html.py:72 msgid "Previous" msgstr "Previous" -#: templates/p4l/home.html:30 templates/p4l/home.html.py:70 +#: templates/p4l/home.html:35 templates/p4l/home.html.py:75 msgid "on" msgstr "on" -#: templates/p4l/home.html:33 templates/p4l/home.html.py:73 +#: templates/p4l/home.html:38 templates/p4l/home.html.py:78 msgid "Next" msgstr "Next" -#: templates/p4l/home.html:43 templates/p4l/record_view.html:36 +#: templates/p4l/home.html:48 templates/p4l/record_view.html:36 msgid "identifier" msgstr "identifier" -#: templates/p4l/home.html:43 templates/p4l/record_view.html:64 +#: templates/p4l/home.html:48 templates/p4l/record_view.html:64 msgid "titles" msgstr "titles" -#: templates/p4l/home.html:43 +#: templates/p4l/home.html:48 msgid "dates" msgstr "dates" -#: templates/p4l/home.html:43 +#: templates/p4l/home.html:48 msgid "actions" msgstr "actions" -#: templates/p4l/home.html:59 +#: templates/p4l/home.html:64 msgid "No record" msgstr "No record" @@ -118,30 +148,30 @@ msgid "View" msgstr "View" -#: templates/p4l/record_update_form.html:52 templates/p4l/translations.html:4 +#: templates/p4l/record_update_form.html:55 templates/p4l/translations.html:4 msgid "Save" msgstr "Save" -#: templates/p4l/record_update_form.html:56 +#: templates/p4l/record_update_form.html:59 msgid "Cancel" msgstr "Cancel" -#: templates/p4l/record_update_form.html:60 -#: templates/p4l/record_update_form.html:248 +#: templates/p4l/record_update_form.html:63 +#: templates/p4l/record_update_form.html:251 #: templates/p4l/translations.html:20 msgid "View the record" msgstr "View the record" -#: templates/p4l/record_update_form.html:61 -#: templates/p4l/record_update_form.html:249 templates/p4l/record_view.html:12 +#: templates/p4l/record_update_form.html:64 +#: templates/p4l/record_update_form.html:252 templates/p4l/record_view.html:12 #: templates/p4l/record_view.html.py:238 msgid "" "Are your sure you want to delete this record ? This action is irreversible." msgstr "" "Are your sure you want to delete this record ? This action is irreversible." -#: templates/p4l/record_update_form.html:61 -#: templates/p4l/record_update_form.html:249 templates/p4l/record_view.html:12 +#: templates/p4l/record_update_form.html:64 +#: templates/p4l/record_update_form.html:252 templates/p4l/record_view.html:12 #: templates/p4l/record_view.html.py:238 msgid "Delete the record" msgstr "Delete the record" @@ -393,6 +423,46 @@ msgid "An error occured. Somes datas may be incorrect or incomplete." msgstr "An error occured. Somes fields may be incorrect or incomplete." +#: templates/p4l/admin/confirm_run_script.html:14 +msgid "Run script" +msgstr "Run script" + +#: templates/p4l/admin/confirm_run_script.html:20 +msgid "Are you sure ?" +msgstr "Are you sure ?" + +#: templates/p4l/admin/confirm_run_script.html:22 +msgid "" +"The ADMIN_SCRIPT setting is not correctly configured. Please configure it to " +"launch commands." +msgstr "" +"The ADMIN_SCRIPT setting is not correctly configured. Please configure it to " +"launch commands." + +#: templates/p4l/admin/confirm_run_script.html:24 +msgid "Are you sure you want to run the script" +msgstr "Are you sure you want to run the script" + +#: templates/p4l/admin/confirm_run_script.html:25 +msgid "cwd:" +msgstr "cwd:" + +#: templates/p4l/admin/confirm_run_script.html:25 +msgid "env:" +msgstr "env:" + +#: templates/p4l/admin/confirm_run_script.html:28 +msgid "Yes, I'm sure" +msgstr "Yes, I'm sure" + +#: templates/p4l/admin/confirm_run_script.html:30 +msgid "Click to stop process (sends SIGINT then SIGKILL)" +msgstr "Click to stop process (sends SIGINT then SIGKILL)" + +#: templates/p4l/admin/confirm_run_script.html:31 +msgid "Done" +msgstr "Done" + #: templates/registration/login.html:8 msgid "Sorry, that's not a valid username or password." msgstr "Sorry, that's not a valid username or password." diff -r 8c32ea1310de -r 7c6fe1dab213 src/p4l/locale/es/LC_MESSAGES/django.mo Binary file src/p4l/locale/es/LC_MESSAGES/django.mo has changed diff -r 8c32ea1310de -r 7c6fe1dab213 src/p4l/locale/es/LC_MESSAGES/django.po --- a/src/p4l/locale/es/LC_MESSAGES/django.po Tue Oct 08 17:25:39 2013 +0200 +++ b/src/p4l/locale/es/LC_MESSAGES/django.po Fri Oct 11 11:46:18 2013 +0200 @@ -7,7 +7,7 @@ msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2013-09-24 06:09-0500\n" +"POT-Creation-Date: 2013-10-11 10:22+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -17,27 +17,35 @@ "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: admin.py:10 forms.py:34 templates/p4l/record_view.html:56 -msgid "language" -msgstr "language" - -#: settings.py:42 +#: settings.py:76 msgid "French" msgstr "French" -#: settings.py:43 +#: settings.py:77 msgid "English" msgstr "English" -#: settings.py:44 +#: settings.py:78 msgid "Spanish" msgstr "Spanish" -#: semantictree/forms/widgets.py:39 +#: admin/components.py:50 admin/forms.py:62 templates/p4l/record_view.html:56 +msgid "language" +msgstr "language" + +#: admin/views.py:143 +msgid "No active process to kill" +msgstr "No active process to kill" + +#: admin/views.py:154 +msgid "Success: The process was killed successfully." +msgstr "Success: The process was killed successfully." + +#: semantictree/forms/widgets.py:68 msgid "Search" msgstr "Search" -#: semantictree/forms/widgets.py:43 semantictree/forms/widgets.py:80 +#: semantictree/forms/widgets.py:72 semantictree/forms/widgets.py:109 msgid "" "\"data-url\", \"data-query\", \"data-root-query\", \"data-childs-query\" and " "\"data-child-count-query\" must be set in CharField configuration" @@ -45,69 +53,91 @@ "\"data-url\", \"data-query\", \"data-root-query\", \"data-childs-query\" and " "\"data-child-count-query\" must be set in CharField configuration" -#: semantictree/forms/widgets.py:44 semantictree/forms/widgets.py:81 +#: semantictree/forms/widgets.py:73 semantictree/forms/widgets.py:110 msgid "Browse" msgstr "Browse" -#: semantictree/forms/widgets.py:49 semantictree/forms/widgets.py:86 +#: semantictree/forms/widgets.py:78 semantictree/forms/widgets.py:115 msgid "or" msgstr "or" -#: templates/p4l/base.html:35 +#: templates/admin/app_index.html:7 +#: templates/p4l/admin/confirm_run_script.html:13 +msgid "Home" +msgstr "Home" + +#: templates/admin/app_index.html:10 +#, python-format +msgid "%(name)s" +msgstr "%(name)s" + +#: templates/admin/index.html:10 +msgid "Commands" +msgstr "Commands" + +#: templates/admin/index.html:12 +msgid "Launch Script" +msgstr "Launch Script" + +#: templates/admin/index.html:13 +msgid "Launch" +msgstr "Launch" + +#: templates/p4l/base.html:36 msgid "logout" msgstr "logout" -#: templates/p4l/base.html:37 templates/registration/login.html:4 +#: templates/p4l/base.html:38 templates/registration/login.html:4 #: templates/registration/login.html:27 msgid "login" msgstr "login" -#: templates/p4l/home.html:6 templates/p4l/home.html.py:10 +#: templates/p4l/home.html:6 templates/p4l/home.html.py:15 msgid "Record List" msgstr "Record list" -#: templates/p4l/home.html:6 templates/p4l/home.html.py:30 -#: templates/p4l/home.html:70 +#: templates/p4l/home.html:6 templates/p4l/home.html.py:35 +#: templates/p4l/home.html:75 msgid "Page" msgstr "Page" -#: templates/p4l/home.html:14 +#: templates/p4l/home.html:19 msgid "Query" msgstr "Query" -#: templates/p4l/home.html:19 +#: templates/p4l/home.html:24 msgid "New record" msgstr "New record" -#: templates/p4l/home.html:27 templates/p4l/home.html.py:67 +#: templates/p4l/home.html:32 templates/p4l/home.html.py:72 msgid "Previous" msgstr "Previous" -#: templates/p4l/home.html:30 templates/p4l/home.html.py:70 +#: templates/p4l/home.html:35 templates/p4l/home.html.py:75 msgid "on" msgstr "on" -#: templates/p4l/home.html:33 templates/p4l/home.html.py:73 +#: templates/p4l/home.html:38 templates/p4l/home.html.py:78 msgid "Next" msgstr "Next" -#: templates/p4l/home.html:43 templates/p4l/record_view.html:36 +#: templates/p4l/home.html:48 templates/p4l/record_view.html:36 msgid "identifier" msgstr "identifier" -#: templates/p4l/home.html:43 templates/p4l/record_view.html:64 +#: templates/p4l/home.html:48 templates/p4l/record_view.html:64 msgid "titles" msgstr "titles" -#: templates/p4l/home.html:43 +#: templates/p4l/home.html:48 msgid "dates" msgstr "dates" -#: templates/p4l/home.html:43 +#: templates/p4l/home.html:48 msgid "actions" msgstr "actions" -#: templates/p4l/home.html:59 +#: templates/p4l/home.html:64 msgid "No record" msgstr "No record" @@ -119,30 +149,30 @@ msgid "View" msgstr "View" -#: templates/p4l/record_update_form.html:52 templates/p4l/translations.html:4 +#: templates/p4l/record_update_form.html:55 templates/p4l/translations.html:4 msgid "Save" msgstr "Save" -#: templates/p4l/record_update_form.html:56 +#: templates/p4l/record_update_form.html:59 msgid "Cancel" msgstr "Cancel" -#: templates/p4l/record_update_form.html:60 -#: templates/p4l/record_update_form.html:248 +#: templates/p4l/record_update_form.html:63 +#: templates/p4l/record_update_form.html:251 #: templates/p4l/translations.html:20 msgid "View the record" msgstr "View the record" -#: templates/p4l/record_update_form.html:61 -#: templates/p4l/record_update_form.html:249 templates/p4l/record_view.html:12 +#: templates/p4l/record_update_form.html:64 +#: templates/p4l/record_update_form.html:252 templates/p4l/record_view.html:12 #: templates/p4l/record_view.html.py:238 msgid "" "Are your sure you want to delete this record ? This action is irreversible." msgstr "" "Are your sure you want to delete this record ? This action is irreversible." -#: templates/p4l/record_update_form.html:61 -#: templates/p4l/record_update_form.html:249 templates/p4l/record_view.html:12 +#: templates/p4l/record_update_form.html:64 +#: templates/p4l/record_update_form.html:252 templates/p4l/record_view.html:12 #: templates/p4l/record_view.html.py:238 msgid "Delete the record" msgstr "Delete the record" @@ -394,6 +424,46 @@ msgid "An error occured. Somes datas may be incorrect or incomplete." msgstr "An error occured. Somes fields may be incorrect or incomplete." +#: templates/p4l/admin/confirm_run_script.html:14 +msgid "Run script" +msgstr "Run script" + +#: templates/p4l/admin/confirm_run_script.html:20 +msgid "Are you sure ?" +msgstr "Are you sure ?" + +#: templates/p4l/admin/confirm_run_script.html:22 +msgid "" +"The ADMIN_SCRIPT setting is not correctly configured. Please configure it to " +"launch commands." +msgstr "" +"The ADMIN_SCRIPT setting is not correctly configured. Please configure it to " +"launch commands." + +#: templates/p4l/admin/confirm_run_script.html:24 +msgid "Are you sure you want to run the script" +msgstr "Are you sure you want to run the script" + +#: templates/p4l/admin/confirm_run_script.html:25 +msgid "cwd:" +msgstr "cwd:" + +#: templates/p4l/admin/confirm_run_script.html:25 +msgid "env:" +msgstr "env:" + +#: templates/p4l/admin/confirm_run_script.html:28 +msgid "Yes, I'm sure" +msgstr "Yes, I'm sure" + +#: templates/p4l/admin/confirm_run_script.html:30 +msgid "Click to stop process (sends SIGINT then SIGKILL)" +msgstr "Click to stop process (sends SIGINT then SIGKILL)" + +#: templates/p4l/admin/confirm_run_script.html:31 +msgid "Done" +msgstr "Done" + #: templates/registration/login.html:8 msgid "Sorry, that's not a valid username or password." msgstr "Sorry, that's not a valid username or password." diff -r 8c32ea1310de -r 7c6fe1dab213 src/p4l/locale/fr/LC_MESSAGES/django.mo Binary file src/p4l/locale/fr/LC_MESSAGES/django.mo has changed diff -r 8c32ea1310de -r 7c6fe1dab213 src/p4l/locale/fr/LC_MESSAGES/django.po --- a/src/p4l/locale/fr/LC_MESSAGES/django.po Tue Oct 08 17:25:39 2013 +0200 +++ b/src/p4l/locale/fr/LC_MESSAGES/django.po Fri Oct 11 11:46:18 2013 +0200 @@ -7,7 +7,7 @@ msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2013-09-24 06:09-0500\n" +"POT-Creation-Date: 2013-10-11 10:22+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -17,27 +17,35 @@ "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" -#: admin.py:10 forms.py:34 templates/p4l/record_view.html:56 -msgid "language" -msgstr "langue" - -#: settings.py:42 +#: settings.py:76 msgid "French" msgstr "Français" -#: settings.py:43 +#: settings.py:77 msgid "English" msgstr "Anglais" -#: settings.py:44 +#: settings.py:78 msgid "Spanish" msgstr "Espagnol" -#: semantictree/forms/widgets.py:39 +#: admin/components.py:50 admin/forms.py:62 templates/p4l/record_view.html:56 +msgid "language" +msgstr "langue" + +#: admin/views.py:143 +msgid "No active process to kill" +msgstr "Pas de processus actif à tuer" + +#: admin/views.py:154 +msgid "Success: The process was killed successfully." +msgstr "Réussi : le process a été tué avec succès." + +#: semantictree/forms/widgets.py:68 msgid "Search" msgstr "Chercher" -#: semantictree/forms/widgets.py:43 semantictree/forms/widgets.py:80 +#: semantictree/forms/widgets.py:72 semantictree/forms/widgets.py:109 msgid "" "\"data-url\", \"data-query\", \"data-root-query\", \"data-childs-query\" and " "\"data-child-count-query\" must be set in CharField configuration" @@ -46,69 +54,91 @@ "\"data-child-count-query\" doivent être renseignés dans la configuration " "CharField" -#: semantictree/forms/widgets.py:44 semantictree/forms/widgets.py:81 +#: semantictree/forms/widgets.py:73 semantictree/forms/widgets.py:110 msgid "Browse" msgstr "Parcourir" -#: semantictree/forms/widgets.py:49 semantictree/forms/widgets.py:86 +#: semantictree/forms/widgets.py:78 semantictree/forms/widgets.py:115 msgid "or" msgstr "ou" -#: templates/p4l/base.html:35 +#: templates/admin/app_index.html:7 +#: templates/p4l/admin/confirm_run_script.html:13 +msgid "Home" +msgstr "Accueil" + +#: templates/admin/app_index.html:10 +#, python-format +msgid "%(name)s" +msgstr "%(name)s" + +#: templates/admin/index.html:10 +msgid "Commands" +msgstr "Commandes" + +#: templates/admin/index.html:12 +msgid "Launch Script" +msgstr "Lancer Script" + +#: templates/admin/index.html:13 +msgid "Launch" +msgstr "Lancer" + +#: templates/p4l/base.html:36 msgid "logout" msgstr "deconnection" -#: templates/p4l/base.html:37 templates/registration/login.html:4 +#: templates/p4l/base.html:38 templates/registration/login.html:4 #: templates/registration/login.html:27 msgid "login" msgstr "connection" -#: templates/p4l/home.html:6 templates/p4l/home.html.py:10 +#: templates/p4l/home.html:6 templates/p4l/home.html.py:15 msgid "Record List" msgstr "Liste notice" -#: templates/p4l/home.html:6 templates/p4l/home.html.py:30 -#: templates/p4l/home.html:70 +#: templates/p4l/home.html:6 templates/p4l/home.html.py:35 +#: templates/p4l/home.html:75 msgid "Page" msgstr "Page" -#: templates/p4l/home.html:14 +#: templates/p4l/home.html:19 msgid "Query" msgstr "Requête" -#: templates/p4l/home.html:19 +#: templates/p4l/home.html:24 msgid "New record" msgstr "Nouvelle notice" -#: templates/p4l/home.html:27 templates/p4l/home.html.py:67 +#: templates/p4l/home.html:32 templates/p4l/home.html.py:72 msgid "Previous" msgstr "Préc." -#: templates/p4l/home.html:30 templates/p4l/home.html.py:70 +#: templates/p4l/home.html:35 templates/p4l/home.html.py:75 msgid "on" msgstr "sur" -#: templates/p4l/home.html:33 templates/p4l/home.html.py:73 +#: templates/p4l/home.html:38 templates/p4l/home.html.py:78 msgid "Next" msgstr "Suiv." -#: templates/p4l/home.html:43 templates/p4l/record_view.html:36 +#: templates/p4l/home.html:48 templates/p4l/record_view.html:36 msgid "identifier" msgstr "identifiant" -#: templates/p4l/home.html:43 templates/p4l/record_view.html:64 +#: templates/p4l/home.html:48 templates/p4l/record_view.html:64 msgid "titles" msgstr "titres" -#: templates/p4l/home.html:43 +#: templates/p4l/home.html:48 msgid "dates" msgstr "dates" -#: templates/p4l/home.html:43 +#: templates/p4l/home.html:48 msgid "actions" msgstr "actions" -#: templates/p4l/home.html:59 +#: templates/p4l/home.html:64 msgid "No record" msgstr "Pas de notice" @@ -120,22 +150,22 @@ msgid "View" msgstr "Vue" -#: templates/p4l/record_update_form.html:52 templates/p4l/translations.html:4 +#: templates/p4l/record_update_form.html:55 templates/p4l/translations.html:4 msgid "Save" msgstr "Enregistrer" -#: templates/p4l/record_update_form.html:56 +#: templates/p4l/record_update_form.html:59 msgid "Cancel" msgstr "Annuler" -#: templates/p4l/record_update_form.html:60 -#: templates/p4l/record_update_form.html:248 +#: templates/p4l/record_update_form.html:63 +#: templates/p4l/record_update_form.html:251 #: templates/p4l/translations.html:20 msgid "View the record" msgstr "Voir la notice" -#: templates/p4l/record_update_form.html:61 -#: templates/p4l/record_update_form.html:249 templates/p4l/record_view.html:12 +#: templates/p4l/record_update_form.html:64 +#: templates/p4l/record_update_form.html:252 templates/p4l/record_view.html:12 #: templates/p4l/record_view.html.py:238 msgid "" "Are your sure you want to delete this record ? This action is irreversible." @@ -143,8 +173,8 @@ "Êtes-vous sûr sur vouloir effacer cette notice ? Cette action est " "irréversible." -#: templates/p4l/record_update_form.html:61 -#: templates/p4l/record_update_form.html:249 templates/p4l/record_view.html:12 +#: templates/p4l/record_update_form.html:64 +#: templates/p4l/record_update_form.html:252 templates/p4l/record_view.html:12 #: templates/p4l/record_view.html.py:238 msgid "Delete the record" msgstr "Effacer la notice" @@ -397,6 +427,46 @@ msgstr "" "Une erreur est survenue. Certaines données sont incorrectes ou incomplètes." +#: templates/p4l/admin/confirm_run_script.html:14 +msgid "Run script" +msgstr "Lancer script" + +#: templates/p4l/admin/confirm_run_script.html:20 +msgid "Are you sure ?" +msgstr "Êtes-vous sûr ?" + +#: templates/p4l/admin/confirm_run_script.html:22 +msgid "" +"The ADMIN_SCRIPT setting is not correctly configured. Please configure it to " +"launch commands." +msgstr "" +"La propriété ADMIN_SCRIPT n'est pas correctement configuré. Configurez la avant " +"de lancer la commande." + +#: templates/p4l/admin/confirm_run_script.html:24 +msgid "Are you sure you want to run the script" +msgstr "Êtes-vous sûr que vous voulez bien lancer le script" + +#: templates/p4l/admin/confirm_run_script.html:25 +msgid "cwd:" +msgstr "cwd :" + +#: templates/p4l/admin/confirm_run_script.html:25 +msgid "env:" +msgstr "env :" + +#: templates/p4l/admin/confirm_run_script.html:28 +msgid "Yes, I'm sure" +msgstr "Oui, je suis sûr(e)" + +#: templates/p4l/admin/confirm_run_script.html:30 +msgid "Click to stop process (sends SIGINT then SIGKILL)" +msgstr "Cliquer pour arrêter le processus (envoie SIGINT puis SIGKILL)" + +#: templates/p4l/admin/confirm_run_script.html:31 +msgid "Done" +msgstr "Terminé" + #: templates/registration/login.html:8 msgid "Sorry, that's not a valid username or password." msgstr "Désolé, utilisateur ou mot de passe invalide" diff -r 8c32ea1310de -r 7c6fe1dab213 src/p4l/management/commands/dump_record.py --- a/src/p4l/management/commands/dump_record.py Tue Oct 08 17:25:39 2013 +0200 +++ b/src/p4l/management/commands/dump_record.py Fri Oct 11 11:46:18 2013 +0200 @@ -90,6 +90,12 @@ default=False, help= 'gzip compress' ), + make_option('--newline', + dest= 'newline', + action='store_true', + default=False, + help= 'show progress with newlines' + ), ) @@ -120,6 +126,7 @@ limit = options.get("limit", -1) skip = options.get("skip", 0) batch = options.get("batch", 100) + newline = options.get("newline", False) qs = Record.objects.all().select_related(*[field.name for field in Record._meta.fields if isinstance(field, ForeignKey)]).prefetch_related(*([field.name for field in Record._meta.many_to_many] + [obj.get_accessor_name() for obj in Record._meta.get_all_related_objects()])).order_by('identifier') # @UndefinedVariable @@ -157,7 +164,7 @@ writer.characters("\n") for n in range((total_records/batch)+1): for i,r in enumerate(qs[n*batch:((n+1)*batch)]): - progress_writer = show_progress(i+(n*batch)+1, total_records, "Exporting record %s" % r.identifier, 50, progress_writer) + progress_writer = show_progress(i+(n*batch)+1, total_records, "Exporting record %s" % r.identifier, 40, writer=progress_writer, newline=newline) graph = self.get_graph_from_object(r) do_write = False for line in graph.serialize(format="pretty-xml", encoding="utf-8").splitlines(True): diff -r 8c32ea1310de -r 7c6fe1dab213 src/p4l/management/commands/import_record.py --- a/src/p4l/management/commands/import_record.py Tue Oct 08 17:25:39 2013 +0200 +++ b/src/p4l/management/commands/import_record.py Fri Oct 11 11:46:18 2013 +0200 @@ -81,6 +81,12 @@ default=False, help= 'index while importing' ), + make_option('--newline', + dest= 'newline', + action='store_true', + default=False, + help= 'show progress with newlines' + ), ) def __init__(self, *args, **kwargs): @@ -115,7 +121,7 @@ for _,elem in context: if elem.tag == "{%s}Record" % IIEP: i += 1 - writer = show_progress(i, total_records, "Processing record nb %d " % i, 50, writer=writer) + writer = show_progress(i, total_records, "Processing record nb %d " % i, 40, writer=writer, newline=self.newline) try: record_graph = get_empty_graph() record_graph.parse(data=ET.tostring(elem, encoding='utf-8'), format='xml') @@ -128,7 +134,7 @@ else: transaction.commit() - if i%self.batch_size == 0: + if i%self.batch_size == 0: reset_queries() return errors @@ -155,6 +161,7 @@ self.batch_size = options.get('batch_size', 50) self.preserve = options.get("preserve", False) self.index = options.get("index", False) + self.newline = options.get("newline", False) if not self.index: old_realtime_indexing = getattr(settings, "REALTIME_INDEXING", None) diff -r 8c32ea1310de -r 7c6fe1dab213 src/p4l/models/__init__.py --- a/src/p4l/models/__init__.py Tue Oct 08 17:25:39 2013 +0200 +++ b/src/p4l/models/__init__.py Fri Oct 11 11:46:18 2013 +0200 @@ -43,4 +43,3 @@ Periodical, Meeting, SubjectMeeting, Audience, Record) from p4l.models.user import User - diff -r 8c32ea1310de -r 7c6fe1dab213 src/p4l/settings.py --- a/src/p4l/settings.py Tue Oct 08 17:25:39 2013 +0200 +++ b/src/p4l/settings.py Fri Oct 11 11:46:18 2013 +0200 @@ -33,6 +33,7 @@ # Django settings for p4l project. from django.conf import global_settings +import os DEBUG = True TEMPLATE_DEBUG = DEBUG @@ -129,6 +130,7 @@ TEMPLATE_LOADERS = ( 'django.template.loaders.filesystem.Loader', 'django.template.loaders.app_directories.Loader', + 'p4l.templateloaders.Loader' # 'django.template.loaders.eggs.Loader', ) @@ -156,6 +158,7 @@ # Put strings here, like "/home/html/django_templates" or "C:/www/django/templates". # Always use forward slashes, even on Windows. # Don't forget to use absolute paths, not relative paths. + os.path.join(os.path.dirname(__file__), 'templates'), ) INSTALLED_APPS = ( @@ -455,6 +458,12 @@ (u"Zhuang; Chuang", "za"), (u"Zulu", "zu")] +# cf http://docs.python.org/2/library/subprocess.html#popen-constructor +ADMIN_SCRIPT = {} + +SCRIPT_WAIT = .250 +SCRIPT_MAX_WAIT = 40 # * SCRIPT_WAIT = 10 sec + from config import * # @UnusedWildImport if not "SRC_BASE_URL" in locals(): diff -r 8c32ea1310de -r 7c6fe1dab213 src/p4l/static/p4l/css/img/ajax-loader.gif Binary file src/p4l/static/p4l/css/img/ajax-loader.gif has changed diff -r 8c32ea1310de -r 7c6fe1dab213 src/p4l/static/p4l/css/img/flags.png Binary file src/p4l/static/p4l/css/img/flags.png has changed diff -r 8c32ea1310de -r 7c6fe1dab213 src/p4l/static/p4l/css/p4l.css --- a/src/p4l/static/p4l/css/p4l.css Tue Oct 08 17:25:39 2013 +0200 +++ b/src/p4l/static/p4l/css/p4l.css Fri Oct 11 11:46:18 2013 +0200 @@ -1,11 +1,9 @@ /*! * modif from bootstrap for p4l */ - -html, -body { - height: 100%; - /* The html and body elements cannot have any padding or margin. */ +html,body { + height: 100%; + /* The html and body elements cannot have any padding or margin. */ } .container { @@ -14,142 +12,159 @@ } .record-table thead td:first-child { - width: 190px; + width: 190px; } + .record-table tbody td:first-child:first-letter { - text-transform: uppercase; + text-transform: uppercase; } + .table thead td:first-letter { - text-transform: uppercase; + text-transform: uppercase; } + .table thead { - font-weight: bold; + font-weight: bold; } -.two_buttons{ - min-width: 100px; + +.two_buttons { + min-width: 100px; } footer { - padding-bottom: 20px; - border-top: 1px solid gray; -} -.bottom-5 { - margin-bottom: 5px; + padding-bottom: 20px; + border-top: 1px solid gray; } -.after-plus { - margin-top: 5px; -} -.after-plus button { - margin-right: 5px; + +.bottom-5 { + margin-bottom: 5px; } -.rotate{ - transform:rotate(90deg); - -ms-transform:rotate(90deg); - -webkit-transform:rotate(90deg); +.after-plus { + margin-top: 5px; +} + +.after-plus button { + margin-right: 5px; +} + +.rotate { + transform: rotate(90deg); + -ms-transform: rotate(90deg); + -webkit-transform: rotate(90deg); } .spinner { - width: 14px; - height: 14px; - float: left; - background:url(./img/ajax-loader.gif) no-repeat center center; - border-radius: 50%; - opacity: .7; - margin-right: 4px; + width: 14px; + height: 14px; + float: left; + background: url("../img/ajax-loader.gif") no-repeat center center; + border-radius: 50%; + opacity: .7; + margin-right: 4px; } .grey-bottom { - border-bottom: 1px dotted #CCC; + border-bottom: 1px dotted #CCC; } .well { - margin-bottom: 5px; - padding: 4px 5px 8px 8px; + margin-bottom: 5px; + padding: 4px 5px 8px 8px; } label { - margin-bottom: 0px; + margin-bottom: 0px; } .edit-form-row:nth-child(odd) { - background: #EEE; + background: #EEE; } .break-word { - word-wrap: break-word; + word-wrap: break-word; } /* Flags */ .flag { - width: 16px; - height: 11px; - padding: 0; - border: none; - background:url(./img/flags.png) no-repeat; - /* hack to hide the button text */ - text-indent: -999em; /* Hide the text, works in most modern browsers */ - font-size: 0px; /* works well in IE7. still a black line (basically the text) in IE6. */ - /*display: block;*/ /* Negative text-indent works in IE(6? worked fine in 7) only if this is added. */ - line-height: 0px; /* Another fix for IE6. */ + width: 16px; + height: 11px; + padding: 0; + border: none; + background: url("../img/flags.png") no-repeat; + /* hack to hide the button text */ + text-indent: -999em; + /* Hide the text, works in most modern browsers */ + font-size: 0px; + /* works well in IE7. still a black line (basically the text) in IE6. */ + /*display: block;*/ + /* Negative text-indent works in IE(6? worked fine in 7) only if this is added. */ + line-height: 0px; /* Another fix for IE6. */ } -.flag.flag-es {background-position: -16px 0} -.flag.flag-fr {background-position: 0 -11px} -.flag.flag-en {background-position: -16px -11px} + +.flag.flag-es { + background-position: -16px 0 +} + +.flag.flag-fr { + background-position: 0 -11px +} + +.flag.flag-en { + background-position: -16px -11px +} /* css class to avoid angular flicker */ -[ng\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak], .ng-cloak, .x-ng-cloak { +[ng\:cloak],[ng-cloak],[data-ng-cloak],[x-ng-cloak],.ng-cloak,.x-ng-cloak + { display: none !important; } - .version { - text-align: right; - color: white; - font-size:9px; + text-align: right; + color: white; + font-size: 9px; } .version:hover { - color: inherit; - text-decoration: none; - border-bottom-width: 0px; - border-bottom-style: none; + color: inherit; + text-decoration: none; + border-bottom-width: 0px; + border-bottom-style: none; } #wrapper { - min-height: 100%; - height: auto !important; - height: 100%; - /* Negative indent footer by it's height */ - margin: 0 auto -70px; + min-height: 100%; + height: auto !important; + height: 100%; + /* Negative indent footer by it's height */ + margin: 0 auto -70px; } /* Set the fixed height of the footer here */ -#push, -footer { - height: 70px; +#push,footer { + height: 70px; } .footer-img { - padding: 10px 0; + padding: 10px 0; } #search-input { - padding-right: 24px; + padding-right: 24px; } #search-input-cancel { - text-indent: -1000em; - top: 3px; - right: 0.5em; + text-indent: -1000em; + top: 3px; + right: 0.5em; } #langselect { - padding-bottom: 10px; + padding-bottom: 10px; } - #copyright-version a { - text-decoration: none; - color: inherit; + text-decoration: none; + color: inherit; } \ No newline at end of file diff -r 8c32ea1310de -r 7c6fe1dab213 src/p4l/static/p4l/css/p4l_admin.css --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/p4l/static/p4l/css/p4l_admin.css Fri Oct 11 11:46:18 2013 +0200 @@ -0,0 +1,41 @@ +.literal { + background-color: #eeeeec; + padding: 1px; + font-family: monospace; +} + +.terminal { + position: relative; + top: 0; + left: 0; + display: block; + font-family: monospace; + white-space: pre; + width: 60%; + height: 30em; + border: 1px solid black; + margin-top: 1em; + overflow: auto; + display: none; +} + + + +#done { + display: none; + margin-top: 2px; +} + +#done h1 { + color: red; +} + +.script-control { + float: left; + margin-left: 10px; +} + +.clear { + clear: both; +} + diff -r 8c32ea1310de -r 7c6fe1dab213 src/p4l/static/p4l/img/ajax-loader.gif Binary file src/p4l/static/p4l/img/ajax-loader.gif has changed diff -r 8c32ea1310de -r 7c6fe1dab213 src/p4l/static/p4l/img/flags.png Binary file src/p4l/static/p4l/img/flags.png has changed diff -r 8c32ea1310de -r 7c6fe1dab213 src/p4l/templateloaders.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/p4l/templateloaders.py Fri Oct 11 11:46:18 2013 +0200 @@ -0,0 +1,71 @@ +# -*- coding: utf-8 -*- +# +# Copyright IRI (c) 2013 +# +# contact@iri.centrepompidou.fr +# +# This software is governed by the CeCILL-B license under French law and +# abiding by the rules of distribution of free software. You can use, +# modify and/ or redistribute the software under the terms of the CeCILL-B +# license as circulated by CEA, CNRS and INRIA at the following URL +# "http://www.cecill.info". +# +# As a counterpart to the access to the source code and rights to copy, +# modify and redistribute granted by the license, users are provided only +# with a limited warranty and the software's author, the holder of the +# economic rights, and the successive licensors have only limited +# liability. +# +# In this respect, the user's attention is drawn to the risks associated +# with loading, using, modifying and/or developing or reproducing the +# software by the user in light of its specific status of free software, +# that may mean that it is complicated to manipulate, and that also +# therefore means that it is reserved for developers and experienced +# professionals having in-depth computer knowledge. Users are therefore +# encouraged to load and test the software's suitability as regards their +# requirements in conditions enabling the security of their systems and/or +# data to be ensured and, more generally, to use and operate it in the +# same conditions as regards security. +# +# The fact that you are presently reading this means that you have had +# knowledge of the CeCILL-B license and that you accept its terms. +# + +''' +Created on Oct 9, 2013 + +From http://djangosnippets.org/snippets/1376/ + +@author: ymh +''' +from os.path import dirname, join, abspath, isdir + +from django.core.exceptions import ImproperlyConfigured +from django.db.models import get_app +from django.template import TemplateDoesNotExist +from django.template.loaders.filesystem import Loader as FilesystemLoader + + +def get_template_vars(template_name): + app_name, template_name = template_name.split(":", 1) + try: + template_dir = abspath(join(dirname(get_app(app_name).__file__), 'templates')) + except ImproperlyConfigured: + raise TemplateDoesNotExist() + + return template_name, template_dir + +class Loader(FilesystemLoader): + + is_usable = True + + def get_template_sources(self, template_name, template_dirs=None): + if ":" not in template_name: + raise TemplateDoesNotExist() + template_name, template_dir = get_template_vars(template_name) + + if not isdir(template_dir): + raise TemplateDoesNotExist() + + return [join(template_dir, template_name)] + diff -r 8c32ea1310de -r 7c6fe1dab213 src/p4l/templates/admin/app_index.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/p4l/templates/admin/app_index.html Fri Oct 11 11:46:18 2013 +0200 @@ -0,0 +1,16 @@ +{% extends "admin:admin/index.html" %} +{% load i18n %} + +{% if not is_popup %} +{% block breadcrumbs %} + +{% endblock %} +{% endif %} + +{% block sidebar %}{% endblock %} diff -r 8c32ea1310de -r 7c6fe1dab213 src/p4l/templates/admin/index.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/p4l/templates/admin/index.html Fri Oct 11 11:46:18 2013 +0200 @@ -0,0 +1,19 @@ +{% extends "admin:admin/index.html" %} +{% load i18n %} + +{% block content %} +
+{{ block.super }} +
+
+ + + + + + +
{% trans 'Commands' %}
{% trans 'Launch Script' %}{% trans 'Launch' %}
+
+
+
+{% endblock %} \ No newline at end of file diff -r 8c32ea1310de -r 7c6fe1dab213 src/p4l/templates/p4l/admin/confirm_run_script.html --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/p4l/templates/p4l/admin/confirm_run_script.html Fri Oct 11 11:46:18 2013 +0200 @@ -0,0 +1,59 @@ +{% extends "admin/base_site.html" %} +{% load i18n static %} + +{% block extrahead %} +{{ block.super }} + + +{% endblock %} + +{% if not is_popup %} +{% block breadcrumbs %} + +{% endblock %} +{% endif %} + +{% block content %} +

{% trans 'Are you sure ?' %}

+{% if not command_line %} +

{% blocktrans %}The ADMIN_SCRIPT setting is not correctly configured. Please configure it to launch commands.{% endblocktrans %} +{% else %} +

{% blocktrans %}Are you sure you want to run the script{% endblocktrans %} {{ command_line }} ?

+

( {% trans 'cwd:' %} {{ pwd }}, {% trans 'env:' %} {{ env }} )

+
+
+
+
+
+

{% trans 'Done' %}

+
+
 
+ + +{% endif %} +{% endblock %} + + diff -r 8c32ea1310de -r 7c6fe1dab213 src/p4l/urls.py --- a/src/p4l/urls.py Tue Oct 08 17:25:39 2013 +0200 +++ b/src/p4l/urls.py Fri Oct 11 11:46:18 2013 +0200 @@ -32,12 +32,13 @@ # from django.conf.urls import patterns, include, url -from django.contrib import admin +#from django.contrib import admin from django.contrib.auth import urls as auth_urls from django.contrib.auth.decorators import login_required from p4l.search.views import RecordSearchView from p4l.views import RecordDetailView, RecordEditView, RecordDeleteView +from p4l import admin js_info_dict = { @@ -45,7 +46,7 @@ 'domain': 'django', } -admin.autodiscover() +#admin.autodiscover() urlpatterns = patterns('', url(r'^$', login_required(RecordSearchView.as_view()), name='p4l_home'), diff -r 8c32ea1310de -r 7c6fe1dab213 src/p4l/utils.py --- a/src/p4l/utils.py Tue Oct 08 17:25:39 2013 +0200 +++ b/src/p4l/utils.py Fri Oct 11 11:46:18 2013 +0200 @@ -46,7 +46,7 @@ logger = logging.getLogger(__name__) -def show_progress(current_line, total_line, label, width, writer=None): +def show_progress(current_line, total_line, label, width, writer=None, newline=False): if writer is None: writer = sys.stdout @@ -60,7 +60,7 @@ loader = u'[' + (u'=' * int(marks)) + (u' ' * int(spaces)) + u']' - s = u"%s %3d%% %*d/%d - %*s\r" % (loader, percent, len(str(total_line)), current_line, total_line, width, label[:width]) + s = u"%s %3d%% %*d/%d - %*s%s" % (loader, percent, len(str(total_line)), current_line, total_line, width, label[:width], "\n" if newline else "\r") writer.write(s) #takes the header into account if percent >= 100: diff -r 8c32ea1310de -r 7c6fe1dab213 src/p4l/views.py --- a/src/p4l/views.py Tue Oct 08 17:25:39 2013 +0200 +++ b/src/p4l/views.py Fri Oct 11 11:46:18 2013 +0200 @@ -52,7 +52,7 @@ 'filter': 'dataquery', 'root': 'datarootquery', 'childs': 'datachildsquery', - 'child-count': 'datachildcountquery' + 'child-count': 'datachildcountquery' } @@ -158,4 +158,5 @@ rec = get_object_or_404(Record, identifier=slug) rec.delete() return redirect('p4l_home') - \ No newline at end of file + +