damned-lies r1239 - in trunk: . media/img templates templates/vertimus vertimus vertimus/tests
- From: stephaner svn gnome org
- To: svn-commits-list gnome org
- Subject: damned-lies r1239 - in trunk: . media/img templates templates/vertimus vertimus vertimus/tests
- Date: Wed, 24 Dec 2008 00:59:38 +0000 (UTC)
Author: stephaner
Date: Wed Dec 24 00:59:37 2008
New Revision: 1239
URL: http://svn.gnome.org/viewvc/damned-lies?rev=1239&view=rev
Log:
2008-12-24 StÃphane Raimbault <stephane raimbault gmail com>
* settings_sample.py: New settings for email and upload.
* templates/stats_show.html: Link to Vertimus view.
* templates/vertimus/vertimus_detail.html: Vertimus template
* urls.py: Forward to vertimus.urls
* vertimus/models.py: Major model changes.
* vertimus/tests/__init__.py: 20 unit tests.
* vertimus/urls.py: Vertimus URLs.
* vertimus/views.py: View and form management.
* media/img/person.png: Nice person icon.
Added:
trunk/media/img/person.png (contents, props changed)
trunk/templates/vertimus/
trunk/templates/vertimus/vertimus_detail.html (contents, props changed)
trunk/vertimus/urls.py
Modified:
trunk/ChangeLog
trunk/settings_sample.py
trunk/templates/stats_show.html
trunk/urls.py
trunk/vertimus/models.py
trunk/vertimus/tests/__init__.py
trunk/vertimus/views.py
Added: trunk/media/img/person.png
==============================================================================
Binary file. No diff available.
Modified: trunk/settings_sample.py
==============================================================================
--- trunk/settings_sample.py (original)
+++ trunk/settings_sample.py Wed Dec 24 00:59:37 2008
@@ -38,6 +38,12 @@
#
# Please refer to the README file to create an UTF-8 database with MySQL.
+EMAIL_HOST = 'localhost'
+EMAIL_HOST_USER = ''
+EMAIL_HOST_PASSWORD = ''
+EMAIL_SUBJECT_PREFIX = '[DL]'
+SERVER_EMAIL = 'server l10n gnome org'
+
# Local time zone for this installation. Choices can be found here:
# http://en.wikipedia.org/wiki/List_of_tz_zones_by_name
# although not all choices may be available on all operating systems.
@@ -64,6 +70,11 @@
# Examples: "http://media.lawrence.com", "http://example.com/media/"
MEDIA_URL = 'media'
+# By default, Django stores files locally, using the MEDIA_ROOT and MEDIA_URL settings
+UPLOAD_DIR = 'upload'
+UPLOAD_BACKUP_DIR = 'upload-backup'
+FILE_UPLOAD_PERMISSIONS = 0600
+
# URL prefix for admin media -- CSS, JavaScript and images. Make sure to use a
# trailing slash.
# Examples: "http://foo.com/media/", "/media/".
@@ -86,6 +97,7 @@
'django.middleware.common.CommonMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
+ 'django.middleware.transaction.TransactionMiddleware',
)
ROOT_URLCONF = 'djamnedlies.urls'
Modified: trunk/templates/stats_show.html
==============================================================================
--- trunk/templates/stats_show.html (original)
+++ trunk/templates/stats_show.html Wed Dec 24 00:59:37 2008
@@ -5,57 +5,61 @@
<h3>{% trans stat1.domain.get_description %}
{% ifnotequal stat1.domain.directory 'help' %}
{% ifnotequal stat1.domain.directory 'po' %}
- <br /><span class='path'>{{ stat1.domain.directory }}</span>
+ <br />
+ <span class="path">{{ stat1.domain.directory }}</span>
{% endifnotequal %}
- {% endifnotequal %}</h3>
+ {% endifnotequal %}
+ </h3>
<a href="{{ stat1.po_url }}"><img src="/media/img/download.png" alt="Download POT file" /></a>
{{ stat1.pot_text }}
-
- <!-- /* This is the title of the section that lists notices about a module */ -->
+ <!-- This is the title of the section that lists notices about a module -->
{% if stat1.information_set.all %}
- <h4>{% trans "Notices" %}</h4>
- <table>
+ <h4>{% trans "Notices" %}</h4>
+ <table>
{% for msg in stat1.information_set.all %}
- <tr><td valign="top"><img src="{{ msg.get_icon }}" alt="{{ msg.type }}" /></td><td>{{ msg.get_description|safe }}</td></tr>
+ <tr>
+ <td valign="top"><img src="{{ msg.get_icon }}" alt="{{ msg.type }}" /></td>
+ <td>{{ msg.get_description|safe }}</td>
+ </tr>
{% endfor %}
- </table>
+ </table>
{% endif %}
-<table class="stats">
-<thead><tr><th>{% trans "Language" %}</th><th>{% trans "Translated" %}</th>
- {% if stat1.fig_count %}
- <th></th>
- {% endif %}
-<th>{% trans "Graph" %}</th></tr></thead>
-
+ <table class="stats">
+ <thead><tr>
+ <th>{% trans "Language" %}</th><th>{% trans "Translated" %}</th>
+ {% if stat1.fig_count %}
+ <th></th>
+ {% endif %}
+ <th>{% trans "Graph" %}</th>
+ </tr></thead>
+ <!-- FIXME line / stat / stats naming -->
{% for line in stat %}
- {% if not forloop.first %}
- <tr>
- <td class="leftcell"><a href="{{ line.po_url }}">{{ line.get_lang }}</a>
- {% with line.most_important_message as msg %}
- {% if msg %}
- <img src="{{ msg.get_icon }}" title="{{ msg.get_description }}" alt="{{ msg.type }}" />
- {% endif %}
- {% endwith %}
+ {% if not forloop.first %}
+ <tr>
+ <td class="leftcell"><a href="{% url vertimus-stats-id-view line.id %}">{{ line.get_lang }}</a>
+ {% with line.most_important_message as msg %}
+ {% if msg %}
+ <img src="{{ msg.get_icon }}" title="{{ msg.get_description }}" alt="{{ msg.type }}" />
+ {% endif %}
+ {% endwith %}
</td>
<td>{{ line.get_translationstat|safe }}</td>
{% if stat1.fig_count %}
- <td><a href="{% url stats.views.docimages module_name=module.name,potbase=stat1.domain.name,branch_name=branch.name,langcode=line.language.locale %}">
- <img src="/media/img/figure.png" alt="{% trans "Display document figures" %}"></a></td>
+ <td><a href="{% url stats.views.docimages module_name=module.name,potbase=stat1.domain.name,branch_name=branch.name,langcode=line.language.locale %}">
+ <img src="/media/img/figure.png" alt="{% trans "Display document figures" %}"></a>
+ </td>
{% endif %}
- <td style="width: 108px; text-align: center;"><div class="graph">
- <div class="translated" style="width: {{ line.tr_percentage }}px;"></div>
- <div class="fuzzy" style="{{ LANGUAGE_BIDI|yesno:"right,left" }}:{{ line.tr_percentage }}px; width:{{ line.fu_percentage }}px;"></div>
- <div class="untranslated" style="{{ LANGUAGE_BIDI|yesno:"right,left" }}:{{ line.tr_percentage|add:line.fu_percentage }}px; width: {{ line.un_percentage }}px;"></div>
+ <td style="width: 108px; text-align: center;">
+ <div class="graph">
+ <div class="translated" style="width: {{ line.tr_percentage }}px;"></div>
+ <div class="fuzzy" style="{{ LANGUAGE_BIDI|yesno:"right,left" }}:{{ line.tr_percentage }}px; width:{{ line.fu_percentage }}px;"></div>
+ <div class="untranslated" style="{{ LANGUAGE_BIDI|yesno:"right,left" }}:{{ line.tr_percentage|add:line.fu_percentage }}px; width: {{ line.un_percentage }}px;"></div>
</div>
</td>
- </tr>
-
- {% endif %}
+ </tr>
+ {% endif %}
{% endfor %}
+ </table>
{% endwith %}
-
-</table>
-
{% endfor %}
-
Added: trunk/templates/vertimus/vertimus_detail.html
==============================================================================
--- (empty file)
+++ trunk/templates/vertimus/vertimus_detail.html Wed Dec 24 00:59:37 2008
@@ -0,0 +1,104 @@
+{% extends "base.html" %}
+{% load i18n %}
+
+{% block title %}
+{% blocktrans with module.get_description as name %}Module Translation: {{ name }}{% endblocktrans %}
+{% endblock %}
+
+{% block content %}
+<div class="mainpage">
+
+<h1>{{ module.get_description }} - {{ branch.name }} - {% trans domain.description %} - {% trans language %}</h1>
+
+{% if module.comment %}
+ <p>{{ module.comment|safe }}</p>
+{% else %}
+ {% ifnotequal module.vcs_root "http://svn.gnome.org/svn" %}
+ <p><i><img src="/media/img/warn.png" alt="Warning logo" />{% trans "This module is not part of the GNOME SVN repository. Please check the module's web page to see where to send translations." %}</i></p>
+ {% endifnotequal %}
+{% endif %}
+
+<h3>State: {{ state }}
+{% ifnotequal state.name 'none' %}
+({{ state.updated|date:"D d M Y P" }})
+{% endifnotequal %}
+</h3>
+
+<a href="{{ stats.po_url }}"><img src="/media/img/download.png" alt="Download POT file" /></a>
+{{ stats.pot_text }}
+
+{% if stats.information_set.all %}
+<h4>{% trans "Notices" %}</h4>
+<table>
+ {% for info in stats.information_set.all %}
+ <tr>
+ <td valign="top"><img src="{{ info.get_icon }}" alt="{{ info.type }}" /></td>
+ <td>{{ info.get_description|safe }}</td>
+ </tr>
+ {% endfor %}
+</table>
+{% endif %}
+
+<table>
+ <tr>
+ <td>{% trans "Translated:" %}</td>
+ <td>{{ stats.get_translationstat|safe }}</td>
+ </tr>
+ <tr>
+ <td>{% trans "Graph:" %}</td>
+ <td><div class="graph">
+ <div class="translated" style="width: {{ stats.tr_percentage }}px;"></div>
+ <div class="fuzzy" style="left:{{ stats.tr_percentage }}px; width:{{ stats.fu_percentage }}px;"></div>
+ <div class="untranslated" style="left:{{ stats.tr_percentage|add:stats.fu_percentage }}px; width: {{ stats.un_percentage }}px;"></div>
+ </div>
+ </td>
+ </tr>
+</table>
+
+{% if stats.fig_count %}
+<p><a href="{% url stats.views.docimages module_name=module.name,potbase=stats.domain.name,branch_name=branch.name,langcode=stats.language.locale %}">
+ <img src="/media/img/figure.png" alt="{% trans "Display document figures" %}"></a>
+</p>
+{% endif %}
+
+{% if action_history %}
+<h3>{% trans "Action History" %}</h3>
+<table>
+ {% for action in action_history %}
+ <tr>
+ <td>{{ action }},
+ <img src="/media/img/person.png" alt="Person"/>
+ <!-- Spam protection -->
+ <a href="{{ action.person.get_absolute_url }}">{{ action.person.name }}</a>
+ {{ action.created }}
+ </td>
+ </tr>
+ <tr>
+ <td>
+ {% if action.file %}
+ {% trans "Uploaded file:" %} <a href="{{ action.file.url }}">{{ action.file.name }}</a>
+ {% if action.comment %}<br/>{% endif %}
+ {% endif %}
+ {{ action.comment|linebreaksbr|default:"No comment" }}<br/>
+ </td>
+ </tr>
+ <tr class="noborder"><td> </td></tr>
+ {% endfor %}
+</table>
+{% endif %}
+
+<h3>{% trans "New Action" %}</h3>
+
+{% if action_form %}
+ <form enctype="multipart/form-data" action="/vertimus/{{ stats.id }}" method="POST">
+ <table>
+ {{ action_form.as_table }}
+ <tr><td></td>
+ <td><input type="submit" value="Submit"></td><tr>
+ </table>
+ </form>
+{% else %}
+ {% blocktrans with language.team.description as team_name %}You need to be authenticated and to be member of the {{ team_name }} team.{% endblocktrans %}
+{% endif %}
+
+{% endblock %}
Modified: trunk/urls.py
==============================================================================
--- trunk/urls.py (original)
+++ trunk/urls.py Wed Dec 24 00:59:37 2008
@@ -16,7 +16,7 @@
# users is the hardcoded url in the contrib.auth User class, making it identical to /people
(r'^users/', include('people.urls')),
(r'^languages/', include('languages.urls')),
- #(r'^stats/', include('stats.urls')),
+ (r'^vertimus/', include('vertimus.urls')),
(r'^admin/(.*)', admin.site.root),
)
Modified: trunk/vertimus/models.py
==============================================================================
--- trunk/vertimus/models.py (original)
+++ trunk/vertimus/models.py Wed Dec 24 00:59:37 2008
@@ -18,271 +18,545 @@
# along with Damned Lies; if not, write to the Free Software Foundation, Inc.,
# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+from datetime import datetime
from django.db import models
-from django.utils.translation import ugettext_lazy as _
+from django.utils.translation import ugettext as _
+from django.core import mail, urlresolvers
+from django.contrib.sites.models import Site
+from django.conf import settings
+from django.core.files.storage import default_storage
+
from stats.models import Branch, Domain
from languages.models import Language
from people.models import Person
-ACTION_CODES = (
- 'WC',
- 'RT', 'UT',
- 'RP', 'UP',
- 'TC', 'RC',
- 'IC', 'TR',
- 'BA', 'UNDO')
+#
+# States
+#
-class VtmAction(models.Model):
+# Sadly, the Django ORM isn't as powerful than SQLAlchemy :-(
+# So we need to use composition with StateDB and State to obtain
+# the desired behaviour.
+class StateDb(models.Model):
+ """Database storage of a State"""
branch = models.ForeignKey(Branch)
domain = models.ForeignKey(Domain)
language = models.ForeignKey(Language)
- person = models.ForeignKey(Person)
-
- code = models.CharField(max_length=8)
- created = models.DateField(auto_now_add=True, editable=False)
- comment = models.TextField(blank=True, null=True)
- file = models.FileField(upload_to='vertimus/%Y/%m/', blank=True, null=True)
+ person = models.ForeignKey(Person, default=None, null=True)
+
+ name = models.SlugField(max_length=20, default='None')
+ updated = models.DateTimeField(default=datetime.now, editable=False)
class Meta:
- db_table = 'vtm_action'
- ordering = ('created',)
- get_latest_by = 'created'
+ db_table = 'state'
+ unique_together = ('branch', 'domain', 'language')
- @classmethod
- def get_all(cls):
- actions = []
- for code in ACTION_CODES:
- actions.append(eval('VtmAction' + code + '()'))
-
- @classmethod
- def get_last_action(cls, branch, domain, language):
- return VtmAction.objects.filter(
- branch=branch, domain=domain, language=language).order_by('-created')[0]
-
- def apply(self, branch, domain, language, person, comment=None, file=None):
- self.branch = branch
- self.domain = domain
- self.language = language
- self.person = person
- self.comment = comment
- self.file = file
- self.save()
-
- return self._apply_child()
+ def get_state(self):
+ state = eval('State'+self.name)()
+ state._state_db = self
+ return state
def __unicode__(self):
return self.name
-#
-# States
-#
-
-class VtmState(object):
+class StateAbstract(object):
"""Abstract class"""
- def __init__(self, code, name):
- self.code = code
- self.name = name
- self.color = ''
- def __unicode__(self):
- return self.name
+ @property
+ def branch(self):
+ return self._state_db.branch
+
+ @property
+ def domain(self):
+ return self._state_db.domain
+
+ @property
+ def language(self):
+ return self._state_db.language
+
+ def get_person(self):
+ return self._state_db.person
+
+ def set_person(self, person):
+ self._state_db.person = person
+ person = property(get_person, set_person)
+
+ @property
+ def updated(self):
+ return self._state_db.updated
- def get_code(self):
- return self.code
+ def get_state_db(self):
+ return self._state_db
- @classmethod
- def get_actions(cls, action_codes=[]):
- action_codes.append('WC')
- return [ eval('VtmAction' + action_code)() for action_code in action_codes ]
-
- def apply_action(self, action, branch, domain, language, person, comment=None, file=None):
- new_state = action.apply(branch, domain, language, person, comment, file)
- if new_state == None:
- return self
+ def __unicode__(self):
+ return self.description
+
+ def _get_available_actions(self, action_names):
+ action_names.append('WC')
+ return [eval('Action' + action_name)() for action_name in action_names]
+
+ def apply_action(self, action, person, comment=None, file=None):
+ if action.name in (a.name for a in self.get_available_actions(person)):
+ new_state = action.apply(self, person, comment, file)
+ if new_state != None:
+ # Reuse the current state_db
+ new_state._state_db = self._state_db
+ # Only the name and the person change
+ new_state._state_db.name = new_state.name
+ new_state._state_db.person = person
+ return new_state
+ else:
+ return self
else:
- return new_state
+ raise Exception('Not allowed')
- def apply_action_code(self, action_code, branch, domain, language, person, comment=None, file=None):
- action = eval('VtmAction' + action_code)()
- self.apply_action(action, branch, domain, language, person, comment, file)
+ def save(self):
+ self._state_db.save()
-class VtmStateNone(VtmState):
- def __init__(self):
- super(VtmStateNone, self).__init__('None', 'Inactive')
+class StateNone(StateAbstract):
+ name = 'None'
+ description = _('Inactive')
- def get_actions(self, branch, domain, language, person):
- return super(VtmStateNone, self).get_actions(['RT'])
+ def get_available_actions(self, person):
+ action_names = []
+ if person.is_translator(self.language.team):
+ action_names = ['RT']
-class VtmStateTranslating(VtmState):
- def __init__(self):
- super(VtmStateTranslating, self).__init__('Translating', 'Translating')
+ return self._get_available_actions(action_names)
- def get_actions(self, branch, domain, language, person):
- action_codes = []
- last_action = VtmAction.get_last_action(branch, domain, language)
- if (last_action.person == person):
- action_codes = ['UT', 'UNDO']
-
- return super(VtmStateTranslating, self).get_actions(action_codes)
+class StateTranslating(StateAbstract):
+ name = 'Translating'
+ description = _('Translating')
+ def get_available_actions(self, person):
+ action_names = []
-class VtmStateTranslated(VtmState):
- def __init__(self):
- super(VtmStateTranslated, self).__init__('Translated', 'Translated')
+ if (self.person == person):
+ action_names = ['UT', 'UNDO']
+
+ return self._get_available_actions(action_names)
- def get_actions(self, branch, domain, language, person):
- # FIXME
- if person.is_reviewer:
- action_codes = ['RP']
- else:
- action_codes = []
- action_codes.append('RT')
- return super(VtmStateTranslated, self).get_actions(action_codes)
+class StateTranslated(StateAbstract):
+ name = 'Translated'
+ description = _('Translated')
+
+ def get_available_actions(self, person):
+ action_names = []
+ if person.is_reviewer(self.language.team):
+ action_names.append('RP')
-class VtmStateToReview(VtmState):
- def __init__(self):
- super(VtmStateToReview, self).__init__('ToReview', 'To Review')
- self.color = 'needswork';
+ if person.is_translator(self.language.team):
+ action_names.append('RT')
+ action_names.append('TR')
- def get_actions(self, branch, domain, language, person):
- return super(VtmStateToReview, self).get_actions(['RT'])
+ return self._get_available_actions(action_names)
-class VtmStateProofreading(VtmState):
- def __init__(self):
- super(VtmStateProofreading, self).__init__('Proofreading', 'Proofreading')
+class StateProofreading(StateAbstract):
+ name = 'Proofreading'
+ description = 'Proofreading'
- def get_actions(self, branch, domain, language, person):
- action_codes = []
+ def get_available_actions(self, person):
+ action_names = []
- # FIXME
- if person.is_commiter:
- last_action = VtmAction.get_last_action(branch, domain, language)
- if last_action.person == person:
- action_codes = ['UP', 'TR', 'TC', 'UNDO']
+ if person.is_reviewer(self.language.team):
+ if (self.person == person):
+ action_names = ['UP', 'TR', 'TC', 'UNDO']
- return super(VtmStateProofreading, self).get_actions(action_codes)
+ return self._get_available_actions(action_names)
-class VtmStateProofread(VtmState):
- def __init__(self):
- super(VtmStateProofread, self).__init__('Proofread', 'Proofread')
+class StateProofread(StateAbstract):
+ name = 'Proofread'
+ description = _('Proofread')
- def get_actions(self, branch, domain, language, person):
- if person.is_reviewer:
- action_codes = ['TC', 'TR']
+ def get_available_actions(self, person):
+ if person.is_reviewer(self.language.team):
+ action_names = ['TC', 'TR']
else:
- action_codes = []
+ action_names = []
+
+ return self._get_available_actions(action_names)
- return super(VtmStateProofread, self).get_actions(action_codes)
+class StateToReview(StateAbstract):
+ name = 'ToReview'
+ description = 'To Review'
-class VtmStateToCommit(VtmState):
- def __init__(self):
- super(VtmStateToCommit, self).__init__('ToCommit', 'To Commit')
+ def get_available_actions(self, person):
+ action_names = []
+ if person.is_translator(self.language.team):
+ action_names.append('RT')
- def get_actions(self, branch, domain, language, person):
- if person.is_commiter:
- action_codes = ['RC', 'TR']
+ return self._get_available_actions(action_names)
+
+
+class StateToCommit(StateAbstract):
+ name = 'ToCommit'
+ description = _('To Commit')
+
+ def get_available_actions(self, person):
+ if person.is_committer(self.language.team):
+ action_names = ['RC', 'TR']
else:
- action_codes = []
+ action_names = []
- return super(VtmStateToCommit, self).get_actions(action_codes)
+ return self._get_available_actions(action_names)
-class VtmStateCommitting(VtmState):
- def __init__(self):
- super(VtmStateCommitting, self).__init__('Committing', 'Committing')
+class StateCommitting(StateAbstract):
+ name = 'Committing'
+ description = _('Committing')
- def get_actions(self, branch, domain, language, person):
- action_codes = []
+ def get_available_actions(self, person):
+ action_names = []
- # FIXME
- if person.is_commiter:
- last_action = VtmAction.get_last_action(branch, domain, language)
- if (last_action.person == person):
- action_codes = ['IC', 'TR', 'TC', 'UNDO']
+ if person.is_committer(self.language.team):
+ if (self.person == person):
+ action_names = ['IC', 'TR', 'UNDO']
- return super(VtmStateCommitting, self).get_actions(action_codes)
+ return self._get_available_actions(action_names)
-class VtmStateCommitted(VtmState):
- def __init__(self):
- super(VtmStateCommitted, self).__init__('Committed', 'Committed')
+class StateCommitted(StateAbstract):
+ name = 'Committed'
+ description = _('Committed')
- def get_actions(self, branch, domain, language, person):
- return super(VtmStateCommitted, self).get_actions()
+ def get_available_actions(self, person):
+ if person.is_committer(self.language.team):
+ action_names = ['BA']
+ else: action_names = []
+
+ return self._get_available_actions(action_names)
#
# Actions
#
-class VtmActionWC(VtmAction):
+
+ACTION_NAMES = (
+ 'WC',
+ 'RT', 'UT',
+ 'RP', 'UP',
+ 'TC', 'RC',
+ 'IC', 'TR',
+ 'BA', 'UNDO')
+
+class ActionDb(models.Model):
+ state_db = models.ForeignKey(StateDb)
+ person = models.ForeignKey(Person)
+
+ name = models.SlugField(max_length=8)
+ description = None
+ created = models.DateTimeField(auto_now_add=True, editable=False)
+ comment = models.TextField(blank=True, null=True)
+ file = models.FileField(upload_to=settings.UPLOAD_DIR, blank=True, null=True)
+
class Meta:
- db_table = 'vtm_action_wc'
+ db_table = 'action'
+ ordering = ('-created',)
+
+ def get_action(self):
+ action = eval('Action' + self.name)()
+ action._action_db = self
+ return action
+
+ @classmethod
+ def get_action_history(cls, state_db):
+ if state_db:
+ return [va_db.get_action() for va_db in ActionDb.objects.filter(
+ state_db__id=state_db.id).order_by('created')]
+ else:
+ return []
- def __init__(self, *args, **kwargs):
- models.Model.__init__(self, *args, **kwargs)
- self.code = 'WC'
- self.name = 'Write a comment'
+ def __unicode__(self):
+ return self.name
+
+class ActionAbstract(object):
+ """Abstract class"""
+
+ @classmethod
+ def new_by_name(cls, action_name):
+ return eval('Action' + action_name)()
+
+ @classmethod
+ def get_all(cls):
+ """Reserved to the admins to access all actions"""
+ return [eval('Action' + action_name)() for action_name in ACTION_NAMES]
+
+ @property
+ def person(self):
+ return self._action_db.person
+
+ @property
+ def comment(self):
+ return self._action_db.comment
+
+ @property
+ def file(self):
+ return self._action_db.file
+
+ def save_action_db(self, state, person, comment=None, file=None):
+ """Used by apply"""
+ self._action_db = ActionDb(state_db=state._state_db,
+ person=person, name=self.name, comment=comment, file=file)
+ self._action_db.save()
+
+ def __unicode__(self):
+ return self.description
+
+ def send_mail_new_state(self, old_state, new_state, recipient_list):
+ # Remove None items from the list
+ recipient_list = filter(lambda x: x is not None, recipient_list)
+
+ if recipient_list:
+ current_site = Site.objects.get_current()
+ url = "http://%s%s" % (current_site.domain, urlresolvers.reverse(
+ 'vertimus-names-view',
+ args = (
+ old_state.branch.module.name,
+ old_state.branch.name,
+ old_state.domain.name,
+ old_state.language.locale)))
+ subject = old_state.branch.module.name + u' - ' + old_state.branch.name
+ message = _(u"""Hello,
+
+The new state of %(module)s - %(branch)s - %(domain)s (%(language)s) is now '%(new_state)s'.
+%(url)s
+
+""") % {
+ 'module': old_state.branch.module.name,
+ 'branch': old_state.branch.name,
+ 'domain': old_state.domain.name,
+ 'language': old_state.language.name,
+ 'new_state': new_state,
+ 'url': url
+ }
+ message += self.comment or _("Without comment")
+ message += "\n" + self.person.name
+ mail.send_mail(subject, message, self.person.email, recipient_list)
+
+class ActionWC(ActionAbstract):
+ name = 'WC'
+ description = _('Write a comment')
def _new_state(self):
return None
- def _apply_child(self):
+ def apply(self, state, person, comment=None, file=None):
+ self.save_action_db(state, person, comment, file)
+
+ # Send an email to all translators of the page
+ translator_emails = set()
+ for d in Person.objects.filter(actiondb__state_db=state.get_state_db()).values('email'):
+ translator_emails.add(d['email'])
+
+ # Remove None items from the list
+ translator_emails = filter(lambda x: x is not None, translator_emails)
+
+ if translator_emails:
+ current_site = Site.objects.get_current()
+ url = "http://%s%s" % (current_site.domain, urlresolvers.reverse(
+ 'vertimus-names-view',
+ args = (
+ state.branch.module.name,
+ state.branch.name,
+ state.domain.name,
+ state.language.locale)))
+ subject = state.branch.module.name + u' - ' + state.branch.name
+ message = _(u"""Hello,
+
+A new comment has been left on %(module)s - %(branch)s - %(domain)s (%(language)s).
+%(url)s
+
+""") % {
+ 'module': state.branch.module.name,
+ 'branch': state.branch.name,
+ 'domain': state.domain.name,
+ 'language': state.language.name,
+ 'url': url
+ }
+ message += comment or _("Without comment")
+ message += "\n" + person.name
+ mail.send_mail(subject, message, person.email, translator_emails)
+
return self._new_state()
+class ActionRT(ActionAbstract):
+ name = 'RT'
+ description = _('Reserve for translation')
+
+ def _new_state(self):
+ return StateTranslating()
-class VtmActionRT(VtmAction):
- class Meta:
- db_table = 'vtm_action_rt'
+ def apply(self, state, person, comment=None, file=None):
+ self.save_action_db(state, person, comment, file)
+ return self._new_state()
- def __init__(self, *args, **kwargs):
- models.Model.__init__(self, *args, **kwargs)
- self.code = 'RT'
- self.name = 'Reserve for translation'
+class ActionUT(ActionAbstract):
+ name = 'UT'
+ description = _('Upload the new translation')
def _new_state(self):
- return VtmStateTranslating()
+ return StateTranslated()
+
+ def apply(self, state, person, comment=None, file=None):
+ self.save_action_db(state, person, comment, file)
- def _apply_child(self):
+ new_state = self._new_state()
+ self.send_mail_new_state(state, new_state, (state.language.team.mailing_list,))
+ return new_state
+
+class ActionRP(ActionAbstract):
+ name = 'RP'
+ description = _('Reserve for proofreading')
+
+ def _new_state(self):
+ return StateProofreading()
+
+ def apply(self, state, person, comment=None, file=None):
+ self.save_action_db(state, person, comment, file)
return self._new_state()
+class ActionUP(ActionAbstract):
+ name = 'UP'
+ description = _('Upload for proofreading')
-class VtmActionUT(VtmAction):
- class Meta:
- db_table = 'vtm_action_ut'
+ def _new_state(self):
+ return StateProofread()
+
+ def apply(self, state, person, comment=None, file=None):
+ self.save_action_db(state, person, comment, file)
+
+ new_state = self._new_state()
+ self.send_mail_new_state(state, new_state, (state.language.team.mailing_list,))
+ return new_state
+
+class ActionTC(ActionAbstract):
+ name = 'TC'
+ description = _('Ready for submission')
- def __init__(self, *args, **kwargs):
- models.Model.__init__(self, *args, **kwargs)
- self.code = 'UT'
- self.name = 'Upload the new translation'
-
def _new_state(self):
- return VtmStateTranslated()
+ return StateToCommit()
+
+ def apply(self, state, person, comment=None, file=None):
+ self.save_action_db(state, person, comment, file)
+
+ new_state = self._new_state()
+ # Send an email to all committers of the team
+ committers = [c.email for c in state.language.team.get_committers()]
+ self.send_mail_new_state(state, new_state, committers)
+ return new_state
+
+class ActionRC(ActionAbstract):
+ name = 'RC'
+ description = _('Reserve to submit')
- def _apply_child(self):
+ def _new_state(self):
+ return StateCommitting()
+
+ def apply(self, state, person, comment=None, file=None):
+ self.save_action_db(state, person, comment, file)
return self._new_state()
+class ActionIC(ActionAbstract):
+ name = 'IC'
+ description = _('Inform of submission')
+
+ def _new_state(self):
+ return StateCommitted()
+
+ def apply(self, state, person, comment=None, file=None):
+ self.save_action_db(state, person, comment, file)
+
+ new_state = self._new_state()
+ self.send_mail_new_state(state, new_state, (state.language.team.mailing_list,))
+ return new_state
+
+class ActionTR(ActionAbstract):
+ name = 'TR'
+ description = _('Requiring review')
+
+ def _new_state(self):
+ return StateToReview()
+
+ def apply(self, state, person, comment=None, file=None):
+ self.save_action_db(state, person, comment, file)
+
+ new_state = self._new_state()
+ self.send_mail_new_state(state, new_state, (state.language.team.mailing_list,))
+ return new_state
+
+class ActionDbBackup(models.Model):
+ state_db = models.ForeignKey(StateDb)
+ person = models.ForeignKey(Person)
+
+ name = models.SlugField(max_length=8)
+ created = models.DateField(auto_now_add=True, editable=False)
+ comment = models.TextField(blank=True, null=True)
+ file = models.FileField(upload_to=settings.UPLOAD_BACKUP_DIR, blank=True, null=True)
+ sequence = models.IntegerField(blank=True, null=True)
-class VtmActionRP(VtmAction):
class Meta:
- db_table = 'vtm_action_rp'
-
- def __init__(self, *args, **kwargs):
- models.Model.__init__(self, *args, **kwargs)
- self.code = 'RP'
- self.name = 'Reserve for proofreading'
+ db_table = 'action_backup'
+
+class ActionBA(ActionAbstract):
+ name = 'BA'
+ description = _('Backup the actions')
def _new_state(self):
- return VtmStateProofreading()
+ return StateNone()
+
+ def apply(self, state, person, comment=None, file=None):
+ self.save_action_db(state, person, comment, file)
+
+ actions_db = ActionDb.objects.filter(state_db=state._state_db).all()
+
+ sequence = None
+ for action_db in actions_db:
+ action_db_backup = ActionDbBackup(
+ state_db=action_db.state_db,
+ person=action_db.person,
+ name=action_db.name,
+ created=action_db.created,
+ comment=action_db.comment,
+ file=action_db.file)
+ action_db_backup.save()
+
+ if sequence == None:
+ sequence = action_db_backup.id
+ action_db_backup.sequence = sequence
+ action_db_backup.save()
+
+ if action_db.file:
+ # Move the file to UPLOAD_BACKUP_DIR
+ # FIXME Hack
+ default_storage.save(
+ settings.UPLOAD_BACKUP_DIR + '/' + action_db.file.name[len(settings.UPLOAD_DIR):],
+ action_db.file)
+ default_storage.delete(action_db.file.path)
+
+ action_db.delete()
- def _apply_child(self, branch, domain, language, person):
return self._new_state()
-
+class ActionUNDO(ActionAbstract):
+ name = 'UNDO'
+ description = _('Undo the last state change')
+
+ def apply(self, state, person, comment=None, file=None):
+ self.save_action_db(state, person, comment, file)
+
+ try:
+ # Exclude himself
+ action_db = ActionDb.objects.filter(state_db__id=state._state_db.id).exclude(
+ name__in=['WC', 'UNDO']).order_by('-created')[1]
+ action = action_db.get_action()
+ return action._new_state()
+ except:
+ return StateNone()
Modified: trunk/vertimus/tests/__init__.py
==============================================================================
--- trunk/vertimus/tests/__init__.py (original)
+++ trunk/vertimus/tests/__init__.py Wed Dec 24 00:59:37 2008
@@ -19,22 +19,54 @@
# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
from django.test import TestCase
+from django.core.files.storage import default_storage
+from django.core.files.base import ContentFile
+from django.conf import settings
+
from people.models import Person
-from teams.models import Team
+from teams.models import Team, Role
from languages.models import Language
from stats.models import Module, Branch, Release, Category, Domain
from vertimus.models import *
-class VtmActionTests(TestCase):
+class VertimusTests(TestCase):
def setUp(self):
- self.p = Person(first_name='John', last_name='Lennon',
- email='jlennon beatles com')
- self.p.save()
+ self.pn = Person(first_name='John', last_name='Nothing',
+ email='jn devnull com', username= 'jn')
+ self.pn.save()
+
+ self.pt = Person(first_name='John', last_name='Translator',
+ email='jt tf1 com', username= 'jt')
+ self.pt.save()
+
+ self.pr = Person(first_name='John', last_name='Reviewer',
+ email='jr csa com', username= 'jr')
+ self.pr.save()
+
+ self.pc = Person(first_name='John', last_name='Committer',
+ email='jc alinsudesonpleingre fr', username= 'jc')
+ self.pc.save()
+
+ self.pcoo = Person(first_name='John', last_name='Coordinator',
+ email='jcoo imthebigboss fr', username= 'jcoo')
+ self.pcoo.save()
- self.t = Team(name='fr', description='French', coordinator=self.p)
+ self.t = Team(name='fr', description='French')
self.t.save()
+ self.role = Role(team=self.t, person=self.pt)
+ self.role.save()
+
+ self.role = Role(team=self.t, person=self.pr, role='reviewer')
+ self.role.save()
+
+ self.role = Role(team=self.t, person=self.pc, role='committer')
+ self.role.save()
+
+ self.role = Role(team=self.t, person=self.pcoo, role='coordinator')
+ self.role.save()
+
self.l = Language(name='french', locale='fr', team=self.t)
self.l.save()
@@ -46,7 +78,8 @@
self.m.save()
self.b = Branch(name='gnome-2-24', module=self.m)
- self.b.save()
+ # Block the update of Statistics by the thread
+ self.b.save(update_statistics=False)
self.r = Release(name='gnome-2-24', status='official',
description='GNOME 2.24 (stable)',
@@ -68,44 +101,277 @@
self.b.delete()
self.m.delete()
self.l.delete()
+ for role in Role.objects.all():
+ role.delete()
self.t.delete()
- self.p.delete()
+ self.pn.delete()
+ self.pt.delete()
+ self.pr.delete()
+ self.pc.delete()
+ self.pcoo.delete()
+
+ def test_state_none(self):
+ sdb = StateDb(branch=self.b, domain=self.d, language=self.l)
+ sdb.name = 'None'
+ state = sdb.get_state()
+ self.assert_(isinstance(state, StateNone))
+
+ action_names = [a.name for a in state.get_available_actions(self.pn)]
+ self.assertEqual(action_names, ['WC'])
+
+ for p in (self.pt, self.pr, self.pc, self.pcoo):
+ action_names = [a.name for a in state.get_available_actions(p)]
+ self.assertEqual(action_names, ['RT', 'WC'])
+
+ def test_state_translating(self):
+ sdb = StateDb(branch=self.b, domain=self.d, language=self.l, person=self.pt)
+ sdb.name = 'Translating'
+ state = sdb.get_state()
+ self.assert_(isinstance(state, StateTranslating))
+
+ for p in (self.pn, self.pr, self.pc, self.pcoo):
+ action_names = [a.name for a in state.get_available_actions(p)]
+ self.assertEqual(action_names, ['WC'])
+
+ # Same person
+ action_names = [a.name for a in state.get_available_actions(self.pt)]
+ self.assertEqual(action_names, ['UT', 'UNDO', 'WC'])
+
+ def test_state_translated(self):
+ sdb = StateDb(branch=self.b, domain=self.d, language=self.l, person=self.pt)
+ sdb.name = 'Translated'
+ state = sdb.get_state()
+ self.assert_(isinstance(state, StateTranslated))
+
+ action_names = [a.name for a in state.get_available_actions(self.pn)]
+ self.assertEqual(action_names, ['WC'])
- def test_action_wc(self):
- a = VtmActionWC()
- self.assertEquals(a.code, 'WC')
- s_next = a.apply(self.b, self.d, self.l, self.p, 'Hi!')
- self.assertEquals(s_next, None)
+ action_names = [a.name for a in state.get_available_actions(self.pt)]
+ self.assertEqual(action_names, ['RT', 'TR', 'WC'])
+
+ for p in (self.pr, self.pc, self.pcoo):
+ action_names = [a.name for a in state.get_available_actions(p)]
+ self.assertEqual(action_names, ['RP', 'RT', 'TR', 'WC'])
+
+ def test_state_proofreading(self):
+ sdb = StateDb(branch=self.b, domain=self.d, language=self.l, person=self.pr)
+ sdb.name = 'Proofreading'
+ state = sdb.get_state()
+ self.assert_(isinstance(state, StateProofreading))
+
+ for p in (self.pn, self.pt, self.pc, self.pcoo):
+ action_names = [a.name for a in state.get_available_actions(p)]
+ self.assertEqual(action_names, ['WC'])
+
+ # Same person and reviewer
+ action_names = [a.name for a in state.get_available_actions(self.pr)]
+ self.assertEqual(action_names, ['UP', 'TR', 'TC', 'UNDO', 'WC'])
+ def test_state_proofread(self):
+ sdb = StateDb(branch=self.b, domain=self.d, language=self.l, person=self.pr)
+ sdb.name = 'Proofread'
+ state = sdb.get_state()
+ self.assert_(isinstance(state, StateProofread))
+
+ for p in (self.pn, self.pt):
+ action_names = [a.name for a in state.get_available_actions(p)]
+ self.assertEqual(action_names, ['WC'])
+
+ for p in (self.pr, self.pc, self.pcoo):
+ action_names = [a.name for a in state.get_available_actions(p)]
+ self.assertEqual(action_names, ['TC', 'TR', 'WC'])
+
+ def test_state_to_review(self):
+ sdb = StateDb(branch=self.b, domain=self.d, language=self.l, person=self.pt)
+ sdb.name = 'ToReview'
+ state = sdb.get_state()
+ self.assert_(isinstance(state, StateToReview))
+
+ action_names = [a.name for a in state.get_available_actions(self.pn)]
+ self.assertEqual(action_names, ['WC'])
+
+ for p in (self.pt, self.pr, self.pc, self.pcoo):
+ action_names = [a.name for a in state.get_available_actions(p)]
+ self.assertEqual(action_names, ['RT', 'WC'])
+
+ def test_state_to_commit(self):
+ sdb = StateDb(branch=self.b, domain=self.d, language=self.l, person=self.pr)
+ sdb.name = 'ToCommit'
+ state = sdb.get_state()
+ self.assert_(isinstance(state, StateToCommit))
+
+ for p in (self.pn, self.pt, self.pr):
+ action_names = [a.name for a in state.get_available_actions(p)]
+ self.assertEqual(action_names, ['WC'])
+
+ for p in (self.pc, self.pcoo):
+ action_names = [a.name for a in state.get_available_actions(p)]
+ self.assertEqual(action_names, ['RC', 'TR', 'WC'])
+
+ def test_state_committing(self):
+ sdb = StateDb(branch=self.b, domain=self.d, language=self.l, person=self.pc)
+ sdb.name = 'Committing'
+ state = sdb.get_state()
+ self.assert_(isinstance(state, StateCommitting))
+
+ for p in (self.pn, self.pt, self.pr, self.pcoo):
+ action_names = [a.name for a in state.get_available_actions(p)]
+ self.assertEqual(action_names, ['WC'])
+
+ action_names = [a.name for a in state.get_available_actions(self.pc)]
+ self.assertEqual(action_names, ['IC', 'TR', 'UNDO', 'WC'])
+
+ def test_state_committed(self):
+ sdb = StateDb(branch=self.b, domain=self.d, language=self.l, person=self.pc)
+ sdb.name = 'Committed'
+ state = sdb.get_state()
+ self.assert_(isinstance(state, StateCommitted))
+
+ for p in (self.pn, self.pt, self.pr):
+ action_names = [a.name for a in state.get_available_actions(p)]
+ self.assertEqual(action_names, ['WC'])
+
+ for p in (self.pc, self.pcoo):
+ action_names = [a.name for a in state.get_available_actions(p)]
+ self.assertEqual(action_names, ['BA', 'WC'])
+
+ def test_action_wc(self):
+ state = StateDb(branch=self.b, domain=self.d, language=self.l, name='None').get_state()
+ state.save()
+
+ action = ActionAbstract.new_by_name('WC')
+ new_state = state.apply_action(action, self.pt, "Hi!", None)
+ new_state.save()
+
def test_action_rt(self):
- a = VtmActionRT()
- self.assertEquals(a.code, 'RT')
- s_next = a.apply(self.b, self.d, self.l, self.p, "Let's go!")
- self.assertEquals(s_next.get_code(), 'Translating')
+ state = StateDb(branch=self.b, domain=self.d, language=self.l, name='None').get_state()
+ state.save()
+
+ action = ActionAbstract.new_by_name('RT')
+ new_state = state.apply_action(action, self.pt, "Reserved!", None)
+ new_state.save()
def test_action_ut(self):
- # Only the person who have reserved the translation is able to
- # upload the new one
- a = VtmActionRT()
- s_current = a.apply(self.b, self.d, self.l, self.p, "Let's go!")
- a = VtmActionUT()
- self.assertEquals(a.code, 'UT')
- s_next = s_current.apply_action(a, self.b, self.d, self.l, self.p, 'Just updated', 'fr.po')
- self.assertEquals(s_next.get_code(), 'Translated')
-
- def test_state_committed_action_wc(self):
- s_current = VtmStateCommitted()
- a_wc = None
- # Writing a comment is always a possible action
- for action in s_current.get_actions(self.b, self.d, self.l, self.p):
- if isinstance(action, VtmActionWC):
- a_wc = action
- break
- self.assertNotEquals(a_wc, None)
- s_next = s_current.apply_action(a_wc, self.b, self.d, self.l, self.p, 'My comment')
- self.assertEquals(s_current, s_next)
+ state = StateDb(branch=self.b, domain=self.d, language=self.l, name='Translating', person=self.pt).get_state()
+ state.save()
+
+ action = ActionAbstract.new_by_name('UT')
+ new_state = state.apply_action(action, self.pt, "Done by translator.", 'myfile.po')
+ new_state.save()
+
+ def test_action_rp(self):
+ state = StateDb(branch=self.b, domain=self.d, language=self.l, name='Translated').get_state()
+ state.save()
+
+ action = ActionAbstract.new_by_name('RP')
+ new_state = state.apply_action(action, self.pr, "Reserved by a reviewer!")
+ new_state.save()
+
+ def test_action_up(self):
+ state = StateDb(branch=self.b, domain=self.d, language=self.l, name='Proofreading', person=self.pr).get_state()
+ state.save()
+
+ action = ActionAbstract.new_by_name('UP')
+ new_state = state.apply_action(action, self.pr, "Done.", 'myfile.po')
+ new_state.save()
+
+ def test_action_tc(self):
+ state = StateDb(branch=self.b, domain=self.d, language=self.l, name='Proofread').get_state()
+ state.save()
+ action = ActionAbstract.new_by_name('TC')
+ new_state = state.apply_action(action, self.pr, "Ready!")
+ new_state.save()
+
+ def test_action_rc(self):
+ state = StateDb(branch=self.b, domain=self.d, language=self.l, name='ToCommit').get_state()
+ state.save()
+
+ action = ActionAbstract.new_by_name('RC')
+ new_state = state.apply_action(action, self.pc, "This work is mine!")
+ new_state.save()
+
+ def test_action_ic(self):
+ state = StateDb(branch=self.b, domain=self.d, language=self.l, name='Committing', person=self.pc).get_state()
+ state.save()
+
+ action = ActionAbstract.new_by_name('IC')
+ new_state = state.apply_action(action, self.pc, "Committed.")
+ new_state.save()
+
+ def test_action_tr(self):
+ state = StateDb(branch=self.b, domain=self.d, language=self.l, name='Translated').get_state()
+ state.save()
+
+ action = ActionAbstract.new_by_name('TR')
+ new_state = state.apply_action(action, self.pc, "Bad work :-/")
+ new_state.save()
+
+ def test_action_ba(self):
+ state = StateDb(branch=self.b, domain=self.d, language=self.l, name='Proofreading', person=self.pr).get_state()
+ state.save()
+
+ # Create a new file
+ filename = 'mytestfile.po'
+ path = default_storage.save(settings.UPLOAD_DIR + filename, ContentFile('test content'))
+
+ action = ActionAbstract.new_by_name('UP')
+ state = state.apply_action(action, self.pr, "Done.", path)
+ state.save()
+
+ action = ActionAbstract.new_by_name('TC')
+ state = state.apply_action(action, self.pc, "To commit.")
+ state.save()
+
+ action = ActionAbstract.new_by_name('RC')
+ state = state.apply_action(action, self.pc, "Reserved commit.")
+ state.save()
+
+ action = ActionAbstract.new_by_name('IC')
+ state = state.apply_action(action, self.pc, "Committed.")
+ state.save()
+
+ action = ActionAbstract.new_by_name('BA')
+ state = state.apply_action(action, self.pc, comment="I don't want to disappear")
+ state.save()
+
+ self.assert_(not default_storage.exists(path))
+ self.assert_(default_storage.exists(settings.UPLOAD_BACKUP_DIR + '/' + filename))
+
+ # Remove test file
+ default_storage.delete(settings.UPLOAD_BACKUP_DIR + '/' + filename)
+
+ def test_action_undo(self):
+ state = StateDb(branch=self.b, domain=self.d, language=self.l, name='None').get_state()
+ state.save()
+
+ action = ActionAbstract.new_by_name('RT')
+ state = state.apply_action(action, self.pt, "Reserved!")
+ state.save()
+
+ action = ActionAbstract.new_by_name('UNDO')
+ state = state.apply_action(action, self.pt, "Ooops! I don't want to do that. Sorry.")
+ state.save()
+
+ self.assertEqual(state.name, 'None')
+
+ action = ActionAbstract.new_by_name('RT')
+ state = state.apply_action(action, self.pt, "Translating")
+ state.save()
+ action = ActionAbstract.new_by_name('UT')
+ state = state.apply_action(action, self.pt, "Translated")
+ state.save()
+
+ action = ActionAbstract.new_by_name('RT')
+ state = state.apply_action(action, self.pt, "Reserved!")
+ state.save()
+
+ action = ActionAbstract.new_by_name('UNDO')
+ state = state.apply_action(action, self.pt, "Ooops! I don't want to do that. Sorry.")
+ state.save()
+ self.assertEqual(state.name, 'Translated')
+
Added: trunk/vertimus/urls.py
==============================================================================
--- (empty file)
+++ trunk/vertimus/urls.py Wed Dec 24 00:59:37 2008
@@ -0,0 +1,7 @@
+from django.conf.urls.defaults import *
+
+urlpatterns = patterns('vertimus.views',
+ url(r'^(?P<stats_id>\d+)', 'vertimus_by_stats_id', name='vertimus-stats-id-view'),
+ url(r'^(?P<branch_id>\d+)/(?P<domain_id>\d+)/(?P<language_id>\d+)', 'vertimus_by_ids', name='vertimus-ids-view'),
+ url(r'^(?P<module_name>[\w\-\.]+)/(?P<branch_name>[\w\-]+)/(?P<domain_name>[\w\-]+)/(?P<locale_name>[\w\- ]+)', 'vertimus_by_names', name='vertimus-names-view')
+)
Modified: trunk/vertimus/views.py
==============================================================================
--- trunk/vertimus/views.py (original)
+++ trunk/vertimus/views.py Wed Dec 24 00:59:37 2008
@@ -1 +1,134 @@
-# Create your views here.
+# -*- coding: utf-8 -*-
+#
+# Copyright (c) 2008 StÃphane Raimbault <stephane raimbault gmail com>
+#
+# This file is part of Damned Lies.
+#
+# Damned Lies is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# Damned Lies is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Damned Lies; if not, write to the Free Software Foundation, Inc.,
+# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+from datetime import datetime
+from django.shortcuts import render_to_response, get_object_or_404
+from django.http import HttpResponseRedirect, Http404
+from django.template import RequestContext
+from django.utils.translation import ugettext_lazy as _
+from django import forms
+from django.core import urlresolvers
+from django.conf import settings
+from django.core.files.storage import default_storage
+
+from people.models import Person
+from stats.models import Statistics, Module, Branch, Domain, Language
+from vertimus.models import StateDb, ActionDb, ActionAbstract
+
+class ActionForm(forms.Form):
+ action = forms.ChoiceField(label=_("Action"),
+# help_text="Choose an action you want to apply",
+ choices=())
+ comment = forms.CharField(label=_("Comment"),
+# help_text="Leave a comment to explain your action",
+ max_length=1000,
+ required=False,
+ widget=forms.Textarea)
+ file = forms.FileField(label=_("File"), required=False)
+
+ def __init__(self, available_actions, *args, **kwargs):
+ super(ActionForm, self).__init__(*args, **kwargs)
+ self.fields['action'].choices = available_actions
+
+def vertimus_by_stats_id(request, stats_id):
+ """Access to Vertimus view by a Statistics ID"""
+ stats = get_object_or_404(Statistics, pk=stats_id)
+ return vertimus(request, stats.branch, stats.domain, stats.language, stats)
+
+def vertimus_by_ids(request, branch_id, domain_id, language_id):
+ """Access to Vertimus view by Branch, Domain and language IDs"""
+ branch = get_object_or_404(Branch, pk=branch_id)
+ domain = get_object_or_404(Domain, pk=domain_id)
+ language = get_object_or_404(Language, pk=language_id)
+ return vertimus(request, branch, domain, language)
+
+def vertimus_by_names(request, module_name, branch_name, domain_name, locale_name):
+ """Access to Vertimus view by Branch, Domain and language names"""
+ module = get_object_or_404(Module, name=module_name)
+ branch = get_object_or_404(Branch, name=branch_name, module__id=module.id)
+ domain = get_object_or_404(Domain, name=domain_name, module__id=module.id)
+ language = get_object_or_404(Language, locale=locale_name)
+
+ return vertimus(request, branch, domain, language)
+
+def handle_uploaded_file(f, branch, domain, language):
+ filename = "%s-%s-%s-%s.po" % (branch.module.name, branch.name, domain.name, language.locale)
+ path = default_storage.save(settings.UPLOAD_DIR + '/' + filename, f)
+
+ # Keep only the new filename (duplicate files)
+ return path
+
+def vertimus(request, branch, domain, language, stats=None):
+ """The Vertimus view and form management"""
+ if not stats:
+ stats = get_object_or_404(Statistics, branch=branch, domain=domain, language=language)
+
+ # Get the state of the translation
+ (state_db, created) = StateDb.objects.get_or_create(
+ branch=branch,
+ domain=domain,
+ language=language)
+
+ state = state_db.get_state()
+ action_history = ActionDb.get_action_history(state_db)
+
+ if request.user.is_authenticated():
+ # Only authenticated user can act on the translation
+ person = request.user.person
+
+ available_actions = [(va.name, va.description) for va in state.get_available_actions(person)]
+ if request.method == 'POST':
+ action_form = ActionForm(available_actions, request.POST, request.FILES)
+
+ if action_form.is_valid():
+ # Process the data in form.cleaned_data
+ action = action_form.cleaned_data['action']
+ comment = action_form.cleaned_data['comment']
+
+ if 'file' in request.FILES:
+ file = handle_uploaded_file(request.FILES['file'], branch, domain, language)
+ else:
+ file = None
+
+ action = ActionAbstract.new_by_name(action)
+ new_state = state.apply_action(action, person, comment, file)
+ new_state.save()
+
+ return HttpResponseRedirect(
+ urlresolvers.reverse('vertimus-names-view',
+ args=(branch.module.name, branch.name, domain.name, language.locale)))
+ else:
+ action_form = ActionForm(available_actions)
+ else:
+ action_form = None
+
+ context = {
+ 'pageSection': 'module',
+ 'stats': stats,
+ 'branch': branch,
+ 'domain': domain,
+ 'language': language,
+ 'module': branch.module,
+ 'state': state,
+ 'action_history': action_history,
+ 'action_form': action_form
+ }
+ return render_to_response('vertimus/vertimus_detail.html', context,
+ context_instance=RequestContext(request))
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]