diff --git a/src/newsreader/accounts/forms.py b/src/newsreader/accounts/forms.py
new file mode 100644
index 0000000..7a29f99
--- /dev/null
+++ b/src/newsreader/accounts/forms.py
@@ -0,0 +1,9 @@
+from django import forms
+
+from newsreader.accounts.models import User
+
+
+class UserSettingsForm(forms.ModelForm):
+ class Meta:
+ model = User
+ fields = ("first_name", "last_name")
diff --git a/src/newsreader/accounts/templates/accounts/password_change.html b/src/newsreader/accounts/templates/accounts/password_change.html
new file mode 100644
index 0000000..1ece1dd
--- /dev/null
+++ b/src/newsreader/accounts/templates/accounts/password_change.html
@@ -0,0 +1,22 @@
+{% extends "base.html" %}
+{% load static i18n %}
+
+{% block content %}
+
+
+
+{% endblock %}
diff --git a/src/newsreader/accounts/templates/accounts/settings.html b/src/newsreader/accounts/templates/accounts/settings.html
new file mode 100644
index 0000000..29a2ee9
--- /dev/null
+++ b/src/newsreader/accounts/templates/accounts/settings.html
@@ -0,0 +1,42 @@
+{% extends "base.html" %}
+{% load i18n %}
+
+{% block content %}
+
+
+
+{% endblock %}
diff --git a/src/newsreader/accounts/tests/test_views.py b/src/newsreader/accounts/tests/test_views.py
new file mode 100644
index 0000000..d3ac77c
--- /dev/null
+++ b/src/newsreader/accounts/tests/test_views.py
@@ -0,0 +1,29 @@
+from django.test import TestCase
+from django.urls import reverse
+
+from newsreader.accounts.models import User
+from newsreader.accounts.tests.factories import UserFactory
+
+
+class UserSettingsViewTestCase(TestCase):
+ def setUp(self):
+ self.user = UserFactory(password="test")
+ self.client.force_login(self.user)
+
+ def test_simple(self):
+ response = self.client.get(reverse("accounts:settings"))
+
+ self.assertEquals(response.status_code, 200)
+
+ def test_user_credential_change(self):
+ response = self.client.post(
+ reverse("accounts:settings"),
+ {"first_name": "First name", "last_name": "Last name"},
+ )
+
+ user = User.objects.get()
+
+ self.assertRedirects(response, reverse("accounts:settings"))
+
+ self.assertEquals(user.first_name, "First name")
+ self.assertEquals(user.last_name, "Last name")
diff --git a/src/newsreader/accounts/urls.py b/src/newsreader/accounts/urls.py
index 8605233..d42ae13 100644
--- a/src/newsreader/accounts/urls.py
+++ b/src/newsreader/accounts/urls.py
@@ -1,3 +1,4 @@
+from django.contrib.auth.decorators import login_required
from django.urls import path
from newsreader.accounts.views import (
@@ -6,6 +7,7 @@ from newsreader.accounts.views import (
ActivationView,
LoginView,
LogoutView,
+ PasswordChangeView,
PasswordResetCompleteView,
PasswordResetConfirmView,
PasswordResetDoneView,
@@ -13,6 +15,7 @@ from newsreader.accounts.views import (
RegistrationClosedView,
RegistrationCompleteView,
RegistrationView,
+ SettingsView,
)
@@ -52,5 +55,10 @@ urlpatterns = [
PasswordResetCompleteView.as_view(),
name="password-reset-complete",
),
- # TODO: create password change views
+ path(
+ "password-change/",
+ login_required(PasswordChangeView.as_view()),
+ name="password-change",
+ ),
+ path("settings/", login_required(SettingsView.as_view()), name="settings"),
]
diff --git a/src/newsreader/accounts/views.py b/src/newsreader/accounts/views.py
index 28ae92d..c0342b2 100644
--- a/src/newsreader/accounts/views.py
+++ b/src/newsreader/accounts/views.py
@@ -2,15 +2,17 @@ from django.contrib.auth import views as django_views
from django.shortcuts import render
from django.urls import reverse_lazy
from django.views.generic import TemplateView
+from django.views.generic.edit import FormView, ModelFormMixin
from registration.backends.default import views as registration_views
+from newsreader.accounts.forms import UserSettingsForm
+from newsreader.accounts.models import User
+
class LoginView(django_views.LoginView):
template_name = "accounts/login.html"
-
- def get_success_url(self):
- return reverse_lazy("index")
+ success_url = reverse_lazy("index")
class LogoutView(django_views.LogoutView):
@@ -89,3 +91,25 @@ class PasswordResetConfirmView(django_views.PasswordResetConfirmView):
class PasswordResetCompleteView(django_views.PasswordResetCompleteView):
template_name = "password-reset/password_reset_complete.html"
+
+
+class PasswordChangeView(django_views.PasswordChangeView):
+ template_name = "accounts/password_change.html"
+ success_url = reverse_lazy("accounts:settings")
+
+
+class SettingsView(ModelFormMixin, FormView):
+ template_name = "accounts/settings.html"
+ success_url = reverse_lazy("accounts:settings")
+ form_class = UserSettingsForm
+ model = User
+
+ def get(self, request, *args, **kwargs):
+ self.object = self.get_object()
+ return super().get(request, *args, **kwargs)
+
+ def get_object(self, **kwargs):
+ return self.request.user
+
+ def get_form_kwargs(self):
+ return {**super().get_form_kwargs(), "instance": self.request.user}
diff --git a/src/newsreader/js/pages/categories/App.js b/src/newsreader/js/pages/categories/App.js
index 95ab396..691aaed 100644
--- a/src/newsreader/js/pages/categories/App.js
+++ b/src/newsreader/js/pages/categories/App.js
@@ -80,7 +80,7 @@ class App extends React.Component {
const pageHeader = (
<>
Categories
-
+
Create category
>
diff --git a/src/newsreader/news/collection/templates/collection/rules.html b/src/newsreader/news/collection/templates/collection/rules.html
index ee6d539..32b6f24 100644
--- a/src/newsreader/news/collection/templates/collection/rules.html
+++ b/src/newsreader/news/collection/templates/collection/rules.html
@@ -1,7 +1,5 @@
{% extends "base.html" %}
-{% load i18n %}
-
-{% load static %}
+{% load i18n static %}
{% block content %}
diff --git a/src/newsreader/scss/components/form/_settings-form.scss b/src/newsreader/scss/components/form/_settings-form.scss
new file mode 100644
index 0000000..fc38d70
--- /dev/null
+++ b/src/newsreader/scss/components/form/_settings-form.scss
@@ -0,0 +1,9 @@
+.settings-form {
+ &__section:last-child {
+ & .settings-form__fieldset {
+ display: flex;
+ flex-direction: row;
+ justify-content: space-between;
+ }
+ }
+}
diff --git a/src/newsreader/scss/components/form/index.scss b/src/newsreader/scss/components/form/index.scss
index 547da89..1555ae9 100644
--- a/src/newsreader/scss/components/form/index.scss
+++ b/src/newsreader/scss/components/form/index.scss
@@ -11,3 +11,5 @@
@import "password-reset-form";
@import "password-reset-confirm-form";
+
+@import "settings-form";
diff --git a/src/newsreader/scss/components/section/_text-section.scss b/src/newsreader/scss/components/section/_text-section.scss
new file mode 100644
index 0000000..88e3e72
--- /dev/null
+++ b/src/newsreader/scss/components/section/_text-section.scss
@@ -0,0 +1,11 @@
+.text-section {
+ @extend .section;
+
+ width: 70%;
+ border-radius: 5px;
+
+ padding: 10px;
+
+ background-color: $white;
+}
+
diff --git a/src/newsreader/scss/components/section/index.scss b/src/newsreader/scss/components/section/index.scss
index 4fb6763..0e02686 100644
--- a/src/newsreader/scss/components/section/index.scss
+++ b/src/newsreader/scss/components/section/index.scss
@@ -1 +1,2 @@
@import "section";
+@import "text-section";
diff --git a/src/newsreader/scss/elements/button/_mixins.scss b/src/newsreader/scss/elements/button/_mixins.scss
index 06a912c..75b70e3 100644
--- a/src/newsreader/scss/elements/button/_mixins.scss
+++ b/src/newsreader/scss/elements/button/_mixins.scss
@@ -1,3 +1,3 @@
@mixin button-padding {
- padding: 10px 50px;
+ padding: 7px 40px;
}
diff --git a/src/newsreader/scss/pages/index.scss b/src/newsreader/scss/pages/index.scss
index 27f0bc6..ddfaf85 100644
--- a/src/newsreader/scss/pages/index.scss
+++ b/src/newsreader/scss/pages/index.scss
@@ -10,3 +10,5 @@
@import "rule/index";
@import "rules/index";
+
+@import "settings/index";
diff --git a/src/newsreader/scss/pages/settings/index.scss b/src/newsreader/scss/pages/settings/index.scss
new file mode 100644
index 0000000..28837cd
--- /dev/null
+++ b/src/newsreader/scss/pages/settings/index.scss
@@ -0,0 +1,12 @@
+#settings--page {
+ .settings-form__fieldset:last-child {
+ & span {
+ display: flex;
+ flex-direction: row;
+
+ & >:first-child {
+ margin: 0 5px;
+ }
+ }
+ }
+}
diff --git a/src/newsreader/templates/base.html b/src/newsreader/templates/base.html
index 1e54729..3f677c0 100644
--- a/src/newsreader/templates/base.html
+++ b/src/newsreader/templates/base.html
@@ -17,7 +17,7 @@
Home
Categories
Feeds
- Settings
+ Settings
{% if request.user.is_superuser %}
Admin
{% endif %}