commit
646dfefdda
36 changed files with 574 additions and 445 deletions
|
|
@ -1,26 +0,0 @@
|
|||
Python 3.4:
|
||||
script:
|
||||
- export PY_EXE=python3.4
|
||||
- virtualenv -p python3 env
|
||||
- source env/bin/activate
|
||||
- pip install -r requirements.txt
|
||||
- python manage.py test --noinput
|
||||
- coverage run --source=accounts,cases,common,contacts,emails,leads,opportunity,planner manage.py test --noinput
|
||||
- coverage report -m
|
||||
except:
|
||||
- tags
|
||||
|
||||
deploy_live:
|
||||
stage: deploy
|
||||
environment:
|
||||
name: live
|
||||
script:
|
||||
- sudo /bin/rm -rf /home/dj_crm/dj_crm/; cp -r . /home/dj_crm/dj_crm
|
||||
- source /home/dj_crm/env/bin/activate
|
||||
- pip install -r /home/dj_crm/dj_crm/requirements.txt
|
||||
- python /home/dj_crm/dj_crm/manage.py migrate --noinput
|
||||
- sudo /etc/init.d/uwsgi restart
|
||||
only:
|
||||
- master
|
||||
tags:
|
||||
- github-crm
|
||||
|
|
@ -1,6 +1,9 @@
|
|||
{% extends 'base.html' %}
|
||||
{% load staticfiles %}
|
||||
{% load paginate %}
|
||||
{% block extralinks %}
|
||||
<link href="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.6-rc.0/css/select2.min.css" rel="stylesheet" />
|
||||
{% endblock %}
|
||||
{% block content %}
|
||||
<!-- main_container starts here -->
|
||||
<div class="main_container">
|
||||
|
|
@ -33,10 +36,9 @@
|
|||
<div class="filter_col col-md-2">
|
||||
<div class="form-group">
|
||||
<label for="exampleInputEmail1">Assigned Users</label>
|
||||
{{request.POST.assigned_to}}
|
||||
<select class="assigned_users1 form-control" name="assigned_to" multiple="multiple">
|
||||
<select class="assigned_users form-control" name="assigned_to" multiple="multiple">
|
||||
{% for user in users %}
|
||||
<option value="{{user.id}}" {% if user in account_obj.assigned_to.all or user.id in assignedto_list %} selected="" {% endif %}>{{user.email}}</option>
|
||||
<option value="{{user.id}}" {% if user in account_obj.assigned_to.all or user.id in assignedto_list or user.id in request.POST.assigned_to %} selected="" {% endif %}>{{user.email}}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
{{ account_form.assigned_to.errors }}
|
||||
|
|
@ -98,7 +100,7 @@
|
|||
<div class="card-body">
|
||||
<div class="panel-heading-list card-title text-right">
|
||||
|
||||
<span class="total_count float-left">List of Open Accounts :{% if show_pageitems %} {% show_pageitems %}{% else %}{{open_accounts|length}}{% endif %}</span>
|
||||
<span class="total_count float-left">Open Accounts - {% if show_pageitems %} {% show_pageitems %}{% else %}{{open_accounts|length}}{% endif %}</span>
|
||||
<span class="filter_toggle ">
|
||||
<a href="#" class="primary_btn"><i class="fas fa-filter"></i></a>
|
||||
</span>
|
||||
|
|
@ -131,7 +133,17 @@
|
|||
<td>{% if each_account.name %}<a href="{% url 'accounts:view_account' each_account.id %}">{{ each_account.name }}</a>{% endif %}</td>
|
||||
<td>{% if each_account.billing_address.city %}{{ each_account.billing_address.city }} {% else %} Not specified {% endif %}</td>
|
||||
<td>{% if each_account.billing_address.state %}{{ each_account.billing_address.state }} {% else %} Not specified {% endif %}</td>
|
||||
<td>santro@mp.com</td>
|
||||
<td>
|
||||
{% with assigned_users=each_account.assigned_to.all %}
|
||||
{% if assigned_users %}
|
||||
{% for user in assigned_users %}
|
||||
<span class="text-left">{{ user.email }}</span><br>
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
Not Assigned
|
||||
{% endif %}
|
||||
{% endwith %}
|
||||
</td>
|
||||
<td>{% if each_account.industry %}{{ each_account.industry }} {% else %} Not specified {% endif %}</td>
|
||||
<td style="display: block;">
|
||||
{% with tags=each_account.tags.all %}
|
||||
|
|
@ -166,9 +178,11 @@
|
|||
<div class="tab-pane fade" id="close" role="tabpanel" aria-labelledby="close">
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<div class="panel-heading-list card-title">
|
||||
List of Closed Accounts
|
||||
<span class="float-right total_count">{% if show_pageitems %} {% show_pageitems %}{% else %}Total Closed Accounts {{close_accounts|length}}{% endif %}</span>
|
||||
<div class="panel-heading-list card-title text-right">
|
||||
<span class="total_count float-left">Close Accounts - {% if show_pageitems %} {% show_pageitems %}{% else %}{{close_accounts|length}}{% endif %}</span>
|
||||
<span class="filter_toggle ">
|
||||
<a href="#" class="primary_btn"><i class="fas fa-filter"></i></a>
|
||||
</span>
|
||||
</div>
|
||||
<div class="table-responsive">
|
||||
<table class="table">
|
||||
|
|
@ -177,11 +191,11 @@
|
|||
<tr>
|
||||
<th width="5%">ID</th>
|
||||
<th width="15%">Name</th>
|
||||
<th width="15%">City</th>
|
||||
<th width="15%">State</th>
|
||||
<th width="15%">Assigned To</th>
|
||||
<th width="15%">Industry</th>
|
||||
<th width="10%">Tags</th>
|
||||
<th width="10%">City</th>
|
||||
<th width="10%">State</th>
|
||||
<th width="25%">Assigned To</th>
|
||||
<th width="10%">Industry</th>
|
||||
<th width="20%">Tags</th>
|
||||
<th width="10%">Actions</th>
|
||||
</tr>
|
||||
{% endif %}
|
||||
|
|
@ -198,7 +212,17 @@
|
|||
<td>{% if each_account.name %}<a href="{% url 'accounts:view_account' each_account.id %}">{{ each_account.name }}</a>{% endif %}</td>
|
||||
<td>{% if each_account.billing_address.city %}{{ each_account.billing_address.city }} {% else %} Not specified {% endif %}</td>
|
||||
<td>{% if each_account.billing_address.state %}{{ each_account.billing_address.state }} {% else %} Not specified {% endif %}</td>
|
||||
<td>santro@mp.com</td>
|
||||
<td>
|
||||
{% with assigned_users=each_account.assigned_to.all %}
|
||||
{% if assigned_users %}
|
||||
{% for user in assigned_users %}
|
||||
<span class="text-left">{{ user.email }}</span><br>
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
Not Assigned
|
||||
{% endif %}
|
||||
{% endwith %}
|
||||
</td>
|
||||
<td>{% if each_account.industry %}{{ each_account.industry }} {% else %} Not specified {% endif %}</td>
|
||||
<td style="display: block;">
|
||||
{% with tags=each_account.tags.all %}
|
||||
|
|
@ -242,7 +266,12 @@
|
|||
<!-- main_container ends here -->
|
||||
{% endblock %}
|
||||
{% block js_block %}
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.6-rc.0/js/select2.min.js"></script>
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function() {
|
||||
$('.assigned_users').select2();
|
||||
});
|
||||
|
||||
$('.remove_account').click(function(e){
|
||||
e.preventDefault()
|
||||
url = $(this).attr('href')
|
||||
|
|
@ -259,7 +288,6 @@
|
|||
$(".filter_toggle").click(function(){
|
||||
$(".list_filter_row").toggle();
|
||||
});
|
||||
$('.assigned_users1').select2();
|
||||
});
|
||||
|
||||
$("a[rel='page']").click(function(e){
|
||||
|
|
|
|||
|
|
@ -121,7 +121,7 @@
|
|||
<div class="col-md-12">
|
||||
<div class="row marl buttons_row form_btn_row text-center">
|
||||
<button class="btn btn-default save" type="submit">Save</button>
|
||||
<a href="{% if not user_obj or request.user.is_superuser or request.user.role == 'ADMIN' %}{% url 'common:users_list' %}{% else %}{% url 'common:profile' %}{% endif %}" class="btn btn-default clear" id="create_user_cancel">Cancel</a>
|
||||
<a href="{% url 'accounts:list' %}" class="btn btn-default clear" id="create_user_cancel">Cancel</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -130,6 +130,18 @@
|
|||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if account_record.tags.all %}
|
||||
<div class="filter_col col-md-12">
|
||||
<div class="form-group">
|
||||
<label class="acc_field_label" for="id_tags" data-name="name">Tags</label>
|
||||
<div class="account_field" id="account_tags" data-name="name">
|
||||
{% for tag in account_record.tags.all %}
|
||||
<span class="text-left" id="list_tag">{{ tag.name }}</span>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="col-md-12">
|
||||
<div class="created_information">
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@ class AccountsListView(LoginRequiredMixin, TemplateView):
|
|||
open_accounts = self.get_queryset().filter(status='open')
|
||||
close_accounts = self.get_queryset().filter(status='close')
|
||||
context["accounts_list"] = self.get_queryset()
|
||||
context["users"] = User.objects.filter(is_active=True).order_by('email')
|
||||
context['open_accounts'] = open_accounts
|
||||
context['close_accounts'] = close_accounts
|
||||
context["industries"] = INDCHOICES
|
||||
|
|
@ -81,8 +82,8 @@ class CreateAccountView(LoginRequiredMixin, CreateView):
|
|||
shipping_form = ShippingAddressForm(request.POST, prefix='ship')
|
||||
if form.is_valid() and billing_form.is_valid() and shipping_form.is_valid():
|
||||
return self.form_valid(form, billing_form, shipping_form)
|
||||
else:
|
||||
return self.form_invalid(form, billing_form, shipping_form)
|
||||
|
||||
return self.form_invalid(form, billing_form, shipping_form)
|
||||
|
||||
def form_valid(self, form, billing_form, shipping_form):
|
||||
# Save Billing & Shipping Address
|
||||
|
|
@ -112,19 +113,19 @@ class CreateAccountView(LoginRequiredMixin, CreateView):
|
|||
if self.request.POST.getlist('teams', []):
|
||||
account_object.teams.add(*self.request.POST.getlist('teams'))
|
||||
if self.request.POST.get('tags', ''):
|
||||
tags = self.request.POST.get("tags")
|
||||
splitted_tags = tags.split(",")
|
||||
for t in splitted_tags:
|
||||
tag = Tags.objects.filter(name=t.lower())
|
||||
if tag:
|
||||
tag = tag[0]
|
||||
else:
|
||||
tag = Tags.objects.create(name=t.lower())
|
||||
account_object.tags.add(tag)
|
||||
tags = self.request.POST.get("tags")
|
||||
splitted_tags = tags.split(",")
|
||||
for t in splitted_tags:
|
||||
tag = Tags.objects.filter(name=t.lower())
|
||||
if tag:
|
||||
tag = tag[0]
|
||||
else:
|
||||
tag = Tags.objects.create(name=t.lower())
|
||||
account_object.tags.add(tag)
|
||||
if self.request.POST.get("savenewform"):
|
||||
return redirect("accounts:new_account")
|
||||
else:
|
||||
return redirect("accounts:list")
|
||||
|
||||
return redirect("accounts:list")
|
||||
|
||||
def form_invalid(self, form, billing_form, shipping_form):
|
||||
return self.render_to_response(
|
||||
|
|
@ -222,8 +223,8 @@ class AccountUpdateView(LoginRequiredMixin, UpdateView):
|
|||
request.POST, instance=self.object.shipping_address, prefix='ship')
|
||||
if form.is_valid() and billing_form.is_valid() and shipping_form.is_valid():
|
||||
return self.form_valid(form, billing_form, shipping_form)
|
||||
else:
|
||||
return self.form_invalid(form, billing_form, shipping_form)
|
||||
|
||||
return self.form_invalid(form, billing_form, shipping_form)
|
||||
|
||||
def form_valid(self, form, billing_form, shipping_form):
|
||||
assigned_to_ids = self.get_object().assigned_to.all().values_list('id', flat=True)
|
||||
|
|
@ -340,11 +341,11 @@ class AddCommentView(LoginRequiredMixin, CreateView):
|
|||
form = self.get_form()
|
||||
if form.is_valid():
|
||||
return self.form_valid(form)
|
||||
else:
|
||||
return self.form_invalid(form)
|
||||
else:
|
||||
data = {'error': "You don't have permission to comment for this account."}
|
||||
return JsonResponse(data)
|
||||
|
||||
return self.form_invalid(form)
|
||||
|
||||
data = {'error': "You don't have permission to comment for this account."}
|
||||
return JsonResponse(data)
|
||||
|
||||
def form_valid(self, form):
|
||||
comment = form.save(commit=False)
|
||||
|
|
@ -370,11 +371,11 @@ class UpdateCommentView(LoginRequiredMixin, View):
|
|||
form = AccountCommentForm(request.POST, instance=self.comment_obj)
|
||||
if form.is_valid():
|
||||
return self.form_valid(form)
|
||||
else:
|
||||
return self.form_invalid(form)
|
||||
else:
|
||||
data = {'error': "You don't have permission to edit this comment."}
|
||||
return JsonResponse(data)
|
||||
|
||||
return self.form_invalid(form)
|
||||
|
||||
data = {'error': "You don't have permission to edit this comment."}
|
||||
return JsonResponse(data)
|
||||
|
||||
def form_valid(self, form):
|
||||
self.comment_obj.comment = form.cleaned_data.get("comment")
|
||||
|
|
@ -396,9 +397,9 @@ class DeleteCommentView(LoginRequiredMixin, View):
|
|||
self.object.delete()
|
||||
data = {"cid": request.POST.get("comment_id")}
|
||||
return JsonResponse(data)
|
||||
else:
|
||||
data = {'error': "You don't have permission to delete this comment."}
|
||||
return JsonResponse(data)
|
||||
|
||||
data = {'error': "You don't have permission to delete this comment."}
|
||||
return JsonResponse(data)
|
||||
|
||||
|
||||
class AddAttachmentView(LoginRequiredMixin, CreateView):
|
||||
|
|
@ -417,11 +418,11 @@ class AddAttachmentView(LoginRequiredMixin, CreateView):
|
|||
form = self.get_form()
|
||||
if form.is_valid():
|
||||
return self.form_valid(form)
|
||||
else:
|
||||
return self.form_invalid(form)
|
||||
else:
|
||||
data = {'error': "You don't have permission to add attachment for this account."}
|
||||
return JsonResponse(data)
|
||||
|
||||
return self.form_invalid(form)
|
||||
|
||||
data = {'error': "You don't have permission to add attachment for this account."}
|
||||
return JsonResponse(data)
|
||||
|
||||
def form_valid(self, form):
|
||||
attachment = form.save(commit=False)
|
||||
|
|
@ -447,11 +448,13 @@ class DeleteAttachmentsView(LoginRequiredMixin, View):
|
|||
|
||||
def post(self, request, *args, **kwargs):
|
||||
self.object = get_object_or_404(Attachments, id=request.POST.get("attachment_id"))
|
||||
if (request.user == self.object.created_by or request.user.is_superuser or
|
||||
request.user.role == 'ADMIN'):
|
||||
if (
|
||||
request.user == self.object.created_by or request.user.is_superuser or
|
||||
request.user.role == 'ADMIN'
|
||||
):
|
||||
self.object.delete()
|
||||
data = {"acd": request.POST.get("attachment_id")}
|
||||
return JsonResponse(data)
|
||||
else:
|
||||
data = {'error': "You don't have permission to delete this attachment."}
|
||||
return JsonResponse(data)
|
||||
|
||||
data = {'error': "You don't have permission to delete this attachment."}
|
||||
return JsonResponse(data)
|
||||
|
|
|
|||
|
|
@ -34,7 +34,8 @@ class CaseForm(forms.ModelForm):
|
|||
case = Case.objects.filter(name__iexact=name).exclude(id=self.instance.id)
|
||||
if case:
|
||||
raise forms.ValidationError("Case Already Exists with this Name")
|
||||
return name
|
||||
else:
|
||||
return name
|
||||
|
||||
|
||||
class CaseCommentForm(forms.ModelForm):
|
||||
|
|
|
|||
|
|
@ -81,7 +81,7 @@
|
|||
<div class="card-body">
|
||||
<div class="panel-heading-list card-title text-right">
|
||||
|
||||
<span class="total_count float-left">Total Cases :{% if show_pageitems %} {% show_pageitems %}{% else %}Total Cases {{ cases|length }}{% endif %}</span>
|
||||
<span class="total_count float-left">Cases - {% if show_pageitems %} {% show_pageitems %}{% else %}{{ cases|length }}{% endif %}</span>
|
||||
<span class="filter_toggle ">
|
||||
<a href="#" class="primary_btn"><i class="fas fa-filter"></i></a>
|
||||
</span>
|
||||
|
|
|
|||
|
|
@ -111,7 +111,7 @@
|
|||
{% if not case_obj %}
|
||||
<button class="btn btn-success save savenew" type="submit">Save & New</button>
|
||||
{% endif %}
|
||||
<a {% if request.GET.view_account %} href="{% url 'accounts:view_account' request.GET.view_account %}" {% else %} href="{% url 'contacts:list' %}" {% endif %} class="btn btn-default clear">Cancel</a>
|
||||
<a {% if request.GET.view_account %} href="{% url 'accounts:view_account' request.GET.view_account %}" {% else %} href="{% url 'cases:list' %}" {% endif %} class="btn btn-default clear">Cancel</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -77,8 +77,8 @@ class CreateCaseView(LoginRequiredMixin, CreateView):
|
|||
form = self.get_form()
|
||||
if form.is_valid():
|
||||
return self.form_valid(form)
|
||||
else:
|
||||
return self.form_invalid(form)
|
||||
|
||||
return self.form_invalid(form)
|
||||
|
||||
def form_valid(self, form):
|
||||
case = form.save(commit=False)
|
||||
|
|
@ -110,8 +110,8 @@ class CreateCaseView(LoginRequiredMixin, CreateView):
|
|||
if self.request.POST.get('from_account'):
|
||||
from_account = self.request.POST.get('from_account')
|
||||
return redirect("accounts:view_account", pk=from_account)
|
||||
else:
|
||||
return redirect('cases:list')
|
||||
|
||||
return redirect('cases:list')
|
||||
|
||||
def form_invalid(self, form):
|
||||
if self.request.is_ajax():
|
||||
|
|
@ -183,8 +183,8 @@ class UpdateCaseView(LoginRequiredMixin, UpdateView):
|
|||
form = self.get_form()
|
||||
if form.is_valid():
|
||||
return self.form_valid(form)
|
||||
else:
|
||||
return self.form_invalid(form)
|
||||
|
||||
return self.form_invalid(form)
|
||||
|
||||
def form_valid(self, form):
|
||||
assigned_to_ids = self.get_object().assigned_to.all().values_list('id', flat=True)
|
||||
|
|
@ -263,8 +263,8 @@ class RemoveCaseView(LoginRequiredMixin, View):
|
|||
if request.GET.get('view_account'):
|
||||
account = request.GET.get('view_account')
|
||||
return redirect("accounts:view_account", pk=account)
|
||||
else:
|
||||
return redirect("cases:list")
|
||||
|
||||
return redirect("cases:list")
|
||||
|
||||
def post(self, request, *args, **kwargs):
|
||||
case_id = kwargs.get("case_id")
|
||||
|
|
@ -324,11 +324,11 @@ class AddCommentView(LoginRequiredMixin, CreateView):
|
|||
form = self.get_form()
|
||||
if form.is_valid():
|
||||
return self.form_valid(form)
|
||||
else:
|
||||
return self.form_invalid(form)
|
||||
else:
|
||||
data = {'error': "You don't have permission to comment."}
|
||||
return JsonResponse(data)
|
||||
|
||||
return self.form_invalid(form)
|
||||
|
||||
data = {'error': "You don't have permission to comment."}
|
||||
return JsonResponse(data)
|
||||
|
||||
def form_valid(self, form):
|
||||
comment = form.save(commit=False)
|
||||
|
|
@ -350,16 +350,18 @@ class UpdateCommentView(LoginRequiredMixin, View):
|
|||
|
||||
def post(self, request, *args, **kwargs):
|
||||
self.comment_obj = get_object_or_404(Comment, id=request.POST.get("commentid"))
|
||||
if (request.user == self.comment_obj.commented_by or request.user.is_superuser or
|
||||
request.user.role == 'ADMIN'):
|
||||
if (
|
||||
request.user == self.comment_obj.commented_by or request.user.is_superuser or
|
||||
request.user.role == 'ADMIN'
|
||||
):
|
||||
form = CaseCommentForm(request.POST, instance=self.comment_obj)
|
||||
if form.is_valid():
|
||||
return self.form_valid(form)
|
||||
else:
|
||||
return self.form_invalid(form)
|
||||
else:
|
||||
data = {'error': "You don't have permission to edit this comment."}
|
||||
return JsonResponse(data)
|
||||
|
||||
return self.form_invalid(form)
|
||||
|
||||
data = {'error': "You don't have permission to edit this comment."}
|
||||
return JsonResponse(data)
|
||||
|
||||
def form_valid(self, form):
|
||||
self.comment_obj.comment = form.cleaned_data.get("comment")
|
||||
|
|
@ -377,14 +379,16 @@ class DeleteCommentView(LoginRequiredMixin, View):
|
|||
|
||||
def post(self, request, *args, **kwargs):
|
||||
self.object = get_object_or_404(Comment, id=request.POST.get("comment_id"))
|
||||
if (request.user == self.object.commented_by or request.user.is_superuser or
|
||||
request.user.role == 'ADMIN'):
|
||||
if (
|
||||
request.user == self.object.commented_by or request.user.is_superuser or
|
||||
request.user.role == 'ADMIN'
|
||||
):
|
||||
self.object.delete()
|
||||
data = {"cid": request.POST.get("comment_id")}
|
||||
return JsonResponse(data)
|
||||
else:
|
||||
data = {'error': "You don't have permission to delete this comment."}
|
||||
return JsonResponse(data)
|
||||
|
||||
data = {'error': "You don't have permission to delete this comment."}
|
||||
return JsonResponse(data)
|
||||
|
||||
|
||||
class AddAttachmentView(LoginRequiredMixin, CreateView):
|
||||
|
|
@ -403,11 +407,11 @@ class AddAttachmentView(LoginRequiredMixin, CreateView):
|
|||
form = self.get_form()
|
||||
if form.is_valid():
|
||||
return self.form_valid(form)
|
||||
else:
|
||||
return self.form_invalid(form)
|
||||
else:
|
||||
data = {"error":True, "errors": "You don't have permission to add attachment for this case."}
|
||||
return JsonResponse(data)
|
||||
|
||||
return self.form_invalid(form)
|
||||
|
||||
data = {"error":True, "errors": "You don't have permission to add attachment for this case."}
|
||||
return JsonResponse(data)
|
||||
|
||||
def form_valid(self, form):
|
||||
attachment = form.save(commit=False)
|
||||
|
|
@ -437,11 +441,13 @@ class DeleteAttachmentsView(LoginRequiredMixin, View):
|
|||
|
||||
def post(self, request, *args, **kwargs):
|
||||
self.object = get_object_or_404(Attachments, id=request.POST.get("attachment_id"))
|
||||
if (request.user == self.object.created_by or request.user.is_superuser or
|
||||
request.user.role == 'ADMIN'):
|
||||
if (
|
||||
request.user == self.object.created_by or request.user.is_superuser or
|
||||
request.user.role == 'ADMIN'
|
||||
):
|
||||
self.object.delete()
|
||||
data = {"attachment_object": request.POST.get("attachment_id"), "error": False}
|
||||
return JsonResponse(data)
|
||||
else:
|
||||
data = {"error":True, "errors": "You don't have permission to delete this attachment."}
|
||||
return JsonResponse(data)
|
||||
|
||||
data = {"error":True, "errors": "You don't have permission to delete this attachment."}
|
||||
return JsonResponse(data)
|
||||
|
|
@ -6,4 +6,4 @@ admin.site.register(User)
|
|||
admin.site.register(Address)
|
||||
admin.site.register(Team)
|
||||
admin.site.register(Comment)
|
||||
admin.site.register(Comment_Files)
|
||||
admin.site.register(Comment_Files)
|
||||
|
|
|
|||
|
|
@ -81,15 +81,13 @@ class UserForm(forms.ModelForm):
|
|||
if self.instance.email != email:
|
||||
if not User.objects.filter(email=self.cleaned_data.get("email")).exists():
|
||||
return self.cleaned_data.get("email")
|
||||
else:
|
||||
raise forms.ValidationError('Email already exists')
|
||||
raise forms.ValidationError('Email already exists')
|
||||
else:
|
||||
return self.cleaned_data.get("email")
|
||||
else:
|
||||
if not User.objects.filter(email=self.cleaned_data.get("email")).exists():
|
||||
return self.cleaned_data.get("email")
|
||||
else:
|
||||
raise forms.ValidationError('User already exists with this email')
|
||||
return self.cleaned_data.get("email")
|
||||
raise forms.ValidationError('User already exists with this email')
|
||||
|
||||
|
||||
class LoginForm(forms.ModelForm):
|
||||
|
|
|
|||
|
|
@ -1,10 +1,9 @@
|
|||
from django.db import models
|
||||
from datetime import datetime
|
||||
from django.template.defaultfilters import slugify
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.contrib.auth.models import AbstractBaseUser, PermissionsMixin, UserManager
|
||||
from common.templatetags.common_tags import *
|
||||
|
||||
from common.templatetags.common_tags import (is_document_file_image,is_document_file_audio,
|
||||
is_document_file_video,is_document_file_pdf,is_document_file_code,is_document_file_text,
|
||||
is_document_file_sheet,is_document_file_zip)
|
||||
from common.utils import COUNTRIES, ROLES
|
||||
import time
|
||||
|
||||
|
|
@ -118,8 +117,8 @@ class Comment_Files(models.Model):
|
|||
def get_file_name(self):
|
||||
if self.comment_file:
|
||||
return self.comment_file.path.split('/')[-1]
|
||||
else:
|
||||
return None
|
||||
|
||||
return None
|
||||
|
||||
|
||||
class Attachments(models.Model):
|
||||
|
|
@ -140,19 +139,19 @@ class Attachments(models.Model):
|
|||
ext = name_ext_list[int(len(name_ext_list) - 1)]
|
||||
if is_document_file_audio(ext):
|
||||
return ("audio", "fa fa-file-audio")
|
||||
elif is_document_file_video(ext):
|
||||
if is_document_file_video(ext):
|
||||
return ("video", "fa fa-file-video")
|
||||
elif is_document_file_image(ext):
|
||||
if is_document_file_image(ext):
|
||||
return ("image", "fa fa-file-image")
|
||||
elif is_document_file_pdf(ext):
|
||||
if is_document_file_pdf(ext):
|
||||
return ("pdf", "fa fa-file-pdf")
|
||||
elif is_document_file_code(ext):
|
||||
if is_document_file_code(ext):
|
||||
return ("code", "fa fa-file-code")
|
||||
elif is_document_file_text(ext):
|
||||
if is_document_file_text(ext):
|
||||
return ("text", "fa fa-file-alt")
|
||||
elif is_document_file_sheet(ext):
|
||||
if is_document_file_sheet(ext):
|
||||
return ("sheet", "fa fa-file-excel")
|
||||
elif is_document_file_zip(ext):
|
||||
if is_document_file_zip(ext):
|
||||
return ("zip", "fa fa-file-archive")
|
||||
return ("file", "fa fa-file")
|
||||
return ("file", "fa fa-file")
|
||||
|
|
@ -189,19 +188,19 @@ class Document(models.Model):
|
|||
ext = name_ext_list[int(len(name_ext_list) - 1)]
|
||||
if is_document_file_audio(ext):
|
||||
return ("audio", "fa fa-file-audio")
|
||||
elif is_document_file_video(ext):
|
||||
if is_document_file_video(ext):
|
||||
return ("video", "fa fa-file-video")
|
||||
elif is_document_file_image(ext):
|
||||
if is_document_file_image(ext):
|
||||
return ("image", "fa fa-file-image")
|
||||
elif is_document_file_pdf(ext):
|
||||
if is_document_file_pdf(ext):
|
||||
return ("pdf", "fa fa-file-pdf")
|
||||
elif is_document_file_code(ext):
|
||||
if is_document_file_code(ext):
|
||||
return ("code", "fa fa-file-code")
|
||||
elif is_document_file_text(ext):
|
||||
if is_document_file_text(ext):
|
||||
return ("text", "fa fa-file-alt")
|
||||
elif is_document_file_sheet(ext):
|
||||
if is_document_file_sheet(ext):
|
||||
return ("sheet", "fa fa-file-excel")
|
||||
elif is_document_file_zip(ext):
|
||||
if is_document_file_zip(ext):
|
||||
return ("zip", "fa fa-file-archive")
|
||||
return ("file", "fa fa-file")
|
||||
return ("file", "fa fa-file")
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@
|
|||
<div class="card">
|
||||
<div class="card-body">
|
||||
<div class="panel-heading-list card-title text-right">
|
||||
<span class="total_count float-left">Documents :{% if show_pageitems %} {% show_pageitems %}{% else %}Total Documents {{documents|length}}{% endif %}</span>
|
||||
<span class="total_count float-left">Documents - {% if show_pageitems %} {% show_pageitems %}{% else %} {{documents|length}}{% endif %}</span>
|
||||
<span class="filter_toggle ">
|
||||
<a href="#" class="primary_btn"><i class="fas fa-filter"></i></a>
|
||||
</span>
|
||||
|
|
@ -116,7 +116,7 @@
|
|||
<script type="text/javascript">
|
||||
|
||||
$(document).ready(function(){
|
||||
$(".filter_toggle").click(function(){
|
||||
$(".filter_toggle").click(function(){
|
||||
$(".list_filter_row").toggle();
|
||||
});
|
||||
});
|
||||
|
|
@ -129,11 +129,6 @@
|
|||
window.location = $(this).attr('href')
|
||||
});
|
||||
|
||||
$(document).ready(function(){
|
||||
$(".filter_toggle").click(function(){
|
||||
$(".list_filter_row").toggle();
|
||||
});
|
||||
});
|
||||
$(".reset").click(function(e){
|
||||
window.location = "{% url 'common:doc_list'%}"
|
||||
});
|
||||
|
|
|
|||
|
|
@ -110,3 +110,7 @@ def is_document_file_zip(ext):
|
|||
ext_list = ['zip', '7Z', 'gz', 'rar', 'ZIPX', 'ACE', 'tar', ]
|
||||
return ext.lower() in ext_list
|
||||
|
||||
|
||||
@register.filter
|
||||
def subtract(value, arg):
|
||||
return value - int(arg)
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
from django.contrib.auth import views as auth_views
|
||||
|
||||
from django.urls import path, re_path
|
||||
from django.urls import path
|
||||
from common.views import (
|
||||
HomeView, LoginView, ForgotPasswordView, LogoutView, ChangePasswordView, ProfileView,
|
||||
UsersListView, CreateUserView, UpdateUserView, UserDetailView, UserDeleteView, PasswordResetView,
|
||||
|
|
@ -46,7 +46,7 @@ urlpatterns = [
|
|||
path('documents/<int:pk>/download/', download_document, name='download_document'),
|
||||
|
||||
# download_attachment
|
||||
path('attachments/<int:pk>/download/', download_attachment, name='download_attachment'),
|
||||
path('attachments/<int:pk>/download/', download_attachment, name='download_attachment'),
|
||||
|
||||
path('user/status/<int:pk>/', change_user_status, name='change_user_status'),
|
||||
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ from opportunity.models import Opportunity
|
|||
from cases.models import Case
|
||||
from contacts.models import Contact
|
||||
from accounts.models import Account
|
||||
from leads.models import Lead
|
||||
from django.template.loader import render_to_string
|
||||
|
||||
|
||||
|
|
@ -42,6 +43,15 @@ class AdminRequiredMixin(AccessMixin):
|
|||
class HomeView(LoginRequiredMixin, TemplateView):
|
||||
template_name = "index.html"
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super(HomeView, self).get_context_data(**kwargs)
|
||||
context["accounts"] = Account.objects.filter(status="open")
|
||||
context["contacts_count"] = Contact.objects.count()
|
||||
context["leads_count"] = Lead.objects.count()
|
||||
context["opportunities"] = Opportunity.objects.all()
|
||||
return context
|
||||
|
||||
|
||||
|
||||
class ChangePasswordView(LoginRequiredMixin, TemplateView):
|
||||
template_name = "change_password.html"
|
||||
|
|
@ -88,21 +98,19 @@ class LoginView(TemplateView):
|
|||
if user.is_active:
|
||||
login(request, user)
|
||||
return HttpResponseRedirect('/')
|
||||
else:
|
||||
return render(request, "login.html", {
|
||||
"error": True,
|
||||
"message": "Your Account is InActive. Please Contact Administrator"
|
||||
})
|
||||
else:
|
||||
|
||||
return render(request, "login.html", {
|
||||
"error": True,
|
||||
"message": "Your Account is not Found. Please Contact Administrator"
|
||||
"message": "Your Account is InActive. Please Contact Administrator"
|
||||
})
|
||||
else:
|
||||
return render(request, "login.html", {
|
||||
"error": True,
|
||||
"message": "Your username and password didn't match. Please try again."
|
||||
"message": "Your Account is not Found. Please Contact Administrator"
|
||||
})
|
||||
return render(request, "login.html", {
|
||||
"error": True,
|
||||
"message": "Your username and password didn't match. Please try again."
|
||||
})
|
||||
|
||||
|
||||
class ForgotPasswordView(TemplateView):
|
||||
|
|
@ -260,7 +268,6 @@ class PasswordResetView(PasswordResetView):
|
|||
email_template_name = 'registration/password_reset_email.html'
|
||||
|
||||
|
||||
|
||||
class DocumentCreateView(LoginRequiredMixin, CreateView):
|
||||
model = Document
|
||||
form_class = DocumentForm
|
||||
|
|
@ -362,7 +369,7 @@ class DocumentDetailView(LoginRequiredMixin, DetailView):
|
|||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super(DocumentDetailView, self).get_context_data(**kwargs)
|
||||
documents = Document.objects.all()
|
||||
# documents = Document.objects.all()
|
||||
context.update({
|
||||
"file_type_code": self.object.file_type()[1],
|
||||
"doc_obj": self.object,
|
||||
|
|
|
|||
|
|
@ -35,8 +35,8 @@ class Migration(migrations.Migration):
|
|||
('teams', models.ManyToManyField(to='common.Team')),
|
||||
],
|
||||
),
|
||||
migrations.AlterUniqueTogether(
|
||||
name='contact',
|
||||
unique_together={('email',)},
|
||||
),
|
||||
# migrations.AlterUniqueTogether(
|
||||
# name='contact',
|
||||
# unique_together={('email',)},
|
||||
# ),
|
||||
]
|
||||
|
|
|
|||
|
|
@ -2,20 +2,18 @@ import json
|
|||
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||
from django.contrib.sites.shortcuts import get_current_site
|
||||
from django.core.mail import EmailMessage
|
||||
from django.db.models import Q
|
||||
from django.http import JsonResponse
|
||||
from django.shortcuts import get_object_or_404, redirect
|
||||
from django.template.loader import render_to_string
|
||||
from django.urls import reverse
|
||||
from django.views.generic import (
|
||||
CreateView, UpdateView, DetailView, ListView, TemplateView, View, DeleteView)
|
||||
CreateView, UpdateView, DetailView, TemplateView, View)
|
||||
from accounts.models import Account
|
||||
from common.models import User, Address, Comment, Team, Attachments
|
||||
from common.models import User, Comment, Team, Attachments
|
||||
from common.forms import BillingAddressForm
|
||||
from common.utils import COUNTRIES
|
||||
from contacts.models import Contact
|
||||
from contacts.forms import ContactForm, ContactCommentForm, ContactAttachmentForm
|
||||
from django.urls import reverse
|
||||
|
||||
|
||||
class ContactsListView(LoginRequiredMixin, TemplateView):
|
||||
|
|
@ -77,8 +75,8 @@ class CreateContactView(LoginRequiredMixin, CreateView):
|
|||
contact_obj.created_by = self.request.user
|
||||
contact_obj.save()
|
||||
return self.form_valid(form)
|
||||
else:
|
||||
return self.form_invalid(form)
|
||||
|
||||
return self.form_invalid(form)
|
||||
|
||||
def form_valid(self, form):
|
||||
contact_obj = form.save(commit=False)
|
||||
|
|
@ -103,11 +101,11 @@ class CreateContactView(LoginRequiredMixin, CreateView):
|
|||
return JsonResponse({'error': False})
|
||||
if self.request.POST.get("savenewform"):
|
||||
return redirect("contacts:add_contact")
|
||||
elif self.request.POST.get('from_account'):
|
||||
if self.request.POST.get('from_account'):
|
||||
from_account = self.request.POST.get('from_account')
|
||||
return redirect("accounts:view_account", pk=from_account)
|
||||
else:
|
||||
return redirect('contacts:list')
|
||||
|
||||
return redirect('contacts:list')
|
||||
|
||||
def form_invalid(self, form):
|
||||
address_form = BillingAddressForm(self.request.POST)
|
||||
|
|
@ -190,8 +188,7 @@ class UpdateContactView(LoginRequiredMixin, UpdateView):
|
|||
contact_obj.address = addres_obj
|
||||
contact_obj.save()
|
||||
return self.form_valid(form)
|
||||
else:
|
||||
return self.form_invalid(form)
|
||||
return self.form_invalid(form)
|
||||
|
||||
def form_valid(self, form):
|
||||
assigned_to_ids = self.get_object().assigned_to.all().values_list('id', flat=True)
|
||||
|
|
@ -276,12 +273,11 @@ class RemoveContactView(LoginRequiredMixin, View):
|
|||
self.object.delete()
|
||||
if self.request.is_ajax():
|
||||
return JsonResponse({'error': False})
|
||||
else:
|
||||
if request.GET.get('view_account'):
|
||||
account = request.GET.get('view_account')
|
||||
return redirect("accounts:view_account", pk=account)
|
||||
else:
|
||||
return redirect("contacts:list")
|
||||
|
||||
if request.GET.get('view_account'):
|
||||
account = request.GET.get('view_account')
|
||||
return redirect("accounts:view_account", pk=account)
|
||||
return redirect("contacts:list")
|
||||
|
||||
|
||||
class AddCommentView(LoginRequiredMixin, CreateView):
|
||||
|
|
@ -300,11 +296,11 @@ class AddCommentView(LoginRequiredMixin, CreateView):
|
|||
form = self.get_form()
|
||||
if form.is_valid():
|
||||
return self.form_valid(form)
|
||||
else:
|
||||
return self.form_invalid(form)
|
||||
else:
|
||||
data = {'error': "You don't have permission to comment."}
|
||||
return JsonResponse(data)
|
||||
|
||||
return self.form_invalid(form)
|
||||
|
||||
data = {'error': "You don't have permission to comment."}
|
||||
return JsonResponse(data)
|
||||
|
||||
def form_valid(self, form):
|
||||
comment = form.save(commit=False)
|
||||
|
|
@ -330,11 +326,11 @@ class UpdateCommentView(LoginRequiredMixin, View):
|
|||
form = ContactCommentForm(request.POST, instance=self.comment_obj)
|
||||
if form.is_valid():
|
||||
return self.form_valid(form)
|
||||
else:
|
||||
return self.form_invalid(form)
|
||||
else:
|
||||
data = {'error': "You don't have permission to edit this comment."}
|
||||
return JsonResponse(data)
|
||||
|
||||
return self.form_invalid(form)
|
||||
|
||||
data = {'error': "You don't have permission to edit this comment."}
|
||||
return JsonResponse(data)
|
||||
|
||||
def form_valid(self, form):
|
||||
self.comment_obj.comment = form.cleaned_data.get("comment")
|
||||
|
|
@ -356,9 +352,9 @@ class DeleteCommentView(LoginRequiredMixin, View):
|
|||
self.object.delete()
|
||||
data = {"cid": request.POST.get("comment_id")}
|
||||
return JsonResponse(data)
|
||||
else:
|
||||
data = {'error': "You don't have permission to delete this comment."}
|
||||
return JsonResponse(data)
|
||||
|
||||
data = {'error': "You don't have permission to delete this comment."}
|
||||
return JsonResponse(data)
|
||||
|
||||
|
||||
class GetContactsView(LoginRequiredMixin, TemplateView):
|
||||
|
|
@ -388,11 +384,11 @@ class AddAttachmentsView(LoginRequiredMixin, CreateView):
|
|||
form = self.get_form()
|
||||
if form.is_valid():
|
||||
return self.form_valid(form)
|
||||
else:
|
||||
return self.form_invalid(form)
|
||||
else:
|
||||
data = {'error': "You don't have permission to add attachment."}
|
||||
return JsonResponse(data)
|
||||
|
||||
return self.form_invalid(form)
|
||||
|
||||
data = {'error': "You don't have permission to add attachment."}
|
||||
return JsonResponse(data)
|
||||
|
||||
def form_valid(self, form):
|
||||
attachment = form.save(commit=False)
|
||||
|
|
@ -418,11 +414,13 @@ class DeleteAttachmentsView(LoginRequiredMixin, View):
|
|||
|
||||
def post(self, request, *args, **kwargs):
|
||||
self.object = get_object_or_404(Attachments, id=request.POST.get("attachment_id"))
|
||||
if (request.user == self.object.created_by or request.user.is_superuser or
|
||||
request.user.role == 'ADMIN'):
|
||||
if (
|
||||
request.user == self.object.created_by or request.user.is_superuser or
|
||||
request.user.role == 'ADMIN'
|
||||
):
|
||||
self.object.delete()
|
||||
data = {"aid": request.POST.get("attachment_id")}
|
||||
return JsonResponse(data)
|
||||
else:
|
||||
data = {'error': "You don't have permission to delete this attachment."}
|
||||
return JsonResponse(data)
|
||||
|
||||
data = {'error': "You don't have permission to delete this attachment."}
|
||||
return JsonResponse(data)
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
|||
SECRET_KEY = 'mwx@&97%!$fx_*zgj(2ygi^(s=oh5j(cqb$=+-mkd9scbt!0v0'
|
||||
|
||||
# SECURITY WARNING: don't run with debug turned on in production!
|
||||
DEBUG = True
|
||||
DEBUG = False
|
||||
|
||||
ALLOWED_HOSTS = ['*']
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
from django.db import models
|
||||
from datetime import datetime
|
||||
# Create your models here.
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
from django import forms
|
||||
from leads.models import Lead
|
||||
from common.models import Address, Comment, Attachments
|
||||
from common.models import Comment, Attachments
|
||||
|
||||
|
||||
class LeadForm(forms.ModelForm):
|
||||
|
|
|
|||
|
|
@ -20,8 +20,8 @@
|
|||
<link rel="stylesheet" type="text/css" href="//ajax.googleapis.com/ajax/libs/jqueryui/1.8.13/themes/start/jquery-ui.css" />
|
||||
</head>
|
||||
<form id="add_form" method="POST" action="" novalidate>
|
||||
<div class="overview_form_block row marl">
|
||||
<div class="col-md-12">
|
||||
<div class="overview_form_block row marl justify-content-center">
|
||||
<div class="col-md-9">
|
||||
<div class="card">
|
||||
|
||||
<div class="card-body">
|
||||
|
|
@ -29,7 +29,7 @@
|
|||
{% if lead_obj %}EDIT{% else %}CREATE{% endif %} LEAD
|
||||
</div>
|
||||
<div class="row marl no-gutters">
|
||||
<div class="col-md-6">
|
||||
<div class="col-md-4">
|
||||
<div class="filter_col col-md-12">
|
||||
<div class="form-group">
|
||||
<label for="exampleInputEmail1" class="name" >Name{% if lead_form.first_name.field.required %}<span class="error">*</span>{% endif %}</label>
|
||||
|
|
@ -76,6 +76,9 @@
|
|||
<span class="error">{{ lead_form.email.errors }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<div class="filter_col col-md-12">
|
||||
<div class="form-group">
|
||||
<label for="exampleInputEmail1">Website{% if lead_form.website.field.required %}<span class="error">*</span>{% endif %}</label>
|
||||
|
|
@ -90,9 +93,7 @@
|
|||
<span class="error">{{ lead_form.description.errors }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="filter_col col-md-12">
|
||||
<div class="filter_col col-md-12">
|
||||
<div class="form-group">
|
||||
<label for="exampleInputEmail1">Assigned Users</label>
|
||||
<select class="assigned_users form-control" name="assigned_to" multiple="multiple">
|
||||
|
|
@ -103,7 +104,7 @@
|
|||
<span class="error">{{ lead_form.assigned_to.errors }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<br>
|
||||
|
||||
<div class="filter_col col-md-12">
|
||||
<div class="form-group">
|
||||
<label for="exampleInputEmail1"/>Status{% if lead_form.status.field.required %}<span class="error">*</span>{% endif %}</label>
|
||||
|
|
@ -111,6 +112,9 @@
|
|||
<span class="error">{{ lead_form.status.errors }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
|
||||
<div class="filter_col col-md-12">
|
||||
<div class="form-group">
|
||||
<label for="exampleInputEmail1"/>Source{% if lead_form.source.field.required %}<span class="error">*</span>{% endif %}</label>
|
||||
|
|
@ -154,20 +158,22 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-12">
|
||||
<div class="row marl buttons_row text-center form_btn_row">
|
||||
<button class="btn btn-default save" type="submit">Save</button>
|
||||
{% if not lead_obj %}
|
||||
<button class="btn btn-success save savenew" type="submit">Save & New</button>
|
||||
{% endif %}
|
||||
<a href="{% url 'leads:list' %}" class="btn btn-default clear" id="create_lead_cancel">Cancel</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<br clear="all">
|
||||
</div>
|
||||
</div>
|
||||
<input type="hidden" id="save_new_form" name="savenewform">
|
||||
</div>
|
||||
<div class="row marl buttons_row text-center form_btn_row">
|
||||
<button class="btn btn-default save" type="submit">Save</button>
|
||||
{% if not lead_obj %}
|
||||
<button class="btn btn-success save savenew" type="submit">Save & New</button>
|
||||
{% endif %}
|
||||
<a href="{% url 'leads:list' %}" class="btn btn-default clear" id="create_lead_cancel">Cancel</a>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
{% endblock %}
|
||||
{% block js_block %}
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@
|
|||
|
||||
<div class="card-body">
|
||||
<div class="card-title text-right">
|
||||
<span class="float-left">Contacts - {% if show_pageitems %} {% show_pageitems %}{% else %} {{ lead_obj|length }}{% endif %}</span>
|
||||
<span class="float-left">Leads - {% if show_pageitems %} {% show_pageitems %}{% else %} {{ lead_obj|length }}{% endif %}</span>
|
||||
<span class="filter_toggle">
|
||||
<a href="#" class="primary_btn"><i class="fas fa-filter"></i></a>
|
||||
</span>
|
||||
|
|
@ -83,12 +83,12 @@
|
|||
{% if lead_obj|length > 0 %}
|
||||
<tr>
|
||||
<th width="5%">ID</th>
|
||||
<th width="20%" >Name</th>
|
||||
<th width="5%" >Status</th>
|
||||
<th width="20%" >Assigned User</th>
|
||||
<th width="25%" >Tags</th>
|
||||
<th width="15%" >Created On</th>
|
||||
<th width="10%" >Actions</th>
|
||||
<th width="10%">Name</th>
|
||||
<th width="10%">Status</th>
|
||||
<th width="20%">Assigned User</th>
|
||||
<th width="20%">Tags</th>
|
||||
<th width="15%">Created On</th>
|
||||
<th width="10%">Actions</th>
|
||||
</tr>
|
||||
{% endif %}
|
||||
</thead>
|
||||
|
|
|
|||
105
leads/views.py
105
leads/views.py
|
|
@ -19,7 +19,6 @@ from leads.models import Lead
|
|||
from leads.forms import LeadCommentForm, LeadForm, LeadAttachmentForm
|
||||
from planner.models import Event, Reminder
|
||||
from planner.forms import ReminderForm
|
||||
from django.urls import reverse
|
||||
|
||||
|
||||
class LeadListView(LoginRequiredMixin, TemplateView):
|
||||
|
|
@ -78,8 +77,8 @@ class CreateLeadView(LoginRequiredMixin, CreateView):
|
|||
address_form = BillingAddressForm(request.POST)
|
||||
if form.is_valid() and address_form.is_valid():
|
||||
return self.form_valid(form, address_form)
|
||||
else:
|
||||
return self.form_invalid(form, address_form)
|
||||
|
||||
return self.form_invalid(form, address_form)
|
||||
|
||||
def form_valid(self, form, address_form):
|
||||
address_object = address_form.save()
|
||||
|
|
@ -88,15 +87,15 @@ class CreateLeadView(LoginRequiredMixin, CreateView):
|
|||
lead_obj.created_by = self.request.user
|
||||
lead_obj.save()
|
||||
if self.request.POST.get('tags', ''):
|
||||
tags = self.request.POST.get("tags")
|
||||
splitted_tags = tags.split(",")
|
||||
for t in splitted_tags:
|
||||
tag = Tags.objects.filter(name=t)
|
||||
if tag:
|
||||
tag = tag[0]
|
||||
else:
|
||||
tag = Tags.objects.create(name=t)
|
||||
lead_obj.tags.add(tag)
|
||||
tags = self.request.POST.get("tags")
|
||||
splitted_tags = tags.split(",")
|
||||
for t in splitted_tags:
|
||||
tag = Tags.objects.filter(name=t)
|
||||
if tag:
|
||||
tag = tag[0]
|
||||
else:
|
||||
tag = Tags.objects.create(name=t)
|
||||
lead_obj.tags.add(tag)
|
||||
if self.request.POST.getlist('assigned_to', []):
|
||||
lead_obj.assigned_to.add(*self.request.POST.getlist('assigned_to'))
|
||||
assigned_to_list = self.request.POST.getlist('assigned_to')
|
||||
|
|
@ -145,8 +144,7 @@ class CreateLeadView(LoginRequiredMixin, CreateView):
|
|||
account_object.save()
|
||||
if self.request.POST.get("savenewform"):
|
||||
return redirect("leads:add_lead")
|
||||
else:
|
||||
return redirect('leads:list')
|
||||
return redirect('leads:list')
|
||||
|
||||
def form_invalid(self, form, address_form):
|
||||
return self.render_to_response(
|
||||
|
|
@ -251,8 +249,8 @@ class UpdateLeadView(LoginRequiredMixin, UpdateView):
|
|||
form.fields['account_name'].required = False
|
||||
if form.is_valid() and address_form.is_valid():
|
||||
return self.form_valid(form, address_form)
|
||||
else:
|
||||
return self.form_invalid(form, address_form)
|
||||
|
||||
return self.form_invalid(form, address_form)
|
||||
|
||||
def form_valid(self, form, address_form):
|
||||
assigned_to_ids = self.get_object().assigned_to.all().values_list('id', flat=True)
|
||||
|
|
@ -264,15 +262,15 @@ class UpdateLeadView(LoginRequiredMixin, UpdateView):
|
|||
lead_obj.tags.clear()
|
||||
all_members_list = []
|
||||
if self.request.POST.get('tags', ''):
|
||||
tags = self.request.POST.get("tags")
|
||||
splitted_tags = tags.split(",")
|
||||
for t in splitted_tags:
|
||||
tag = Tags.objects.filter(name=t)
|
||||
if tag:
|
||||
tag = tag[0]
|
||||
else:
|
||||
tag = Tags.objects.create(name=t)
|
||||
lead_obj.tags.add(tag)
|
||||
tags = self.request.POST.get("tags")
|
||||
splitted_tags = tags.split(",")
|
||||
for t in splitted_tags:
|
||||
tag = Tags.objects.filter(name=t)
|
||||
if tag:
|
||||
tag = tag[0]
|
||||
else:
|
||||
tag = Tags.objects.create(name=t)
|
||||
lead_obj.tags.add(tag)
|
||||
if self.request.POST.getlist('assigned_to', []):
|
||||
if self.request.POST.get('status') != "converted":
|
||||
|
||||
|
|
@ -329,8 +327,8 @@ class UpdateLeadView(LoginRequiredMixin, UpdateView):
|
|||
status = self.request.GET.get('status', None)
|
||||
if status:
|
||||
return redirect('accounts:list')
|
||||
else:
|
||||
return redirect('leads:list')
|
||||
|
||||
return redirect('leads:list')
|
||||
|
||||
def form_invalid(self, form, address_form):
|
||||
return self.render_to_response(
|
||||
|
|
@ -406,9 +404,9 @@ class ConvertLeadView(LoginRequiredMixin, View):
|
|||
email = EmailMessage(mail_subject, message, to=[user.email])
|
||||
email.send()
|
||||
return redirect("accounts:list")
|
||||
else:
|
||||
return HttpResponseRedirect(
|
||||
reverse('leads:edit_lead', kwargs={'pk': lead_obj.id}) + '?status=converted')
|
||||
|
||||
return HttpResponseRedirect(
|
||||
reverse('leads:edit_lead', kwargs={'pk': lead_obj.id}) + '?status=converted')
|
||||
|
||||
|
||||
class AddCommentView(LoginRequiredMixin, CreateView):
|
||||
|
|
@ -427,11 +425,11 @@ class AddCommentView(LoginRequiredMixin, CreateView):
|
|||
form = self.get_form()
|
||||
if form.is_valid():
|
||||
return self.form_valid(form)
|
||||
else:
|
||||
return self.form_invalid(form)
|
||||
else:
|
||||
data = {'error': "You don't have permission to comment."}
|
||||
return JsonResponse(data)
|
||||
|
||||
return self.form_invalid(form)
|
||||
|
||||
data = {'error': "You don't have permission to comment."}
|
||||
return JsonResponse(data)
|
||||
|
||||
def form_valid(self, form):
|
||||
comment = form.save(commit=False)
|
||||
|
|
@ -457,11 +455,11 @@ class UpdateCommentView(LoginRequiredMixin, View):
|
|||
form = LeadCommentForm(request.POST, instance=self.comment_obj)
|
||||
if form.is_valid():
|
||||
return self.form_valid(form)
|
||||
else:
|
||||
return self.form_invalid(form)
|
||||
else:
|
||||
data = {'error': "You don't have permission to edit this comment."}
|
||||
return JsonResponse(data)
|
||||
|
||||
return self.form_invalid(form)
|
||||
|
||||
data = {'error': "You don't have permission to edit this comment."}
|
||||
return JsonResponse(data)
|
||||
|
||||
def form_valid(self, form):
|
||||
self.comment_obj.comment = form.cleaned_data.get("comment")
|
||||
|
|
@ -483,9 +481,9 @@ class DeleteCommentView(LoginRequiredMixin, View):
|
|||
self.object.delete()
|
||||
data = {"cid": request.POST.get("comment_id")}
|
||||
return JsonResponse(data)
|
||||
else:
|
||||
data = {'error': "You don't have permission to delete this comment."}
|
||||
return JsonResponse(data)
|
||||
|
||||
data = {'error': "You don't have permission to delete this comment."}
|
||||
return JsonResponse(data)
|
||||
|
||||
|
||||
class GetLeadsView(LoginRequiredMixin, ListView):
|
||||
|
|
@ -515,11 +513,10 @@ class AddAttachmentsView(LoginRequiredMixin, CreateView):
|
|||
form = self.get_form()
|
||||
if form.is_valid():
|
||||
return self.form_valid(form)
|
||||
else:
|
||||
return self.form_invalid(form)
|
||||
else:
|
||||
data = {'error': "You don't have permission to add attachment."}
|
||||
return JsonResponse(data)
|
||||
return self.form_invalid(form)
|
||||
|
||||
data = {'error': "You don't have permission to add attachment."}
|
||||
return JsonResponse(data)
|
||||
|
||||
def form_valid(self, form):
|
||||
attachment = form.save(commit=False)
|
||||
|
|
@ -545,11 +542,13 @@ class DeleteAttachmentsView(LoginRequiredMixin, View):
|
|||
|
||||
def post(self, request, *args, **kwargs):
|
||||
self.object = get_object_or_404(Attachments, id=request.POST.get("attachment_id"))
|
||||
if (request.user == self.object.created_by or request.user.is_superuser or
|
||||
request.user.role == 'ADMIN'):
|
||||
if (
|
||||
request.user == self.object.created_by or request.user.is_superuser or
|
||||
request.user.role == 'ADMIN'
|
||||
):
|
||||
self.object.delete()
|
||||
data = {"aid": request.POST.get("attachment_id")}
|
||||
return JsonResponse(data)
|
||||
else:
|
||||
data = {'error': "You don't have permission to delete this attachment."}
|
||||
return JsonResponse(data)
|
||||
|
||||
data = {'error': "You don't have permission to delete this attachment."}
|
||||
return JsonResponse(data)
|
||||
|
|
|
|||
|
|
@ -12,7 +12,8 @@ if __name__ == "__main__":
|
|||
# issue is really that Django is missing to avoid masking other
|
||||
# exceptions on Python 2.
|
||||
try:
|
||||
import django
|
||||
pass
|
||||
|
||||
except ImportError:
|
||||
raise ImportError(
|
||||
"Couldn't import Django. Are you sure it's installed and "
|
||||
|
|
|
|||
19
opportunity/migrations/0002_opportunity_tags.py
Normal file
19
opportunity/migrations/0002_opportunity_tags.py
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
# Generated by Django 2.1.5 on 2019-02-06 10:15
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('accounts', '0004_account_status'),
|
||||
('opportunity', '0001_initial'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='opportunity',
|
||||
name='tags',
|
||||
field=models.ManyToManyField(blank=True, to='accounts.Tags'),
|
||||
),
|
||||
]
|
||||
|
|
@ -2,7 +2,7 @@ from django.db import models
|
|||
from django.utils.translation import pgettext_lazy
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from accounts.models import Account
|
||||
from accounts.models import Account, Tags
|
||||
from contacts.models import Contact
|
||||
from common.models import User, Team
|
||||
from common.utils import STAGES, SOURCES, CURRENCY_CODES
|
||||
|
|
@ -27,6 +27,7 @@ class Opportunity(models.Model):
|
|||
created_by = models.ForeignKey(User, related_name='opportunity_created_by', on_delete=models.CASCADE)
|
||||
created_on = models.DateTimeField(_("Created on"), auto_now_add=True)
|
||||
is_active = models.BooleanField(default=False)
|
||||
tags = models.ManyToManyField(Tags, blank=True)
|
||||
|
||||
class Meta:
|
||||
ordering = ['-created_on']
|
||||
|
|
|
|||
|
|
@ -12,6 +12,12 @@
|
|||
</nav>
|
||||
{% endblock %}
|
||||
{% block content %}
|
||||
<head>
|
||||
<link rel="stylesheet" type="text/css" href="//xoxco.com/projects/code/tagsinput/jquery.tagsinput.css" />
|
||||
<script type="text/javascript" src="//xoxco.com/projects/code/tagsinput/jquery.tagsinput.js"></script>
|
||||
<script type='text/javascript' src='https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.13/jquery-ui.min.js'></script>
|
||||
<link rel="stylesheet" type="text/css" href="//ajax.googleapis.com/ajax/libs/jqueryui/1.8.13/themes/start/jquery-ui.css" />
|
||||
</head>
|
||||
<form class= "form_user" method="POST" action="" novalidate>
|
||||
<div class="overview_form_block row marl justify-content-center">
|
||||
<div class="col-md-9">
|
||||
|
|
@ -39,21 +45,15 @@
|
|||
<div class="filter_col col-md-12">
|
||||
<div class="form-group">
|
||||
<label for="exampleInputEmail1">Amount</label>
|
||||
<div class="input-group" style="width:100%;">
|
||||
<div class="input-group-btn left-dropdown" style="width:auto;">
|
||||
{{request.POST.assigned_to}}
|
||||
<select class="assigned_users form-control" name="assigned_to" multiple="multiple">
|
||||
{% for user in users %}
|
||||
<option value="{{user.id}}" {% if user in account_obj.assigned_to.all or user.id in assignedto_list %} selected="" {% endif %}>{{user.email}}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
{{ account_form.assigned_to.errors }}
|
||||
{{ opportunity_form.currency }}
|
||||
<span class="error">{{opportunity_form.currency.errors}}</span>
|
||||
</div>
|
||||
{{ opportunity_form.amount }}
|
||||
{{ opportunity_form.amount }}
|
||||
<span class="error">{{opportunity_form.amount.errors}}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="filter_col col-md-12">
|
||||
<div class="form-group">
|
||||
<label for="exampleInputEmail1">Currency</label>
|
||||
{{ opportunity_form.currency }}
|
||||
<span class="error">{{opportunity_form.currency.errors}}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="filter_col col-md-12">
|
||||
|
|
@ -97,10 +97,6 @@
|
|||
<span class="error">{{opportunity_form.contacts.errors}}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
|
||||
|
||||
<div class="filter_col col-md-12">
|
||||
<div class="form-group">
|
||||
<label for="exampleInputEmail1">Close Date{% if opportunity_form.closed_on.field.required %}<span class="error">*</span>{% endif %}</label>
|
||||
|
|
@ -113,6 +109,15 @@
|
|||
<span class="error">{{opportunity_form.closed_on.errors}}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<div class="filter_col col-12">
|
||||
<div class="form-group">
|
||||
<label>Tags</label>
|
||||
<div class="txt-box-div" id="tag-div"><input type="text" name="tags" id="tags_1" value="{% for t in opportunity_obj.tags.all %}{{t.name}}, {% endfor %}" class="tags"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group col-md-12">
|
||||
<label for="exampleInputEmail1" >Description{% if opportunity_form.description.field.required %}<span class="error">*</span>{% endif %}</label>
|
||||
{{ opportunity_form.description }}
|
||||
|
|
@ -142,6 +147,8 @@
|
|||
{% endblock %}
|
||||
{% block js_block %}
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.6-rc.0/js/select2.min.js"></script>
|
||||
<link href="https://cdnjs.cloudflare.com/ajax/libs/jquery-tagsinput/1.3.6/jquery.tagsinput.min.css" rel="stylesheet">
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-tagsinput/1.3.6/jquery.tagsinput.min.js"></script>
|
||||
<script type="text/javascript">
|
||||
$(function () {
|
||||
var date = new Date();
|
||||
|
|
@ -290,6 +297,45 @@
|
|||
});
|
||||
|
||||
}
|
||||
|
||||
function onAddTag(tag) {
|
||||
alert("Added a tag: " + tag);
|
||||
}
|
||||
function onRemoveTag(tag) {
|
||||
alert("Removed a tag: " + tag);
|
||||
}
|
||||
|
||||
function onChangeTag(input,tag) {
|
||||
alert("Changed a tag: " + tag);
|
||||
}
|
||||
|
||||
$(function() {
|
||||
|
||||
$('#tags_1').tagsInput({width:'auto'});
|
||||
$('#tags_2').tagsInput({
|
||||
width: 'auto',
|
||||
onChange: function(elem, elem_tags)
|
||||
{
|
||||
var languages = ['php','ruby','javascript'];
|
||||
$('.tag', elem_tags).each(function()
|
||||
{
|
||||
if($(this).text().search(new RegExp('\\b(' + languages.join('|') + ')\\b')) >= 0)
|
||||
$(this).css('background-color', 'yellow');
|
||||
});
|
||||
}
|
||||
});
|
||||
$('#tags_3').tagsInput({
|
||||
width: 'auto',
|
||||
|
||||
//autocomplete_url:'test/fake_plaintext_endpoint.html' //jquery.autocomplete (not jquery ui)
|
||||
autocomplete_url:'test/fake_json_endpoint.html' // jquery ui autocomplete requires a json endpoint
|
||||
});
|
||||
|
||||
|
||||
// Uncomment this line to see the callback functions in action
|
||||
// $('input.tags').tagsInput({onAddTag:onAddTag,onRemoveTag:onRemoveTag,onChange: onChangeTag});
|
||||
|
||||
// Uncomment this line to see an input with no interface for adding new tags.
|
||||
// $('input.tags').tagsInput({interactive:false});
|
||||
});
|
||||
</script>
|
||||
{% endblock js_block %}
|
||||
|
|
|
|||
|
|
@ -109,6 +109,18 @@
|
|||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% if opportunity_record.tags.all %}
|
||||
<div class="filter_col col-md-12">
|
||||
<div class="form-group">
|
||||
<label class="acc_field_label" for="id_tags" data-name="name">Tags</label>
|
||||
<div class="account_field" id="account_tags" data-name="name">
|
||||
{% for tag in opportunity_record.tags.all %}
|
||||
<span class="text-left" id="list_tag">{{ tag.name }}</span>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="col-md-12">
|
||||
<div class="created_information">
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ from django.urls import path
|
|||
from opportunity.views import (
|
||||
OpportunityListView, CreateOpportunityView, OpportunityDetailView, UpdateOpportunityView,
|
||||
DeleteOpportunityView, GetContactView, GetOpportunitiesView, AddCommentView,
|
||||
UpdateCommentView, DeleteCommentView,AddAttachmentsView,DeleteAttachmentsView)
|
||||
UpdateCommentView, DeleteCommentView,AddAttachmentsView)
|
||||
|
||||
|
||||
app_name = 'opportunity'
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ from django.http import JsonResponse
|
|||
from django.shortcuts import get_object_or_404, redirect
|
||||
from django.template.loader import render_to_string
|
||||
from django.views.generic import CreateView, UpdateView, DetailView, ListView, TemplateView, View
|
||||
from accounts.models import Account
|
||||
from accounts.models import Account, Tags
|
||||
from common.models import User, Comment, Team, Attachments
|
||||
from common.utils import STAGES, SOURCES, CURRENCY_CODES
|
||||
from contacts.models import Contact
|
||||
|
|
@ -73,8 +73,7 @@ class CreateOpportunityView(LoginRequiredMixin, CreateView):
|
|||
form = self.get_form()
|
||||
if form.is_valid():
|
||||
return self.form_valid(form)
|
||||
else:
|
||||
return self.form_invalid(form)
|
||||
return self.form_invalid(form)
|
||||
|
||||
def form_valid(self, form):
|
||||
opportunity_obj = form.save(commit=False)
|
||||
|
|
@ -101,6 +100,16 @@ class CreateOpportunityView(LoginRequiredMixin, CreateView):
|
|||
opportunity_obj.teams.add(*self.request.POST.getlist('teams'))
|
||||
if self.request.POST.getlist('contacts', []):
|
||||
opportunity_obj.contacts.add(*self.request.POST.getlist('contacts'))
|
||||
if self.request.POST.get('tags', ''):
|
||||
tags = self.request.POST.get("tags")
|
||||
splitted_tags = tags.split(",")
|
||||
for t in splitted_tags:
|
||||
tag = Tags.objects.filter(name=t.lower())
|
||||
if tag:
|
||||
tag = tag[0]
|
||||
else:
|
||||
tag = Tags.objects.create(name=t.lower())
|
||||
opportunity_obj.tags.add(tag)
|
||||
if self.request.is_ajax():
|
||||
return JsonResponse({'error': False})
|
||||
if self.request.POST.get("savenewform"):
|
||||
|
|
@ -108,8 +117,7 @@ class CreateOpportunityView(LoginRequiredMixin, CreateView):
|
|||
if self.request.POST.get('from_account'):
|
||||
from_account = self.request.POST.get('from_account')
|
||||
return redirect("accounts:view_account", pk=from_account)
|
||||
else:
|
||||
return redirect('opportunities:list')
|
||||
return redirect('opportunities:list')
|
||||
|
||||
def form_invalid(self, form):
|
||||
if self.request.is_ajax():
|
||||
|
|
@ -185,8 +193,7 @@ class UpdateOpportunityView(LoginRequiredMixin, UpdateView):
|
|||
form = self.get_form()
|
||||
if form.is_valid():
|
||||
return self.form_valid(form)
|
||||
else:
|
||||
return self.form_invalid(form)
|
||||
return self.form_invalid(form)
|
||||
|
||||
def form_valid(self, form):
|
||||
assigned_to_ids = self.get_object().assigned_to.all().values_list('id', flat=True)
|
||||
|
|
@ -221,7 +228,17 @@ class UpdateOpportunityView(LoginRequiredMixin, UpdateView):
|
|||
opportunity_obj.teams.add(*self.request.POST.getlist('teams'))
|
||||
if self.request.POST.getlist('contacts', []):
|
||||
opportunity_obj.contacts.add(*self.request.POST.getlist('contacts'))
|
||||
|
||||
opportunity_obj.tags.clear()
|
||||
if self.request.POST.get('tags', ''):
|
||||
tags = self.request.POST.get("tags")
|
||||
splitted_tags = tags.split(",")
|
||||
for t in splitted_tags:
|
||||
tag = Tags.objects.filter(name=t.lower())
|
||||
if tag:
|
||||
tag = tag[0]
|
||||
else:
|
||||
tag = Tags.objects.create(name=t.lower())
|
||||
opportunity_obj.tags.add(tag)
|
||||
if self.request.POST.get('from_account'):
|
||||
from_account = self.request.POST.get('from_account')
|
||||
return redirect("accounts:view_account", pk=from_account)
|
||||
|
|
@ -265,12 +282,12 @@ class DeleteOpportunityView(LoginRequiredMixin, View):
|
|||
self.object.delete()
|
||||
if request.is_ajax():
|
||||
return JsonResponse({'error': False})
|
||||
else:
|
||||
if request.GET.get('view_account'):
|
||||
account = request.GET.get('view_account')
|
||||
return redirect("accounts:view_account", pk=account)
|
||||
else:
|
||||
return redirect("opportunities:list")
|
||||
|
||||
if request.GET.get('view_account'):
|
||||
account = request.GET.get('view_account')
|
||||
return redirect("accounts:view_account", pk=account)
|
||||
|
||||
return redirect("opportunities:list")
|
||||
|
||||
|
||||
class GetContactView(LoginRequiredMixin, View):
|
||||
|
|
@ -302,11 +319,10 @@ class AddCommentView(LoginRequiredMixin, CreateView):
|
|||
form = self.get_form()
|
||||
if form.is_valid():
|
||||
return self.form_valid(form)
|
||||
else:
|
||||
return self.form_invalid(form)
|
||||
else:
|
||||
data = {'error': "You don't have permission to comment."}
|
||||
return JsonResponse(data)
|
||||
return self.form_invalid(form)
|
||||
|
||||
data = {'error': "You don't have permission to comment."}
|
||||
return JsonResponse(data)
|
||||
|
||||
def form_valid(self, form):
|
||||
comment = form.save(commit=False)
|
||||
|
|
@ -332,11 +348,10 @@ class UpdateCommentView(LoginRequiredMixin, View):
|
|||
form = OpportunityCommentForm(request.POST, instance=self.comment_obj)
|
||||
if form.is_valid():
|
||||
return self.form_valid(form)
|
||||
else:
|
||||
return self.form_invalid(form)
|
||||
else:
|
||||
data = {'error': "You don't have permission to edit this comment."}
|
||||
return JsonResponse(data)
|
||||
return self.form_invalid(form)
|
||||
|
||||
data = {'error': "You don't have permission to edit this comment."}
|
||||
return JsonResponse(data)
|
||||
|
||||
def form_valid(self, form):
|
||||
self.comment_obj.comment = form.cleaned_data.get("comment")
|
||||
|
|
@ -358,9 +373,9 @@ class DeleteCommentView(LoginRequiredMixin, View):
|
|||
self.object.delete()
|
||||
data = {"cid": request.POST.get("comment_id")}
|
||||
return JsonResponse(data)
|
||||
else:
|
||||
data = {'error': "You don't have permission to delete this comment."}
|
||||
return JsonResponse(data)
|
||||
|
||||
data = {'error': "You don't have permission to delete this comment."}
|
||||
return JsonResponse(data)
|
||||
|
||||
|
||||
class GetOpportunitiesView(LoginRequiredMixin, ListView):
|
||||
|
|
@ -390,11 +405,10 @@ class AddAttachmentsView(LoginRequiredMixin, CreateView):
|
|||
form = self.get_form()
|
||||
if form.is_valid():
|
||||
return self.form_valid(form)
|
||||
else:
|
||||
return self.form_invalid(form)
|
||||
else:
|
||||
data = {'error': "You don't have permission to add attachment."}
|
||||
return JsonResponse(data)
|
||||
return self.form_invalid(form)
|
||||
|
||||
data = {'error': "You don't have permission to add attachment."}
|
||||
return JsonResponse(data)
|
||||
|
||||
def form_valid(self, form):
|
||||
attachment = form.save(commit=False)
|
||||
|
|
@ -420,11 +434,10 @@ class DeleteAttachmentsView(LoginRequiredMixin, View):
|
|||
|
||||
def post(self, request, *args, **kwargs):
|
||||
self.object = get_object_or_404(Attachments, id=request.POST.get("attachment_id"))
|
||||
if (request.user == self.object.created_by or request.user.is_superuser or
|
||||
request.user.role == 'ADMIN'):
|
||||
if (request.user == self.object.created_by or request.user.is_superuser or request.user.role == 'ADMIN'):
|
||||
self.object.delete()
|
||||
data = {"aid": request.POST.get("attachment_id")}
|
||||
return JsonResponse(data)
|
||||
else:
|
||||
data = {'error': "You don't have permission to delete this attachment."}
|
||||
return JsonResponse(data)
|
||||
|
||||
data = {'error': "You don't have permission to delete this attachment."}
|
||||
return JsonResponse(data)
|
||||
|
|
@ -3,6 +3,5 @@ from django.contrib import admin
|
|||
from planner.models import Event, Reminder
|
||||
# Register your models here.
|
||||
|
||||
|
||||
admin.site.register(Event)
|
||||
admin.site.register(Reminder)
|
||||
admin.site.register(Reminder)
|
||||
|
|
|
|||
|
|
@ -72,6 +72,7 @@ a{
|
|||
}
|
||||
.errorlist li{
|
||||
color: red;
|
||||
font-size: 0.83rem;
|
||||
}
|
||||
label {
|
||||
font-size: 14px;
|
||||
|
|
@ -864,8 +865,9 @@ padding:0px !important;
|
|||
}
|
||||
|
||||
#list_tag{
|
||||
background: #e5e5e5;
|
||||
color: #555;
|
||||
color: #fff;
|
||||
border: none;
|
||||
background: #333;
|
||||
font-weight: 500;
|
||||
padding: 1px 5px;
|
||||
margin-right: 5px;
|
||||
|
|
@ -873,7 +875,21 @@ padding:0px !important;
|
|||
display: inline-block;
|
||||
margin-bottom: 5px;
|
||||
border-radius: 2px;
|
||||
border: 1px solid #bbb;
|
||||
&.color1{
|
||||
background: darken($dark_sky, 5%);
|
||||
}
|
||||
&.red{
|
||||
background: darken($color_cerise_red_approx, 5%);
|
||||
}
|
||||
&.green{
|
||||
background: darken($green, 5%);
|
||||
}
|
||||
&.color2{
|
||||
background: darken($dark_yellow, 10%);
|
||||
}
|
||||
&.color3{
|
||||
background: darken($color_apricot_peach_approx, 40%);
|
||||
}
|
||||
}
|
||||
.nav-tabs{
|
||||
li{
|
||||
|
|
@ -973,20 +989,24 @@ pre{
|
|||
.item{
|
||||
background: #fff;
|
||||
border-radius: 0;
|
||||
border: 1px solid #dedede;
|
||||
padding:0;
|
||||
border: none;
|
||||
text-align: center;
|
||||
.title{
|
||||
background: #dedede;
|
||||
line-height: 2.5rem;
|
||||
font-weight: 600;
|
||||
font-size: 0.85rem;
|
||||
color: #fff;
|
||||
text-transform: uppercase;
|
||||
a{
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
.count{
|
||||
font-size: 2rem;
|
||||
font-weight: 600;
|
||||
padding: 0.5rem 0;
|
||||
color: #fff;
|
||||
}
|
||||
.more{
|
||||
font-size: 0.85rem;
|
||||
|
|
@ -1013,6 +1033,18 @@ pre{
|
|||
}
|
||||
}
|
||||
}
|
||||
&.sky_blue{
|
||||
background: darken($dark_sky, 10%);
|
||||
}
|
||||
&.red{
|
||||
background: darken($color_cerise_red_approx, 10%);
|
||||
}
|
||||
&.green{
|
||||
background: darken($green, 5%);
|
||||
}
|
||||
&.yellow{
|
||||
background: darken($dark_yellow, 10%);
|
||||
}
|
||||
}
|
||||
}
|
||||
/* open_sections */
|
||||
|
|
@ -1021,6 +1053,21 @@ pre{
|
|||
.table_container_row{
|
||||
.table{
|
||||
margin-bottom: 0;
|
||||
tbody{
|
||||
tr{
|
||||
td{
|
||||
a{
|
||||
color: #333;
|
||||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.errorlist{
|
||||
li{
|
||||
font-size: 0.83rem;
|
||||
}
|
||||
}
|
||||
|
|
@ -16,6 +16,7 @@ $green:#41B871;
|
|||
$dark_sky:#099CBE;
|
||||
$dark_yellow:#FEA124;
|
||||
$inner_page_bg:#CDCDCD;
|
||||
$green: #5cca64;
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@
|
|||
{% if request.user.is_authenticated %}
|
||||
<div class="collapse navbar-collapse" id="navbarSupportedContent">
|
||||
<ul class="navbar-nav mr-auto">
|
||||
<li class="nav-item"><a class="nav-link" id="dashboard" href="{% url 'common:home' %}">Dashboard</a></li>
|
||||
{% if request.user.role == "ADMIN" or request.user.is_superuser %}
|
||||
<li class="nav-item"><a class="nav-link" id="users" href="{% url 'common:users_list' %}">Users</a></li>
|
||||
{% endif %}
|
||||
|
|
@ -94,7 +95,12 @@
|
|||
<script type="text/javascript">
|
||||
$(document).ready(function(){
|
||||
word = window.location.pathname.split('/')[1]
|
||||
$('#' + word).addClass('active')
|
||||
if(word == ""){
|
||||
$("#dashboard").addClass('active')
|
||||
}
|
||||
else{
|
||||
$('#' + word).addClass('active')
|
||||
}
|
||||
})
|
||||
</script>
|
||||
</body>
|
||||
|
|
|
|||
|
|
@ -1,37 +1,46 @@
|
|||
{% extends 'base.html' %}
|
||||
{% load staticfiles %}
|
||||
{% block content %}
|
||||
{% load common_tags %}
|
||||
<!-- <a href="{% url "common:logout" %}"><button class="btn btn-primary" type="button">Logout</button></a> -->
|
||||
<div class="row marl justify-content-center">
|
||||
<div class="col-md-9">
|
||||
<!-- count_blocks_row starts here -->
|
||||
<div class="row count_blocks_row">
|
||||
<div class="col-md-3">
|
||||
<div class="item">
|
||||
<div class="title">Accounts</div>
|
||||
<div class="count">100</div>
|
||||
<div class="more"><a href="#">Go Live</a></div>
|
||||
<div class="item sky_blue">
|
||||
<a href="{% url 'accounts:list'%}">
|
||||
<div class="title">Accounts</div>
|
||||
<div class="count">{{accounts|length}}</div>
|
||||
<!-- <div class="more"><a href="#">Go Live</a></div> -->
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<div class="item">
|
||||
<div class="title">Contacts</div>
|
||||
<div class="count">3520</div>
|
||||
<div class="more "><a href="#">Go Live</a></div>
|
||||
<div class="item green">
|
||||
<a href="{% url 'contacts:list' %}">
|
||||
<div class="title">Contacts</div>
|
||||
<div class="count">{{contacts_count}}</div>
|
||||
</a>
|
||||
<!-- <div class="more"><a href="#">Go Live</a></div> -->
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<div class="item">
|
||||
<div class="title">Leads</div>
|
||||
<div class="count">47</div>
|
||||
<div class="more "><a href="#">Go Live</a></div>
|
||||
<div class="item red">
|
||||
<a href="{% url 'leads:list' %}">
|
||||
<div class="title">Leads</div>
|
||||
<div class="count">{{leads_count}}</div>
|
||||
<!-- <div class="more"><a href="#">Go Live</a></div> -->
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<div class="item">
|
||||
<div class="title">Opportunities</div>
|
||||
<div class="count">80</div>
|
||||
<div class="more "><a href="#">Go Live</a></div>
|
||||
<div class="item yellow">
|
||||
<a href="{% url 'opportunity:list' %}">
|
||||
<div class="title">Opportunities</div>
|
||||
<div class="count">{{opportunities|length}}</div>
|
||||
<!-- <div class="more"><a href="#">Go Live</a></div> -->
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -52,48 +61,21 @@
|
|||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for account in accounts|slice:"15" %}
|
||||
<tr>
|
||||
<td><a href="/contacts/1/view/">santharao</a></td>
|
||||
<td><a href="{% url 'accounts:view_account' account.id %}">{{account.name}}</a></td>
|
||||
<td style="display: block;">
|
||||
<span class="text-left" id="list_tag">design</span>
|
||||
<span class="text-left" id="list_tag">device</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="/contacts/1/view/">santharao</a></td>
|
||||
<td style="display: block;">
|
||||
<span class="text-left" id="list_tag">design</span>
|
||||
<span class="text-left" id="list_tag">device</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="/contacts/1/view/">santharao</a></td>
|
||||
<td style="display: block;">
|
||||
<span class="text-left" id="list_tag">design</span>
|
||||
<span class="text-left" id="list_tag">device</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="/contacts/1/view/">santharao</a></td>
|
||||
<td style="display: block;">
|
||||
<span class="text-left" id="list_tag">design</span>
|
||||
<span class="text-left" id="list_tag">device</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="/contacts/1/view/">santharao</a></td>
|
||||
<td style="display: block;">
|
||||
<span class="text-left" id="list_tag">design</span>
|
||||
<span class="text-left" id="list_tag">device</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="/contacts/1/view/">santharao</a></td>
|
||||
<td style="display: block;">
|
||||
<span class="text-left" id="list_tag">design</span>
|
||||
<span class="text-left" id="list_tag">device</span>
|
||||
{% for tag in account.tags.all|slice:'3' %}
|
||||
<span class="text-left color{{forloop.counter}}" id="list_tag">{{tag.name}}</span>
|
||||
{% empty %}
|
||||
<span class="text-left">No Tags</span>
|
||||
{% endfor %}
|
||||
{% if account.tags.all|length > 3 %}
|
||||
<span class="text-left" id="list_tag">{{account.tags.all|length|subtract:'3'}}<span>+</span></span>
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
|
@ -115,48 +97,21 @@
|
|||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for opportunity in opportunities|slice:"15" %}
|
||||
<tr>
|
||||
<td><a href="/contacts/1/view/">Opportunity1</a></td>
|
||||
<td><a href="{% url 'opportunity:opp_view' opportunity.id %}">{{opportunity.name}}</a></td>
|
||||
<td style="display: block;">
|
||||
<span class="text-left" id="list_tag">test</span>
|
||||
<span class="text-left" id="list_tag">test2</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="/contacts/1/view/">Opportunity2</a></td>
|
||||
<td style="display: block;">
|
||||
<span class="text-left" id="list_tag">test2</span>
|
||||
<span class="text-left" id="list_tag">device</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="/contacts/1/view/">Opportunity5</a></td>
|
||||
<td style="display: block;">
|
||||
<span class="text-left" id="list_tag">tst3</span>
|
||||
<span class="text-left" id="list_tag">device</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="/contacts/1/view/">Opportunity3</a></td>
|
||||
<td style="display: block;">
|
||||
<span class="text-left" id="list_tag">bug</span>
|
||||
<span class="text-left" id="list_tag">bugs</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="/contacts/1/view/">Opportunity5</a></td>
|
||||
<td style="display: block;">
|
||||
<span class="text-left" id="list_tag">edit</span>
|
||||
<span class="text-left" id="list_tag">delete</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="/contacts/1/view/">Opportunity5</a></td>
|
||||
<td style="display: block;">
|
||||
<span class="text-left" id="list_tag">webdesign</span>
|
||||
<span class="text-left" id="list_tag">testing</span>
|
||||
{% for tag in opportunity.tags.all|slice:'3' %}
|
||||
<span class="text-left color{{forloop.counter}}" id="list_tag">{{tag.name}}</span>
|
||||
{% empty %}
|
||||
<span class="text-left">No Tags</span>
|
||||
{% endfor %}
|
||||
{% if opportunity.tags.all|length > 3 %}
|
||||
{{opportunity.tags.all|length|subtract:'3'}}<span>+</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
|
|
|||
Loading…
Reference in a new issue