Commit 3235789c authored by Michal Čihař's avatar Michal Čihař

Merge remote-tracking branch 'origin/pull/989'

parents 82ecd158 7ddc50ca
...@@ -217,7 +217,7 @@ class SubscriptionSettingsForm(forms.ModelForm): ...@@ -217,7 +217,7 @@ class SubscriptionSettingsForm(forms.ModelForm):
class UserSettingsForm(forms.ModelForm): class UserSettingsForm(forms.ModelForm):
''' '''
User subscription management. User settings form.
''' '''
class Meta(object): class Meta(object):
model = Profile model = Profile
...@@ -228,6 +228,28 @@ class UserSettingsForm(forms.ModelForm): ...@@ -228,6 +228,28 @@ class UserSettingsForm(forms.ModelForm):
) )
class DashboardSettingsForm(forms.ModelForm):
'''
Dashboard settings form.
'''
class Meta(object):
model = Profile
fields = (
'dashboard_view',
'dashboard_component_list',
)
def clean(self):
'''
Check if component list is selected when required.
'''
if self.cleaned_data.get('dashboard_view') == \
Profile.DASHBOARD_COMPONENT_LIST and \
self.cleaned_data.get('dashboard_component_list') is None:
raise forms.ValidationError(
_("Component list must be selected when used as default."))
class UserForm(forms.ModelForm): class UserForm(forms.ModelForm):
''' '''
User information form. User information form.
......
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('trans', '0058_componentlist'),
('accounts', '0013_auto_20151222_1006'),
]
operations = [
migrations.AddField(
model_name='profile',
name='dashboard_component_list',
field=models.ForeignKey(verbose_name='Default component list', blank=True, to='trans.ComponentList', null=True),
),
migrations.AddField(
model_name='profile',
name='dashboard_view',
field=models.CharField(default='your-subscriptions', max_length=100, verbose_name='Default dashboard view', choices=[('your-subscriptions', 'Your subscriptions'), ('your-languages', 'Your languages'), ('projects', 'All projects'), ('list', 'Component list')]),
),
migrations.AlterField(
model_name='profile',
name='language',
field=models.CharField(max_length=10, verbose_name='Interface Language', choices=[(b'az', 'Az\u0259rbaycan'), (b'be', '\u0411\u0435\u043b\u0430\u0440\u0443\u0441\u043a\u0430\u044f'), (b'be@latin', 'Bie\u0142aruskaja'), (b'br', 'Brezhoneg'), (b'ca', 'Catal\xe0'), (b'cs', '\u010ce\u0161tina'), (b'da', 'Dansk'), (b'de', 'Deutsch'), (b'en', 'English'), (b'el', '\u0395\u03bb\u03bb\u03b7\u03bd\u03b9\u03ba\u03ac'), (b'es', 'Espa\xf1ol'), (b'fi', 'Suomi'), (b'fr', 'Fran\xe7ais'), (b'fy', 'Frysk'), (b'gl', 'Galego'), (b'he', '\u05e2\u05d1\u05e8\u05d9\u05ea'), (b'hu', 'Magyar'), (b'id', b'Indonesia'), (b'ja', '\u65e5\u672c\u8a9e'), (b'ko', '\ud55c\uad6d\uc5b4'), (b'ksh', 'K\xf6lsch'), (b'nl', 'Nederlands'), (b'pl', 'Polski'), (b'pt', 'Portugu\xeas'), (b'pt-br', 'Portugu\xeas brasileiro'), (b'ru', '\u0420\u0443\u0441\u0441\u043a\u0438\u0439'), (b'sk', 'Sloven\u010dina'), (b'sl', 'Sloven\u0161\u010dina'), (b'sr', '\u0421\u0440\u043f\u0441\u043a\u0438'), (b'sv', 'Svenska'), (b'tr', 'T\xfcrk\xe7e'), (b'uk', '\u0423\u043a\u0440\u0430\u0457\u043d\u0441\u044c\u043a\u0430'), (b'zh-hans', '\u7b80\u4f53\u5b57'), (b'zh-hant', '\u6b63\u9ad4\u5b57')]),
),
]
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('accounts', '0014_dashboard_settings'),
]
operations = [
migrations.AlterField(
model_name='profile',
name='dashboard_view',
field=models.IntegerField(default=1, verbose_name='Default dashboard view', choices=[(1, 'Your subscriptions'), (2, 'Your languages'), (3, 'All projects'), (4, 'Component list')]),
),
migrations.AlterField(
model_name='profile',
name='secondary_languages',
field=models.ManyToManyField(help_text='Choose languages you can understand, strings in those languages will be shown in addition to the source string.', related_name='secondary_profile_set', verbose_name='Secondary languages', to='lang.Language', blank=True),
),
]
...@@ -500,6 +500,42 @@ class Profile(models.Model): ...@@ -500,6 +500,42 @@ class Profile(models.Model):
default=False default=False
) )
DASHBOARD_SUBSCRIPTIONS = 1
DASHBOARD_LANGUAGES = 2
DASHBOARD_ALL = 3
DASHBOARD_COMPONENT_LIST = 4
DASHBOARD_CHOICES = (
(DASHBOARD_SUBSCRIPTIONS, _('Your subscriptions')),
(DASHBOARD_LANGUAGES, _('Your languages')),
(DASHBOARD_ALL, _('All projects')),
(DASHBOARD_COMPONENT_LIST, _('Component list')),
)
DASHBOARD_SLUGS = {
DASHBOARD_SUBSCRIPTIONS: 'your-subscriptions',
DASHBOARD_LANGUAGES: 'your-languages',
DASHBOARD_ALL: 'projects',
DASHBOARD_COMPONENT_LIST: 'list',
}
DASHBOARD_SLUGMAP = {
d[1]: d[0] for d in DASHBOARD_SLUGS.items()
}
dashboard_view = models.IntegerField(
choices=DASHBOARD_CHOICES,
verbose_name=_('Default dashboard view'),
default=DASHBOARD_SUBSCRIPTIONS,
)
dashboard_component_list = models.ForeignKey(
'trans.ComponentList',
verbose_name=_('Default component list'),
blank=True,
null=True,
)
subscriptions = models.ManyToManyField( subscriptions = models.ManyToManyField(
'trans.Project', 'trans.Project',
verbose_name=_('Subscribed projects'), verbose_name=_('Subscribed projects'),
......
...@@ -231,6 +231,7 @@ class ProfileTest(ViewTestCase): ...@@ -231,6 +231,7 @@ class ProfileTest(ViewTestCase):
'first_name': 'First Last', 'first_name': 'First Last',
'email': 'noreply@weblate.org', 'email': 'noreply@weblate.org',
'username': 'testik', 'username': 'testik',
'dashboard_view': Profile.DASHBOARD_SUBSCRIPTIONS,
} }
) )
self.assertRedirects(response, reverse('profile')) self.assertRedirects(response, reverse('profile'))
...@@ -53,7 +53,7 @@ from weblate.accounts.models import set_lang, remove_user, Profile ...@@ -53,7 +53,7 @@ from weblate.accounts.models import set_lang, remove_user, Profile
from weblate.trans.models import Change, Project, SubProject from weblate.trans.models import Change, Project, SubProject
from weblate.accounts.forms import ( from weblate.accounts.forms import (
ProfileForm, SubscriptionForm, UserForm, ContactForm, ProfileForm, SubscriptionForm, UserForm, ContactForm,
SubscriptionSettingsForm, UserSettingsForm SubscriptionSettingsForm, UserSettingsForm, DashboardSettingsForm
) )
from weblate import appsettings from weblate import appsettings
...@@ -147,6 +147,7 @@ def user_profile(request): ...@@ -147,6 +147,7 @@ def user_profile(request):
SubscriptionForm, SubscriptionForm,
SubscriptionSettingsForm, SubscriptionSettingsForm,
UserSettingsForm, UserSettingsForm,
DashboardSettingsForm,
] ]
if request.method == 'POST': if request.method == 'POST':
...@@ -201,7 +202,8 @@ def user_profile(request): ...@@ -201,7 +202,8 @@ def user_profile(request):
'subscriptionform': forms[1], 'subscriptionform': forms[1],
'subscriptionsettingsform': forms[2], 'subscriptionsettingsform': forms[2],
'usersettingsform': forms[3], 'usersettingsform': forms[3],
'userform': forms[4], 'dashboardsettingsform': forms[4],
'userform': forms[5],
'profile': profile, 'profile': profile,
'title': _('User profile'), 'title': _('User profile'),
'licenses': license_projects, 'licenses': license_projects,
......
...@@ -69,6 +69,7 @@ ...@@ -69,6 +69,7 @@
<div class="panel-heading"><h4 class="panel-title">{% trans "Preferences" %}</h4></div> <div class="panel-heading"><h4 class="panel-title">{% trans "Preferences" %}</h4></div>
<div class="panel-body"> <div class="panel-body">
{{ usersettingsform|crispy }} {{ usersettingsform|crispy }}
{{ dashboardsettingsform|crispy }}
</div> </div>
<div class="panel-footer"> <div class="panel-footer">
<input type="submit" value="{% trans "Save" %}" class="btn btn-default" /> <input type="submit" value="{% trans "Save" %}" class="btn btn-default" />
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
{% load translations %} {% load translations %}
{% block form_top %} {% block form_top %}
{% if opts.model_name == 'project' or opts.model_name == 'subproject' or opts.model_name == 'advertisement' or opts.model_name == 'whiteboardmessage' or opts.model_name == 'groupacl' %} {% if opts.model_name == 'project' or opts.model_name == 'subproject' or opts.model_name == 'advertisement' or opts.model_name == 'whiteboardmessage' or opts.model_name == 'groupacl' or opts.model_name == 'componentlist' %}
{% if opts.model_name == 'advertisement' %} {% if opts.model_name == 'advertisement' %}
{% doc_url 'admin/advertisement' as url %} {% doc_url 'admin/advertisement' as url %}
{% else %} {% else %}
......
...@@ -77,11 +77,11 @@ ...@@ -77,11 +77,11 @@
<div class="collapse navbar-collapse" id="wl-navbar-main"> <div class="collapse navbar-collapse" id="wl-navbar-main">
<ul class="nav navbar-nav"> <ul class="nav navbar-nav">
<li><a href="{% url 'home' %}">{% trans "Dashboard" %}</a></li> <li><a href="{% url 'home' %}">{% trans "Dashboard" %}</a></li>
{% if usertranslations %} {% if subscribed_projects %}
<li class="dropdown"> <li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">{% trans "Your translations" %}<b class="caret"></b></a> <a href="#" class="dropdown-toggle" data-toggle="dropdown">{% trans "Your subscriptions" %}<b class="caret"></b></a>
<ul class="dropdown-menu"> <ul class="dropdown-menu">
{% for project in usertranslations %} {% for project in subscribed_projects %}
<li><a href="{{ project.get_absolute_url }}">{{ project }}</a></li> <li><a href="{{ project.get_absolute_url }}">{{ project }}</a></li>
{% endfor %} {% endfor %}
</ul> </ul>
......
...@@ -18,13 +18,23 @@ ...@@ -18,13 +18,23 @@
{% whiteboard_messages %} {% whiteboard_messages %}
<ul class="nav nav-pills"> <ul class="nav nav-pills">
{% if user.is_authenticated %} <li class="dropdown active">
<li class="active"><a href="#your" data-toggle="tab">{% trans "Your translations" %}</a></li> <a class="dropdown-toggle" data-toggle="dropdown" href="#" id="views-title">
<li><a href="#projects" data-toggle="tab">{% trans "Projects" %}</a></li> {{active_tab_label}} <span class="caret"></span>
{% else %} </a>
<li class="active"><a href="#projects" data-toggle="tab">{% trans "Projects" %}</a></li> <ul class="dropdown-menu" id="views-menu">
{% endif %} <li><a href="#projects" data-toggle="tab">{% trans "All projects" %}</a></li>
{% if user.is_authenticated %}
<li><a href="#your-languages" data-toggle="tab">{% trans "Your languages" %}</a></li>
<li><a href="#your-subscriptions" data-toggle="tab">{% trans "Your subscriptions" %}</a></li>
{% endif %}
{% for componentlist in componentlists %}
<li><a href="#{{ componentlist.tab_slug }}" data-toggle="tab">{{ componentlist.name }}</a></li>
{% endfor %}
</ul>
</li>
<li><a href="#search" data-toggle="tab">{% trans "Search" %}</a></li> <li><a href="#search" data-toggle="tab">{% trans "Search" %}</a></li>
<li><a href="#history" data-toggle="tab">{% trans "History" %}</a></li> <li><a href="#history" data-toggle="tab">{% trans "History" %}</a></li>
<li><a href="#activity" data-toggle="tab" data-load="activity" data-yearly="{% url 'yearly_activity' %}" data-monthly="{% url 'monthly_activity' %}">{% trans "Activity" %}</a></li> <li><a href="#activity" data-toggle="tab" data-load="activity" data-yearly="{% url 'yearly_activity' %}" data-monthly="{% url 'monthly_activity' %}">{% trans "Activity" %}</a></li>
...@@ -44,51 +54,63 @@ ...@@ -44,51 +54,63 @@
<div class="tab-content"> <div class="tab-content">
{% if user.is_authenticated %} {% if user.is_authenticated %}
<div class="tab-pane active" id="your"> <div {% active_tab "your-subscriptions" %}>
{% if usertranslations %} {% if subscribed_projects %}
{% with usertranslations as translations and 2 as show_language and user.profile.hide_completed as hide_completed %} {% if usersubscriptions %}
{% include "list-translations.html" %} {% with usersubscriptions as translations and 2 as show_language and user.profile.hide_completed as hide_completed %}
{% endwith %} {% include "list-translations.html" %}
{% endwith %}
{% else %}
{% with subscribed_projects as projects %}
{% include "list-projects.html" %}
{% endwith %}
{% endif %}
{% else %} {% else %}
<p class="help-block">{% trans "Choose your languages in preferences and you will get an overview here of available translations for those languages." %}</p> <p class="help-block">{% trans "Choose your languages in preferences and you will get an overview here of available translations for those languages in your subscribed projects." %}</p>
{% endif %} {% endif %}
<p><a class="btn btn-default" href="{% url 'profile' %}#languages">{% trans "Manage your translations" %}</a></p> <p>
<a class="btn btn-default" href="{% url 'profile' %}#languages">{% trans "Manage your languages" %}</a>
<a class="btn btn-default" href="{% url 'profile' %}#subscriptions">{% trans "Manage your subscriptions" %}</a>
</p>
</div> </div>
<div {% active_tab "your-languages" %}>
<div class="tab-pane" id="projects"> {% if userlanguages %}
{% else %} {% with userlanguages as translations and 2 as show_language and user.profile.hide_completed as hide_completed %}
<div class="tab-pane active" id="projects"> {% include "list-translations.html" %}
{% endif %}
<table class="sort table">
<thead>
<tr>
<th>{% trans "Project" %}</th>
<th colspan="2">{% trans "Translated" %}</th>
</tr>
<tbody>
{% for prj in projects %}
{% with prj.get_translated_percent as percent and prj.get_fuzzy_percent as fuzzy and prj.get_failing_checks_percent as check_percent %}
<tr>
<th><a href="{{ prj.get_absolute_url }}">{{ prj }}</a></th>
<td class="progress-cell">{% translation_progress prj %}</td>
<td class="percent">{{ percent }}%</td>
</tr>
{% endwith %} {% endwith %}
{% endfor %} {% else %}
</tbody> <p class="help-block">{% trans "Choose your languages in preferences and you will get an overview here of available translations for those languages in all projects." %}</p>
</table> {% endif %} {# userlanguages #}
<p><a class="btn btn-default" href="{% url 'profile' %}#languages">{% trans "Manage your languages" %}</a></p>
<p> </div>
{% include "legend.html" %} {% endif %} {# user.is_authenticated #}
</p>
{# All projects#}
<div {% active_tab "projects" %}>
{% include "list-projects.html" %}
<p>{% include "legend.html" %}</p>
{% if offer_hosting %} {% if offer_hosting %}
<p><a class="btn btn-default" href="{% url 'hosting' %}">{% trans "Ask for project hosting" %}</a> <p><a class="btn btn-default" href="{% url 'hosting' %}">{% trans "Ask for project hosting" %}</a>
{% endif %} {% endif %}
</div> </div>
{% for componentlist in componentlists %}
<div {% active_tab componentlist.tab_slug %}>
{% if userlanguages %}
{% with componentlist.translations as translations and 2 as show_language and user.profile.hide_completed as hide_completed %}
{% include "list-translations.html" %}
{% endwith %}
{% else %}
{% with componentlist.components.all as projects %}
{% include "list-projects.html" %}
{% endwith %}
<p class="help-block">{% trans "Choose your languages in preferences and you will get an overview here of available translations for those languages." %}</p>
{% endif %} {# userlanguages #}
<p><a class="btn btn-default" href="{% url 'profile' %}#languages">{% trans "Manage your languages" %}</a></p>
</div>{% endfor %}
<div class="tab-pane" id="search"> <div class="tab-pane" id="search">
<form action="{% url 'search' %}" method="GET"> <form action="{% url 'search' %}" method="GET">
......
{% load i18n %}
{% load translations %}
<table class="sort table">
<thead>
<tr>
<th>{% trans "Project" %}</th>
<th colspan="2">{% trans "Translated" %}</th>
</tr>
<tbody>
{% for prj in projects %}
{% with prj.get_translated_percent as percent and prj.get_fuzzy_percent as fuzzy and prj.get_failing_checks_percent as check_percent %}
<tr>
<th><a href="{{ prj.get_absolute_url }}">{{ prj }}</a></th>
<td class="progress-cell">{% translation_progress prj %}</td>
<td class="percent">{{ percent }}%</td>
</tr>
{% endwith %}
{% endfor %}
</tbody>
</table>
...@@ -934,4 +934,11 @@ $(function () { ...@@ -934,4 +934,11 @@ $(function () {
} }
}); });
} }
/* Labels in dropdown menu in Dashboard */
$("#views-menu li a").click(function(){
$("#views-title").html($(this).text()+' <span class="caret"></span>');
});
}); });
...@@ -24,7 +24,7 @@ from django.utils.translation import ugettext_lazy as _ ...@@ -24,7 +24,7 @@ from django.utils.translation import ugettext_lazy as _
from weblate.trans.models import ( from weblate.trans.models import (
Project, SubProject, Translation, Advertisement, Project, SubProject, Translation, Advertisement,
Unit, Suggestion, Comment, Check, Dictionary, Change, Unit, Suggestion, Comment, Check, Dictionary, Change,
Source, WhiteboardMessage, GroupACL Source, WhiteboardMessage, GroupACL, ComponentList,
) )
...@@ -228,6 +228,10 @@ class WhiteboardAdmin(admin.ModelAdmin): ...@@ -228,6 +228,10 @@ class WhiteboardAdmin(admin.ModelAdmin):
list_filter = ['project', 'language'] list_filter = ['project', 'language']
class ComponentListAdmin(admin.ModelAdmin):
list_display = ['name']
class AdvertisementAdmin(admin.ModelAdmin): class AdvertisementAdmin(admin.ModelAdmin):
list_display = ['placement', 'date_start', 'date_end', 'text'] list_display = ['placement', 'date_start', 'date_end', 'text']
search_fields = ['text', 'note'] search_fields = ['text', 'note']
...@@ -263,6 +267,7 @@ admin.site.register(SubProject, SubProjectAdmin) ...@@ -263,6 +267,7 @@ admin.site.register(SubProject, SubProjectAdmin)
admin.site.register(Advertisement, AdvertisementAdmin) admin.site.register(Advertisement, AdvertisementAdmin)
admin.site.register(WhiteboardMessage, WhiteboardAdmin) admin.site.register(WhiteboardMessage, WhiteboardAdmin)
admin.site.register(GroupACL, GroupACLAdmin) admin.site.register(GroupACL, GroupACLAdmin)
admin.site.register(ComponentList, ComponentListAdmin)
# Show some controls only in debug mode # Show some controls only in debug mode
if settings.DEBUG: if settings.DEBUG:
......
...@@ -26,7 +26,6 @@ import weblate ...@@ -26,7 +26,6 @@ import weblate
from weblate import appsettings from weblate import appsettings
from weblate.trans.site import get_site_url from weblate.trans.site import get_site_url
from weblate.trans.models.project import Project from weblate.trans.models.project import Project
from weblate.trans.models.translation import Translation
URL_BASE = 'https://weblate.org/?utm_source=weblate&utm_term=%s' URL_BASE = 'https://weblate.org/?utm_source=weblate&utm_term=%s'
URL_DONATE = 'https://weblate.org/donate/?utm_source=weblate&utm_term=%s' URL_DONATE = 'https://weblate.org/donate/?utm_source=weblate&utm_term=%s'
...@@ -44,14 +43,9 @@ def weblate_context(request): ...@@ -44,14 +43,9 @@ def weblate_context(request):
projects = Project.objects.all_acl(request.user) projects = Project.objects.all_acl(request.user)
# Load user translations if user is authenticated # Load user translations if user is authenticated
usertranslations = None subscribed_projects = None
if request.user.is_authenticated(): if request.user.is_authenticated():
usertranslations = Translation.objects.filter( subscribed_projects = request.user.profile.subscriptions.all()
language__in=request.user.profile.languages.all(),
subproject__project__in=projects,
).order_by(
'subproject__project__name', 'subproject__name'
).select_related()
if appsettings.OFFER_HOSTING: if appsettings.OFFER_HOSTING:
description = _( description = _(
...@@ -91,5 +85,5 @@ def weblate_context(request): ...@@ -91,5 +85,5 @@ def weblate_context(request):
'registration_open': appsettings.REGISTRATION_OPEN, 'registration_open': appsettings.REGISTRATION_OPEN,
'acl_projects': projects, 'acl_projects': projects,
'usertranslations': usertranslations, 'subscribed_projects': subscribed_projects,
} }
...@@ -30,10 +30,10 @@ import csv ...@@ -30,10 +30,10 @@ import csv
import traceback import traceback
import importlib import importlib
from django.utils.translation import ugettext_lazy as _
import six import six
from django.utils.translation import ugettext_lazy as _
from translate.convert import po2php from translate.convert import po2php
from translate.storage.lisa import LISAfile from translate.storage.lisa import LISAfile
from translate.storage.properties import propunit, propfile from translate.storage.properties import propunit, propfile
......
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('trans', '0057_indexupdate_language_code'),
]
operations = [
migrations.CreateModel(
name='ComponentList',
fields=[
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
('name', models.CharField(help_text='Name to display', unique=True, max_length=100, verbose_name='Component list name')),
('slug', models.SlugField(help_text='Name used in URLs and file names.', unique=True, max_length=100, verbose_name='URL slug')),
('components', models.ManyToManyField(to='trans.SubProject')),
],
options={
'verbose_name': 'Component list',
'verbose_name_plural': 'Component lists',
},
),
]
...@@ -38,6 +38,7 @@ from weblate.trans.models.group_acl import GroupACL ...@@ -38,6 +38,7 @@ from weblate.trans.models.group_acl import GroupACL
from weblate.trans.models.source import Source from weblate.trans.models.source import Source
from weblate.trans.models.advertisement import Advertisement from weblate.trans.models.advertisement import Advertisement
from weblate.trans.models.whiteboard import WhiteboardMessage from weblate.trans.models.whiteboard import WhiteboardMessage
from weblate.trans.models.componentlist import ComponentList
from weblate.trans.search import clean_search_unit from weblate.trans.search import clean_search_unit
from weblate.trans.signals import ( from weblate.trans.signals import (
vcs_post_push, vcs_post_update, vcs_pre_commit, vcs_post_commit, vcs_post_push, vcs_post_update, vcs_pre_commit, vcs_post_commit,
...@@ -51,7 +52,7 @@ from weblate.trans.scripts import ( ...@@ -51,7 +52,7 @@ from weblate.trans.scripts import (
__all__ = [ __all__ = [
'Project', 'SubProject', 'Translation', 'Unit', 'Check', 'Suggestion', 'Project', 'SubProject', 'Translation', 'Unit', 'Check', 'Suggestion',
'Comment', 'Vote', 'IndexUpdate', 'Change', 'Dictionary', 'Source', 'Comment', 'Vote', 'IndexUpdate', 'Change', 'Dictionary', 'Source',
'Advertisement', 'WhiteboardMessage', 'GroupACL', 'Advertisement', 'WhiteboardMessage', 'GroupACL', 'ComponentList',
] ]
......
...@@ -18,14 +18,13 @@ ...@@ -18,14 +18,13 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
# #
import six.moves
from django.db import models from django.db import models
from django.contrib.auth.models import User from django.contrib.auth.models import User
from django.db.models import Count, Q from django.db.models import Count, Q
from django.utils.encoding import python_2_unicode_compatible from django.utils.encoding import python_2_unicode_compatible, force_text
from django.utils.translation import ugettext as _, ugettext_lazy from django.utils.translation import ugettext as _, ugettext_lazy
from django.utils import timezone from django.utils import timezone
from django.utils.encoding import force_text
import six.moves
from weblate.trans.models.project import Project from weblate.trans.models.project import Project
from weblate.accounts.avatar import get_user_display from weblate.accounts.avatar import get_user_display
......
# -*- coding: utf-8 -*-
#
# Copyright © 2012 - 2015 Michal Čihař <michal@cihar.com>
#
# This file is part of Weblate <https://weblate.org/>
#
# This program 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 3 of the License, or
# (at your option) any later version.
#
# This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
#
"""Components list."""
from django.db import models
from django.utils.encoding import python_2_unicode_compatible
from django.utils.translation import ugettext_lazy as _
@python_2_unicode_compatible
class ComponentList(models.Model):
name = models.CharField(
verbose_name=_('Component list name'),
max_length=100,
unique=True,
help_text=_('Name to display')
)
slug = models.SlugField(
verbose_name=_('URL slug'),
db_index=True, unique=True,
max_length=100,
help_text=_('Name used in URLs and file names.')
)
components = models.ManyToManyField('SubProject')
def tab_slug(self):
return "list-" + self.slug
def __str__(self):
return self.name
class Meta(object):
verbose_name = _('Component list')
verbose_name_plural = _('Component lists')
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
# #
"""Whiteboard model.""" """Group ACL."""
from django.db import models from django.db import models
from django.core.exceptions import ValidationError from django.core.exceptions import ValidationError
......
...@@ -612,3 +612,9 @@ def whiteboard_messages(project=None, subproject=None, language=None): ...@@ -612,3 +612,9 @@ def whiteboard_messages(project=None, subproject=None, language=None):
) )
return mark_safe('\n'.join(ret)) return mark_safe('\n'.join(ret))
@register.simple_tag(takes_context=True)
def active_tab(context, slug):
active = "active" if slug == context['active_tab_slug'] else ""
return mark_safe('class="tab-pane %s" id="%s"' % (active, slug))
...@@ -36,7 +36,7 @@ from django.core.exceptions import ValidationError ...@@ -36,7 +36,7 @@ from django.core.exceptions import ValidationError
from weblate.trans.formats import FILE_FORMATS from weblate.trans.formats import FILE_FORMATS
from weblate.trans.models import ( from weblate.trans.models import (
Project, SubProject, Source, Unit, WhiteboardMessage, Check, Project, SubProject, Source, Unit, WhiteboardMessage, Check, ComponentList,
get_related_units, get_related_units,
) )
from weblate import appsettings from weblate import appsettings
...@@ -476,6 +476,17 @@ class WhiteboardMessageTest(TestCase): ...@@ -476,6 +476,17 @@ class WhiteboardMessageTest(TestCase):
WhiteboardMessage() WhiteboardMessage()
class ComponentListTest(TestCase):
"""Test(s) for ComponentList model."""
def test_can_be_imported(self):
"""Test that ComponentList model can be imported.
Rather dumb test just to make sure there are no obvious parsing errors.
"""
ComponentList()
class ModelTestCase(RepoTestCase): class ModelTestCase(RepoTestCase):
def setUp(self): def setUp(self):
super(ModelTestCase, self).setUp() super(ModelTestCase, self).setUp()
......
...@@ -27,15 +27,16 @@ from io import BytesIO ...@@ -27,15 +27,16 @@ from io import BytesIO
from six.moves.urllib.parse import urlsplit from six.moves.urllib.parse import urlsplit
from PIL import Image
from django.test.client import RequestFactory from django.test.client import RequestFactory
from django.contrib.auth.models import Group, User from django.contrib.auth.models import Group, User
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from django.contrib.messages.storage.fallback import FallbackStorage from django.contrib.messages.storage.fallback import FallbackStorage
from django.core import mail from django.core import mail
from PIL import Image from weblate.lang.models import Language
from weblate.trans.models import ComponentList, WhiteboardMessage
from weblate.trans.models import WhiteboardMessage
from weblate.trans.tests.test_models import RepoTestCase from weblate.trans.tests.test_models import RepoTestCase
from weblate.accounts.models import Profile from weblate.accounts.models import Profile
...@@ -399,6 +400,42 @@ class HomeViewTest(ViewTestCase): ...@@ -399,6 +400,42 @@ class HomeViewTest(ViewTestCase):
response = self.client.get(reverse('home')) response = self.client.get(reverse('home'))
self.assertNotContains(response, 'whiteboard') self.assertNotContains(response, 'whiteboard')
def test_component_list(self):
clist = ComponentList(name="TestCL", slug="testcl")
clist.save()
response = self.client.get(reverse('home'))
self.assertContains(response, 'TestCL')
self.assertEqual(len(response.context['componentlists']), 1)
def test_subscriptions(self):
# no subscribed projects at first
response = self.client.get(reverse('home'))
self.assertFalse(len(response.context['subscribed_projects']))
# subscribe a project
self.user.profile.subscriptions.add(self.project)
response = self.client.get(reverse('home'))
self.assertEqual(len(response.context['subscribed_projects']), 1)
def test_language_filters(self):
# check language filters
response = self.client.get(reverse('home'))
self.assertFalse(response.context['userlanguages'])
self.assertFalse(response.context['usersubscriptions'])
# add a language
lang = Language.objects.get(code='cs')
self.user.profile.languages.add(lang)
response = self.client.get(reverse('home'))
self.assertEqual(len(response.context['userlanguages']), 1)
self.assertFalse(response.context['usersubscriptions'])
# add a subscription
self.user.profile.subscriptions.add(self.project)
response = self.client.get(reverse('home'))
self.assertEqual(len(response.context['usersubscriptions']), 1)
class SourceStringsTest(ViewTestCase): class SourceStringsTest(ViewTestCase):
def test_edit_priority(self): def test_edit_priority(self):
......
...@@ -33,7 +33,7 @@ from django.utils import timezone ...@@ -33,7 +33,7 @@ from django.utils import timezone
import django.views.defaults import django.views.defaults
from weblate.trans.models import ( from weblate.trans.models import (
Project, SubProject, Translation, Check, Project, SubProject, Translation, Check, ComponentList,
Dictionary, Change, Unit, WhiteboardMessage Dictionary, Change, Unit, WhiteboardMessage
) )
from weblate.requirements import get_versions, get_optional_versions from weblate.requirements import get_versions, get_optional_versions
...@@ -72,8 +72,9 @@ def home(request): ...@@ -72,8 +72,9 @@ def home(request):
wb_messages = WhiteboardMessage.objects.all() wb_messages = WhiteboardMessage.objects.all()
projects = Project.objects.all_acl(request.user) projects = Project.objects.all_acl(request.user)
subproject_list = None
if projects.count() == 1: if projects.count() == 1:
projects = SubProject.objects.filter( subproject_list = SubProject.objects.filter(
project=projects[0] project=projects[0]
).select_related() ).select_related()
...@@ -88,15 +89,54 @@ def home(request): ...@@ -88,15 +89,54 @@ def home(request):
# Some stats # Some stats
last_changes = Change.objects.last_changes(request.user)[:10] last_changes = Change.objects.last_changes(request.user)[:10]
# Dashboard project/subproject view
componentlists = ComponentList.objects.all()
# dashboard_choices is dict with labels of choices as a keys
dashboard_choices = dict(Profile.DASHBOARD_CHOICES)
usersubscriptions = None
userlanguages = None
active_tab_id = Profile.DASHBOARD_ALL
active_tab_slug = Profile.DASHBOARD_SLUGS.get(active_tab_id)
if request.user.is_authenticated():
active_tab_id = request.user.profile.dashboard_view
active_tab_slug = Profile.DASHBOARD_SLUGS.get(active_tab_id)
if active_tab_id == Profile.DASHBOARD_COMPONENT_LIST:
clist = request.user.profile.dashboard_component_list
active_tab_slug = clist.tab_slug()
dashboard_choices[active_tab_id] = clist.name
subscribed_projects = request.user.profile.subscriptions.all()
components_by_language = Translation.objects.filter(
language__in=request.user.profile.languages.all(),
).order_by(
'subproject__project__name', 'subproject__name'
).select_related()
usersubscriptions = components_by_language.filter(
subproject__project__in=subscribed_projects)
userlanguages = components_by_language.filter(
subproject__project__in=projects)
for componentlist in componentlists:
componentlist.translations = components_by_language.filter(
subproject__in=componentlist.components.all())
return render( return render(
request, request,
'index.html', 'index.html',
{ {
'projects': projects, 'projects': subproject_list or projects,
'last_changes': last_changes, 'last_changes': last_changes,
'last_changes_url': '', 'last_changes_url': '',
'search_form': SiteSearchForm(), 'search_form': SiteSearchForm(),
'whiteboard_messages': wb_messages, 'whiteboard_messages': wb_messages,
'usersubscriptions': usersubscriptions,
'userlanguages': userlanguages,
'componentlists': componentlists,
'active_tab_slug': active_tab_slug,
'active_tab_label': dashboard_choices.get(active_tab_id)
} }
) )
......
...@@ -21,13 +21,13 @@ ...@@ -21,13 +21,13 @@
import os.path import os.path
from io import BytesIO from io import BytesIO
from django.utils.translation import ugettext as _
from django.template.loader import render_to_string
from PIL import Image, ImageDraw from PIL import Image, ImageDraw
from six.moves.urllib.parse import quote from six.moves.urllib.parse import quote
from django.utils.translation import ugettext as _
from django.template.loader import render_to_string
from weblate.trans.fonts import is_base, get_font from weblate.trans.fonts import is_base, get_font
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment