Added the user form, and revised the text in the user list and user detail in the Mia core application.
This commit is contained in:
parent
7596935ca2
commit
d7ddee340b
161
mia_core/forms.py
Normal file
161
mia_core/forms.py
Normal file
@ -0,0 +1,161 @@
|
||||
# The core application of the Mia project.
|
||||
# by imacat <imacat@mail.imacat.idv.tw>, 2020/8/9
|
||||
|
||||
# Copyright (c) 2020 imacat.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
"""The forms of the Mia core application.
|
||||
|
||||
"""
|
||||
from django import forms
|
||||
from django.core.validators import RegexValidator
|
||||
from django.db.models import Q
|
||||
from django.utils.translation import gettext as _
|
||||
|
||||
from mia_core.models import User
|
||||
|
||||
|
||||
class UserForm(forms.Form):
|
||||
"""A user account form."""
|
||||
login_id = forms.CharField(
|
||||
max_length=32,
|
||||
error_messages={
|
||||
"required": _("Please fill in the log in ID."),
|
||||
"max_length": _("This log in ID is too long (max 32 characters)."),
|
||||
},
|
||||
validators=[
|
||||
RegexValidator(
|
||||
regex="^[^/]+$",
|
||||
message=_("You cannot use slash (/) in the log in ID.")),
|
||||
])
|
||||
password = forms.CharField(required=False)
|
||||
password2 = forms.CharField(required=False)
|
||||
name = forms.CharField(
|
||||
max_length=32,
|
||||
error_messages={
|
||||
"required": _("Please fill in the name."),
|
||||
"max_length": _("This name is too long (max 32 characters)."),
|
||||
})
|
||||
is_disabled = forms.BooleanField()
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(UserForm, self).__init__(*args, **kwargs)
|
||||
self.user = None
|
||||
self.current_user = None
|
||||
|
||||
def clean(self):
|
||||
"""Validates the form globally.
|
||||
|
||||
Raises:
|
||||
ValidationError: When the validation fails.
|
||||
"""
|
||||
errors = []
|
||||
validators = [self._validate_login_id_unique,
|
||||
self._validate_password_required,
|
||||
self._validate_password2_required,
|
||||
self._validate_passwords_equal,
|
||||
self._validate_is_disabled_not_oneself]
|
||||
for validator in validators:
|
||||
try:
|
||||
validator()
|
||||
except forms.ValidationError as e:
|
||||
errors.append(e)
|
||||
if errors:
|
||||
raise forms.ValidationError(errors)
|
||||
|
||||
def _validate_login_id_unique(self):
|
||||
"""Validates whether the log in ID is unique.
|
||||
|
||||
Raises:
|
||||
forms.ValidationError: When the validation fails.
|
||||
"""
|
||||
if "login_id" not in self.data:
|
||||
return
|
||||
condition = Q(login_id=self.data["login_id"])
|
||||
if self.user is not None:
|
||||
condition = condition & ~Q(pk=self.user.pk)
|
||||
if User.objects.filter(condition).first() is None:
|
||||
return
|
||||
error = forms.ValidationError(_("This log in ID is already in use."),
|
||||
code="login_id_unique")
|
||||
self.add_error("login_id", error)
|
||||
raise error
|
||||
|
||||
def _validate_password_required(self):
|
||||
"""Validates whether the password is entered for newly-created users.
|
||||
|
||||
Raises:
|
||||
forms.ValidationError: When the validation fails.
|
||||
"""
|
||||
if self.user is not None:
|
||||
return
|
||||
if "password" in self.data:
|
||||
return
|
||||
error = forms.ValidationError(_("Please fill in the password."),
|
||||
code="password_required")
|
||||
self.add_error("password", error)
|
||||
raise error
|
||||
|
||||
def _validate_password2_required(self):
|
||||
"""Validates whether the second password is entered.
|
||||
|
||||
Raises:
|
||||
forms.ValidationError: When the validation fails.
|
||||
"""
|
||||
if "password" not in self.data:
|
||||
return
|
||||
if "password2" in self.data:
|
||||
return
|
||||
error = forms.ValidationError(
|
||||
_("Please enter the password again to verify it."),
|
||||
code="password2_required")
|
||||
self.add_error("password2", error)
|
||||
raise error
|
||||
|
||||
def _validate_passwords_equal(self):
|
||||
"""Validates whether the two passwords are equa.
|
||||
|
||||
Raises:
|
||||
forms.ValidationError: When the validation fails.
|
||||
"""
|
||||
if "password" not in self.data:
|
||||
return
|
||||
if "password2" not in self.data:
|
||||
return
|
||||
if self.data["password"] == self.data["password2"]:
|
||||
return
|
||||
error = forms.ValidationError(_("The two passwords do not match."),
|
||||
code="passwords_equal")
|
||||
self.add_error("password2", error)
|
||||
raise error
|
||||
|
||||
def _validate_is_disabled_not_oneself(self):
|
||||
"""Validates whether the user tries to disable herself
|
||||
|
||||
Raises:
|
||||
forms.ValidationError: When the validation fails.
|
||||
"""
|
||||
if "is_disabled" not in self.data:
|
||||
return
|
||||
if self.user is None:
|
||||
return
|
||||
if self.current_user is None:
|
||||
return
|
||||
if self.user.pk != self.current_user.pk:
|
||||
return
|
||||
error = forms.ValidationError(
|
||||
_("You cannot disable your own account."),
|
||||
code="not_oneself")
|
||||
self.add_error("is_disabled", error)
|
||||
raise error
|
@ -7,8 +7,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: mia 1.0\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-08-09 20:48+0800\n"
|
||||
"PO-Revision-Date: 2020-08-09 20:48+0800\n"
|
||||
"POT-Creation-Date: 2020-08-09 22:03+0800\n"
|
||||
"PO-Revision-Date: 2020-08-09 22:05+0800\n"
|
||||
"Last-Translator: imacat <imacat@mail.imacat.idv.tw>\n"
|
||||
"Language-Team: Traditional Chinese <imacat@mail.imacat.idv.tw>\n"
|
||||
"Language: Traditional Chinese\n"
|
||||
@ -16,6 +16,46 @@ msgstr ""
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
#: mia_core/forms.py:34
|
||||
msgid "Please fill in the log in ID."
|
||||
msgstr "請填寫登入帳號。"
|
||||
|
||||
#: mia_core/forms.py:35
|
||||
msgid "This log in ID is too long (max 32 characters)."
|
||||
msgstr "登入帳號太長了(最長32個字)。"
|
||||
|
||||
#: mia_core/forms.py:40
|
||||
msgid "You cannot use slash (/) in the log in ID."
|
||||
msgstr "登入帳號不可以包含斜線 (/) 。"
|
||||
|
||||
#: mia_core/forms.py:47
|
||||
msgid "Please fill in the name."
|
||||
msgstr "請填寫姓名。"
|
||||
|
||||
#: mia_core/forms.py:48
|
||||
msgid "This name is too long (max 32 characters)."
|
||||
msgstr "姓名太長了(最長32個字)。"
|
||||
|
||||
#: mia_core/forms.py:90
|
||||
msgid "This log in ID is already in use."
|
||||
msgstr "登入帳號和其他人重複。"
|
||||
|
||||
#: mia_core/forms.py:105
|
||||
msgid "Please fill in the password."
|
||||
msgstr "請填寫密碼。"
|
||||
|
||||
#: mia_core/forms.py:121
|
||||
msgid "Please enter the password again to verify it."
|
||||
msgstr "請再次確認密碼。"
|
||||
|
||||
#: mia_core/forms.py:138
|
||||
msgid "The two passwords do not match."
|
||||
msgstr "兩次密碼不符,請重新輸入。"
|
||||
|
||||
#: mia_core/forms.py:158 mia_core/templates/mia_core/user_form.html:84
|
||||
msgid "You cannot disable your own account."
|
||||
msgstr "不能停用自己的帳號。"
|
||||
|
||||
#: mia_core/period.py:447 mia_core/period.py:482 mia_core/period.py:500
|
||||
#: mia_core/period.py:513 mia_core/period.py:559
|
||||
#, python-format
|
||||
@ -133,6 +173,7 @@ msgid "Cancel"
|
||||
msgstr "取消"
|
||||
|
||||
#: mia_core/templates/mia_core/user_detail.html:69
|
||||
#: mia_core/templates/mia_core/user_form.html:41
|
||||
msgid "Back"
|
||||
msgstr "回上頁"
|
||||
|
||||
@ -161,13 +202,15 @@ msgstr "帳號已刪除。"
|
||||
|
||||
#: mia_core/templates/mia_core/user_detail.html:99
|
||||
msgid "Log in ID.:"
|
||||
msgstr "帳號"
|
||||
msgstr "登入帳號:"
|
||||
|
||||
#: mia_core/templates/mia_core/user_detail.html:104
|
||||
#: mia_core/templates/mia_core/user_form.html:74
|
||||
msgid "Name:"
|
||||
msgstr "姓名"
|
||||
msgstr "姓名:"
|
||||
|
||||
#: mia_core/templates/mia_core/user_detail.html:110
|
||||
#: mia_core/templates/mia_core/user_form.html:88
|
||||
msgid "This account is disabled."
|
||||
msgstr "帳號停用。"
|
||||
|
||||
@ -219,6 +262,26 @@ msgstr "更新時間:"
|
||||
msgid "Updated by:"
|
||||
msgstr "更新人:"
|
||||
|
||||
#: mia_core/templates/mia_core/user_form.html:31
|
||||
msgid "Add a New Account"
|
||||
msgstr "建立帳號"
|
||||
|
||||
#: mia_core/templates/mia_core/user_form.html:50
|
||||
msgid "Log in ID:"
|
||||
msgstr "登入帳號:"
|
||||
|
||||
#: mia_core/templates/mia_core/user_form.html:58
|
||||
msgid "Password:"
|
||||
msgstr "密碼:"
|
||||
|
||||
#: mia_core/templates/mia_core/user_form.html:66
|
||||
msgid "Confirm password:"
|
||||
msgstr "確認密碼:"
|
||||
|
||||
#: mia_core/templates/mia_core/user_form.html:97
|
||||
msgid "Submit"
|
||||
msgstr "傳送"
|
||||
|
||||
#: mia_core/templates/mia_core/user_list.html:27
|
||||
msgid "Account Management"
|
||||
msgstr "帳號管理"
|
||||
@ -229,7 +292,7 @@ msgstr "新增"
|
||||
|
||||
#: mia_core/templates/mia_core/user_list.html:43
|
||||
msgid "Log in ID"
|
||||
msgstr "帳號"
|
||||
msgstr "登入帳號"
|
||||
|
||||
#: mia_core/templates/mia_core/user_list.html:44
|
||||
msgid "Name"
|
||||
|
46
mia_core/locale/zh_Hant/LC_MESSAGES/djangojs.po
Normal file
46
mia_core/locale/zh_Hant/LC_MESSAGES/djangojs.po
Normal file
@ -0,0 +1,46 @@
|
||||
# Traditional Chinese PO file for the JavaScript on the Mia Website
|
||||
# Copyright (C) 2020 imacat
|
||||
# This file is distributed under the same license as the Mia package.
|
||||
# imacat <imacat@mail.imacat.idv.tw>, 2020.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: core 1.0\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2020-08-09 21:54+0800\n"
|
||||
"PO-Revision-Date: 2020-08-09 22:05+0800\n"
|
||||
"Last-Translator: imacat <imacat@mail.imacat.idv.tw>\n"
|
||||
"Language-Team: Traditional Chinese <imacat@mail.imacat.idv.tw>\n"
|
||||
"Language: Traditional Chinese\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=1; plural=0;\n"
|
||||
|
||||
#: mia_core/static/mia_core/js/user-form.js:129
|
||||
msgid "Please fill in the log in ID."
|
||||
msgstr "請填寫登入帳號。"
|
||||
|
||||
#: mia_core/static/mia_core/js/user-form.js:134
|
||||
msgid "You cannot use slash (/) in the log in ID."
|
||||
msgstr "登入帳號不可以包含斜線 (/) 。"
|
||||
|
||||
#: mia_core/static/mia_core/js/user-form.js:154
|
||||
msgid "This log in ID is already in use."
|
||||
msgstr "登入帳號和其他人重複。"
|
||||
|
||||
#: mia_core/static/mia_core/js/user-form.js:177
|
||||
msgid "Please fill in the password."
|
||||
msgstr "請填寫密碼。"
|
||||
|
||||
#: mia_core/static/mia_core/js/user-form.js:201
|
||||
msgid "Please enter the password again to verify it."
|
||||
msgstr "請再次確認密碼。"
|
||||
|
||||
#: mia_core/static/mia_core/js/user-form.js:207
|
||||
msgid "The two passwords do not match."
|
||||
msgstr "兩次密碼不符,請重新輸入。"
|
||||
|
||||
#: mia_core/static/mia_core/js/user-form.js:228
|
||||
msgid "Please fill in the name."
|
||||
msgstr "請填寫姓名。"
|
234
mia_core/static/mia_core/js/user-form.js
Normal file
234
mia_core/static/mia_core/js/user-form.js
Normal file
@ -0,0 +1,234 @@
|
||||
/* The Mia Website
|
||||
* edit.js: The JavaScript to edit the user data
|
||||
*/
|
||||
|
||||
/* Copyright (c) 2019-2020 imacat.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/* Author: imacat@mail.imacat.idv.tw (imacat)
|
||||
* First written: 2020/3/26
|
||||
*/
|
||||
|
||||
// Initializes the page JavaScript.
|
||||
$(function () {
|
||||
$("#user-login-id").on("blur", function () {
|
||||
validateLoginId();
|
||||
});
|
||||
$("#user-password").on("blur", function () {
|
||||
validatePassword();
|
||||
});
|
||||
$("#user-password2").on("blur", function () {
|
||||
validatePassword2();
|
||||
});
|
||||
$("#user-name").on("blur", function () {
|
||||
validateName();
|
||||
});
|
||||
$("#user-form").on("submit", function () {
|
||||
return validateForm();
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
/*******************
|
||||
* Form Validation *
|
||||
*******************/
|
||||
|
||||
/**
|
||||
* The validation result
|
||||
* @type {object}
|
||||
* @private
|
||||
*/
|
||||
let isValidated;
|
||||
|
||||
/**
|
||||
* Validates the form.
|
||||
*
|
||||
* @returns {boolean} true if the validation succeed, or false
|
||||
* otherwise
|
||||
* @private
|
||||
*/
|
||||
function validateForm() {
|
||||
isValidated = {
|
||||
"id": null,
|
||||
"_sync": true,
|
||||
};
|
||||
validateLoginIdAsync().then();
|
||||
validateSyncColumns();
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates the form on synchronous validations.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
function validateSyncColumns() {
|
||||
let isSyncValidated = true;
|
||||
isSyncValidated = isSyncValidated && validatePassword();
|
||||
isSyncValidated = isSyncValidated && validatePassword2();
|
||||
isSyncValidated = isSyncValidated && validateName();
|
||||
isValidated["_sync"] = isSyncValidated;
|
||||
validateFormAsync();
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates the form for the asynchronous validation.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
function validateFormAsync() {
|
||||
let isFormValidated = true;
|
||||
const keys = Object.keys(isValidated);
|
||||
for (let i = 0; i < keys.length; i++) {
|
||||
if (isValidated[keys[i]] === null) {
|
||||
return;
|
||||
}
|
||||
isFormValidated = isFormValidated && isValidated[keys[i]];
|
||||
}
|
||||
if (isFormValidated) {
|
||||
$("#user-form")[0].submit();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates the log in ID for asynchronous form validation.
|
||||
*
|
||||
* @returns {Promise<void>}
|
||||
* @private
|
||||
*/
|
||||
async function validateLoginIdAsync() {
|
||||
isValidated["id"] = await validateLoginId();
|
||||
validateFormAsync();
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates the log in ID.
|
||||
*
|
||||
* @returns {boolean} true if the validation succeed, or false
|
||||
* otherwise
|
||||
* @private
|
||||
*/
|
||||
async function validateLoginId() {
|
||||
const id = $("#user-login-id")[0];
|
||||
const errorMessage = $("#user-login-id-error");
|
||||
id.value = id.value.trim();
|
||||
if (id.value === "") {
|
||||
id.classList.add("is-invalid");
|
||||
errorMessage.text(gettext("Please fill in the log in ID."));
|
||||
return false;
|
||||
}
|
||||
if (id.value.match(/\//)) {
|
||||
id.classList.add("is-invalid");
|
||||
errorMessage.text(gettext("You cannot use slash (/) in the log in ID."));
|
||||
return false;
|
||||
}
|
||||
const originalId = $("#user-login-id-original").val();
|
||||
if (originalId === "" || id.value !== originalId) {
|
||||
let exists = null;
|
||||
const request = new XMLHttpRequest();
|
||||
request.onreadystatechange = function() {
|
||||
if (this.readyState === 4 && this.status === 200) {
|
||||
exists = JSON.parse(this.responseText);
|
||||
}
|
||||
};
|
||||
const url = $("#exists-url").val().replace("ID", id.value);
|
||||
request.open("GET", url, true);
|
||||
request.send();
|
||||
while (exists === null) {
|
||||
await new Promise(r => setTimeout(r, 200));
|
||||
}
|
||||
if (exists) {
|
||||
id.classList.add("is-invalid");
|
||||
errorMessage.text(gettext("This log in ID is already in use."));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
id.classList.remove("is-invalid");
|
||||
errorMessage.text("");
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates the password.
|
||||
*
|
||||
* @returns {boolean} true if the validation succeed, or false
|
||||
* otherwise
|
||||
* @private
|
||||
*/
|
||||
async function validatePassword() {
|
||||
const password = $("#user-password")[0];
|
||||
const errorMessage = $("#user-password-error");
|
||||
password.value = password.value.trim();
|
||||
if (password.required) {
|
||||
if (password.value === "") {
|
||||
password.classList.add("is-invalid");
|
||||
errorMessage.text(gettext("Please fill in the password."));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
password.classList.remove("is-invalid");
|
||||
errorMessage.text("");
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates the password verification.
|
||||
*
|
||||
* @returns {boolean} true if the validation succeed, or false
|
||||
* otherwise
|
||||
* @private
|
||||
*/
|
||||
function validatePassword2() {
|
||||
const password2 = $("#user-password2")[0];
|
||||
const errorMessage = $("#user-password2-error");
|
||||
password2.value = password2.value.trim();
|
||||
const password = $("#user-password").val();
|
||||
if (password !== "") {
|
||||
if (password2.value === "") {
|
||||
password2.classList.add("is-invalid");
|
||||
errorMessage.text(gettext("Please enter the password again to verify it."));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (password2.value !== password) {
|
||||
password2.classList.add("is-invalid");
|
||||
errorMessage.text(gettext("The two passwords do not match."));
|
||||
return false;
|
||||
}
|
||||
password2.classList.remove("is-invalid");
|
||||
errorMessage.text("");
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates the name.
|
||||
*
|
||||
* @returns {boolean} true if the validation succeed, or false
|
||||
* otherwise
|
||||
* @private
|
||||
*/
|
||||
function validateName() {
|
||||
const name = $("#user-name")[0];
|
||||
const errorMessage = $("#user-name-error");
|
||||
name.value = name.value.trim();
|
||||
if (name.value === "") {
|
||||
name.classList.add("is-invalid");
|
||||
errorMessage.text(gettext("Please fill in the name."));
|
||||
return false;
|
||||
}
|
||||
name.classList.remove("is-invalid");
|
||||
errorMessage.text("");
|
||||
return true;
|
||||
}
|
103
mia_core/templates/mia_core/user_form.html
Normal file
103
mia_core/templates/mia_core/user_form.html
Normal file
@ -0,0 +1,103 @@
|
||||
{% extends "base.html" %}
|
||||
{% comment %}
|
||||
The Mia Core Application
|
||||
user_form.html: The template for the form of a user
|
||||
|
||||
Copyright (c) 2020 imacat.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
Author: imacat@mail.imacat.idv.tw (imacat)
|
||||
First written: 2020/8/9
|
||||
{% endcomment %}
|
||||
{% load static %}
|
||||
{% load i18n %}
|
||||
{% load mia_core %}
|
||||
|
||||
{% block settings %}
|
||||
{% if form.user %}
|
||||
{% setvar "title" user.name %}
|
||||
{% else %}
|
||||
{% setvar "title" _("Add a New Account") %}
|
||||
{% endif %}
|
||||
{% static "mia_core/js/user-form.js" as file %}{% add_js file %}
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<div class="btn-group btn-actions">
|
||||
<a class="btn btn-primary" role="button" href="{% if form.user %}{% url "mia_core:users.detail" user %}{% else %}{% url "mia_core:users" %}{% endif %}">
|
||||
<i class="fas fa-chevron-circle-left"></i>
|
||||
{{ _("Back")|force_escape }}
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<form id="user-form" action="{% if form.user %}{% url "mia_core:users.update" user %}{% else %}{% url "mia_core:users.store" %}{% endif %}" method="POST">
|
||||
{% csrf_token %}
|
||||
<input id="exists-url" type="hidden" value="{% url "mia_core:api.users.exists" "ID" %}" />
|
||||
<input id="user-login-id-original" type="hidden" value="{{ form.user.login_id }}" />
|
||||
<div class="row form-group">
|
||||
<label class="col-sm-2 col-form-label" for="user-login-id">{{ _("Log in ID:")|force_escape }}</label>
|
||||
<div class="col-sm-10">
|
||||
<input id="user-login-id" class="form-control {% if form.login_id.errors %} is-invalid {% endif %}" type="text" name="login-id" value="{{ form.login_id.value|default:"" }}" maxlength="32" required="required" />
|
||||
<div id="user-login-id-error" class="invalid-feedback">{{ form.login_id.errors.0 }}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row form-group">
|
||||
<label class="col-sm-2 col-form-label" for="user-password">{{ _("Password:")|force_escape }}</label>
|
||||
<div class="col-sm-10">
|
||||
<input id="user-password" class="form-control {% if form.password.errors %} is-invalid {% endif %}" type="password" name="password" value="" {% if not form.user %} required="required" {% endif %} />
|
||||
<div id="user-password-error" class="invalid-feedback">{{ form.password.errors.0 }}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row form-group">
|
||||
<label class="col-sm-2 col-form-label" for="user-password2">{{ _("Confirm password:")|force_escape }}</label>
|
||||
<div class="col-sm-10">
|
||||
<input id="user-password2" class="form-control {% if form.password2.errors %} is-invalid {% endif %}" type="password" name="password2" value="" {% if not form.user %} required="required" {% endif %} />
|
||||
<div id="user-password2-error" class="invalid-feedback">{{ form.password2.errors.0 }}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row form-group">
|
||||
<label class="col-sm-2 col-form-label" for="user-name">{{ _("Name:")|force_escape }}</label>
|
||||
<div class="col-sm-10">
|
||||
<input id="user-name" class="form-control {% if form.name.errors %} is-invalid {% endif %}" type="text" name="name" value="{{ form.name.value|default:"" }}" maxlength="32" required="required" />
|
||||
<div id="user-name-error" class="invalid-feedback">{{ form.name.errors.0 }}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row form-group form-check">
|
||||
<div class="col-sm-12">
|
||||
{% if form.user and form.user.pk == request.user.pk %}
|
||||
{{ _("You cannot disable your own account.")|force_escape }}
|
||||
{% else %}
|
||||
<input id="user-is-disabled" class="form-check-input" type="checkbox" name="is_disabled" value="1" {% if form.is_disabled.value %} checked="checked" {% endif %} />
|
||||
<label class="form-check-label" for="user-is-disabled">
|
||||
{{ _("This account is disabled.")|force_escape }}
|
||||
</label>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row form-group">
|
||||
<div class="col-sm-12">
|
||||
<button class="btn btn-primary" type="submit">
|
||||
{{ _("Submit")|force_escape }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
{% endblock %}
|
@ -27,19 +27,17 @@ register_converter(converters.UserConverter, "user")
|
||||
app_name = "mia_core"
|
||||
urlpatterns = [
|
||||
path("users", views.UserListView.as_view(), name="users"),
|
||||
# TODO: To be done.
|
||||
path("users/create", views.todo, name="users.create"),
|
||||
path("users/create", views.user_form, name="users.create"),
|
||||
# TODO: To be done.
|
||||
path("users/store", views.todo, name="users.store"),
|
||||
path("users/<user:user>", views.UserView.as_view(), name="users.detail"),
|
||||
# TODO: To be done.
|
||||
path("users/<user:user>/edit", views.todo, name="users.edit"),
|
||||
path("users/<user:user>/edit", views.user_form, name="users.edit"),
|
||||
# TODO: To be done.
|
||||
path("users/<user:user>/update", views.todo, name="users.update"),
|
||||
# TODO: To be done.
|
||||
path("users/<user:user>/delete", views.todo, name="users.delete"),
|
||||
# TODO: To be done.
|
||||
path("api/users/<str:login_id>/exists", views.todo,
|
||||
path("api/users/<str:login_id>/exists", views.api_users_exists,
|
||||
name="api.users.exists"),
|
||||
# TODO: To be done.
|
||||
path("my-account", views.todo, name="my-account"),
|
||||
|
@ -21,13 +21,16 @@
|
||||
from django.contrib import messages
|
||||
from django.contrib.auth import logout as logout_user
|
||||
from django.contrib.messages.views import SuccessMessageMixin
|
||||
from django.http import HttpResponse
|
||||
from django.shortcuts import redirect
|
||||
from django.views.decorators.http import require_POST
|
||||
from django.http import HttpResponse, JsonResponse
|
||||
from django.shortcuts import redirect, render
|
||||
from django.views.decorators.http import require_POST, require_GET
|
||||
from django.views.generic import DeleteView as CoreDeleteView, ListView, \
|
||||
DetailView
|
||||
|
||||
from mia_core.models import User
|
||||
from . import stored_post
|
||||
from .digest_auth import login_required
|
||||
from .forms import UserForm
|
||||
from .models import User
|
||||
|
||||
|
||||
class DeleteView(SuccessMessageMixin, CoreDeleteView):
|
||||
@ -67,6 +70,54 @@ class UserView(DetailView):
|
||||
return self.request.resolver_match.kwargs["user"]
|
||||
|
||||
|
||||
@require_GET
|
||||
@login_required
|
||||
def user_form(request, user=None):
|
||||
"""The view to edit an accounting transaction.
|
||||
|
||||
Args:
|
||||
request (HttpRequest): The request.
|
||||
user (User): The account.
|
||||
|
||||
Returns:
|
||||
HttpResponse: The response.
|
||||
"""
|
||||
previous_post = stored_post.get_previous_post(request)
|
||||
if previous_post is not None:
|
||||
form = UserForm(previous_post)
|
||||
elif user is not None:
|
||||
form = UserForm({
|
||||
"login_id": user.login_id,
|
||||
"name": user.name,
|
||||
"is_disabled": user.is_disabled,
|
||||
})
|
||||
else:
|
||||
form = UserForm()
|
||||
form.user = user
|
||||
form.current_user = request.user
|
||||
return render(request, "mia_core/user_form.html", {
|
||||
"form": form,
|
||||
})
|
||||
|
||||
|
||||
def api_users_exists(request, login_id):
|
||||
"""The view to check whether a user with a log in ID exists.
|
||||
|
||||
Args:
|
||||
request (HttpRequest): The request.
|
||||
login_id (str): The log in ID.
|
||||
|
||||
Returns:
|
||||
JsonResponse: The response.
|
||||
"""
|
||||
try:
|
||||
User.objects.get(login_id=login_id)
|
||||
except User.DoesNotExist:
|
||||
return JsonResponse(False, safe=False)
|
||||
return JsonResponse(True, safe=False)
|
||||
|
||||
|
||||
|
||||
# TODO: To be removed.
|
||||
def todo(request, **kwargs):
|
||||
"""A dummy placeholder view for the URL settings that are not
|
||||
|
Loading…
Reference in New Issue
Block a user