0.2.3 #99

Merged
sonny merged 112 commits from development into master 2020-05-23 16:58:42 +02:00
80 changed files with 525 additions and 775 deletions
Showing only changes of commit a4b5373ed2 - Show all commits

View file

@ -0,0 +1,17 @@
{% extends "components/form/form.html" %}
{% load i18n %}
{% block actions %}
<section class="section form__section--last">
<fieldset class="fieldset form__fieldset">
{% include "components/form/cancel-button.html" %}
{% include "components/form/confirm-button.html" %}
</fieldset>
<fieldset class="fieldset form__fieldset">
<a class="link" href="{% url 'accounts:password-reset' %}">
<small class="small">{% trans "I forgot my password" %}</small>
</a>
</fieldset>
</section>
{% endblock actions %}

View file

@ -0,0 +1,18 @@
{% extends "components/form/form.html" %}
{% load i18n %}
{% block actions %}
<section class="section form__section--last">
<fieldset class="fieldset form__fieldset">
{% include "components/form/cancel-button.html" %}
</fieldset>
<fieldset class="fieldset form__fieldset">
<a class="link button button--primary" href="{% url 'accounts:password-change' %}">
{% trans "Change password" %}
</a>
{% include "components/form/confirm-button.html" %}
</fieldset>
</section>
{% endblock actions %}

View file

@ -1,24 +0,0 @@
{% extends "base.html" %}
{% load static %}
{% block content %}
<main id="login--page" class="main">
<form class="form login-form" method="POST" action="{% url 'accounts:login' %}">
{% csrf_token %}
<div class="form__header">
<h1 class="form__title">Login</h1>
</div>
<fieldset class="login-form__fieldset">
{{ form }}
</fieldset>
<fieldset class="login-form__fieldset">
<button class="button button--confirm" type="submit">Login</button>
<a class="link" href="{% url 'accounts:password-reset' %}">
<small class="small">I forgot my password</small>
</a>
</fieldset>
</form>
</main>
{% endblock %}

View file

@ -1,22 +0,0 @@
{% extends "base.html" %}
{% load static i18n %}
{% block content %}
<main class="main">
<form class="form password-change-form" method="post">
{% csrf_token %}
<div class="form__header">
<h1 class="h1 form__title">{% trans "Password change" %}</h1>
</div>
<fieldset class="fieldset password-change-form__fieldset">
{{ form }}
</fieldset>
<fieldset class="fieldset password-reset-form__fieldset">
<a class="button button--cancel" href="{% url 'accounts:settings' %}">Cancel</a>
<button class="button button--confirm" type="submit">Change</button>
</fieldset>
</form>
</main>
{% endblock %}

View file

@ -1,42 +0,0 @@
{% extends "base.html" %}
{% load i18n %}
{% block content %}
<main id="settings--page" class="main">
<form class="form settings-form" method="post">
{% csrf_token %}
<div class="form__header">
<h1 class="h1 form__title">{% trans "User settings" %}</h1>
</div>
{{ form.non_field_errors }}
<section class="section form__section settings-form__section">
<fieldset class="form__fieldset settings-form__fieldset">
<label class="label settings-form__label" for="first_name">{% trans "First name" %}</label>
{{ form.first_name.errors }}
{{ form.first_name }}
</fieldset>
<fieldset class="form__fieldset settings-form__fieldset">
<label class="label settings-form__label" for="last_name">{% trans "Last name" %}</label>
{{ form.last_name.errors }}
{{ form.last_name }}
</fieldset>
</section>
<section class="section form__section settings-form__section">
<fieldset class="form__fieldset settings-form__fieldset">
<a class="link button button--cancel" href="{% url 'index' %}">Cancel</a>
<span class="span">
<a class="link button button--primary" href="{% url 'accounts:password-change' %}">
{% trans "Change password" %}
</a>
<button class="button button--confirm">Save</button>
</span>
</fieldset>
</section>
</form>
</main>
{% endblock %}

View file

@ -0,0 +1,7 @@
{% extends "base.html" %}
{% block content %}
<main id="login--page" class="main">
{% include "accounts/components/login-form.html" with form=form title="Login" confirm_text="Login" %}
</main>
{% endblock %}

View file

@ -0,0 +1,8 @@
{% extends "base.html" %}
{% block content %}
<main id="password-change--page" class="main">
{% url 'accounts:settings' as cancel_url %}
{% include "components/form/form.html" with form=form title="Change password" confirm_text="Change password" cancel_url=cancel_url %}
</main>
{% endblock %}

View file

@ -0,0 +1,7 @@
{% extends "base.html" %}
{% block content %}
<main id="settings--page" class="main">
{% include "accounts/components/settings-form.html" with form=form title="User profile" confirm_text="Save" %}
</main>
{% endblock %}

View file

@ -11,7 +11,7 @@ from newsreader.accounts.models import User
class LoginView(django_views.LoginView): class LoginView(django_views.LoginView):
template_name = "accounts/login.html" template_name = "accounts/views/login.html"
success_url = reverse_lazy("index") success_url = reverse_lazy("index")
@ -74,32 +74,32 @@ class ActivationResendView(registration_views.ResendActivationView):
# prompts for a new password # prompts for a new password
# PasswordResetCompleteView shows a success message for the above # PasswordResetCompleteView shows a success message for the above
class PasswordResetView(django_views.PasswordResetView): class PasswordResetView(django_views.PasswordResetView):
template_name = "password-reset/password_reset_form.html" template_name = "password-reset/password-reset.html"
subject_template_name = "password-reset/password_reset_subject.txt" subject_template_name = "password-reset/password-reset-subject.txt"
email_template_name = "password-reset/password_reset_email.html" email_template_name = "password-reset/password-reset-email.html"
success_url = reverse_lazy("accounts:password-reset-done") success_url = reverse_lazy("accounts:password-reset-done")
class PasswordResetDoneView(django_views.PasswordResetDoneView): class PasswordResetDoneView(django_views.PasswordResetDoneView):
template_name = "password-reset/password_reset_done.html" template_name = "password-reset/password-reset-done.html"
class PasswordResetConfirmView(django_views.PasswordResetConfirmView): class PasswordResetConfirmView(django_views.PasswordResetConfirmView):
template_name = "password-reset/password_reset_confirm.html" template_name = "password-reset/password-reset-confirm.html"
success_url = reverse_lazy("accounts:password-reset-complete") success_url = reverse_lazy("accounts:password-reset-complete")
class PasswordResetCompleteView(django_views.PasswordResetCompleteView): class PasswordResetCompleteView(django_views.PasswordResetCompleteView):
template_name = "password-reset/password_reset_complete.html" template_name = "password-reset/password-reset-complete.html"
class PasswordChangeView(django_views.PasswordChangeView): class PasswordChangeView(django_views.PasswordChangeView):
template_name = "accounts/password_change.html" template_name = "accounts/views/password-change.html"
success_url = reverse_lazy("accounts:settings") success_url = reverse_lazy("accounts:settings")
class SettingsView(ModelFormMixin, FormView): class SettingsView(ModelFormMixin, FormView):
template_name = "accounts/settings.html" template_name = "accounts/views/settings.html"
success_url = reverse_lazy("accounts:settings") success_url = reverse_lazy("accounts:settings")
form_class = UserSettingsForm form_class = UserSettingsForm
model = User model = User

View file

@ -172,6 +172,8 @@ AUTH_PASSWORD_VALIDATORS = [
# Authentication user model # Authentication user model
AUTH_USER_MODEL = "accounts.User" AUTH_USER_MODEL = "accounts.User"
LOGIN_REDIRECT_URL = "/"
# Internationalization # Internationalization
# https://docs.djangoproject.com/en/2.2/topics/i18n/ # https://docs.djangoproject.com/en/2.2/topics/i18n/
LANGUAGE_CODE = "en-us" LANGUAGE_CODE = "en-us"

View file

@ -1,4 +1,5 @@
from django import forms from django import forms
from django.utils.translation import gettext_lazy as _
import pytz import pytz
@ -11,6 +12,7 @@ class CollectionRuleForm(forms.ModelForm):
timezone = forms.ChoiceField( timezone = forms.ChoiceField(
widget=forms.Select(attrs={"size": len(pytz.all_timezones)}), widget=forms.Select(attrs={"size": len(pytz.all_timezones)}),
choices=((timezone, timezone) for timezone in pytz.all_timezones), choices=((timezone, timezone) for timezone in pytz.all_timezones),
help_text=_("The timezone which the feed uses"),
) )
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):

View file

@ -1,37 +0,0 @@
{% extends "base.html" %}
{% load static i18n %}
{% block content %}
<main id="import--page" class="main">
<form class="form import-form" method="post" enctype="multipart/form-data">
{% csrf_token %}
{{ form.non_field_errors }}
<div class="form__header">
<h1 class="h1 form__title">{% trans "Import an OPML file" %}</h1>
</div>
<section class="section form__section import-form__section">
<fieldset class="form__fieldset import-form__fieldset">
<label class="label import-form__label" for="name">
{% trans "File" %}
</label>
{{ form.file.errors }}
{{ form.file }}
</fieldset>
<fieldset class="form__fieldset import-form__fieldset">
<label class="label import-form__label" for="name">
{% trans "Skip existing" %}
</label>
{{ form.skip_existing }}
</fieldset>
<fieldset class="form__fieldset import-form__fieldset">
<a class="link button button--cancel" href="{% url 'news:collection:rules' %}">Cancel</a>
<button class="button button--confirm">Import</button>
</fieldset>
</section>
</form>
</main>
{% endblock %}

View file

@ -1,9 +0,0 @@
{% extends "collection/rule.html" %}
{% block form-header %}
<h1 class="h1 form__title">Create a rule</h1>
{% endblock %}
{% block confirm-button %}
<button class="button button--confirm">Create rule</button>
{% endblock %}

View file

@ -1,9 +0,0 @@
{% extends "collection/rule.html" %}
{% block form-header %}
<h1 class="h1 form__title">Update rule</h1>
{% endblock %}
{% block confirm-button %}
<button class="button button--confirm">Save rule</button>
{% endblock %}

View file

@ -1,55 +0,0 @@
{% extends "base.html" %}
{% load static %}
{% block content %}
<main id="rule--page" class="main">
<form class="form rule-form" method="post">
{% csrf_token %}
{{ form.non_field_errors }}
<div class="form__header">
{% block form-header %}{% endblock %}
</div>
<section class="section form__section rule-form__section">
<fieldset class="form__fieldset rule-form__fieldset">
<label class="label" for="name">Name</label>
{{ form.name.errors }}
{{ form.name }}
</fieldset>
<fieldset class="form__fieldset rule-form__fieldset">
<label class="label" for="name">Category</label>
{{ form.category.errors }}
{{ form.category }}
</fieldset>
<fieldset class="form__fieldset rule-form__fieldset">
<label class="label" for="name">Feed url</label>
{{ form.url.errors }}
{{ form.url }}
</fieldset>
<fieldset class="form__fieldset rule-form__fieldset">
<label class="label" for="name">Favicon url</label>
{{ form.favicon.errors }}
{{ form.favicon }}
</fieldset>
<fieldset class="form__fieldset rule-form__fieldset">
<label class="label" for="name">Timezone</label>
<small class="small helptext">The timezone which the feed uses</small>
{{ form.timezone.errors }}
{{ form.timezone }}
</fieldset>
</section>
<section class="section form__section rule-form__section">
<fieldset class="form__fieldset rule-form__fieldset">
<a class="link button button--cancel" href="{% url 'news:collection:rules' %}">Cancel</a>
{% block confirm-button %}{% endblock %}
</fieldset>
</section>
</form>
</main>
{% endblock %}

View file

@ -1,69 +0,0 @@
{% extends "base.html" %}
{% load i18n static %}
{% block content %}
<main id="rules--page" class="main">
<form class="form rules-form">
{% csrf_token %}
<div class="form__actions">
<input type="submit" class="button button--primary" formaction="{% url "news:collection:rules-enable" %}" formmethod="post" value="{% trans "Enable" %}" />
<input type="submit" class="button button--primary" formaction="{% url "news:collection:rules-disable" %}" formmethod="post" value="{% trans "Disable" %}" />
<input type="submit" class="button button--error" formaction="{% url "news:collection:rules-delete" %}" formmethod="post" value="{% trans "Delete" %}"/>
</div>
<table class="table rules-table">
<thead class="table__header rules-table__header">
<tr class="table__row rules-table__row">
<th class="table__heading rules-table__heading--select">
<input type="checkbox" id="select-all" data-input="rules" />
</th>
<th class="table__heading rules-table__heading--name">{% trans "Name" %}</th>
<th class="table__heading rules-table__heading--category">{% trans "Category" %}</th>
<th class="table__heading rules-table__heading--url">{% trans "URL" %}</th>
<th class="table__heading rules-table__heading--succeeded">{% trans "Successfuly ran" %}</th>
<th class="table__heading rules-table__heading--enabled">{% trans "Enabled" %}</th>
<th class="table__heading rules-table__heading--link"></th>
</tr>
</thead>
<tbody class="table__body">
{% for rule in rules %}
<tr class="table__row rules-table__row">
<td class="table__item rules-table__item"><input name="rules" type="checkbox" value="{{ rule.pk }}" /></td>
<td class="table__item rules-table__item" title="{{ rule.name }}">{{ rule.name }}</td>
<td class="table__item rules-table__item" title="{{ rule.category.name }}">{{ rule.category.name }}</td>
<td class="table__item rules-table__item" title="{{ rule.url }}">{{ rule.url }}</td>
<td class="table__item rules-table__item" title="{{ rule.succeeded }}">{{ rule.succeeded }}</td>
<td class="table__item rules-table__item" title="{{ rule.enabled }}">{{ rule.enabled }}</td>
<td class="table__item rules-table__item">
<a class="link" href="{% url "news:collection:rule-update" rule.pk %}"><i class="gg-pen"></i></a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</form>
<div class="table__footer">
<div class="pagination">
<span class="pagination__previous">
{% if page_obj.has_previous %}
<a class="link button" href="?page=1">{% trans "first" %}</a>
<a class="link button" href="?page={{ page_obj.previous_page_number }}">{% trans "previous" %}</a>
{% endif %}
</span>
<span class="pagination__current">
{% blocktrans with current_number=page_obj.number total_count=page_obj.paginator.num_pages %}
Page {{ current_number }} of {{ total_count }}
{% endblocktrans %}
</span>
<span class="pagination__next">
{% if page_obj.has_next %}
<a class="link button" href="?page={{ page_obj.next_page_number }}">{% trans "next" %}</a>
<a class="link button" href="?page={{ page_obj.paginator.num_pages }}">{% trans "last" %}</a>
{% endif %}
</span>
</div>
</div>
</main>
{% endblock %}

View file

@ -0,0 +1,9 @@
{% extends "base.html" %}
{% load static %}
{% block content %}
<main id="import--page" class="main">
{% url "news:collection:rules" as cancel_url %}
{% include "components/form/form.html" with form=form title="Import an OPML file" cancel_url=cancel_url confirm_text="Import rules" %}
</main>
{% endblock %}

View file

@ -0,0 +1,9 @@
{% extends "base.html" %}
{% load static %}
{% block content %}
<main id="rule--page" class="main">
{% url "news:collection:rules" as cancel_url %}
{% include "components/form/form.html" with form=form title="Create rule" cancel_url=cancel_url confirm_text="Create rule" %}
</main>
{% endblock %}

View file

@ -0,0 +1,9 @@
{% extends "base.html" %}
{% load static %}
{% block content %}
<main id="rule--page" class="main">
{% url "news:collection:rules" as cancel_url %}
{% include "components/form/form.html" with form=form title="Update rule" cancel_url=cancel_url confirm_text="Save rule" %}
</main>
{% endblock %}

View file

@ -0,0 +1,79 @@
{% extends "base.html" %}
{% load i18n static %}
{% block content %}
<main id="rules--page" class="main">
<form class="form rules-form">
{% csrf_token %}
<section class="section form__section form__section--actions">
<fieldset class="fieldset form__fieldset">
<input type="submit" class="button button--primary" formaction="{% url "news:collection:rules-enable" %}" formmethod="post" value="{% trans "Enable" %}" />
<input type="submit" class="button button--primary" formaction="{% url "news:collection:rules-disable" %}" formmethod="post" value="{% trans "Disable" %}" />
<input type="submit" class="button button--error" formaction="{% url "news:collection:rules-delete" %}" formmethod="post" value="{% trans "Delete" %}"/>
</fieldset>
<div class="form__actions">
<a class="link button button--confirm" href="{% url "news:collection:rule-create" %}">{% trans "Add a rule" %}</a>
</div>
</section>
<section class="section form__section">
<table class="table rules-table">
<thead class="table__header rules-table__header">
<tr class="table__row rules-table__row">
<th class="table__heading rules-table__heading--select">
<input type="checkbox" id="select-all" data-input="rules" />
</th>
<th class="table__heading rules-table__heading--name">{% trans "Name" %}</th>
<th class="table__heading rules-table__heading--category">{% trans "Category" %}</th>
<th class="table__heading rules-table__heading--url">{% trans "URL" %}</th>
<th class="table__heading rules-table__heading--succeeded">{% trans "Successfuly ran" %}</th>
<th class="table__heading rules-table__heading--enabled">{% trans "Enabled" %}</th>
<th class="table__heading rules-table__heading--link"></th>
</tr>
</thead>
<tbody class="table__body">
{% for rule in rules %}
<tr class="table__row rules-table__row">
<td class="table__item rules-table__item"><input name="rules" type="checkbox" value="{{ rule.pk }}" /></td>
<td class="table__item rules-table__item" title="{{ rule.name }}">{{ rule.name }}</td>
<td class="table__item rules-table__item" title="{{ rule.category.name }}">{{ rule.category.name }}</td>
<td class="table__item rules-table__item" title="{{ rule.url }}">{{ rule.url }}</td>
<td class="table__item rules-table__item" title="{{ rule.succeeded }}">{{ rule.succeeded }}</td>
<td class="table__item rules-table__item" title="{{ rule.enabled }}">{{ rule.enabled }}</td>
<td class="table__item rules-table__item">
<a class="link" href="{% url "news:collection:rule-update" rule.pk %}"><i class="gg-pen"></i></a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</section>
</form>
<div class="table__footer">
<div class="pagination">
<span class="pagination__previous">
{% if page_obj.has_previous %}
<a class="link button" href="?page=1">{% trans "first" %}</a>
<a class="link button" href="?page={{ page_obj.previous_page_number }}">{% trans "previous" %}</a>
{% endif %}
</span>
<span class="pagination__current">
{% blocktrans with current_number=page_obj.number total_count=page_obj.paginator.num_pages %}
Page {{ current_number }} of {{ total_count }}
{% endblocktrans %}
</span>
<span class="pagination__next">
{% if page_obj.has_next %}
<a class="link button" href="?page={{ page_obj.next_page_number }}">{% trans "next" %}</a>
<a class="link button" href="?page={{ page_obj.paginator.num_pages }}">{% trans "last" %}</a>
{% endif %}
</span>
</div>
</div>
</main>
{% endblock %}

View file

@ -48,21 +48,21 @@ class CollectionRuleDetailMixin:
class CollectionRuleListView(CollectionRuleViewMixin, ListView): class CollectionRuleListView(CollectionRuleViewMixin, ListView):
paginate_by = 50 paginate_by = 50
template_name = "collection/rules.html" template_name = "news/collection/views/rules.html"
context_object_name = "rules" context_object_name = "rules"
class CollectionRuleUpdateView( class CollectionRuleUpdateView(
CollectionRuleViewMixin, CollectionRuleDetailMixin, UpdateView CollectionRuleViewMixin, CollectionRuleDetailMixin, UpdateView
): ):
template_name = "collection/rule-update.html" template_name = "news/collection/views/rule-update.html"
context_object_name = "rule" context_object_name = "rule"
class CollectionRuleCreateView( class CollectionRuleCreateView(
CollectionRuleViewMixin, CollectionRuleDetailMixin, CreateView CollectionRuleViewMixin, CollectionRuleDetailMixin, CreateView
): ):
template_name = "collection/rule-create.html" template_name = "news/collection/views/rule-create.html"
class CollectionRuleBulkView(FormView): class CollectionRuleBulkView(FormView):
@ -122,7 +122,7 @@ class CollectionRuleBulkDeleteView(CollectionRuleBulkView):
class OPMLImportView(FormView): class OPMLImportView(FormView):
form_class = OPMLImportForm form_class = OPMLImportForm
success_url = reverse_lazy("news:collection:rules") success_url = reverse_lazy("news:collection:rules")
template_name = "collection/import.html" template_name = "news/collection/views/import.html"
def form_valid(self, form): def form_valid(self, form):
user = self.request.user user = self.request.user

View file

@ -1,15 +1,27 @@
from django import forms from django import forms
from django.forms.widgets import CheckboxSelectMultiple
from newsreader.accounts.models import User from newsreader.accounts.models import User
from newsreader.news.collection.models import CollectionRule from newsreader.news.collection.models import CollectionRule
from newsreader.news.core.models import Category from newsreader.news.core.models import Category
class RulesWidget(CheckboxSelectMultiple):
template_name = "news/core/widgets/rules.html"
option_template_name = "news/core/widgets/rule.html"
def create_option(self, *args, **kwargs):
option = super().create_option(*args, **kwargs)
instance = self.choices.queryset.get(pk=option["value"])
if self.category and instance.category:
option["selected"] = self.category.pk == instance.category.pk
return {**option, "instance": instance}
class CategoryForm(forms.ModelForm): class CategoryForm(forms.ModelForm):
rules = forms.ModelMultipleChoiceField( rules = forms.ModelMultipleChoiceField(
required=False, required=False, queryset=CollectionRule.objects.none(), widget=RulesWidget
queryset=CollectionRule.objects.all(),
widget=forms.widgets.CheckboxSelectMultiple,
) )
user = forms.ModelChoiceField( user = forms.ModelChoiceField(
@ -23,6 +35,8 @@ class CategoryForm(forms.ModelForm):
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)
self.fields["rules"].queryset = CollectionRule.objects.filter(user=self.user) self.fields["rules"].queryset = CollectionRule.objects.filter(user=self.user)
self.fields["rules"].widget.category = self.instance
self.fields["user"].queryset = User.objects.filter(pk=self.user.pk) self.fields["user"].queryset = User.objects.filter(pk=self.user.pk)
self.initial["user"] = self.user self.initial["user"] = self.user

View file

@ -1,9 +0,0 @@
{% extends "core/category.html" %}
{% block form-header %}
<h1 class="h1 form__title">Create a category</h1>
{% endblock %}
{% block confirm-button %}
<button class="button button--confirm">Create category</button>
{% endblock %}

View file

@ -1,9 +0,0 @@
{% extends "core/category.html" %}
{% block form-header %}
<h1 class="h1 form__title">Update category</h1>
{% endblock %}
{% block confirm-button %}
<button class="button button--confirm">Save category</button>
{% endblock %}

View file

@ -1,62 +0,0 @@
{% extends "base.html" %}
{% load static %}
{% block content %}
<main id="category--page" class="main">
<form class="form category-form" method="post">
{% csrf_token %}
<div class="form__header">
{% block form-header %}{% endblock %}
</div>
{{ form.non_field_errors }}
{{ form.user.errors }}
{{ form.user }}
<section class="section form__section category-form__section">
<fieldset class="form__fieldset category-form__fieldset">
<label class="label category-form__label" for="name">Name</label>
{{ form.name.errors }}
{{ form.name }}
</fieldset>
</section>
<section class="section form__section category-form__section">
<fieldset class="form__fieldset category-form__fieldset">
<label class="label category-form__label" for="rules">Collection rules</label>
<small class="small help-text">
Note that existing assigned rules will be reassigned to this category
</small>
{{ form.rules.errors }}
<ul class="list checkbox-list">
{% for rule in rules %}
<li class="list__item checkbox-list__item">
<input class="input category-form__input" type="checkbox" name="rules"
{% if category and rule.pk in category.rule_ids %}checked{% endif %}
value="{{ rule.pk }}" />
{% if rule.favicon %}
<img class="favicon" src="{{ rule.favicon }}" />
{% else %}
<i class="gg-image"></i>
{% endif %}
<span>{{ rule.name }}</span>
</li>
{% endfor %}
</ul>
</fieldset>
</section>
<section class="section form__section category-form__section">
<fieldset class="form__fieldset category-form__fieldset">
<a class="link button button--cancel" href="{% url 'news:core:categories' %}">Cancel</a>
{% block confirm-button %}{% endblock %}
</fieldset>
</section>
</form>
</main>
{% endblock %}

View file

@ -1,5 +1,4 @@
{% extends "base.html" %} {% extends "base.html" %}
{% load static %} {% load static %}
{% block content %} {% block content %}

View file

@ -0,0 +1,9 @@
{% extends "base.html" %}
{% load static %}
{% block content %}
<main id="category--page" class="main">
{% url "news:core:categories" as cancel_url %}
{% include "components/form/form.html" with form=form title="Create category" cancel_url=cancel_url confirm_text="Create category" %}
</main>
{% endblock %}

View file

@ -0,0 +1,9 @@
{% extends "base.html" %}
{% load static %}
{% block content %}
<main id="category--page" class="main">
{% url "news:core:categories" as cancel_url %}
{% include "components/form/form.html" with form=form title="Update category" cancel_url=cancel_url confirm_text="Save category" %}
</main>
{% endblock %}

View file

@ -1,5 +1,4 @@
{% extends "base.html" %} {% extends "base.html" %}
{% load static %} {% load static %}
{% block content %} {% block content %}

View file

@ -0,0 +1,10 @@
<input class="input category-form__input" type="{{ option.type }}"
name="{{ option.name }}" value="{{ option.value|stringformat:'s' }}"{% if option.selected %} checked{% endif %} />
{% if option.instance.favicon %}
<img class="favicon" src="{{ option.instance.favicon }}" />
{% else %}
<i class="gg-image"></i>
{% endif %}
<span>{{ option.label }}</span>

View file

@ -0,0 +1,9 @@
<ul class="list checkbox-list">
{% for group, options, index in widget.optgroups %}
{% for option in options %}
<li class="list__item checkbox-list__item">
{% include "news/core/widgets/rule.html" with option=option only %}
</li>
{% endfor %}
{% endfor %}
</ul>

View file

@ -9,7 +9,7 @@ from newsreader.news.core.models import Category
class NewsView(TemplateView): class NewsView(TemplateView):
template_name = "core/homepage.html" template_name = "news/core/views/homepage.html"
# TODO serialize objects to show filled main page # TODO serialize objects to show filled main page
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
@ -55,14 +55,14 @@ class CategoryDetailMixin:
class CategoryListView(CategoryViewMixin, ListView): class CategoryListView(CategoryViewMixin, ListView):
template_name = "core/categories.html" template_name = "news/core/views/categories.html"
context_object_name = "categories" context_object_name = "categories"
class CategoryUpdateView(CategoryViewMixin, CategoryDetailMixin, UpdateView): class CategoryUpdateView(CategoryViewMixin, CategoryDetailMixin, UpdateView):
template_name = "core/category-update.html" template_name = "news/core/views/category-update.html"
context_object_name = "category" context_object_name = "category"
class CategoryCreateView(CategoryViewMixin, CategoryDetailMixin, CreateView): class CategoryCreateView(CategoryViewMixin, CategoryDetailMixin, CreateView):
template_name = "core/category-create.html" template_name = "news/core/views/category-create.html"

View file

@ -1,11 +0,0 @@
.activation-form {
margin: 10px 0;
& h4 {
padding: 20px 24px 5px 24px;
}
&__fieldset:last-child {
flex-direction: row;
justify-content: space-between;
}
}

View file

@ -1,13 +0,0 @@
.category-form {
@extend .form;
margin: 20px 0;
&__section:last-child {
& .category-form__fieldset {
display: flex;
flex-direction: row;
justify-content: space-between;
}
}
}

View file

@ -1,3 +1,5 @@
@import "mixin.scss";
.form { .form {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
@ -8,6 +10,29 @@
font-family: $form-font; font-family: $form-font;
background-color: $white; background-color: $white;
&__section {
&--last {
& .form__fieldset {
display: flex;
flex-direction: row;
justify-content: space-between;
}
}
&--actions {
display: flex;
flex-direction: row !important;
& .form__fieldset {
flex-direction: row;
& > * {
margin: 0 0 0 5px;
}
}
}
}
&__fieldset { &__fieldset {
@extend .fieldset; @extend .fieldset;
} }
@ -16,21 +41,24 @@
display: flex; display: flex;
flex-direction: row; flex-direction: row;
padding: 15px; @include form-padding;
} }
&__actions { &__actions {
display: flex; display: flex;
justify-content: space-between; flex-direction: row;
width: 50%; @include form-padding;
padding: 15px;
} }
&__title { &__title {
font-size: 18px; font-size: 18px;
} }
&__intro {
@include form-padding;
}
& .favicon { & .favicon {
height: 20px; height: 20px;
} }

View file

@ -1,17 +0,0 @@
.import-form {
margin: 20px 0;
&__fieldset:last-child {
display: flex;
flex-direction: row;
justify-content: space-between;
}
& input[type=file] {
width: 50%;
}
& input[type=checkbox] {
margin: 0 auto 0 10px;
}
}

View file

@ -1,33 +0,0 @@
.login-form {
@extend .form;
width: 100%;
h4 {
margin: 0;
padding: 20px 24px 5px 24px;
}
&__fieldset {
@extend .form__fieldset;
& label {
@extend .label;
}
& input {
@extend .input;
}
}
&__fieldset:last-child {
flex-direction: row-reverse;
justify-content: space-between;
}
&__fieldset:last-child {
.button {
padding: 10px 50px;
}
}
}

View file

@ -0,0 +1,3 @@
@mixin form-padding {
padding: 15px;
}

View file

@ -1,3 +0,0 @@
.password-reset-confirm-form {
margin: 20px 0;
}

View file

@ -1,18 +0,0 @@
.password-reset-form {
margin: 20px 0;
&__fieldset:last-child {
display: flex;
flex-direction: row;
justify-content: space-between;
}
& .form__header {
display: flex;
flex-direction: column;
}
& .form__title {
margin: 0 0 5px 0;
}
}

View file

@ -1,11 +0,0 @@
.register-form {
margin: 10px 0;
& h4 {
padding: 20px 24px 5px 24px;
}
&__fieldset:last-child {
flex-direction: row;
justify-content: space-between;
}
}

View file

@ -1,25 +0,0 @@
.rule-form {
margin: 20px 0;
&__section:last-child {
& .rule-form__fieldset {
display: flex;
flex-direction: row;
justify-content: space-between;
}
}
#id_category {
width: 50%;
padding: 0 10px;
}
#id_timezone {
max-height: 200px;
width: 50%;
margin: 0 15px;
padding: 0 10px;
}
}

View file

@ -1,9 +0,0 @@
.settings-form {
&__section:last-child {
& .settings-form__fieldset {
display: flex;
flex-direction: row;
justify-content: space-between;
}
}
}

View file

@ -1,15 +1,3 @@
@import "form"; @import "form";
@import "category-form";
@import "rule-form";
@import "rules-form"; @import "rules-form";
@import "import-form";
@import "login-form";
@import "activation-form";
@import "register-form";
@import "password-reset-form";
@import "password-reset-confirm-form";
@import "settings-form";

View file

@ -1,10 +1,11 @@
@import "badge/index";
@import "button/index"; @import "button/index";
@import "help-text/index";
@import "input/index";
@import "label/index";
@import "link/index"; @import "link/index";
@import "h1/index"; @import "h1/index";
@import "h2/index"; @import "h2/index";
@import "h3/index"; @import "h3/index";
@import "small/index"; @import "small/index";
@import "input/index"; @import "select/index";
@import "label/index";
@import "help-text/index";
@import "badge/index";

View file

@ -8,6 +8,15 @@
&:focus { &:focus {
border: 1px $focus-blue solid; border: 1px $focus-blue solid;
} }
&[type="file"] {
width: 40%;
}
&[type="checkbox"] {
align-self: flex-start;
margin: 0 0 0 10px;
}
} }
input { input {

View file

@ -0,0 +1,13 @@
.select {
max-height: 200px;
&:not([size]){
width: 40%;
}
padding: 0 15px;
}
select {
@extend .select;
}

View file

@ -0,0 +1 @@
@import "select";

View file

@ -3,4 +3,29 @@
width: 50%; width: 50%;
border-radius: 4px; border-radius: 4px;
& .form {
@extend .form;
width: 100%;
h4 {
margin: 0;
padding: 20px 24px 5px 24px;
}
&__section {
&--last {
flex-direction: row-reverse;
justify-content: space-between;
}
}
&__fieldset {
@extend .form__fieldset;
&--last {
}
}
}
} }

View file

@ -0,0 +1,13 @@
<div class="card">
{% if header_text %}
{% include "components/card/header.html" %}
{% endif %}
{% if content %}
{% include "components/card/content.html" %}
{% endif %}
{% if footer_text %}
{% include "components/card/footer.html" %}
{% endif %}
</div>

View file

@ -0,0 +1,3 @@
<div class="card__content">
<p>{{ content }}</p>
</div>

View file

@ -0,0 +1,3 @@
<div class="card__footer">
<p>{{ footer_text }}</p>
</div>

View file

@ -0,0 +1,3 @@
<div class="card__header">
<h1>{{ header_text }}</h1>
</div>

View file

@ -0,0 +1,5 @@
{% load i18n %}
{% if cancel_url %}
<a class="link button button--cancel" href="{{ cancel_url }}">{% trans "Cancel" %}</a>
{% endif %}

View file

@ -0,0 +1,9 @@
{% load i18n %}
<button class="button button--confirm">
{% if confirm_text %}
{{ confirm_text }}
{% else %}
{% trans "Save" %}
{% endif %}
</button>

View file

@ -0,0 +1,3 @@
<section class="section form__section form__section--errors">
{{ errors }}
</section>

View file

@ -0,0 +1,43 @@
{% load i18n %}
<form class="form{% if classes %} {{ classes }}{% endif %}" method="{{ method|default:"post" }}" enctype="multipart/form-data">
{% csrf_token %}
{% if title %}
{% include "components/form/title.html" with title=title only %}
{% endif %}
{% block intro %}
{% endblock intro %}
{% if form.non_field_errors %}
{% include "components/form/errors.html" with errors=form.non_field_errors only %}
{% endif %}
{% block fields %}
<section class="section form__section">
{% for field in form.hidden_fields %}
{{ field }}
{% endfor %}
{% for field in form.visible_fields %}
<fieldset class="fieldset form__fieldset">
{% include "components/form/label.html" %}
{{ field.errors }}
{{ field }}
{% include "components/form/help-text.html" %}
</fieldset>
{% endfor %}
</section>
{% endblock fields %}
{% block actions %}
<section class="section form__section--last">
<fieldset class="fieldset form__fieldset">
{% include "components/form/cancel-button.html" %}
{% include "components/form/confirm-button.html" %}
</fieldset>
</section>
{% endblock actions %}
</form>

View file

@ -0,0 +1 @@
<small class="small helptext">{{ field.help_text }}</small>

View file

@ -0,0 +1,3 @@
<label class="label form__label" for="{{ field.name }}">
{{ field.label }}
</label>

View file

@ -0,0 +1,3 @@
<section class="section form__header">
<h1 class="h1 form__title">{{ title }}</h1>
</section>

View file

@ -0,0 +1,13 @@
{% extends "base.html" %}
{% load i18n %}
{% block content %}
<main class="main">
{% trans "Password reset complete" as header_text %}
{% blocktrans asvar content %}
You may now <a href="{{ login_url }}">log in</a>
{% endblocktrans %}
{% include "components/card/card.html" with header_text=header_text content=content %}
</main>
{% endblock %}

View file

@ -0,0 +1,30 @@
{% extends "base.html" %}
{% load i18n %}
{% block meta %}
<!-- NOTE(joshblum): This prevents leaking the password reset token via the
Referer header to any 3rd party apps on the page. -->
<meta name="referrer" content="origin">
{% endblock %}
{% block content %}
<main class="main">
{% if validlink %}
{% url 'accounts:login' as cancel_url %}
{% trans "Enter your new password below to reset your password:" as title %}
{% trans "Change password" as confirm_text %}
{% include "components/form/form.html" with form=form title=title confirm_text=confirm_text cancel_url=cancel_url %}
{% else %}
{% trans "Password reset unsuccessful" as header_text %}
{% url 'accounts:password-reset' as reset_url %}
{% blocktrans asvar content %}
Password reset unsuccessful. Please
<a class="link" href="{{ reset_url }}">try again.</a>
{% endblocktrans %}
{% include "components/card/card.html" with header_text=header_text content=content %}
{% endif %}
</main>
{% endblock %}
{# This is used by django.contrib.auth #}

View file

@ -0,0 +1,16 @@
{% extends "base.html" %}
{% load static i18n %}
{% block title %}{% trans "Password reset" %}{% endblock %}
{% block content %}
<main class="main">
{% trans "Password reset" as header_text %}
{% blocktrans asvar content %}
We have sent you an email with a link to reset your password. Please check
your email and click the link to continue.
{% endblocktrans %}
{% include "components/card/card.html" with header_text=header_text content=content %}
</main>
{% endblock %}

View file

@ -0,0 +1,11 @@
{% extends "components/form/form.html" %}
{% load i18n %}
{% block intro %}
<p class="form__intro">
{% blocktrans %}
Forgot your password? Enter your email in the form below and we'll send you
instructions for creating a new one.
{% endblocktrans %}
</p>
{% endblock intro %}

View file

@ -0,0 +1,7 @@
{% extends "base.html" %}
{% block content %}
<main class="main">
{% include "password-reset/password-reset-form.html" with form=form title="Reset password" confirm_text="Reset password" %}
</main>
{% endblock %}

View file

@ -1,23 +0,0 @@
{% extends "base.html" %}
{% load static i18n %}
{% block title %}{% trans "Password reset complete" %}{% endblock %}
{% block content %}
<main class="main">
<div class="card">
<div class="card__header">
<h1>{% trans "Password reset complete" %}</h1>
</div>
<div class="card__content">
<p>
{% trans "Your password has been reset!" %}
{% blocktrans %}
You may now <a href="{{ login_url }}">log in</a>
{% endblocktrans %}.
</p>
</div>
<div class="card__footer" />
</div>
</main>
{% endblock %}

View file

@ -1,55 +0,0 @@
{% extends "base.html" %}
{% load static i18n %}
{% block meta %}
<!-- NOTE(joshblum): This prevents leaking the password reset token via the
Referer header to any 3rd party apps on the page. -->
<meta name="referrer" content="origin">
{% endblock %}
{% block title %}{% trans "Confirm password reset" %}{% endblock %}
{% block content %}
<main class="main">
{% if validlink %}
<form class="form password-reset-confirm-form" method="POST">
{% csrf_token %}
<div class="form__header">
<h1 class="form__title">
{% trans "Enter your new password below to reset your password:" %}
</h1>
</div>
<fieldset class="fieldset password-reset-form__fieldset">
{{ form }}
</fieldset>
<fieldset class="fieldset password-reset-form__fieldset">
<a class="button button--cancel" href="{% url 'accounts:login' %}">Cancel</a>
<button class="button button--confirm" type="submit">Change password</button>
</fieldset>
</form>
{% else %}
<div class="card">
<div class="card__header">
<h1>{% trans "Password reset unsuccessful" %}</h1>
</div>
<div class="card__content">
<p>
{% url 'accounts:password-reset' as reset_url %}
{% blocktrans %}
Password reset unsuccessful. Please
<a class="link" href="{{ reset_url }}">try again.</a>
{% endblocktrans %}
</p>
</div>
<div class="card__footer" />
</div>
{% endif %}
</main>
{% endblock %}
{# This is used by django.contrib.auth #}

View file

@ -1,23 +0,0 @@
{% extends "base.html" %}
{% load static i18n %}
{% block title %}{% trans "Password reset" %}{% endblock %}
{% block content %}
<main class="main">
<div class="card">
<div class="card__header">
<h1>{% trans "Password reset" %}</h1>
</div>
<div class="card__content">
<p>
{% blocktrans %}
We have sent you an email with a link to reset your password. Please check
your email and click the link to continue.
{% endblocktrans %}
</p>
</div>
<div class="card__footer" />
</div>
</main>
{% endblock %}

View file

@ -1,30 +0,0 @@
{% extends "base.html" %}
{% load static i18n %}
{% block title %}{% trans "Reset password" %}{% endblock %}
{% block content %}
<main class="main">
<form class="form password-reset-form" method="POST">
{% csrf_token %}
<div class="form__header">
<h1 class="form__title">{% trans "Reset password" %}</h1>
<p>
{% blocktrans %}
Forgot your password? Enter your email in the form below and we'll send you
instructions for creating a new one.
{% endblocktrans %}
</p>
</div>
<fieldset class="fieldset password-reset-form__fieldset">
{{ form }}
</fieldset>
<fieldset class="fieldset password-reset-form__fieldset">
<a class="button button--cancel" href="{% url 'accounts:login' %}">Cancel</a>
<button class="button button--confirm" type="submit">Send reset mail</button>
</fieldset>
</form>
</main>
{% endblock %}

View file

@ -1,7 +1,5 @@
{% extends "base.html" %} {% extends "base.html" %}
{% load static i18n %} {% load i18n %}
{% block title %}{% trans "Account Activated" %}{% endblock %}
{% comment %} {% comment %}
**registration/activation_complete.html** **registration/activation_complete.html**
@ -13,19 +11,14 @@ account is now active.
{% block content %} {% block content %}
<main class="main"> <main class="main">
<div class="card"> {% trans "Account activated" as header_text %}
<div class="card__header">
<h1>{% trans "Account activated" %}</h1> {% if user.is_authenticated %}
</div> {% trans "Your account is activated. You can now log in." as content %}
<div class="card__content"> {% else %}
<p> {% trans "Your account is activated." as content %}
{% trans "Your account is now activated." %}
{% if not user.is_authenticated %}
{% trans "You can log in." %}
{% endif %} {% endif %}
</p>
</div> {% include "components/card/card.html" with header_text=header_text content=content %}
<div class="card__footer" />
</div>
</main> </main>
{% endblock %} {% endblock %}

View file

@ -68,5 +68,5 @@ following context:
``HttpRequest`` instance for better flexibility. ``HttpRequest`` instance for better flexibility.
For example it can be used to compute absolute register URL: For example it can be used to compute absolute register URL:
{{ request.scheme }}://{{ request.get_host }}{% url 'registration_activate' activation_key %} {{ request.scheme }}://{{ request.get_host }}{% url 'accounts:activate' activation_key %}
{% endcomment %} {% endcomment %}

View file

@ -48,5 +48,5 @@ following context:
``HttpRequest`` instance for better flexibility. ``HttpRequest`` instance for better flexibility.
For example it can be used to compute absolute register URL: For example it can be used to compute absolute register URL:
{{ request.scheme }}://{{ request.get_host }}{% url 'registration_activate' activation_key %} {{ request.scheme }}://{{ request.get_host }}{% url 'accounts:activate' activation_key %}
{% endcomment %} {% endcomment %}

View file

@ -1,7 +1,5 @@
{% extends "base.html" %} {% extends "base.html" %}
{% load static i18n %} {% load i18n %}
{% block title %}{% trans "Activation Failure" %}{% endblock %}
{% comment %} {% comment %}
**registration/activate.html** **registration/activate.html**
@ -14,14 +12,8 @@ Used if account activation fails. With the default setup, has the following cont
{% block content %} {% block content %}
<main class="main"> <main class="main">
<div class="card"> {% trans "Activation Failure" as header_text %}
<div class="card__header"> {% trans "Account activation failed." as content %}
<h1>{% trans "Activation Failure" %}</h1> {% include "components/card/card.html" with header_text=header_text content=content %}
</div>
<div class="card__content">
<p>{% trans "Account activation failed." %}</p>
</div>
<div class="card__footer" />
</div>
</main> </main>
{% endblock %} {% endblock %}

View file

@ -14,18 +14,10 @@ the following context:
{% block content %} {% block content %}
<main class="main"> <main class="main">
<div class="card"> {% trans "Account activation resent" as header_text %}
<div class="card__header"> {% blocktrans asvar content %}
<h1>{% trans "Account activation resent" %}</h1>
</div>
<div class="card__content">
<p>
{% blocktrans %}
We have sent an email to {{ email }} with further instructions. We have sent an email to {{ email }} with further instructions.
{% endblocktrans %} {% endblocktrans %}
</p> {% include "components/card/card.html" with header_text=header_text content=content %}
</div>
<div class="card__footer" />
</div>
</main> </main>
{% endblock %} {% endblock %}

View file

@ -1,35 +1,9 @@
{% extends "base.html" %} {% extends "base.html" %}
{% load static i18n %} {% load static %}
{% block title %}{% trans "Resend Activation Email" %}{% endblock %}
{% comment %}
**registration/resend_activation_form.html**
Used to show the form users will fill out to resend the activation email. By
default, has the following context:
``form``
The registration form. This will be an instance of some subclass
of ``django.forms.Form``; consult `Django's forms documentation
<http://docs.djangoproject.com/en/dev/topics/forms/>`_ for
information on how to display this in a template.
{% endcomment %}
{% block content %} {% block content %}
<main class="main"> <main class="main">
<form class="form activation-form" method="POST"> {% url "accounts:login" as cancel_url %}
{% csrf_token %} {% include "components/form/form.html" with form=form title="Resend activation code" cancel_url=cancel_url confirm_text="Resend code" %}
<div class="form__header">
<h1 class="form__title">Resend activation code</h1>
</div>
<fieldset class="fieldset activation-form__fieldset">
{{ form }}
</fieldset>
<fieldset class="fieldset activation-form__fieldset">
<a class="button button--cancel" href="{% url 'accounts:login' %}">Cancel</a>
<button class="button button--confirm" type="submit">Resend code</button>
</fieldset>
</form>
</main> </main>
{% endblock %} {% endblock %}

View file

@ -1,20 +1,10 @@
{% extends "base.html" %} {% extends "base.html" %}
{% load static i18n %} {% load static i18n %}
{% block title %}{% trans "Registration is closed" %}{% endblock %}
{% block content %} {% block content %}
<main class="main"> <main class="main">
<div class="card"> {% trans "Registration is closed" as header_text %}
<div class="card__header"> {% trans "Sorry, but registration is closed at this moment. Come back later." as content %}
<h1>{% trans "Registration is closed" %}</h1> {% include "components/card/card.html" with header_text=header_text content=content %}
</div>
<div class="card__content">
<p>
{% trans "Sorry, but registration is closed at this moment. Come back later." %}
</p>
</div>
<div class="card__footer" />
</div>
</main> </main>
{% endblock %} {% endblock %}

View file

@ -1,7 +1,5 @@
{% extends "base.html" %} {% extends "base.html" %}
{% load static i18n %} {% load i18n %}
{% block title %}{% trans "Activation email sent" %}{% endblock %}
{% comment %} {% comment %}
**registration/registration_complete.html** **registration/registration_complete.html**
@ -14,16 +12,8 @@ been sent.
{% block content %} {% block content %}
<main class="main"> <main class="main">
<div class="card"> {% trans "Activation email sent" as header_text %}
<div class="card__header"> {% trans "Please check your email to complete the registration process." as content %}
<h1>{% trans "Activation email sent" %}</h1> {% include "components/card/card.html" with header_text=header_text content=content %}
</div>
<div class="card__content">
<p>
{% trans "Please check your email to complete the registration process." %}
</p>
</div>
<div class="card__footer" />
</div>
</main> </main>
{% endblock %} {% endblock %}

View file

@ -1,22 +1,9 @@
{% extends "base.html" %} {% extends "base.html" %}
{% load static %} {% load static %}
{% block content %} {% block content %}
<main class="main"> <main class="main">
<form class="form register-form" method="POST"> {% url "accounts:login" as cancel_url %}
{% csrf_token %} {% include "components/form/form.html" with form=form title="Register" cancel_url=cancel_url confirm_text="Register" %}
<div class="form__header">
<h1 class="form__title">Register</h1>
</div>
<fieldset class="fieldset register-form__fieldset">
{{ form }}
</fieldset>
<fieldset class="fieldset register-form__fieldset">
<a class="button button--cancel" href="{% url 'accounts:login' %}">Cancel</a>
<button class="button button--confirm" type="submit">Register</button>
</fieldset>
</form>
</main> </main>
{% endblock %} {% endblock %}