Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Empty file added accounts/__init__.py
Empty file.
3 changes: 3 additions & 0 deletions accounts/admin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from django.contrib import admin

# Register your models here.
5 changes: 5 additions & 0 deletions accounts/apps.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
from django.apps import AppConfig


class AccountsConfig(AppConfig):
name = 'accounts'
43 changes: 43 additions & 0 deletions accounts/forms.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
from django import forms
from .models import CustomUser
from django.contrib.auth import get_user_model

User = get_user_model()


class SignUpForm(forms.ModelForm):
password1 = forms.CharField(label='Password', widget=forms.PasswordInput)
password2 = forms.CharField(label='Password confirmation', widget=forms.PasswordInput)

class Meta:
model = User
fields = ['name','email','phone']

def clean_password2(self):
password1 = self.cleaned_data.get("password1")
password2 = self.cleaned_data.get("password2")
if password1 and password2 and password1 != password2:
raise forms.ValidationError("Passwords don't match")
if len(password1) < 8:
raise forms.ValidationError('It must be 8 character or more')
return password2

def save(self, commit=True):
user = super().save(commit=False)
user.set_password(self.cleaned_data["password1"])
if commit:
user.save()
return user


class CreateStaffForm(forms.ModelForm):

class Meta:
model = User
fields = ['name','email','phone','is_active']

class UpdateStaffForm(forms.ModelForm):

class Meta:
model = User
fields = ['name','email','phone','is_active']
30 changes: 30 additions & 0 deletions accounts/managers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
from django.db import models
from django.contrib.auth.models import BaseUserManager


class CustomUserManager(BaseUserManager):
def create_user(self, email, name, password=None):

if not email:
raise ValueError('Staff must have an email address')

user = self.model(
email=self.normalize_email(email),
name=name,
)

user.set_password(password)
user.save(using=self._db)
return user

def create_superuser(self, email, name, phone, password=None):

user = self.create_user(
email,
password=password,
name=name,
)
user.is_active = True
user.is_superuser = True
user.save(using=self._db)
return user
44 changes: 44 additions & 0 deletions accounts/migrations/0001_initial.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# Generated by Django 3.0.7 on 2020-10-13 07:44

import accounts.models
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion


class Migration(migrations.Migration):

initial = True

dependencies = [
]

operations = [
migrations.CreateModel(
name='CustomUser',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('password', models.CharField(max_length=128, verbose_name='password')),
('last_login', models.DateTimeField(blank=True, null=True, verbose_name='last login')),
('name', models.CharField(max_length=100, verbose_name='Full Name')),
('email', models.EmailField(max_length=100, unique=True, verbose_name='Email Address')),
('phone', models.CharField(max_length=50, unique=True, verbose_name='Phone Number')),
('is_superuser', models.BooleanField(default=False)),
('is_admin', models.BooleanField(default=False)),
('is_manager', models.BooleanField(default=True)),
('is_staff', models.BooleanField(default=False)),
('is_active', models.BooleanField(default=False)),
('created_by', models.CharField(blank=True, max_length=100, null=True)),
],
options={
'abstract': False,
},
),
migrations.CreateModel(
name='Profile',
fields=[
('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, primary_key=True, serialize=False, to=settings.AUTH_USER_MODEL)),
('profile_pic', models.ImageField(default='profile_pics/user.svg', upload_to=accounts.models.profile_pic_filename, verbose_name='Profile Picture')),
],
),
]
Empty file added accounts/migrations/__init__.py
Empty file.
61 changes: 61 additions & 0 deletions accounts/models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
from uuid import uuid4
from django.db import models
from django.contrib.auth.models import AbstractBaseUser


from .managers import CustomUserManager


class CustomUser(AbstractBaseUser):
name = models.CharField(verbose_name='Full Name', max_length=100)
email = models.EmailField(verbose_name='Email Address', unique=True, max_length=100)
phone = models.CharField(max_length=50, unique=True, verbose_name='Phone Number')

is_superuser = models.BooleanField(default=False)
is_admin = models.BooleanField(default=False)

is_manager = models.BooleanField(default=True)
is_staff = models.BooleanField(default=False)

is_active = models.BooleanField(default=False)
created_by = models.CharField(max_length=100, blank=True, null=True)

objects = CustomUserManager()

USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['name', 'phone']


def has_perms(self, perm, obj=None):

if self.is_superuser or self.is_admin or self.is_manager:
return True

def has_module_perms(self, app_label):

if self.is_superuser or self.is_admin or self.is_manager:
return True

def __str__(self):
return self.email


# Profile Picture
def profile_pic_filename(instance, filename):
ext = filename.split('.')[1]
new_filename = f'{uuid4()}.{ext}'
return f'profile_pics/{new_filename}'


class Profile(models.Model):
user = models.OneToOneField(CustomUser, primary_key=True, on_delete=models.CASCADE)
profile_pic = models.ImageField(verbose_name='Profile Picture', default='profile_pics/user.svg', upload_to=profile_pic_filename)

def get_absolute_url(self):
return reverse('accounts:profile', kwargs={'pk': self.user_id})

def get_profile_update_url(self):
return reverse('accounts:profile-update', kwargs={'pk': self.user_id})

def __str__(self):
return f'{self.user.name} Profile'
20 changes: 20 additions & 0 deletions accounts/templates/accounts/account_activation_email.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Registration Confirmation - Fagrimacs</title>
</head>


<body>
<h2>Welcome to Fagrimacs</h2>
<p>
Please click link below to confirm your email and complete registration.
</p>
<p>
<a href="{{ confirm_url }}">{{ confirm_url }}</a>
</p>
</body>
</html>
72 changes: 72 additions & 0 deletions accounts/templates/accounts/create_staff.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
{% extends 'dashboard/base.html' %}
{% block content %}
<nav class="navbar navbar-expand-lg context-bar">
<a class="navbar-brand" href="#">
<i class="fa fa-users"></i> Staff
</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNavAltMarkup" aria-controls="navbarNavAltMarkup" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNavAltMarkup">
<div class="navbar-nav ml-auto">
<a class="nav-item nav-link" href="{% url 'accounts:home' %}">
<i class="fa fa-list"></i> View</a>
</div>
</div>
</nav>

{% include 'messages.html' %}

<div class="row">
<div class="col-4">
<div class="card">
<div class="card-header">
<h5 class="">Add New Staff</h5>
</div>
<div class="card-body">
<form action="{% url 'accounts:create-staff' %}" method="post">{% csrf_token %}
{{ form.as_p }}
<span class="text-muted">Phone number will be used as default password</span>
<button type="submit" class="btn btn-info btn-block mt-2">Save</button>
</form>

</div>
</div>
</div>
<div class="col-8">
<div class="card">
<div class="card-header">
<h5 class="">10 Most Recent Staff</h5>
</div>
<div class="card-body">
{% if staff|length > 0 %}
<table class="table table-striped table-bordered table-hover table-condensed">
<thead>
<th>#</th><th>Name</th><th>Phone</th><th>Email</th>
</thead>
<tbody>
{% for person in staff %}
<tr>
<td>{{ person.num }}.</td>
<td>
<a href="{% url 'accounts:update-staff' pk=person.pk %}"> {{ person.name }}</a>
</td>
<td>{{ person.phone_number }}</td>
<td>{{ person.email }}</td>
</tr>
{% endfor %}
</tbody>
</table>
{% else %}
<div class="alert alert-info">No staff have been added yet</div>
{% endif %}
</div>
</div>
</div>
</div>





{% endblock %}
59 changes: 59 additions & 0 deletions accounts/templates/accounts/customuser_confirm_delete.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
{% extends 'base.html' %}
{% block content %}
<nav class="navbar navbar-expand-lg context-bar">
<a class="navbar-brand" href="#"> <i class="fa fa-briefcase"></i> Staff</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNavAltMarkup" aria-controls="navbarNavAltMarkup" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNavAltMarkup">
<div class="navbar-nav ml-auto">

<a class="nav-item nav-link" href="{% url 'accounts:create-staff' %}">
<i class="fa fa-plus-circle"></i> Add New
</a>
<a class="nav-item nav-link" href="{% url 'accounts:home' %}">
<i class="fa fa-list"></i> View
</a>
</div>
</div>
</nav>

{% include 'messages.html' %}
<div class="row">
<div class="col-4">
<div class="card">
<div class="card-header">
<h5 class="">Delete Staff {{ customuser.name }}</h5>
</div>
<div class="card-body">
<h5 class="text-danger">Proceed to delete {{ customuser.name }} ?</h5>
<form action="{% url 'accounts:delete-staff' pk=customuser.pk %}" method="post">{% csrf_token %}
<button type="submit" class="btn btn-danger btn-block">Delete</button>
</form>
</div>
</div>
</div>
<div class="col-8">
<div class="card">
<div class="card-header">
<h5 class="">{{ customuser.name }} Details</h5>
</div>
<div class="card-body">
<table class="table table-hover table-striped table-responsive">
<tbody>
<tr><td>Name</td><td>{{ customuser.name }}</td></tr>
<tr><td>Phone</td><td>{{ customuser.phone_number }}</td></tr>
<tr><td>Email</td><td>{{ customuser.email }}</td></tr>
<tr><td>Created</td><td>{{ customuser.date_joined|date:'d-m-Y H:i' }}</td></tr>
</tbody>
</table>
</div>
</div>
</div>
</div>





{% endblock %}
Loading