mirror of
https://git.linux-kernel.at/oliver/ivatar.git
synced 2025-11-15 04:28:03 +00:00
Merge branch 'preferences' into 'master'
Feature: Userpreferences See merge request oliver/ivatar!24
This commit is contained in:
@@ -16,6 +16,7 @@ from ivatar.settings import MIN_LENGTH_EMAIL, MAX_LENGTH_EMAIL
|
|||||||
from ivatar.settings import MIN_LENGTH_URL, MAX_LENGTH_URL
|
from ivatar.settings import MIN_LENGTH_URL, MAX_LENGTH_URL
|
||||||
from . models import UnconfirmedEmail, ConfirmedEmail, Photo
|
from . models import UnconfirmedEmail, ConfirmedEmail, Photo
|
||||||
from . models import UnconfirmedOpenId, ConfirmedOpenId
|
from . models import UnconfirmedOpenId, ConfirmedOpenId
|
||||||
|
from . models import UserPreference
|
||||||
|
|
||||||
MAX_NUM_UNCONFIRMED_EMAILS_DEFAULT = 5
|
MAX_NUM_UNCONFIRMED_EMAILS_DEFAULT = 5
|
||||||
|
|
||||||
@@ -180,3 +181,16 @@ class AddOpenIDForm(forms.Form):
|
|||||||
unconfirmed.save()
|
unconfirmed.save()
|
||||||
|
|
||||||
return unconfirmed.pk
|
return unconfirmed.pk
|
||||||
|
|
||||||
|
class UpdatePreferenceForm(forms.ModelForm):
|
||||||
|
'''
|
||||||
|
Form for updating user preferences
|
||||||
|
'''
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
'''
|
||||||
|
Meta class for UpdatePreferenceForm
|
||||||
|
'''
|
||||||
|
model = UserPreference
|
||||||
|
fields = ['theme']
|
||||||
|
|
||||||
|
|||||||
35
ivatar/ivataraccount/migrations/0008_userpreference.py
Normal file
35
ivatar/ivataraccount/migrations/0008_userpreference.py
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
# Generated by Django 2.0.6 on 2018-07-04 12:32
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
|
||||||
|
|
||||||
|
def add_preference_to_user(apps, schema_editor):
|
||||||
|
'''
|
||||||
|
Make sure all users have preferences set up
|
||||||
|
'''
|
||||||
|
from django.contrib.auth.models import User
|
||||||
|
UserPreference = apps.get_model('ivataraccount', 'UserPreference')
|
||||||
|
for u in User.objects.filter(userpreference=None):
|
||||||
|
p = UserPreference.objects.create(user_id=u.pk)
|
||||||
|
p.save()
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('auth', '0009_alter_user_last_name_max_length'),
|
||||||
|
('ivataraccount', '0007_auto_20180627_0624'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='UserPreference',
|
||||||
|
fields=[
|
||||||
|
('theme', models.CharField(choices=[('default', 'Default theme'), ('clime', 'Climes theme')], default='default', max_length=10)),
|
||||||
|
('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, primary_key=True, serialize=False, to=settings.AUTH_USER_MODEL)),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
migrations.RunPython(add_preference_to_user),
|
||||||
|
]
|
||||||
18
ivatar/ivataraccount/migrations/0009_auto_20180705_1152.py
Normal file
18
ivatar/ivataraccount/migrations/0009_auto_20180705_1152.py
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
# Generated by Django 2.0.6 on 2018-07-05 11:52
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('ivataraccount', '0008_userpreference'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='userpreference',
|
||||||
|
name='theme',
|
||||||
|
field=models.CharField(choices=[('default', 'Default theme'), ('clime', 'climes theme'), ('falko', 'falkos theme')], default='default', max_length=10),
|
||||||
|
),
|
||||||
|
]
|
||||||
18
ivatar/ivataraccount/migrations/0010_auto_20180705_1201.py
Normal file
18
ivatar/ivataraccount/migrations/0010_auto_20180705_1201.py
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
# Generated by Django 2.0.6 on 2018-07-05 12:01
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('ivataraccount', '0009_auto_20180705_1152'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='userpreference',
|
||||||
|
name='theme',
|
||||||
|
field=models.CharField(choices=[('default', 'Default theme'), ('falko', 'falkos theme')], default='default', max_length=10),
|
||||||
|
),
|
||||||
|
]
|
||||||
@@ -57,6 +57,32 @@ def pil_format(image_type):
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
class UserPreference(models.Model):
|
||||||
|
'''
|
||||||
|
Holds the user users preferences
|
||||||
|
'''
|
||||||
|
THEMES = (
|
||||||
|
('default', 'Default theme'),
|
||||||
|
# ('clime', 'climes theme'), # Not yet available
|
||||||
|
('falko', 'falkos theme'),
|
||||||
|
)
|
||||||
|
|
||||||
|
theme = models.CharField(
|
||||||
|
max_length=10,
|
||||||
|
choices=THEMES,
|
||||||
|
default='default',
|
||||||
|
)
|
||||||
|
|
||||||
|
user = models.OneToOneField(
|
||||||
|
User,
|
||||||
|
on_delete=models.deletion.CASCADE,
|
||||||
|
primary_key=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return '<UserPreference (%i) for %s>' % (self.pk, self.user)
|
||||||
|
|
||||||
|
|
||||||
class BaseAccountModel(models.Model):
|
class BaseAccountModel(models.Model):
|
||||||
'''
|
'''
|
||||||
Base, abstract model, holding fields we use in all cases
|
Base, abstract model, holding fields we use in all cases
|
||||||
|
|||||||
20
ivatar/ivataraccount/templates/preferences.html
Normal file
20
ivatar/ivataraccount/templates/preferences.html
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
{% extends 'base.html' %}
|
||||||
|
{% load i18n %}
|
||||||
|
{% load bootstrap4 %}
|
||||||
|
{% load static %}
|
||||||
|
|
||||||
|
{% block title %}{% trans 'Your Preferences' %}{% endblock title %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
|
||||||
|
<div style="width:600px;">
|
||||||
|
<form method="post" name="check">{% csrf_token %}
|
||||||
|
{% bootstrap_form form %}
|
||||||
|
{% buttons %}
|
||||||
|
<button type="submit" class="btn btn-primary">{% trans 'Update' %}</button>
|
||||||
|
<button type="cancel" class="btn btn-danger">{% trans 'Cancel' %}</button>
|
||||||
|
{% endbuttons %}
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% endblock content %}
|
||||||
@@ -13,6 +13,7 @@ from . views import ImportPhotoView, RawImageView, DeletePhotoView
|
|||||||
from . views import UploadPhotoView, AssignPhotoOpenIDView
|
from . views import UploadPhotoView, AssignPhotoOpenIDView
|
||||||
from . views import AddOpenIDView, RedirectOpenIDView, ConfirmOpenIDView
|
from . views import AddOpenIDView, RedirectOpenIDView, ConfirmOpenIDView
|
||||||
from . views import CropPhotoView
|
from . views import CropPhotoView
|
||||||
|
from . views import UserPreferenceView
|
||||||
|
|
||||||
# Define URL patterns, self documenting
|
# Define URL patterns, self documenting
|
||||||
# To see the fancy, colorful evaluation of these use:
|
# To see the fancy, colorful evaluation of these use:
|
||||||
@@ -73,4 +74,5 @@ urlpatterns = [ # pylint: disable=invalid-name
|
|||||||
DeletePhotoView.as_view(), name='delete_photo'),
|
DeletePhotoView.as_view(), name='delete_photo'),
|
||||||
url(r'raw_image/(?P<pk>\d+)', RawImageView.as_view(), name='raw_image'),
|
url(r'raw_image/(?P<pk>\d+)', RawImageView.as_view(), name='raw_image'),
|
||||||
url(r'crop_photo/(?P<pk>\d+)', CropPhotoView.as_view(), name='crop_photo'),
|
url(r'crop_photo/(?P<pk>\d+)', CropPhotoView.as_view(), name='crop_photo'),
|
||||||
|
url(r'pref/$', UserPreferenceView.as_view(), name='user_preference'),
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ from django.contrib.auth.decorators import login_required
|
|||||||
from django.utils.decorators import method_decorator
|
from django.utils.decorators import method_decorator
|
||||||
from django.contrib.messages.views import SuccessMessageMixin
|
from django.contrib.messages.views import SuccessMessageMixin
|
||||||
from django.contrib import messages
|
from django.contrib import messages
|
||||||
from django.views.generic.edit import FormView
|
from django.views.generic.edit import FormView, UpdateView
|
||||||
from django.views.generic.base import View, TemplateView
|
from django.views.generic.base import View, TemplateView
|
||||||
from django.views.generic.detail import DetailView
|
from django.views.generic.detail import DetailView
|
||||||
from django.contrib.auth import authenticate, login
|
from django.contrib.auth import authenticate, login
|
||||||
@@ -19,8 +19,10 @@ from openid import oidutil
|
|||||||
from openid.consumer import consumer
|
from openid.consumer import consumer
|
||||||
|
|
||||||
from .forms import AddEmailForm, UploadPhotoForm, AddOpenIDForm
|
from .forms import AddEmailForm, UploadPhotoForm, AddOpenIDForm
|
||||||
|
from .forms import UpdatePreferenceForm
|
||||||
from .models import UnconfirmedEmail, ConfirmedEmail, Photo
|
from .models import UnconfirmedEmail, ConfirmedEmail, Photo
|
||||||
from .models import UnconfirmedOpenId, ConfirmedOpenId, DjangoOpenIDStore
|
from .models import UnconfirmedOpenId, ConfirmedOpenId, DjangoOpenIDStore
|
||||||
|
from .models import UserPreference
|
||||||
|
|
||||||
from ivatar.settings import MAX_NUM_PHOTOS, MAX_PHOTO_SIZE
|
from ivatar.settings import MAX_NUM_PHOTOS, MAX_PHOTO_SIZE
|
||||||
|
|
||||||
@@ -561,3 +563,16 @@ class CropPhotoView(TemplateView):
|
|||||||
pass # Ignore automatic assignment
|
pass # Ignore automatic assignment
|
||||||
|
|
||||||
return photo.perform_crop(request, dimensions, email, openid)
|
return photo.perform_crop(request, dimensions, email, openid)
|
||||||
|
|
||||||
|
@method_decorator(login_required, name='dispatch')
|
||||||
|
class UserPreferenceView(FormView, UpdateView):
|
||||||
|
'''
|
||||||
|
View class for user preferences view/update
|
||||||
|
'''
|
||||||
|
template_name = 'preferences.html'
|
||||||
|
model = UserPreference
|
||||||
|
form_class = UpdatePreferenceForm
|
||||||
|
success_url = reverse_lazy('user_preference')
|
||||||
|
|
||||||
|
def get_object(self):
|
||||||
|
return self.request.user.userpreference
|
||||||
|
|||||||
41
ivatar/static/css/falko.css
Normal file
41
ivatar/static/css/falko.css
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
/* Main palette from http://www.colourlovers.com/palette/4581580/Dr._Hans_6 */
|
||||||
|
|
||||||
|
body {
|
||||||
|
background-color: #DEE8F1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#site-name {
|
||||||
|
color: #675E57;
|
||||||
|
}
|
||||||
|
|
||||||
|
#site-branding {
|
||||||
|
color: #4F6384;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
color: #675E57;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
color: #4F6384;
|
||||||
|
}
|
||||||
|
|
||||||
|
#outer {
|
||||||
|
background-color: #9AB5D2;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: #675E57;
|
||||||
|
}
|
||||||
|
|
||||||
|
#content {
|
||||||
|
background-color: #FFFFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
#content a {
|
||||||
|
color: #4F6384;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fas, .fab {
|
||||||
|
color: #675E57;
|
||||||
|
}
|
||||||
@@ -40,7 +40,7 @@
|
|||||||
<a href="{{ mailurl }}">
|
<a href="{{ mailurl }}">
|
||||||
<img src="{{ mailurl }}" style="max-width: {{ size }}px; max-height: {{ size }}px;">
|
<img src="{{ mailurl }}" style="max-width: {{ size }}px; max-height: {{ size }}px;">
|
||||||
</a>
|
</a>
|
||||||
<div style="float:inline-end; font-size:{% widthratio size 3 1 %}px;">
|
<div style="padding-left:2px; float:inline-end; font-size:{% widthratio size 3 1 %}px;">
|
||||||
<i class="fas fa-unlock" title="None-SSL connection (http)"></i>
|
<i class="fas fa-unlock" title="None-SSL connection (http)"></i>
|
||||||
<br/>
|
<br/>
|
||||||
<i class="fas fa-at" title="mail: {{ form.mail.value }}"></i>
|
<i class="fas fa-at" title="mail: {{ form.mail.value }}"></i>
|
||||||
@@ -53,7 +53,7 @@
|
|||||||
<a href="{{ mailurl_secure }}">
|
<a href="{{ mailurl_secure }}">
|
||||||
<img src="{{ mailurl_secure }}" style="max-width: {{ size }}px; max-height: {{ size }}px;">
|
<img src="{{ mailurl_secure }}" style="max-width: {{ size }}px; max-height: {{ size }}px;">
|
||||||
</a>
|
</a>
|
||||||
<div style="float:inline-end; font-size:{% widthratio size 3 1 %}px;">
|
<div style="padding-left:2px; float:inline-end; font-size:{% widthratio size 3 1 %}px;">
|
||||||
<i class="fas fa-lock" title="Secure connection (https)"></i>
|
<i class="fas fa-lock" title="Secure connection (https)"></i>
|
||||||
<br/>
|
<br/>
|
||||||
<i class="fas fa-at" title="mail: {{ form.mail.value }}"></i>
|
<i class="fas fa-at" title="mail: {{ form.mail.value }}"></i>
|
||||||
@@ -67,7 +67,7 @@
|
|||||||
<a href="{{ BASE_URL }}{{ mail_hash256 }}?s={{ size }}">
|
<a href="{{ BASE_URL }}{{ mail_hash256 }}?s={{ size }}">
|
||||||
<img src="{{ BASE_URL }}{{ mail_hash256 }}?s={{ size }}" style="max-width: {{ size }}px; max-height: {{ size }}px;">
|
<img src="{{ BASE_URL }}{{ mail_hash256 }}?s={{ size }}" style="max-width: {{ size }}px; max-height: {{ size }}px;">
|
||||||
</a>
|
</a>
|
||||||
<div style="float:inline-end; font-size:{% widthratio size 3 1 %}px;">
|
<div style="padding-left:2px; float:inline-end; font-size:{% widthratio size 3 1 %}px;">
|
||||||
<i class="fas fa-unlock" title="None-SSL connection (http)"></i>
|
<i class="fas fa-unlock" title="None-SSL connection (http)"></i>
|
||||||
<br/>
|
<br/>
|
||||||
<i class="fas fa-at" title="mail: {{ form.mail.value }}"></i>
|
<i class="fas fa-at" title="mail: {{ form.mail.value }}"></i>
|
||||||
@@ -80,7 +80,7 @@
|
|||||||
<a href="{{ SECURE_BASE_URL }}{{ mail_hash256 }}?s={{ size }}">
|
<a href="{{ SECURE_BASE_URL }}{{ mail_hash256 }}?s={{ size }}">
|
||||||
<img src="{{ SECURE_BASE_URL }}{{ mail_hash256 }}?s={{ size }}" style="max-width: {{ size }}px; max-height: {{ size }}px;">
|
<img src="{{ SECURE_BASE_URL }}{{ mail_hash256 }}?s={{ size }}" style="max-width: {{ size }}px; max-height: {{ size }}px;">
|
||||||
</a>
|
</a>
|
||||||
<div style="float:inline-end; font-size:{% widthratio size 3 1 %}px;">
|
<div style="padding-left:2px; float:inline-end; font-size:{% widthratio size 3 1 %}px;">
|
||||||
<i class="fas fa-lock" title="Secure connection (https)"></i>
|
<i class="fas fa-lock" title="Secure connection (https)"></i>
|
||||||
<br/>
|
<br/>
|
||||||
<i class="fas fa-at" title="mail: {{ form.mail.value }}"></i>
|
<i class="fas fa-at" title="mail: {{ form.mail.value }}"></i>
|
||||||
@@ -96,7 +96,7 @@
|
|||||||
<a href="{{ openidurl }}">
|
<a href="{{ openidurl }}">
|
||||||
<img src="{{ openidurl }}" style="max-width: {{ size }}px; max-height: {{ size }}px;">
|
<img src="{{ openidurl }}" style="max-width: {{ size }}px; max-height: {{ size }}px;">
|
||||||
</a>
|
</a>
|
||||||
<div style="float:inline-end; font-size:{% widthratio size 3 1 %}px">
|
<div style="padding-left:2px; float:inline-end; font-size:{% widthratio size 3 1 %}px">
|
||||||
<i class="fas fa-unlock" title="None-SSL connection (http)"></i>
|
<i class="fas fa-unlock" title="None-SSL connection (http)"></i>
|
||||||
<br/>
|
<br/>
|
||||||
<i class="fab fa-openid" title="openid: {{ form.openid.value }}"></i>
|
<i class="fab fa-openid" title="openid: {{ form.openid.value }}"></i>
|
||||||
@@ -109,7 +109,7 @@
|
|||||||
<a href="{{ openidurl_secure }}">
|
<a href="{{ openidurl_secure }}">
|
||||||
<img src="{{ openidurl_secure }}" style="max-width: {{ size }}px; max-height: {{ size }}px;">
|
<img src="{{ openidurl_secure }}" style="max-width: {{ size }}px; max-height: {{ size }}px;">
|
||||||
</a>
|
</a>
|
||||||
<div style="float:inline-end; font-size:{% widthratio size 3 1 %}px">
|
<div style="padding-left:2px; float:inline-end; font-size:{% widthratio size 3 1 %}px">
|
||||||
<i class="fas fa-lock" title="Secure connection (http)"></i>
|
<i class="fas fa-lock" title="Secure connection (http)"></i>
|
||||||
<br/>
|
<br/>
|
||||||
<i class="fab fa-openid" title="openid: {{ form.openid.value }}"></i>
|
<i class="fab fa-openid" title="openid: {{ form.openid.value }}"></i>
|
||||||
|
|||||||
@@ -23,6 +23,7 @@
|
|||||||
<div id="account">
|
<div id="account">
|
||||||
{% if user.is_authenticated %}
|
{% if user.is_authenticated %}
|
||||||
<a href="{% url 'profile' %}">{% trans 'Profile' %}</a> |
|
<a href="{% url 'profile' %}">{% trans 'Profile' %}</a> |
|
||||||
|
<a href="{% url 'user_preference' %}">{% trans 'Preferences' %}</a> |
|
||||||
<a href="{% url 'tools_check' %}">{% trans 'Check' %}</a> |
|
<a href="{% url 'tools_check' %}">{% trans 'Check' %}</a> |
|
||||||
<a href="{{ contact_us }}">{% trans 'Contact Us' %}</a> |
|
<a href="{{ contact_us }}">{% trans 'Contact Us' %}</a> |
|
||||||
<a href="{{ security_url }}">{% trans 'Security' %}</a> |
|
<a href="{{ security_url }}">{% trans 'Security' %}</a> |
|
||||||
|
|||||||
@@ -20,6 +20,11 @@
|
|||||||
<link rel="mask-icon" href="{% static '/img/safari-pinned-tab.svg' %}" color="#fa711f">
|
<link rel="mask-icon" href="{% static '/img/safari-pinned-tab.svg' %}" color="#fa711f">
|
||||||
<link rel="stylesheet" href="{% static '/css/ivatar.css' %}" type="text/css">
|
<link rel="stylesheet" href="{% static '/css/ivatar.css' %}" type="text/css">
|
||||||
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.1.0/css/all.css" integrity="sha384-lKuwvrZot6UHsBSfcMvOkWwlCMgc0TaWr+30HWe3a4ltaBwTZhyTEggF5tJv8tbt" crossorigin="anonymous">
|
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.1.0/css/all.css" integrity="sha384-lKuwvrZot6UHsBSfcMvOkWwlCMgc0TaWr+30HWe3a4ltaBwTZhyTEggF5tJv8tbt" crossorigin="anonymous">
|
||||||
|
{% if user.is_authenticated %}
|
||||||
|
{% if user.userpreference and user.userpreference.theme != 'default' %}
|
||||||
|
<link rel="stylesheet" href="{% static 'css/' %}{{ user.userpreference.theme }}.css" type="text/css">
|
||||||
|
{% endif %}
|
||||||
|
{% endif %}
|
||||||
<link rel="manifest" href="/manifest.json">
|
<link rel="manifest" href="/manifest.json">
|
||||||
<meta name="msapplication-TileImage" content="{% static '/img/nobody/144.png' %}">
|
<meta name="msapplication-TileImage" content="{% static '/img/nobody/144.png' %}">
|
||||||
<meta name="msapplication-TileColor" content="#fa711f">
|
<meta name="msapplication-TileColor" content="#fa711f">
|
||||||
|
|||||||
Reference in New Issue
Block a user