added profile pic for user model, updated code to upload profile pic in user edit, few changes in list pages (#112)

* updated python version in travis yml file

* added 404 & 500 pages, updated text in account, cases, leads, contact, opportunity add edit pages

* updated debug to false, added local manage.py file

* updated the code to redirect to create page only after clicking on save & new in accounts page, updated text in forgot password

* Added the relevant place holders in all the forms, displaying error message in forgot password form

* updated django version for security reasons

* fixed issue of showing column names if there is no data in list pages, fixed design in comment update section, changed the url of cancel button in user update page

* added profile pic for user model, updated code to upload profile pric in user edit, few changes in list pages
This commit is contained in:
nikhila05 2018-10-09 18:44:55 +05:30 committed by GitHub
parent 56c9a74461
commit c0576a3d7d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
18 changed files with 139 additions and 28 deletions

View file

@ -236,6 +236,7 @@
</div>
<div class="table-responsive">
<table class="table table-bordered table-striped table-condensed">
{% if contacts|length > 0 %}
<thead>
<tr>
<th width="5%" style="text-align:center;">S.No</th>
@ -245,6 +246,7 @@
<th width="25%" style="text-align:center;">Actions</th>
</tr>
</thead>
{% endif %}
<tbody>
{% for contact in contacts %}
<tr id="contacts_details{{contact.id}}" class="text-center">
@ -262,6 +264,9 @@
</tbody>
</table>
</div>
{% ifequal contacts|length 0 %}
<h6 class="text-center">No Contact Records Found</h6>
{% endifequal %}
</div>
</div>
<br clear="all">
@ -748,6 +753,7 @@
</div>
<div class="table-responsive">
<table class="table table-bordered table-striped table-condensed">
{% if opportunity_list|length > 0 %}
<thead>
<tr>
<th width="5%" style="text-align:center;">S.No</th>
@ -757,6 +763,7 @@
<th width="25%" style="text-align:center;">Actions </th>
</tr>
</thead>
{% endif %}
<tbody>
{% for opportunity in opportunity_list %}
<tr id="opp_details{{opportunity.id}}" class="text-center">
@ -774,6 +781,9 @@
</tbody>
</table>
</div>
`{% ifequal contacts|length 0 %}
<h6 class="text-center">No Opportunity Records Found</h6>
{% endifequal %}
</div>
</div>
<br clear="all">
@ -1306,6 +1316,7 @@
</div>
<div class="table-responsive">
<table class="table table-bordered table-striped table-condensed">
{% if cases|length > 0 %}
<thead>
<tr>
<th width="5%" style="text-align:center;">S.No</th>
@ -1315,6 +1326,7 @@
<th width="25%" style="text-align:center;">Actions</th>
</tr>
</thead>
{% endif %}
<tbody>
{% for case in cases %}
<tr id="cases_details{{case.id}}" class="text-center">
@ -1333,6 +1345,9 @@
</tbody>
</table>
</div>
{% ifequal cases|length 0 %}
<h6 class="text-center">No Case Records Found</h6>
{% endifequal %}
</div>
</div>
<br clear="all">

View file

@ -96,6 +96,7 @@
<table class="table " id="multiselect">
<thead>
{% if cases|length > 0 %}
<tr>
<th width="5%">S.No</th>
<th width="20%">Name</th>

View file

@ -55,7 +55,7 @@ class UserForm(forms.ModelForm):
class Meta:
model = User
fields = ['email', 'first_name', 'last_name', 'username', 'role']
fields = ['email', 'first_name', 'last_name', 'username', 'role', 'profile_pic']
def __init__(self, *args, **kwargs):
super(UserForm, self).__init__(*args, **kwargs)

View file

@ -0,0 +1,19 @@
# Generated by Django 2.1.1 on 2018-10-09 06:44
import common.models
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('common', '0003_user_role'),
]
operations = [
migrations.AddField(
model_name='user',
name='profile_pic',
field=models.FileField(blank=True, max_length=1000, null=True, upload_to=common.models.img_url),
),
]

View file

@ -3,9 +3,16 @@ from django.utils.translation import ugettext_lazy as _
from django.contrib.auth.models import AbstractBaseUser, PermissionsMixin, UserManager
from common.utils import COUNTRIES, ROLES
import time
def img_url(self, filename):
hash_ = int(time.time())
return "%s/%s/%s" % ("profile_pics", hash_, filename)
class User(AbstractBaseUser, PermissionsMixin):
file_prepend = "users/profile_pics"
username = models.CharField(max_length=100, unique=True)
first_name = models.CharField(max_length=150, blank=True)
last_name = models.CharField(max_length=150, blank=True)
@ -15,6 +22,8 @@ class User(AbstractBaseUser, PermissionsMixin):
is_staff = models.BooleanField(default=False)
date_joined = models.DateTimeField(('date joined'), auto_now_add=True)
role = models.CharField(max_length=50, choices=ROLES)
profile_pic = models.FileField(max_length=1000, upload_to=img_url, null=True, blank=True)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['username', ]

View file

@ -25,21 +25,21 @@
<label for="id_firstname">First Name{% if user_form.first_name.field.required %}<span class="error">*</span>{% endif %}</label>
<input type="text" class="form-control" name="first_name" value="{% if user_obj %}{{ user_obj.first_name }}{% else %}{{request.POST.first_name}}{% endif %}" placeholder="First Name">
</div>
<span class="error">{{ errors.first_name }}</span>
<span class="error" id="id_first_name">{{ errors.first_name }}</span>
</div>
<div class="filter_col col-md-12">
<div class="form-group">
<label for="id_lastname">Last Name{% if user_form.last_name.field.required %}<span class="error">*</span>{% endif %}</label>
<input type="text" class="form-control" name="last_name" value="{% if user_obj %}{{ user_obj.last_name }}{% else %}{{request.POST.last_name}} {% endif %}" placeholder="Last Name">
</div>
<span class="error">{{ errors.last_name }}</span>
<span class="error" id="id_last_name">{{ errors.last_name }}</span>
</div>
<div class="filter_col col-md-12">
<div class="form-group">
<label for="id_username">Username{% if user_form.username.field.required %}<span class="error">*</span>{% endif %}</label>
<input type="text" class="form-control" name="username" value="{% if user_obj %}{{ user_obj.username }}{% else %}{{request.POST.username}}{% endif %}" placeholder="Username">
</div>
<span class="error">{{ errors.username }}</span>
<span class="error" id="id_username">{{ errors.username }}</span>
</div>
<div class="filter_col col-md-12">
<div class="form-group">
@ -47,7 +47,7 @@
<input type="text" class="form-control" name="email" value="{% if user_obj %}{{ user_obj.email }}{% else %}{{request.POST.email}}{% endif %}" {% if user_obj %} readonly=""{% endif %} placeholder="Email">
</div>
<span class="error">{{ errors.email }}</span>
<span class="error" id="id_email">{{ errors.email }}</span>
</div>
<div class="filter_col col-md-12" {% if request.user.role != 'ADMIN' and not request.user.is_superuser %}style="display:none;"{% endif %}>
<div class="form-group">
@ -63,7 +63,7 @@
<option value="{{user_obj.role}}">{{user_obj.role}}</option>
</select>
{% endif %}
<span class="error">{{ user_form.role.errors }}</span>
<span class="error" id="id_role">{{ user_form.role.errors }}</span>
</div>
</div>
{% if not user_obj %}
@ -72,9 +72,17 @@
<label for="exampleInputEmail1">Password{% if user_form.password.field.required %}<span class="error">*</span>{% endif %}</label>
<input type="password" class="form-control" name="password" value="{{request.POST.password}}" placeholder="Password">
</div>
<span class="error">{{ errors.password }}</span>
<span class="error" id="id_password">{{ errors.password }}</span>
</div>
{% endif %}
<div class="filter_col col-md-12">
<div class="form-group">
<label for="exampleInputEmail1">Upload Profile Picture{% if user_form.profile_pic.field.required %}<span class="error">*</span>{% endif %}</label>
<input type="file" name="profile_pic" accept="image/*" class="form-control" />
</div>
{% if user_obj %}<span>{{user_obj.profile_pic }}</span>{% endif %}
<span class="error" id="id_profile_pic">{{ errors.profile_pic }}</span>
</div>
</div>
</div>
<div class="row marl buttons_row form_btn_row text-center">
@ -87,3 +95,26 @@
</div>
</form>
{% endblock content %}
{% block js_block %}
<script src="http://malsup.github.com/jquery.form.js"></script>
<script type="text/javascript">
$('form#add_form').ajaxForm({
type:'POST',
dataType:'json',
url: ".",
data:$('#add_form').serialize(),
success: function(data) {
if(data.error){
$('.error').html('')
for (var key in data.errors) {
$('#id_'+key).html("<p>" + data.errors[key][0] + "</p>");
};
}
else{
window.location = data.success_url;
}
}
});
</script>
{% endblock js_block %}

View file

@ -72,6 +72,7 @@
<table class="table table-bordered table-striped table-condensed">
<thead>
{% if users|length > 0 %}
<tr>
<th width="5%" style="text-align:center;">S.No</th>
<th width="20%" style="text-align:center;">First Name</th>
@ -105,7 +106,7 @@
</td>
<td class="actions">
<!-- <a href="{% url 'common:view_user' user.id %}" class="btn btn-info view"><i class="fas fa-eye"></i>View</a> -->
{% if request.user.id != user.id and user.email != "admin@micropyramid.com" %}
{% if user.email != admin_email or request.user.email == admin_email %}
<a href="{% url 'common:edit_user' user.id %}" class="btn btn-success edit"><i class="fas fa-pencil-alt"></i>Edit</a>
{% endif %}
<a href="{% url 'common:remove_user' user.id %}" class="btn btn-danger trash" {% if request.user.email == user.email or user.role == "ADMIN" or user.is_superuser %} style="visibility: hidden;" {% endif %}><i class="fas fa-trash-alt"></i>Delete</a>

View file

@ -4,6 +4,8 @@ from django.urls import path, re_path
from common.views import (
HomeView, LoginView, ForgotPasswordView, LogoutView, ChangePasswordView, ProfileView,
UsersListView, CreateUserView, UpdateUserView, UserDetailView, UserDeleteView)
from django.conf.urls.static import static
from django.conf import settings
app_name = 'common'
@ -32,4 +34,4 @@ urlpatterns = [
path('reset/done/', auth_views.PasswordResetCompleteView.as_view(), name='password_reset_complete'),
]
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

View file

@ -1,12 +1,14 @@
from django.contrib.auth import logout, authenticate, login
from django.contrib.auth.hashers import check_password
from django.contrib.auth.mixins import LoginRequiredMixin, AccessMixin
from django.http import HttpResponseRedirect
from django.http import HttpResponseRedirect, JsonResponse
from django.shortcuts import render, redirect, get_object_or_404
from django.views.generic import (
CreateView, UpdateView, DetailView, TemplateView, View, DeleteView)
from common.models import User
from common.forms import UserForm, LoginForm, ChangePasswordForm
from django.urls import reverse_lazy
from django.conf import settings
def handler404(request, exception):
@ -132,6 +134,7 @@ class UsersListView(AdminRequiredMixin, TemplateView):
context["active_users"] = self.get_queryset().filter(is_active=True)
context["inactive_users"] = self.get_queryset().filter(is_active=False)
context["per_page"] = self.request.POST.get('per_page')
context['admin_email'] = settings.ADMIN_EMAIL
return context
def post(self, request, *args, **kwargs):
@ -149,11 +152,17 @@ class CreateUserView(AdminRequiredMixin, CreateView):
if form.cleaned_data.get("password"):
user.set_password(form.cleaned_data.get("password"))
user.save()
return redirect("common:users_list")
if self.request.is_ajax():
data = {'success_url': reverse_lazy('common:users_list'), 'error': False}
return JsonResponse(data)
return super(CreateUserView, self).form_valid(form)
def form_invalid(self, form):
return self.render_to_response(
self.get_context_data(form=form, errors=form.errors))
response = super(CreateUserView, self).form_invalid(form)
if self.request.is_ajax():
return JsonResponse({'error': True, 'errors': form.errors})
return response
def get_context_data(self, **kwargs):
context = super(CreateUserView, self).get_context_data(**kwargs)
@ -190,12 +199,20 @@ class UpdateUserView(LoginRequiredMixin, UpdateView):
user.is_superuser = False
user.save()
if self.request.user.role == "ADMIN" or self.request.user.is_superuser:
return redirect("common:users_list")
return redirect("common:profile")
if self.request.is_ajax():
data = {'success_url': reverse_lazy('common:users_list'), 'error': False}
return JsonResponse(data)
if self.request.is_ajax():
data = {'success_url': reverse_lazy('common:profile'), 'error': False}
return JsonResponse(data)
return super(UpdateUserView, self).form_valid(form)
def form_invalid(self, form):
return self.render_to_response(
self.get_context_data(form=form, errors=form.errors))
response = super(UpdateUserView, self).form_invalid(form)
if self.request.is_ajax():
return JsonResponse({'error': True, 'errors': form.errors})
return response
def get_context_data(self, **kwargs):
context = super(UpdateUserView, self).get_context_data(**kwargs)

View file

@ -78,6 +78,7 @@
<div class="table-responsive">
<table class="table">
<thead>
{% if contact_obj_list|length > 0 %}
<tr>
<th width="5%" >S.no</th>

View file

@ -34,6 +34,7 @@ INSTALLED_APPS = [
'leads',
'opportunity',
'planner',
'sorl.thumbnail',
]
@ -182,3 +183,5 @@ SG_USER = os.getenv('SG_USER', '')
SG_PWD = os.getenv('SG_PWD', '')
MANDRILL_API_KEY = os.getenv('MANDRILL_API_KEY', '')
ADMIN_EMAIL = "admin@micropyramid.com"

View file

@ -186,7 +186,8 @@
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title">Update Your Comment</h4>
<button type="button" class="close" data-dismiss="modal">&times;</button>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">&times;</button>
</div>
<form id="comment_edit_form" method="POST" >
<div class="modal-body">

View file

@ -95,6 +95,7 @@
<table class="table ">
<thead>
{% if opportunity_list|length > 0 %}
<tr>
<th width="5%">S.No</th>
<th width="15%">Name</th>

View file

@ -168,7 +168,8 @@
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title">Update Your Comment</h4>
<button type="button" class="close" data-dismiss="modal">&times;</button>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">&times;</button>
</div>
<form id="comment_edit_form" method="POST" >
<div class="modal-body">

View file

@ -1,4 +1,4 @@
Django==2.1.2
Django==2.1.1
django-simple-pagination==1.1.8
pytz==2018.3
psycopg2-binary==2.7.4
@ -9,3 +9,5 @@ pytest==3.6.3
pytest-cov==2.5.1
pytest-django==3.1.2
codacy-coverage==1.3.6
sorl-thumbnail==12.5.0
Pillow==5.3.0

View file

@ -638,7 +638,6 @@ $color_2: #000;
.buttons_row{
margin:0;
position: relative;
top: -4px;
}
.form-control{
border-radius: 0;

View file

@ -1,6 +1,6 @@
{% load staticfiles %}
{% load compress %}
{% load thumbnail %}
<!DOCTYPE html>
<html lang="en">
<head>
@ -41,16 +41,16 @@
<ul class="navbar-nav navbar-right my-2 my-lg-0">
<li class="nav-item dropdown">
{% with request.profile as profile %}
<a href="#" class="dropdown-toggle abcd nav-link" data-toggle="dropdown" role="button" aria-haspopup="true"
aria-expanded="false" >
{% if not profile.profile_pic %}
{% if not request.user.profile_pic %}
<img src="{% static 'images/user.png' %}" alt="Micro profile pic">
{% else %}
<img src="{{profile.profile_pic.url}}" alt="Micro profile pic">
{% thumbnail request.user.profile_pic "25x25" as im %}
<img src="{{ im.url }}">
{% endthumbnail %}
{% endif %}
<b class="caret"></b></a>
{% endwith %}
<div class="dropdown-menu dropdown-menu-right" aria-labelledby="navbarDropdown">
{% if request.user.email != "admin@micropyramid.com" %}
<a class="dropdown-item" href="/change-password/"><i class="fas fa-key"></i> Change Password</a>

View file

@ -1,6 +1,8 @@
{% extends 'base.html' %}
{% load staticfiles %}
{% load thumbnail %}
{% block content%}
<!-- OPPORTUNITY VIEW STARTS -->
<div class="main_container" id="maincontainer">
<div class="overview_form_block row marl justify-content-center">
@ -21,18 +23,18 @@
</div>
</span> -->
</h5>
{% if not request.user.role == "ADMIN" and not request.user.is_superuser %}
<a href="{% url 'common:edit_user' user_obj.id %}" class="btn btn-success edit">Edit</a>
{% endif %}
</div>
<div class="row marl no-gutters">
<div class="col-md-8">
{% if user_obj.first_name %}
<div class="filter_col col-md-12">
<div class="form-group">
<label class="contact_field_label" for="id_name" data-name="name">Name</label>
<div class="contact_field" id="contact_name" data-name="name">{{ user_obj.first_name }} {{ user_obj.last_name }}</div>
</div>
</div>
{% endif %}
<div class="filter_col col-md-12">
<div class="form-group">
<label class="contact_field_label" for="id_contact_account" data-name="name">UserName</label>
@ -48,7 +50,13 @@
</div>
<div class="col-md-4">
<div class="profile_pic">
{% if user_obj.profile_pic %}
{% thumbnail request.user.profile_pic "125x125" as im %}
<img src="{{ im.url }}">
{% endthumbnail %}
{% else %}
<img src="https://cdn.dribbble.com/users/99875/screenshots/4353558/2018-03-01biker_site-2.gif" />
{% endif %}
</div>
</div>
</div>