towards 0.4 and some fixes

This commit is contained in:
Ashwin 2019-07-05 10:57:48 +05:30
parent 153c8d7deb
commit 15bbb94818
60 changed files with 930 additions and 308 deletions

View file

@ -4,9 +4,12 @@ from common.models import Comment, Attachments, User
from leads.models import Lead
from contacts.models import Contact
from django.db.models import Q
from teams.models import Teams
class AccountForm(forms.ModelForm):
teams_queryset = []
teams = forms.MultipleChoiceField(choices=teams_queryset)
def __init__(self, *args, **kwargs):
account_view = kwargs.pop('account', False)
@ -39,13 +42,17 @@ class AccountForm(forms.ModelForm):
# self.fields["lead"].queryset = Lead.objects.all(
# ).exclude(status='closed')
if request_user.role == 'ADMIN':
self.fields["lead"].queryset = Lead.objects.filter().exclude(status='closed')
self.fields["lead"].queryset = Lead.objects.filter().exclude(
status='closed')
self.fields["contacts"].queryset = Contact.objects.filter()
self.fields["teams"].choices = [(team.get('id'), team.get('name')) for team in Teams.objects.all().values('id', 'name')]
self.fields["teams"].required = False
else:
self.fields["lead"].queryset = Lead.objects.filter(
Q(assigned_to__in=[request_user]) | Q(created_by=request_user)).exclude(status='closed')
self.fields["contacts"].queryset = Contact.objects.filter(
Q(assigned_to__in=[request_user]) | Q(created_by=request_user))
self.fields["teams"].required = False
self.fields['assigned_to'].required = False
if account_view:
@ -56,6 +63,10 @@ class AccountForm(forms.ModelForm):
self.fields['billing_postcode'].required = True
self.fields['billing_country'].required = True
# lead is not mandatory while editing
if self.instance.id:
self.fields['lead'].required = False
class Meta:
model = Account
fields = ('name', 'phone', 'email', 'website', 'industry',

View file

@ -67,7 +67,7 @@
<option value="" selected="">---------</option>
{% for lead in leads %}
<option value="{{lead.id}}" {% ifequal account_obj.lead.id lead.id %}selected{% endifequal %}>
{{lead.first_name}} {{lead.last_name}}</option>
{{lead.first_name}} {{lead.last_name}}</option>
{% endfor %}
</select>
<span class="error" id="id__lead">{{ account_form.lead.errors }}</span>
@ -142,11 +142,20 @@
</div>
</div>
<div class="col-md-4">
{% if request.user.is_superuser or request.user.role == 'ADMIN' %}
<div class="filter_col col-12">
<div class="form-group">
<label for="id_sattus">Teams{% if account_form.teams.field.required %}<span
class="error">*</span>{% endif %}</label>
{{ account_form.teams }}
<span class="error" id="id__teams">{{ account_form.teams.errors }}</span>
</div>
</div>
{% endif %}
<div class="filter_col col-12">
<div class="form-group">
<label for="exampleInputEmail1">Assign To </label>
<select name="assigned_to" id="id_assigned_to" class="assigned_users form-control"
multiple>
<select name="assigned_to" id="id_assigned_to" class="assigned_users form-control" multiple>
{% for user in users %}
<option value="{{user.id}}" {% if user in account_obj.assigned_to.all %} selected="" {% endif %}>
{{user.email}}</option>
@ -229,7 +238,8 @@
$(document).ready(function () {
$("#id_contacts").select2();
$("#id_assigned_to").select2()
$("#id_assigned_to").change(function(){
$("#id_teams").select2()
$("#id_assigned_to").change(function () {
$("#id_assigned_to").attr('name', 'assigned_to')
})
// $("#id_assigned_to")

View file

@ -6,7 +6,7 @@
{% block extralinks %}
<link rel="stylesheet" href="{% static 'css/bootstrap-suggest.css' %}">
<style>
.opacity_block{
.opacity_block {
opacity: 0.2;
}
</style>
@ -121,7 +121,9 @@
<label class="case_field_label" for="id_contact" data-name="name">Assigned To</label>
<div class="case_field" id="case_contact" data-name="name">
{% for user in account_record.assigned_to.all %}
<div>{{ user }}</div>
<div>
<a href="{% url 'common:view_user' user.id %}">{{user}}</a>
</div>
{% endfor %}
</div>
</div>
@ -331,7 +333,8 @@
<td>{{ contact.phone }}</td>
<td>{{ contact.email }}</td>
<td class="actions">
<a href="{% url 'contacts:view_contact' pk=contact.id %}" class="btn btn-primary" style="color: white;">View</a>
<a href="{% url 'contacts:view_contact' pk=contact.id %}" class="btn btn-primary"
style="color: white;">View</a>
<a href="{% url 'contacts:edit_contact' pk=contact.id %}?view_account={{account_record.id}}"
class="btn btn-success">Edit</a>
<a href="{% url 'contacts:remove_contact' pk=contact.id %}?view_account={{account_record.id}}"
@ -382,8 +385,8 @@
<td>{{opportunity.stage}}</td>
<td>{{opportunity.probability}} {% if opportunity.probability %} % {% endif %}</td>
<td class="actions">
<a href="{% url 'opportunities:opp_view' pk=opportunity.id %}"
class="btn btn-primary" style="color: white;">View</a>
<a href="{% url 'opportunities:opp_view' pk=opportunity.id %}" class="btn btn-primary"
style="color: white;">View</a>
<a href="{% url 'opportunities:opp_edit' pk=opportunity.id %}?view_account={{account_record.id}}"
class="btn btn-success">Edit</a>
<a href="{% url 'opportunities:opp_remove' pk=opportunity.id %}?view_account={{account_record.id}}"
@ -434,7 +437,8 @@
<td>{{ case.status }}</td>
<td>{{ case.priority }}</td>
<td class="actions">
<a href="{% url 'cases:view_case' pk=case.id %}" class="btn btn-primary" style="color: white;">View</a>
<a href="{% url 'cases:view_case' pk=case.id %}" class="btn btn-primary"
style="color: white;">View</a>
<a href="{% url 'cases:edit_case' pk=case.id %}?view_account={{account_record.id}}"
class="btn btn-success">Edit</a>
<a href="{% url 'cases:remove_case' case_id=case.id %}?view_account={{account_record.id}}"
@ -485,7 +489,8 @@
<td>{{task.status}}</td>
<td>{{task.priority}} {% if task.probability %} % {% endif %}</td>
<td class="actions">
<a href="{% url 'tasks:task_detail' task.id %}" class="btn btn-primary" style="color: white;">View</a>
<a href="{% url 'tasks:task_detail' task.id %}" class="btn btn-primary"
style="color: white;">View</a>
<a href="{% url 'tasks:task_edit' task.id %}?view_account={{account_record.id}}"
class="btn btn-success">Edit</a>
<a href="{% url 'tasks:task_delete' task.id %}?view_account={{account_record.id}}"
@ -507,13 +512,13 @@
</form>
</div>
<div class="overview_form_block row marl justify-content-center" id="loading_spinner"
style="z-index: 10; left: 0; right: 0; vertical-align: middle; position: absolute; margin-top: 15%;">
<div class="spinner-border text-primary" style="width: 5em; height: 5em;" role="status">
<span class="sr-only">Processing File...</span>
style="z-index: 10; left: 0; right: 0; vertical-align: middle; position: absolute; margin-top: 15%;">
<div class="spinner-border text-primary" style="width: 5em; height: 5em;" role="status">
<span class="sr-only">Processing File...</span>
</div>
</div>
</div>
</div>
</div>
<!-- ACCOUNTS VIEW ENDS -->
{% endblock content %}
@ -637,7 +642,7 @@
cache: false,
contentType: false,
processData: false,
beforeSend: function(){
beforeSend: function () {
$('#loading_spinner').show()
$('#opacity_block').addClass('opacity_block')
},

View file

@ -22,6 +22,7 @@ from common.tasks import send_email_user_mentions
from django.contrib.sites.shortcuts import get_current_site
from common.access_decorators_mixins import (
sales_access_required, marketing_access_required, SalesAccessRequiredMixin, MarketingAccessRequiredMixin)
from teams.models import Teams
class AccountsListView(SalesAccessRequiredMixin, LoginRequiredMixin, TemplateView):
model = Account
@ -156,6 +157,13 @@ class CreateAccountView(SalesAccessRequiredMixin, LoginRequiredMixin, CreateView
attachment.attachment = self.request.FILES.get(
'account_attachment')
attachment.save()
if self.request.POST.getlist('teams', []):
user_ids = Teams.objects.filter(id__in=self.request.POST.getlist('teams')).values_list('users', flat=True)
assinged_to_users_ids = account_object.assigned_to.all().values_list('id', flat=True)
for user_id in user_ids:
if user_id not in assinged_to_users_ids:
account_object.assigned_to.add(user_id)
if self.request.POST.get("savenewform"):
return redirect("accounts:new_account")
@ -304,6 +312,12 @@ class AccountUpdateView(SalesAccessRequiredMixin, LoginRequiredMixin, UpdateView
attachment.attachment = self.request.FILES.get(
'account_attachment')
attachment.save()
if self.request.POST.getlist('teams', []):
user_ids = Teams.objects.filter(id__in=self.request.POST.getlist('teams')).values_list('users', flat=True)
assinged_to_users_ids = account_object.assigned_to.all().values_list('id', flat=True)
for user_id in user_ids:
if user_id not in assinged_to_users_ids:
account_object.assigned_to.add(user_id)
if self.request.is_ajax():
data = {'success_url': reverse_lazy(

View file

@ -1,9 +1,12 @@
from django import forms
from cases.models import Case
from common.models import Comment, Attachments
from teams.models import Teams
class CaseForm(forms.ModelForm):
teams_queryset = []
teams = forms.MultipleChoiceField(choices=teams_queryset)
def __init__(self, *args, **kwargs):
assigned_users = kwargs.pop('assigned_to', [])
@ -23,6 +26,9 @@ class CaseForm(forms.ModelForm):
for key, value in self.fields.items():
value.widget.attrs['placeholder'] = value.label
self.fields["teams"].choices = [(team.get('id'), team.get('name')) for team in Teams.objects.all().values('id', 'name')]
self.fields["teams"].required = False
class Meta:
model = Case
fields = ('assigned_to', 'name', 'status',

View file

@ -64,6 +64,16 @@
<span class="error error_message" id="error_id_closed_on">{{ case_form.closed_on.errors }}</span>
</div>
</div>
{% if request.user.is_superuser or request.user.role == 'ADMIN' %}
<div class="filter_col col-12">
<div class="form-group">
<label for="id_sattus">Teams{% if case_form.teams.field.required %}<span
class="error">*</span>{% endif %}</label>
{{ case_form.teams }}
<span class="error" id="id__teams">{{ case_form.teams.errors }}</span>
</div>
</div>
{% endif %}
<div class="filter_col col-md-12">
<div class="form-group">
<label for="exampleInputEmail1">Assigned Users</label>
@ -231,6 +241,7 @@
$(document).ready(function() {
$('.assigned_users').select2();
$("#id_contacts").select2();
$("#id_teams").select2();
});
$('#id_account').change(function(){

View file

@ -22,6 +22,7 @@ from common.tasks import send_email_user_mentions
from cases.tasks import send_email_to_assigned_user
from common.access_decorators_mixins import (
sales_access_required, marketing_access_required, SalesAccessRequiredMixin, MarketingAccessRequiredMixin)
from teams.models import Teams
class CasesListView(SalesAccessRequiredMixin, LoginRequiredMixin, TemplateView):
@ -111,10 +112,10 @@ def create_case(request):
if request.POST.getlist('assigned_to', []):
case.assigned_to.add(*request.POST.getlist('assigned_to'))
assigned_to_list = request.POST.getlist('assigned_to')
current_site = get_current_site(request)
recipients = assigned_to_list
send_email_to_assigned_user.delay(recipients, case.id, domain=current_site.domain,
protocol=request.scheme)
# current_site = get_current_site(request)
# recipients = assigned_to_list
# send_email_to_assigned_user.delay(recipients, case.id, domain=current_site.domain,
# protocol=request.scheme)
# for assigned_to_user in assigned_to_list:
# user = get_object_or_404(User, pk=assigned_to_user)
# mail_subject = 'Assigned to case.'
@ -132,6 +133,17 @@ def create_case(request):
if request.POST.getlist('contacts', []):
case.contacts.add(*request.POST.getlist('contacts'))
if request.POST.getlist('teams', []):
user_ids = Teams.objects.filter(id__in=request.POST.getlist('teams')).values_list('users', flat=True)
assinged_to_users_ids = case.assigned_to.all().values_list('id', flat=True)
for user_id in user_ids:
if user_id not in assinged_to_users_ids:
case.assigned_to.add(user_id)
current_site = get_current_site(request)
recipients = list(case.assigned_to.all().values_list('id', flat=True))
send_email_to_assigned_user.delay(recipients, case.id, domain=current_site.domain,
protocol=request.scheme)
if request.FILES.get('case_attachment'):
attachment = Attachments()
attachment.created_by = request.user
@ -248,9 +260,9 @@ def update_case(request, pk):
all_members_list = list(
set(list(assigned_form_users)) -
set(list(assigned_to_ids)))
recipients = all_members_list
send_email_to_assigned_user.delay(recipients, case_obj.id, domain=current_site.domain,
protocol=request.scheme)
# recipients = all_members_list
# send_email_to_assigned_user.delay(recipients, case_obj.id, domain=current_site.domain,
# protocol=request.scheme)
# if all_members_list:
# for assigned_to_user in all_members_list:
# user = get_object_or_404(User, pk=assigned_to_user)
@ -272,6 +284,18 @@ def update_case(request, pk):
else:
case_obj.assigned_to.clear()
if request.POST.getlist('teams', []):
user_ids = Teams.objects.filter(id__in=request.POST.getlist('teams')).values_list('users', flat=True)
assinged_to_users_ids = case_obj.assigned_to.all().values_list('id', flat=True)
for user_id in user_ids:
if user_id not in assinged_to_users_ids:
case_obj.assigned_to.add(user_id)
current_site = get_current_site(request)
recipients = list(case_obj.assigned_to.all().values_list('id', flat=True))
send_email_to_assigned_user.delay(recipients, case_obj.id, domain=current_site.domain,
protocol=request.scheme)
if request.POST.getlist('contacts', []):
case_obj.contacts.add(*request.POST.getlist('contacts'))

View file

@ -26,7 +26,7 @@ def marketing_access_required(function):
class SalesAccessRequiredMixin(AccessMixin):
""" """ # TODO add docs
""" Mixin used to authorize if a user has sales access """
def dispatch(self, request, *args, **kwargs):
if not request.user.is_authenticated:
@ -39,6 +39,7 @@ class SalesAccessRequiredMixin(AccessMixin):
class MarketingAccessRequiredMixin(AccessMixin):
""" Mixin used to authorize if a user has marketing access """
def dispatch(self, request, *args, **kwargs):
if not request.user.is_authenticated:

View file

@ -79,8 +79,8 @@ class UserForm(forms.ModelForm):
'has_sales_access', 'has_marketing_access']
def __init__(self, *args, **kwargs):
self.request_user = kwargs.pop('request_user', None)
super(UserForm, self).__init__(*args, **kwargs)
self.fields['first_name'].required = True
if not self.instance.pk:
self.fields['password'].required = True
@ -107,11 +107,29 @@ class UserForm(forms.ModelForm):
def clean_has_sales_access(self):
sales = self.cleaned_data.get('has_sales_access', False)
marketing = self.data.get('has_marketing_access', False)
if not sales and not marketing:
raise forms.ValidationError('Select atleast one option')
user_role = self.cleaned_data.get('role')
if user_role == 'ADMIN':
is_admin = True
else:
is_admin = False
if self.request_user.role == 'ADMIN' or self.request_user.is_superuser:
if not is_admin:
marketing = self.data.get('has_marketing_access', False)
if not sales and not marketing:
raise forms.ValidationError('Select atleast one option.')
# if not (self.instance.role == 'ADMIN' or self.instance.is_superuser):
# marketing = self.data.get('has_marketing_access', False)
# if not sales and not marketing:
# raise forms.ValidationError('Select atleast one option.')
if self.request_user.role == 'USER':
sales = self.instance.has_sales_access
return sales
def clean_has_marketing_access(self):
marketing = self.cleaned_data.get('has_marketing_access', False)
if self.request_user.role == 'USER':
marketing = self.instance.has_marketing_access
return marketing
def clean_email(self):
email = self.cleaned_data.get("email")
@ -198,6 +216,8 @@ class PasswordResetEmailForm(PasswordResetForm):
class DocumentForm(forms.ModelForm):
teams_queryset = []
teams = forms.MultipleChoiceField(choices=teams_queryset)
def __init__(self, *args, **kwargs):
self.instance = kwargs.get('instance', None)
@ -214,6 +234,8 @@ class DocumentForm(forms.ModelForm):
if users:
self.fields['shared_to'].queryset = users
self.fields['shared_to'].required = False
self.fields["teams"].choices = [(team.get('id'), team.get('name')) for team in Teams.objects.all().values('id', 'name')]
self.fields["teams"].required = False
class Meta:
model = Document

View file

@ -70,14 +70,14 @@
<label for="id_role">User Role{% if user_form.role.field.required %}<span
class="error">*</span>{% endif %}</label>
{% if request.user.role == 'ADMIN' or request.user.is_superuser %}
<select name="role" class="form-control">
<select name="role" class="form-control" id="user_role">
{% for key, value in form.role.field.choices %}
<option value="{{key}}" {% if value == user_obj.role %}selected="selected"
{% elif user_obj.is_superuser and value == "ADMIN" %}selected{% endif %}>{{value}}</option>
{% endfor %}
</select>
{% else %}
<select name="role">
<select name="role" id="user_roles">
<option value="{{user_obj.role}}">{{user_obj.role}}</option>
</select>
{% endif %}
@ -109,18 +109,21 @@
{% if request.user.is_superuser or request.user.role == 'ADMIN' %}
<div class="filter_col col-md-6">
<div class="form-group">
<label for="exampleInputEmail1">Permissions {% if user_form.profile_pic.field.required %}<span
class="error">*</span>{% endif %}</label>
<label for="exampleInputEmail1">Permissions <span class="error">*</span></label>
<br>
<!-- {{user_form.sales}} -->
<div class="btn-group">
<label class="btn "> Sales
<input type="checkbox" name="has_sales_access" id="" autocomplete="off"
{% if user_obj.has_sales_access %} checked {% endif %}>
<input type="checkbox" name="has_sales_access" id="has_sales_access_" autocomplete="off"
{% if user_obj.has_sales_access %} checked {% endif %}
{% if user_obj.is_superuser or user_obj.role == 'ADMIN' %} disabled="disabled" readonly="readonly"
checked="checked" {% endif %}>
</label>
<label class="btn "> Marketing
<input type="checkbox" name="has_marketing_access" id="" autocomplete="off"
{% if user_obj.has_marketing_access %} checked {% endif %}>
<input type="checkbox" name="has_marketing_access" id="has_marketing_access_" autocomplete="off"
{% if user_obj.has_marketing_access %} checked {% endif %}
{% if user_obj.is_superuser or user_obj.role == 'ADMIN' %} disabled="disabled" readonly="readonly"
checked="checked" {% endif %}>
</label>
</div>
<span class="error_ajax" id="id_has_sales_access" style="color: red;"></span>
@ -163,6 +166,27 @@
<script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.6-rc.0/js/select2.min.js"></script>
<script type="text/javascript">
$("#id_teams").select2();
$("#user_role").change(function () {
if ($(this).val() == 'ADMIN') {
$("#has_marketing_access_").attr('checked', 'true')
$("#has_sales_access_").attr('checked', 'true')
$("#has_marketing_access_").attr('readonly', 'true')
$("#has_marketing_access_").attr('disabled', 'true')
$("#has_sales_access_").attr('readonly', 'true')
$("#has_sales_access_").attr('disabled', 'true')
}
else {
$("#has_marketing_access_").removeAttr('checked')
$("#has_sales_access_").removeAttr('checked')
$("#has_marketing_access_").removeAttr('readonly')
$("#has_sales_access_").removeAttr('readonly')
$("#has_marketing_access_").removeAttr('disabled')
$("#has_sales_access_").removeAttr('disabled')
}
})
$('form#add_form').ajaxForm({
type: 'POST',
dataType: 'json',

View file

@ -38,6 +38,16 @@
{% if doc_obj %}<span>{{doc_file_name}}</span>{% endif %}
<span class="error" id="id_document_file">{{ errors.document_file }}</span>
</div>
{% if request.user.is_superuser or request.user.role == 'ADMIN' %}
<div class="filter_col col-12">
<div class="form-group">
<label for="id_sattus">Teams{% if doc_form.teams.field.required %}<span
class="error">*</span>{% endif %}</label>
{{ doc_form.teams }}
<span class="error" id="id__teams">{{ doc_form.teams.errors }}</span>
</div>
</div>
{% endif %}
<div class="filter_col col-md-12">
<div class="form-group">
<label for="exampleInputEmail1">Share To{% if doc_form.shared_to.field.required %}<span class="error">*</span>{% endif %}</label>
@ -91,6 +101,7 @@
$(document).ready(function() {
$('.assigned_users').select2();
$('#id_teams').select2();
});
var bar = $('.bar');

View file

@ -5,7 +5,7 @@
<nav aria-label="breadcrumb">
<ol class="breadcrumb">
<li class="breadcrumb-item"><a href="{% url 'common:doc_list' %}">Documents</a></li>
<li class="breadcrumb-item" active >View</li>
<li class="breadcrumb-item" active>View</li>
</ol>
</nav>
<!-- OPPORTUNITY VIEW STARTS -->
@ -50,6 +50,35 @@
<div class="contact_field" id="created_on" data-name="created_on">{{ doc_obj.created_on }}</div>
</div>
</div>
{% with document_users=document.shared_to.all %}
{% if document_users %}
<div class="filter_col col-md-12">
<div class="form-group">
<label class="contact_field_label" for="id_created_on" data-name="created_on">Shared To</label>
<br>
{% for user in document_users %}
{% if user.profile_pic %}
{% thumbnail user.profile_pic "40x40" crop="center" as im %}
<span>
<a href="{% url 'common:view_user' user.id %}">
<img src="{{ im.url }}" width="{{ im.width }}" height="{{ im.height }}" title="{{ user.email }}">
</a>
</span>
{% endthumbnail %}
{% else %}
<span>
<a href="{% url 'common:view_user' user.id %}">
<img src="{% static 'images/user.png' %}" title="{{ user.email }}" width="40" height="40">
</a>
</span>
{% endif %}
{% empty %}
None
{% endfor %}
</div>
</div>
{% endif %}
{% endwith %}
</div>
<div class="col-md-4">
<div class="profile_pic">

View file

@ -11,7 +11,8 @@
<!-- heading_create starts here -->
<div class="row marl">
<div class="col-lg-12 text-right">
<span class="d-inline"><a class="primary_btn" href="{% url 'common:create_doc' %}"><i class="fa fa-plus"></i> Add New Document</a></span>
<span class="d-inline"><a class="primary_btn" href="{% url 'common:create_doc' %}"><i class="fa fa-plus"></i> Add
New Document</a></span>
</div>
</div>
<div class="filter_row list_filter_row row marl">
@ -25,7 +26,8 @@
<div class="filter_col col-md-4">
<div class="form-group">
<label for="exampleInputEmail1">Title</label>
<input type="text" class="form-control" placeholder="Document Title" name="doc_name" {% if request.POST.doc_name %} value="{{request.POST.doc_name}}" {%endif%}/>
<input type="text" class="form-control" placeholder="Document Title" name="doc_name"
{% if request.POST.doc_name %} value="{{request.POST.doc_name}}" {%endif%} />
</div>
</div>
<div class="filter_col col-md-2">
@ -34,7 +36,9 @@
<select class="form-control" id="id_status" name="status">
<option value="">--Status--</option>
{% for each_status in status_choices %}
<option value="{{each_status.0}}" {% if request.POST.status %} {% ifequal each_status.0 request.POST.status %}selected{% endifequal %}{% endif %} >{{each_status.1}} </option>
<option value="{{each_status.0}}" {% if request.POST.status %}
{% ifequal each_status.0 request.POST.status %}selected{% endifequal %}{% endif %}>
{{each_status.1}} </option>
{% endfor%}
</select>
</div>
@ -43,9 +47,10 @@
<div class="form-group">
<label for="exampleInputEmail1">Shared To</label>
<select class="assigned_users form-control" name="shared_to" multiple="multiple">
{% for user in users %}
<option value="{{user.id}}" {% if user.id in sharedto_list %} selected="" {% endif %}>{{user.email}}</option>
{% endfor %}
{% for user in users %}
<option value="{{user.id}}" {% if user.id in sharedto_list %} selected="" {% endif %}>
{{user.email}}</option>
{% endfor %}
</select>
</div>
</div>
@ -68,9 +73,10 @@
<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 %} {{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>
<a href="#" class="primary_btn"><i class="fas fa-filter"></i></a>
</span>
</div>
<div class="table-responsive">
@ -95,44 +101,58 @@
{% paginate 10 documents %}
{% endif %}
{% for document in documents %}
<tr id="account_details{{each_account.id}}" class="text-center">
<td scope="row">{{ forloop.counter }}</td>
<td>{% if document.title %}<a href="{% url 'common:view_doc' document.id %}">{{ document.title }}</a>{% endif %}</td>
<td>
{% if document.created_by %}
{% if document.created_by.profile_pic %}
{% thumbnail document.created_by.profile_pic "40x40" crop="center" as im %}
<img src="{{ im.url }}" width="{{ im.width }}" height="{{ im.height }}" title="{{ document.created_by }}">
{% endthumbnail %}
{% else %}
<img src="{% static 'images/user.png' %}" title="{{ document.created_by }}" width="40" height="40">
{% endif %}
{% else %}
None
{% endif %}
</td>
<td>{{document.created_on}}</td>
<td>{{document.status}}</td>
<td>{% with shared_users=document.shared_to.all %}
{% if shared_users %}
{% for user in shared_users %}
<span class="text-left">{{ user.email }}</span><br>
{% endfor %}
{% else %}
Not shared with anyone
{% endif %}
{% endwith %}
</td>
<td class="actions">
{% if request.user == document.created_by or request.user.role == 'ADMIN' %}
<a href="{% url 'common:edit_doc' document.id %}" class="btn btn-success edit"><i class="fas fa-pencil-alt"></i></a>
<a href="{% url 'common:remove_doc' document.id %}" class="btn btn-danger delete remove_document"><i class="fas fa-trash-alt"></i></a>
{% endif %}
{% if request.user in document.shared_to.all or request.user == document.created_by or request.user.role == 'ADMIN' %}
<a href="{% url 'common:download_document' document.id %}"class="btn btn-info"><i class="fas fa-download"></i></a>
{% endif %}
</td>
</tr>
<tr id="account_details{{each_account.id}}" class="text-center">
<td scope="row">{{ forloop.counter }}</td>
<td>{% if document.title %}<a
href="{% url 'common:view_doc' document.id %}">{{ document.title }}</a>{% endif %}</td>
<td>
{% if document.created_by %}
{% if document.created_by.profile_pic %}
{% thumbnail document.created_by.profile_pic "40x40" crop="center" as im %}
<img src="{{ im.url }}" width="{{ im.width }}" height="{{ im.height }}"
title="{{ document.created_by }}">
{% endthumbnail %}
{% else %}
<img src="{% static 'images/user.png' %}" title="{{ document.created_by }}" width="40" height="40">
{% endif %}
{% else %}
None
{% endif %}
</td>
<td>{{document.created_on}}</td>
<td>{{document.status}}</td>
<td>
{% with document_users=document.shared_to.all %}
{% for user in document_users %}
{% if user.profile_pic %}
{% thumbnail user.profile_pic "40x40" crop="center" as im %}
<a href="{% url 'common:view_user' user.id %}">
<img src="{{ im.url }}" width="{{ im.width }}" height="{{ im.height }}" title="{{ user.email }}">
</a>
{% endthumbnail %}
{% else %}
<a href="{% url 'common:view_user' user.id %}">
<img src="{% static 'images/user.png' %}" title="{{ user.email }}" width="40" height="40">
</a>
{% endif %}
{% empty %}
None
{% endfor %}
{% endwith %}
</td>
<td class="actions">
{% if request.user == document.created_by or request.user.role == 'ADMIN' %}
<a href="{% url 'common:edit_doc' document.id %}" class="btn btn-success edit"><i
class="fas fa-pencil-alt"></i></a>
<a href="{% url 'common:remove_doc' document.id %}" class="btn btn-danger delete remove_document"><i
class="fas fa-trash-alt"></i></a>
{% endif %}
{% if request.user in document.shared_to.all or request.user == document.created_by or request.user.role == 'ADMIN' %}
<a href="{% url 'common:download_document' document.id %}" class="btn btn-info"><i
class="fas fa-download"></i></a>
{% endif %}
</td>
</tr>
{% endfor %}
</tbody>
</table>
@ -156,36 +176,35 @@
{% 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(){
$(document).ready(function () {
$('.assigned_users').select2();
$(".filter_toggle").click(function(){
$(".list_filter_row").toggle();
});
$(".filter_toggle").click(function () {
$(".list_filter_row").toggle();
});
});
search = "{{search}}"
if (search == 'True'){
if (search == 'True') {
$(".list_filter_row").show();
}
$('.remove_document').click(function(e){
$('.remove_document').click(function (e) {
e.preventDefault()
url = $(this).attr('href')
if (!confirm('Are you sure you want to delete?'))
return;
window.location = $(this).attr('href')
});
$(".reset").click(function(e){
$(".reset").click(function (e) {
window.location = "{% url 'common:doc_list'%}"
});
$("a[rel='page']").click(function(e){
$("a[rel='page']").click(function (e) {
e.preventDefault();
$('#docs_filter').attr("action", $(this).attr("href"));
$('#docs_filter').submit();
});
</script>
{% endblock js_block %}
{% endblock js_block %}

View file

@ -58,7 +58,7 @@
<div class="form-group">
<label for="exampleInputEmail1">Email</label>
<input type="text" class="form-control" placeholder="email" name="email" {% if request.POST %}
value="{{request.POST.email}}" {%endif%} />
value="{{request.POST.email}}" {%endif%} minlength="2"/>
</div>
</div>
<input type="hidden" name="tab_status" id="tab_status">
@ -78,7 +78,7 @@
<div class="filter_col col-lg-2">
<div class="form-group buttons_row">
<button class="btn btn-primary save" type="submit">Search</button>
<a href="{% url 'accounts:list' %}" class="btn btn-default clear">Clear</a>
<a href="{% url 'common:users_list' %}" class="btn btn-default clear">Clear</a>
</div>
</div>
</div>
@ -144,7 +144,7 @@
<td>
{% if user.is_superuser or user.role == 'ADMIN' %}
Sales, Marketing
{% endif %}
{% else %}
{% if user.has_sales_access and user.has_marketing_access %}
Sales, Marketing
{% elif user.has_sales_access and not user.has_marketing_access %}
@ -154,6 +154,7 @@
{% else %}
{{''}}
{% endif %}
{% endif %}
</td>
<td>
{% ifnotequal request.user user %}

View file

@ -341,7 +341,7 @@ class CreateCommentFile(TestCase):
'username': user1.username, 'role': user1.role,
'profile_pic': user1.profile_pic,
'password': user1.password}
form = UserForm(data=data)
form = UserForm(data=data, request_user=user1)
userr = User.objects.get(username='robert')
# print(userr)
self.assertEqual(len(userr.password), 3)
@ -616,7 +616,7 @@ class TestUserUpdate(ObjectsCreation, TestCase):
json.dumps({"error": True, "errors": {"email": ["This field is required."],
"first_name": ["This field is required."], "username": ["This field is required."],
"role": ["This field is required."],
'has_sales_access': ['Select atleast one option']}}))
'has_sales_access': ['Select atleast one option.']}}))
def test_user_update_permissions(self):
self.user_obj = User.objects.create(
@ -729,7 +729,7 @@ class TestUserCreationView(ObjectsCreation, TestCase):
"first_name": ["This field is required."],
"username": ["This field is required."],
"role": ["This field is required."],
"has_sales_access": ["Select atleast one option"],
"has_sales_access": ["Select atleast one option."],
"password": ["This field is required."]}}))
response=self.client.post(reverse('common:create_user'), {

View file

@ -163,7 +163,12 @@ class LoginView(TemplateView):
if user is not None:
login(request, user)
return HttpResponseRedirect('/')
if user.has_sales_access:
return HttpResponseRedirect('/')
elif user.has_marketing_access:
return redirect('marketing:dashboard')
else:
return HttpResponseRedirect('/')
return render(request, "login.html", {
"ENABLE_GOOGLE_LOGIN": settings.ENABLE_GOOGLE_LOGIN,
"GP_CLIENT_SECRET": settings.GP_CLIENT_SECRET,
@ -227,7 +232,7 @@ class UsersListView(AdminRequiredMixin, TemplateView):
username__icontains=request_post.get('username'))
if request_post.get('email'):
queryset = queryset.filter(
email=request_post.get('email'))
email__icontains=request_post.get('email'))
if request_post.get('role'):
queryset = queryset.filter(
role=request_post.get('role'))
@ -291,6 +296,12 @@ class CreateUserView(AdminRequiredMixin, CreateView):
return JsonResponse({'error': True, 'errors': form.errors})
return response
def get_form_kwargs(self):
kwargs = super(CreateUserView, self).get_form_kwargs()
kwargs.update({"request_user": self.request.user})
return kwargs
def get_context_data(self, **kwargs):
context = super(CreateUserView, self).get_context_data(**kwargs)
context["user_form"] = context["form"]
@ -372,6 +383,11 @@ class UpdateUserView(LoginRequiredMixin, UpdateView):
return JsonResponse({'error': True, 'errors': form.errors})
return response
def get_form_kwargs(self):
kwargs = super(UpdateUserView, self).get_form_kwargs()
kwargs.update({"request_user": self.request.user})
return kwargs
def get_context_data(self, **kwargs):
context = super(UpdateUserView, self).get_context_data(**kwargs)
context["user_obj"] = self.object
@ -423,6 +439,14 @@ def document_create(request):
doc.save()
if request.POST.getlist('shared_to'):
doc.shared_to.add(*request.POST.getlist('shared_to'))
if request.POST.getlist('teams', []):
user_ids = Teams.objects.filter(id__in=request.POST.getlist('teams')).values_list('users', flat=True)
assinged_to_users_ids = doc.shared_to.all().values_list('id', flat=True)
for user_id in user_ids:
if user_id not in assinged_to_users_ids:
doc.shared_to.add(user_id)
data = {'success_url': reverse_lazy(
'common:doc_list'), 'error': False}
return JsonResponse(data)
@ -534,6 +558,13 @@ def document_update(request, pk):
if request.POST.getlist('shared_to'):
doc.shared_to.add(*request.POST.getlist('shared_to'))
if request.POST.getlist('teams', []):
user_ids = Teams.objects.filter(id__in=request.POST.getlist('teams')).values_list('users', flat=True)
assinged_to_users_ids = doc.shared_to.all().values_list('id', flat=True)
for user_id in user_ids:
if user_id not in assinged_to_users_ids:
doc.shared_to.add(user_id)
data = {'success_url': reverse_lazy(
'common:doc_list'), 'error': False}
return JsonResponse(data)
@ -891,7 +922,8 @@ def google_login(request):
first_name=first_name,
last_name=last_name,
role="USER",
has_sales_access=True
has_sales_access=True,
has_marketing_access=True,
)
google, _ = Google.objects.get_or_create(user=user)

View file

@ -1,9 +1,12 @@
from django import forms
from contacts.models import Contact
from common.models import Comment, Attachments
from teams.models import Teams
class ContactForm(forms.ModelForm):
teams_queryset = []
teams = forms.MultipleChoiceField(choices=teams_queryset)
def __init__(self, *args, **kwargs):
assigned_users = kwargs.pop('assigned_to', [])
@ -21,6 +24,8 @@ class ContactForm(forms.ModelForm):
value.widget.attrs['placeholder'] = "+91-123-456-7890"
else:
value.widget.attrs['placeholder'] = value.label
self.fields["teams"].choices = [(team.get('id'), team.get('name')) for team in Teams.objects.all().values('id', 'name')]
self.fields["teams"].required = False
class Meta:
model = Contact

View file

@ -101,10 +101,14 @@
{% for user in contact_users %}
{% if user.profile_pic %}
{% thumbnail user.profile_pic "40x40" crop="center" as im %}
<img src="{{ im.url }}" width="{{ im.width }}" height="{{ im.height }}" title="{{ user.email }}">
<a href="{% url 'common:view_user' user.id %}">
<img src="{{ im.url }}" width="{{ im.width }}" height="{{ im.height }}" title="{{ user.email }}">
</a>
{% endthumbnail %}
{% else %}
<img src="{% static 'images/user.png' %}" title="{{ user.email }}" width="40" height="40">
<a href="{% url 'common:view_user' user.id %}">
<img src="{% static 'images/user.png' %}" title="{{ user.email }}" width="40" height="40">
</a>
{% endif %}
{% empty %}
None

View file

@ -52,6 +52,16 @@
<span class="error">{{ contact_form.email.errors }}</span>
</div>
</div>
{% if request.user.is_superuser or request.user.role == 'ADMIN' %}
<div class="filter_col col-12">
<div class="form-group">
<label for="id_sattus">Teams{% if contact_form.teams.field.required %}<span
class="error">*</span>{% endif %}</label>
{{ contact_form.teams }}
<span class="error" id="id__teams">{{ contact_form.teams.errors }}</span>
</div>
</div>
{% endif %}
</div>
<div class="col-md-4">
<div class="filter_col col-12">
@ -148,6 +158,7 @@
});
$(document).ready(function() {
$('.assigned_users').select2();
$('#id_teams').select2();
});
function remove_attachment(x) {
const con = confirm("Do you want to Delete it for Sure!?");

View file

@ -308,9 +308,6 @@ class TestContactCreateContact(ContactObjectsCreation, TestCase):
def test_contact_detail_view_error(self):
self.client.login(username='mp@mp.com', password='mp')
self.contact = Contact.objects.create(created_by=self.user)
# Todo
# response = self.client.get(reverse('contacts:view_contact', args=(self.contact.id,)))
# self.assertEqual(403, response.status_code)
def test_contact_update_view(self):
self.client.login(username='n@mp.com', password='navi123')

View file

@ -21,6 +21,7 @@ from common.tasks import send_email_user_mentions
from contacts.tasks import send_email_to_assigned_user
from common.access_decorators_mixins import (
sales_access_required, marketing_access_required, SalesAccessRequiredMixin, MarketingAccessRequiredMixin)
from teams.models import Teams
class ContactsListView(SalesAccessRequiredMixin, LoginRequiredMixin, TemplateView):
@ -126,11 +127,6 @@ class CreateContactView(SalesAccessRequiredMixin, LoginRequiredMixin, CreateView
if self.request.POST.getlist('assigned_to', []):
contact_obj.assigned_to.add(
*self.request.POST.getlist('assigned_to'))
assigned_to_list = self.request.POST.getlist('assigned_to')
current_site = get_current_site(self.request)
recipients = assigned_to_list
send_email_to_assigned_user.delay(recipients, contact_obj.id, domain=current_site.domain,
protocol=self.request.scheme)
# for assigned_to_user in assigned_to_list:
# user = get_object_or_404(User, pk=assigned_to_user)
# mail_subject = 'Assigned to contact.'
@ -144,6 +140,18 @@ class CreateContactView(SalesAccessRequiredMixin, LoginRequiredMixin, CreateView
# email = EmailMessage(mail_subject, message, to=[user.email])
# email.content_subtype = "html"
# email.send()
if self.request.POST.getlist('teams', []):
user_ids = Teams.objects.filter(id__in=self.request.POST.getlist('teams')).values_list('users', flat=True)
assinged_to_users_ids = contact_obj.assigned_to.all().values_list('id', flat=True)
for user_id in user_ids:
if user_id not in assinged_to_users_ids:
contact_obj.assigned_to.add(user_id)
assigned_to_list = list(contact_obj.assigned_to.all().values_list('id', flat=True))
current_site = get_current_site(self.request)
recipients = assigned_to_list
send_email_to_assigned_user.delay(recipients, contact_obj.id, domain=current_site.domain,
protocol=self.request.scheme)
if self.request.FILES.get('contact_attachment'):
attachment = Attachments()
@ -278,10 +286,6 @@ class UpdateContactView(SalesAccessRequiredMixin, LoginRequiredMixin, UpdateView
'assigned_to').values_list('id', flat=True)
all_members_list = list(
set(list(assigned_form_users)) - set(list(assigned_to_ids)))
current_site = get_current_site(self.request)
recipients = all_members_list
send_email_to_assigned_user.delay(recipients, contact_obj.id, domain=current_site.domain,
protocol=self.request.scheme)
# if all_members_list:
# for assigned_to_user in all_members_list:
# user = get_object_or_404(User, pk=assigned_to_user)
@ -304,6 +308,18 @@ class UpdateContactView(SalesAccessRequiredMixin, LoginRequiredMixin, UpdateView
else:
contact_obj.assigned_to.clear()
if self.request.POST.getlist('teams', []):
user_ids = Teams.objects.filter(id__in=self.request.POST.getlist('teams')).values_list('users', flat=True)
assinged_to_users_ids = contact_obj.assigned_to.all().values_list('id', flat=True)
for user_id in user_ids:
if user_id not in assinged_to_users_ids:
contact_obj.assigned_to.add(user_id)
current_site = get_current_site(self.request)
recipients = list(contact_obj.assigned_to.all().values_list('id', flat=True))
send_email_to_assigned_user.delay(recipients, contact_obj.id, domain=current_site.domain,
protocol=self.request.scheme)
if self.request.FILES.get('contact_attachment'):
attachment = Attachments()
attachment.created_by = self.request.user

View file

@ -263,4 +263,4 @@ texinfo_documents = [
#texinfo_show_urls = 'footnote'
# If true, do not generate a @detailmenu in the "Top" node's menu.
#texinfo_no_detailmenu = False
#texinfo_no_detailmenu = False

View file

@ -3,6 +3,7 @@ from contacts.models import Contact
from common.models import User, Attachments, Comment
from django.db.models import Q
from events.models import Event
from teams.models import Teams
class EventForm(forms.ModelForm):
@ -18,6 +19,9 @@ class EventForm(forms.ModelForm):
recurring_days = forms.MultipleChoiceField(
required=False, choices=WEEKDAYS)
teams_queryset = []
teams = forms.MultipleChoiceField(choices=teams_queryset)
def __init__(self, *args, **kwargs):
request_user = kwargs.pop('request_user', None)
self.obj_instance = kwargs.get('instance', None)
@ -29,6 +33,7 @@ class EventForm(forms.ModelForm):
self.fields['assigned_to'].queryset = User.objects.all()
self.fields["contacts"].queryset = Contact.objects.filter()
self.fields['assigned_to'].required = True
self.fields["teams"].choices = [(team.get('id'), team.get('name')) for team in Teams.objects.all().values('id', 'name')]
elif request_user.google.all():
self.fields['assigned_to'].queryset = User.objects.none()
self.fields["contacts"].queryset = Contact.objects.filter(
@ -47,6 +52,7 @@ class EventForm(forms.ModelForm):
self.fields['start_date'].widget.attrs['readonly'] = True
self.fields['end_date'].widget.attrs['readonly'] = True
self.fields["teams"].required = False
self.fields['name'].required = True
self.fields['event_type'].required = True
self.fields['contacts'].required = True
@ -58,9 +64,10 @@ class EventForm(forms.ModelForm):
def clean_recurring_days(self):
recurring_days = self.cleaned_data.get('recurring_days')
if self.cleaned_data.get('event_type') == 'Recurring':
if len(recurring_days) < 1:
raise forms.ValidationError('Choose atleast on recurring day')
if not self.obj_instance:
if self.cleaned_data.get('event_type') == 'Recurring':
if len(recurring_days) < 1:
raise forms.ValidationError('Choose atleast one recurring day')
def clean_name(self):
name = self.cleaned_data.get('name')
@ -81,10 +88,13 @@ class EventForm(forms.ModelForm):
def clean_start_date(self):
start_date = self.cleaned_data.get('start_date')
if self.obj_instance:
return self.obj_instance.start_date
if start_date:
if self.obj_instance:
return self.obj_instance.start_date
else:
return start_date
else:
return start_date
raise forms.ValidationError('Enter a valid Start date.')
def clean_end_date(self):
end_date = self.cleaned_data.get('end_date')
@ -100,6 +110,8 @@ class EventForm(forms.ModelForm):
def clean_end_time(self):
end_time = self.cleaned_data.get('end_time')
if not self.cleaned_data.get('start_time'):
raise forms.ValidationError('Enter a valid start time.')
if self.cleaned_data.get('start_time') > end_time:
raise forms.ValidationError(
'End Time cannot be less than Start Time')

View file

@ -50,15 +50,6 @@
<span class="error" id="id__contacts">{{ form.contacts.errors }}</span>
</div>
</div>
<div class="filter_col col-md-12">
<div class="form-group">
<label for="exampleInputEmail1" class="required">Assigned
To{% if form.assigned_to.field.required %}<span class="error_marker"
style="color:red">*</span>{% endif %}</label>
{{ form.assigned_to }}
<span class="error" id="id__assigned_to">{{ form.assigned_to.errors }}</span>
</div>
</div>
</div>
<div class="col-md-4">
<div class="filter_col billing_block col-md-12" style="padding: 0px;">
@ -101,6 +92,25 @@
</div>
</div>
<div class="col-md-4">
{% if request.user.is_superuser or request.user.role == 'ADMIN' %}
<div class="filter_col col-12">
<div class="form-group">
<label for="id_sattus">Teams{% if form.teams.field.required %}<span
class="error">*</span>{% endif %}</label>
{{ form.teams }}
<span class="error" id="id__teams">{{ form.teams.errors }}</span>
</div>
</div>
{% endif %}
<div class="filter_col col-md-12">
<div class="form-group">
<label for="exampleInputEmail1" class="required">Assigned
To{% if form.assigned_to.field.required %}<span class="error_marker"
style="color:red">*</span>{% endif %}</label>
{{ form.assigned_to }}
<span class="error" id="id__assigned_to">{{ form.assigned_to.errors }}</span>
</div>
</div>
<div class="filter_col col-md-12">
<div class="form-group ">
<label for="id_contacts" class="required">Description{% if form.description.field.required %}<span
@ -186,6 +196,7 @@
$('#recurring_block').hide()
$("#id_contacts").select2();
$("#id_assigned_to").select2();
$("#id_teams").select2();
$("#id_start_date").css('color', 'black');
$("#id_end_date").css('color', 'black');
var date = new Date();

View file

@ -96,7 +96,11 @@
<label class="acc_field_label" for="id_website" data-name="name">Assigned To</label>
{% if users %}
{% for user in users %}
<div class="account_field" id="account_website" data-name="name">{{ user }}</div>
<div class="account_field" id="account_website" data-name="name">
<a href="{% url 'common:view_user' user.id %}">
{{ user }}
</a>
</div>
{% endfor %}
{% else %}
<div class="account_field" id="account_website" data-name="name">None</div>

View file

@ -61,7 +61,7 @@
<div class="form-group">
<label for="exampleInputEmail1" class="required">Date of Meeting</label>
<input type="text" id="date_of_meeting" name="date_of_meeting" class="form-control"
value="{{request.POST.date_of_meeting}}">
value="{{request.POST.date_of_meeting}}">
</div>
</div>
<div class="filter_col col-md-2">
@ -161,11 +161,15 @@
{% for user in users %}
{% if user.profile_pic %}
{% thumbnail user.profile_pic "40x40" crop="center" as im %}
<img src="{{ im.url }}" width="{{ im.width }}" height="{{ im.height }}"
title="{{ user.email }}">
<a href="{% url 'common:view_user' user.id %}">
<img src="{{ im.url }}" width="{{ im.width }}" height="{{ im.height }}"
title="{{ user.email }}">
</a>
{% endthumbnail %}
{% else %}
<img src="{% static 'images/user.png' %}" title="{{ user.email }}" width="40" height="40">
<a href="{% url 'common:view_user' user.id %}">
<img src="{% static 'images/user.png' %}" title="{{ user.email }}" width="40" height="40">
</a>
{% endif %}
{% empty %}
None
@ -181,11 +185,11 @@
{% if event.created_by.profile_pic %}
{% thumbnail event.created_by.profile_pic "40x40" crop="center" as im %}
<img src="{{ im.url }}" width="{{ im.width }}" height="{{ im.height }}"
title="{{ event.created_by }}" style="border-radius: 50%" />
title="{{ event.created_by }}" style="border-radius: 50%" />
{% endthumbnail %}
{% else %}
<img src="{% static 'images/user.png' %}" alt="Micro profile pic"
style="width: 40px;height: 40px;border-radius: 50%;" title="{{ event.created_by }}" />
style="width: 40px;height: 40px;border-radius: 50%;" title="{{ event.created_by }}" />
{% endif %}
{% else %}
None

View file

@ -17,6 +17,7 @@ from events.models import Event
from events.tasks import send_email
from common.access_decorators_mixins import (
sales_access_required, marketing_access_required, SalesAccessRequiredMixin, MarketingAccessRequiredMixin)
from teams.models import Teams
@login_required
@ -95,6 +96,12 @@ def event_create(request):
event.created_by = request.user
event.save()
form.save_m2m()
if request.POST.getlist('teams', []):
user_ids = Teams.objects.filter(id__in=request.POST.getlist('teams')).values_list('users', flat=True)
assinged_to_users_ids = event.assigned_to.all().values_list('id', flat=True)
for user_id in user_ids:
if user_id not in assinged_to_users_ids:
event.assigned_to.add(user_id)
send_email.delay(
event.id, domain=request.get_host(), protocol=request.scheme)
@ -120,6 +127,12 @@ def event_create(request):
)
event.contacts.add(*request.POST.getlist('contacts'))
event.assigned_to.add(*request.POST.getlist('assigned_to'))
if request.POST.getlist('teams', []):
user_ids = Teams.objects.filter(id__in=request.POST.getlist('teams')).values_list('users', flat=True)
assinged_to_users_ids = event.assigned_to.all().values_list('id', flat=True)
for user_id in user_ids:
if user_id not in assinged_to_users_ids:
event.assigned_to.add(user_id)
send_email.delay(
event.id, domain=request.get_host(), protocol=request.scheme)
@ -186,6 +199,12 @@ def event_update(request, event_id):
# event.created_by = request.user
event.save()
form.save_m2m()
if request.POST.getlist('teams', []):
user_ids = Teams.objects.filter(id__in=request.POST.getlist('teams')).values_list('users', flat=True)
assinged_to_users_ids = event.assigned_to.all().values_list('id', flat=True)
for user_id in user_ids:
if user_id not in assinged_to_users_ids:
event.assigned_to.add(user_id)
send_email.delay(
event.id, domain=request.get_host(), protocol=request.scheme)
@ -193,6 +212,12 @@ def event_update(request, event_id):
event = form.save(commit=False)
event.save()
form.save_m2m()
if request.POST.getlist('teams', []):
user_ids = Teams.objects.filter(id__in=request.POST.getlist('teams')).values_list('users', flat=True)
assinged_to_users_ids = event.assigned_to.all().values_list('id', flat=True)
for user_id in user_ids:
if user_id not in assinged_to_users_ids:
event.assigned_to.add(user_id)
send_email.delay(
event.id, domain=request.get_host(), protocol=request.scheme)

View file

@ -2,9 +2,12 @@ from django import forms
from invoices.models import Invoice
from common.models import User, Comment, Attachments, Address
from django.db.models import Q
from teams.models import Teams
class InvoiceForm(forms.ModelForm):
teams_queryset = []
teams = forms.MultipleChoiceField(choices=teams_queryset)
def __init__(self, *args, **kwargs):
request_user = kwargs.pop('request_user', None)
@ -16,6 +19,7 @@ class InvoiceForm(forms.ModelForm):
if request_user.role == 'ADMIN' or request_user.is_superuser:
self.fields['assigned_to'].queryset = User.objects.all()
self.fields["teams"].choices = [(team.get('id'), team.get('name')) for team in Teams.objects.all().values('id', 'name')]
elif request_user.google.all():
self.fields['assigned_to'].queryset = User.objects.none()
elif request_user.role == 'USER':
@ -24,6 +28,7 @@ class InvoiceForm(forms.ModelForm):
else:
pass
self.fields["teams"].required = False
self.fields['phone'].widget.attrs.update({
'placeholder': '+91-123-456-7890'})
self.fields['invoice_title'].required = True

View file

@ -183,24 +183,6 @@
<!-- <input type="text" class="form-control" id="staticEmail" placeholder="6566589125"> -->
</div>
</div>
</div>
<div class="col-md-6 mt-5">
<div class="form-group row">
<label for="inputState" class="col-sm-4">Currency{% if form.currency.field.required %}<span
class="error_marker" style="color:red"> * </span>{% endif %}</label>
<div class="col-sm-8 pl-0">
{{ form.currency }}
<span class="error" id="id__currency">{{ form.currency.errors }}</span>
</div>
</div>
<div class="form-group row">
<label for="staticEmail" class="col-sm-4 col-form-label">Assign To</label>
<div class="col-sm-8 pl-0">
<!-- <input type="text" class="form-control" id="staticEmail" placeholder="santhrao N"> -->
{{form.assigned_to}}
<span class="error" id="id__assigned_to">{{ form.assigned_to.errors }}</span>
</div>
</div>
<div class="form-group row">
<label for="staticEmail" class="col-sm-4 col-form-label">Due Date
{% if form.due_date.field.required %}<span class="error_marker"
@ -216,6 +198,34 @@
</div>
</div>
</div>
<div class="col-md-6 mt-5">
<div class="form-group row">
<label for="inputState" class="col-sm-4">Currency{% if form.currency.field.required %}<span
class="error_marker" style="color:red"> * </span>{% endif %}</label>
<div class="col-sm-8 pl-0">
{{ form.currency }}
<span class="error" id="id__currency">{{ form.currency.errors }}</span>
</div>
</div>
{% if request.user.is_superuser or request.user.role == 'ADMIN' %}
<div class="form-group row">
<label for="staticEmail" class="col-sm-4 col-form-label">Teams</label>
<div class="col-sm-8 pl-0">
<!-- <input type="text" class="form-control" id="staticEmail" placeholder="santhrao N"> -->
{{form.teams}}
<span class="error" id="id__teams">{{ form.teams.errors }}</span>
</div>
</div>
{% endif %}
<div class="form-group row">
<label for="staticEmail" class="col-sm-4 col-form-label">Assign To</label>
<div class="col-sm-8 pl-0">
<!-- <input type="text" class="form-control" id="staticEmail" placeholder="santhrao N"> -->
{{form.assigned_to}}
<span class="error" id="id__assigned_to">{{ form.assigned_to.errors }}</span>
</div>
</div>
</div>
<div class="col-md-12 mt-5">
<div class="row pt-0 pb-4">
<div class="form-group col-md-4">
@ -279,6 +289,7 @@
$("#id_contacts").select2();
$("#id_assigned_to").select2();
$('#id_currency').select2();
$('#id_teams').select2();
var date = new Date();
var today = new Date(date.getFullYear(), date.getMonth(), date.getDate());
$('#id_due_date').datetimepicker({

View file

@ -161,7 +161,11 @@
<div class="form-group">
<label class="acc_field_label" for="id_website" data-name="name">Assigned To</label>
{% for user in invoice.assigned_to.all %}
<div class="account_field" id="account_website" data-name="name">{{ user }}</div>
<div class="account_field" id="account_website" data-name="name">
<a href="{% url 'common:view_user' user.id %}">
{{ user }}
</a>
</div>
{% endfor %}
</div>
</div>

View file

@ -175,7 +175,9 @@
<div class="col-sm-8 pl-0 col-form-label">
{% for user in invoice.assigned_to.all %}
<div>
{{user}}
<a href="{% url 'common:view_user' user.id %}">
{{user}}
</a>
</div>
{% endfor %}
</div>

View file

@ -153,11 +153,15 @@
{% for user in users %}
{% if user.profile_pic %}
{% thumbnail user.profile_pic "40x40" crop="center" as im %}
<img src="{{ im.url }}" width="{{ im.width }}" height="{{ im.height }}"
title="{{ user.email }}">
<a href="{% url 'common:view_user' user.id %}">
<img src="{{ im.url }}" width="{{ im.width }}" height="{{ im.height }}"
title="{{ user.email }}">
</a>
{% endthumbnail %}
{% else %}
<img src="{% static 'images/user.png' %}" title="{{ user.email }}" width="40" height="40">
<a href="{% url 'common:view_user' user.id %}">
<img src="{% static 'images/user.png' %}" title="{{ user.email }}" width="40" height="40">
</a>
{% endif %}
{% empty %}
None

View file

@ -21,6 +21,7 @@ from invoices.models import Invoice
from invoices.tasks import send_email, send_invoice_email, send_invoice_email_cancel
from common.access_decorators_mixins import (
sales_access_required, marketing_access_required, SalesAccessRequiredMixin, MarketingAccessRequiredMixin)
from teams.models import Teams
@login_required
@ -121,6 +122,14 @@ def invoices_create(request):
invoice_obj.to_address = to_address_obj
invoice_obj.save()
form.save_m2m()
if request.POST.getlist('teams', []):
user_ids = Teams.objects.filter(id__in=request.POST.getlist('teams')).values_list('users', flat=True)
assinged_to_users_ids = invoice_obj.assigned_to.all().values_list('id', flat=True)
for user_id in user_ids:
if user_id not in assinged_to_users_ids:
invoice_obj.assigned_to.add(user_id)
kwargs = {'domain': request.get_host(), 'protocol': request.scheme}
send_email.delay(invoice_obj.id, **kwargs)
return JsonResponse({'error': False, 'success_url': reverse('invoices:invoices_list')})
@ -190,6 +199,14 @@ def invoice_edit(request, invoice_id):
invoice_obj.to_address = to_address_obj
invoice_obj.save()
form.save_m2m()
if request.POST.getlist('teams', []):
user_ids = Teams.objects.filter(id__in=request.POST.getlist('teams')).values_list('users', flat=True)
assinged_to_users_ids = invoice_obj.assigned_to.all().values_list('id', flat=True)
for user_id in user_ids:
if user_id not in assinged_to_users_ids:
invoice_obj.assigned_to.add(user_id)
kwargs = {'domain': request.get_host(), 'protocol': request.scheme}
send_email.delay(invoice_obj.id, **kwargs)
return JsonResponse({'error': False, 'success_url': reverse('invoices:invoices_list')})

View file

@ -1,9 +1,12 @@
from django import forms
from leads.models import Lead
from common.models import Comment, Attachments
from teams.models import Teams
class LeadForm(forms.ModelForm):
teams_queryset = []
teams = forms.MultipleChoiceField(choices=teams_queryset)
def __init__(self, *args, **kwargs):
assigned_users = kwargs.pop('assigned_to', [])
@ -48,6 +51,8 @@ class LeadForm(forms.ModelForm):
'placeholder': 'Postcode'})
self.fields["country"].choices = [
("", "--Country--"), ] + list(self.fields["country"].choices)[1:]
self.fields["teams"].choices = [(team.get('id'), team.get('name')) for team in Teams.objects.all().values('id', 'name')]
self.fields["teams"].required = False
class Meta:
model = Lead

View file

@ -109,7 +109,16 @@
<span class="error error_message" id="error_id_description">{{ lead_form.description.errors }}</span>
</div>
</div>
{% if request.user.is_superuser or request.user.role == 'ADMIN' %}
<div class="filter_col col-12">
<div class="form-group">
<label for="id_sattus">Teams{% if lead_form.teams.field.required %}<span
class="error">*</span>{% endif %}</label>
{{ lead_form.teams }}
<span class="error" id="id__teams">{{ lead_form.teams.errors }}</span>
</div>
</div>
{% endif %}
<div class="filter_col col-md-12">
<div class="form-group">
<label for="exampleInputEmail1">Assigned Users</label>
@ -271,6 +280,7 @@
});
$(document).ready(function() {
$('.assigned_users').select2();
$('#id_teams').select2();
});
$(function() {

View file

@ -150,12 +150,16 @@
{% if lead.created_by %}
{% if lead.created_by.profile_pic %}
{% thumbnail lead.created_by.profile_pic "40x40" crop="center" as im %}
<img src="{{ im.url }}" width="{{ im.width }}" height="{{ im.height }}"
title="{{ lead.created_by }}">
<a href="{% url 'common:view_user' user.id %}">
<img src="{{ im.url }}" width="{{ im.width }}" height="{{ im.height }}"
title="{{ lead.created_by }}">
</a>
{% endthumbnail %}
{% else %}
<img src="{% static 'images/user.png' %}" alt="Micro profile pic"
style="width: 40px;height: 40px;" title="{{ lead.created_by }}" />
<a href="{% url 'common:view_user' user.id %}">
<img src="{% static 'images/user.png' %}" alt="Micro profile pic"
style="width: 40px;height: 40px;" title="{{ lead.created_by }}" />
</a>
{% endif %}
{% else %}
None
@ -168,11 +172,15 @@
{% for user in lead_users %}
{% if user.profile_pic %}
{% thumbnail user.profile_pic "40x40" crop="center" as im %}
<img src="{{ im.url }}" width="{{ im.width }}" height="{{ im.height }}"
title="{{ user.email }}">
<a href="{% url 'common:view_user' user.id %}">
<img src="{{ im.url }}" width="{{ im.width }}" height="{{ im.height }}"
title="{{ user.email }}">
</a>
{% endthumbnail %}
{% else %}
<img src="{% static 'images/user.png' %}" title="{{ user.email }}" width="40" height="40">
<a href="{% url 'common:view_user' user.id %}">
<img src="{% static 'images/user.png' %}" title="{{ user.email }}" width="40" height="40">
</a>
{% endif %}
{% empty %}
None
@ -255,7 +263,18 @@
<td>
{% with lead_users=lead.assigned_to.all %}
{% for user in lead_users %}
<span class="text-left">{{ user.email }}</span><br>
{% if user.profile_pic %}
{% thumbnail user.profile_pic "40x40" crop="center" as im %}
<a href="{% url 'common:view_user' user.id %}">
<img src="{{ im.url }}" width="{{ im.width }}" height="{{ im.height }}"
title="{{ user.email }}">
</a>
{% endthumbnail %}
{% else %}
<a href="{% url 'common:view_user' user.id %}">
<img src="{% static 'images/user.png' %}" title="{{ user.email }}" width="40" height="40">
</a>
{% endif %}
{% empty %}
None
{% endfor %}

View file

@ -27,6 +27,7 @@ from common.tasks import send_email_user_mentions
from leads.tasks import send_email_to_assigned_user
from common.access_decorators_mixins import (
sales_access_required, marketing_access_required, SalesAccessRequiredMixin, MarketingAccessRequiredMixin)
from teams.models import Teams
class LeadListView(SalesAccessRequiredMixin, LoginRequiredMixin, TemplateView):
@ -138,10 +139,10 @@ def create_lead(request):
if request.POST.getlist('assigned_to', []):
lead_obj.assigned_to.add(*request.POST.getlist('assigned_to'))
assigned_to_list = request.POST.getlist('assigned_to')
current_site = get_current_site(request)
recipients = assigned_to_list
send_email_to_assigned_user.delay(recipients, lead_obj.id, domain=current_site.domain,
protocol=request.scheme)
# current_site = get_current_site(request)
# recipients = assigned_to_list
# send_email_to_assigned_user.delay(recipients, lead_obj.id, domain=current_site.domain,
# protocol=request.scheme)
# for assigned_to_user in assigned_to_list:
# user = get_object_or_404(User, pk=assigned_to_user)
# mail_subject = 'Assigned to lead.'
@ -156,6 +157,17 @@ def create_lead(request):
# mail_subject, message, to=[user.email])
# email.content_subtype = "html"
# email.send()
if request.POST.getlist('teams', []):
user_ids = Teams.objects.filter(id__in=request.POST.getlist('teams')).values_list('users', flat=True)
assinged_to_users_ids = lead_obj.assigned_to.all().values_list('id', flat=True)
for user_id in user_ids:
if user_id not in assinged_to_users_ids:
lead_obj.assigned_to.add(user_id)
current_site = get_current_site(request)
recipients = list(lead_obj.assigned_to.all().values_list('id', flat=True))
send_email_to_assigned_user.delay(recipients, lead_obj.id, domain=current_site.domain,
protocol=request.scheme)
if request.FILES.get('lead_attachment'):
attachment = Attachments()
@ -339,10 +351,10 @@ def update_lead(request, pk):
all_members_list = list(
set(list(assigned_form_users)) -
set(list(assigned_to_ids)))
current_site = get_current_site(request)
recipients = all_members_list
send_email_to_assigned_user.delay(recipients, lead_obj.id, domain=current_site.domain,
protocol=request.scheme)
# current_site = get_current_site(request)
# recipients = all_members_list
# send_email_to_assigned_user.delay(recipients, lead_obj.id, domain=current_site.domain,
# protocol=request.scheme)
# if all_members_list:
# for assigned_to_user in all_members_list:
# user = get_object_or_404(User, pk=assigned_to_user)
@ -364,6 +376,18 @@ def update_lead(request, pk):
else:
lead_obj.assigned_to.clear()
if request.POST.getlist('teams', []):
user_ids = Teams.objects.filter(id__in=request.POST.getlist('teams')).values_list('users', flat=True)
assinged_to_users_ids = lead_obj.assigned_to.all().values_list('id', flat=True)
for user_id in user_ids:
if user_id not in assinged_to_users_ids:
lead_obj.assigned_to.add(user_id)
current_site = get_current_site(request)
recipients = list(lead_obj.assigned_to.all().values_list('id', flat=True))
send_email_to_assigned_user.delay(recipients, lead_obj.id, domain=current_site.domain,
protocol=request.scheme)
if request.FILES.get('lead_attachment'):
attachment = Attachments()
attachment.created_by = request.user

View file

@ -205,12 +205,12 @@ class ContactForm(forms.ModelForm):
fields = ["name", "email", "contact_number",
"last_name", "city", "state", "company_name"]
def clean_email(self):
email = self.cleaned_data.get('email')
if Contact.objects.filter(email=email).exclude(id=self.instance.id).exists():
raise forms.ValidationError(
'Contact with this Email already exists')
return email
# def clean_email(self):
# email = self.cleaned_data.get('email')
# if Contact.objects.filter(email=email).exclude(id=self.instance.id).exists():
# raise forms.ValidationError(
# 'Contact with this Email already exists')
# return email
# def clean_contact_list(self):
# contact_list = self.cleaned_data.get("contact_list")
@ -320,4 +320,18 @@ class SendCampaignForm(forms.ModelForm):
raise forms.ValidationError(
'The contact list "{}" does not have any contacts in it .'.format(contacts_list_obj.name))
return contact_list
return contact_list
def clean_html(self):
html = self.cleaned_data.get('html')
count = 0
for i in html:
if i == "{":
count += 1
elif i == "}":
count -= 1
if count < 0:
raise forms.ValidationError('Brackets do not match, Enter valid tags.')
if count != 0:
raise forms.ValidationError('Brackets do not match, Enter valid tags.')
return html

View file

@ -293,6 +293,8 @@ class Link(models.Model):
clicks = models.IntegerField(default='0')
unique = models.IntegerField(default='0')
class Meta:
ordering = ('id',)
class CampaignLog(models.Model):
created_on = models.DateTimeField(auto_now_add=True)
@ -305,7 +307,7 @@ class CampaignLog(models.Model):
class CampaignLinkClick(models.Model):
campaign = models.ForeignKey(Campaign, on_delete=models.CASCADE)
campaign = models.ForeignKey(Campaign, on_delete=models.CASCADE, related_name="campaign_link_click")
link = models.ForeignKey(
Link, blank=True, null=True, on_delete=models.CASCADE)
ip_address = models.GenericIPAddressField()

View file

@ -155,6 +155,7 @@ def run_campaign(campaign, domain='demo.django-crm.io', protocol='https'):
'state': each_contact.state if each_contact.state else '',
'first_name': each_contact.name,
'email': each_contact.email, 'email_id': each_contact.id,
'name': each_contact.name + ' ' + each_contact.last_name if each_contact.last_name else '',
'unsubscribe_from_campaign_url': unsubscribe_from_campaign_url}
html = Template(html).render(Context(names_dict))

View file

@ -5,7 +5,8 @@ from .views import (
email_template_detail, campaign_list, campaign_new, campaign_edit, campaign_details, campaign_delete,
edit_contact_list, delete_contact_list, failed_contact_list_detail, failed_contact_list_download_delete,
campaign_link_click, campaign_open, demo_file_download, delete_contact, unsubscribe_from_campaign, contact_detail,
edit_failed_contact, delete_failed_contact, download_contacts_for_campaign, create_campaign_from_template
edit_failed_contact, delete_failed_contact, download_contacts_for_campaign, create_campaign_from_template,
download_links_clicked
)
app_name = 'marketing'
@ -46,4 +47,5 @@ urlpatterns = [
path('contacts/<int:contact_id>/view/', contact_detail, name="contact_detail"),
path('download-contacts-for-campaign/<int:compaign_id>/', download_contacts_for_campaign, name="download_contacts_for_campaign"),
path('create-campaign-from-template/<int:template_id>/', create_campaign_from_template, name="create_campaign_from_template"),
path('download-links-clicked/<int:campaign_id>/', download_links_clicked, name="download_links_clicked"),
]

View file

@ -137,7 +137,7 @@ def contacts_list(request):
name__icontains=data.get('contact_name'))
if data.get('contact_email'):
contacts = contacts.filter(email=data.get('contact_email'))
contacts = contacts.filter(email__icontains=data.get('contact_email'))
if data.get('created_by'):
contacts = contacts.filter(created_by=data.get('created_by'))
@ -303,16 +303,21 @@ def edit_contact(request, pk):
if contact_list_obj:
contact_obj.contact_list.remove(contact_list_obj)
updated_contact = ContactForm(request.POST)
updated_contact_obj = updated_contact.save()
updated_contact_obj.contact_list.add(contact_list_obj)
if updated_contact.is_valid():
updated_contact_obj = updated_contact.save()
updated_contact_obj.created_by = request.user
updated_contact_obj.save()
updated_contact_obj.contact_list.add(contact_list_obj)
else:
contact = form.save(commit=False)
contact.save()
form.save_m2m()
if form.is_valid():
contact.save()
form.save_m2m()
else:
contact = form.save(commit=False)
contact.save()
form.save_m2m()
if form.is_valid():
contact.save()
form.save_m2m()
if request.POST.get('from_url'):
return JsonResponse({'error': False,
'success_url': reverse('marketing:contact_list_detail', args=(request.POST.get('from_url'),))})
@ -347,7 +352,7 @@ def contact_list_detail(request, pk):
name__icontains=request.POST.get('name'))
if request.POST.get('email'):
contacts_list = contacts_list.filter(
email=request.POST.get('email'))
email__icontains=request.POST.get('email'))
if request.POST.get('company_name'):
contacts_list = contacts_list.filter(
company_name=request.POST.get('company_name'))
@ -554,13 +559,14 @@ def campaign_new(request):
# Replace Links with new One
# domain_url = '%s://%s' % (request.scheme, request.META['HTTP_HOST'])
domain_url = settings.URL_FOR_LINKS
domain_url = request.scheme + '://' + request.get_host()
if Link.objects.filter(campaign_id=camp.id):
Link.objects.filter(campaign_id=camp.id).delete()
for l in links:
link = Link.objects.create(campaign_id=camp.id, original=l)
html = html.replace(
'href="' + l + '"', 'href="' + domain_url + '/m/cm/link/' + str(link.id) + '/e/{{email_id}}"')
'href="' + l + '"', 'href="' + domain_url + '/marketing/cm/link/' + str(link.id) + '/e/{{email_id}}"')
camp.html_processed = html
camp.sent_status = "scheduled"
camp.save()
@ -910,3 +916,28 @@ def create_campaign_from_template(request, template_id):
url_query_params = '?email_template={}'.format(template_id)
url = url_location + url_query_params
return HttpResponseRedirect(url)
def download_links_clicked(request, campaign_id):
campaign_obj = get_object_or_404(Campaign, pk=campaign_id)
campaign_link_click_objects = campaign_obj.campaign_link_click.all().select_related('link', 'campaign', 'contact')
csv_row_headers = ['email', 'company', 'first name', 'last name', 'city', 'state', 'original link', 'unique clicks', 'total clicks', 'campaign title']
data = []
data.append(','.join(csv_row_headers) + '\n')
if campaign_link_click_objects:
for campaign_link_click_object in campaign_link_click_objects:
data.append(
campaign_link_click_object.contact.email + ',' +
campaign_link_click_object.contact.company_name + ',' +
campaign_link_click_object.contact.name + ',' +
campaign_link_click_object.contact.last_name + ',' +
campaign_link_click_object.contact.city + ',' +
campaign_link_click_object.contact.state + ',' +
campaign_link_click_object.link.original + ',' +
str(campaign_link_click_object.link.unique) + ',' +
str(campaign_link_click_object.link.clicks) + ',' +
campaign_link_click_object.link.campaign.title + '\n'
)
response = HttpResponse(data, content_type='text/plain')
response['Content-Disposition'] = 'attachment; filename={}'.format('data_downloads.csv')
return response

View file

@ -1,10 +1,13 @@
from django import forms
from opportunity.models import Opportunity
from common.models import Comment, Attachments
from teams.models import Teams
class OpportunityForm(forms.ModelForm):
probability = forms.IntegerField(max_value=100, required=False)
teams_queryset = []
teams = forms.MultipleChoiceField(choices=teams_queryset)
def __init__(self, *args, **kwargs):
assigned_users = kwargs.pop('assigned_to', [])
@ -29,6 +32,8 @@ class OpportunityForm(forms.ModelForm):
self.fields['probability'].widget.attrs.update({
'placeholder': 'Probability'})
self.fields["teams"].choices = [(team.get('id'), team.get('name')) for team in Teams.objects.all().values('id', 'name')]
self.fields["teams"].required = False
class Meta:
model = Opportunity

View file

@ -91,6 +91,16 @@
<span class="error error_message" id="error_id_probability">{{opportunity_form.probability.errors}}</span>
</div>
</div>
{% if request.user.is_superuser or request.user.role == 'ADMIN' %}
<div class="filter_col col-12">
<div class="form-group">
<label for="id_sattus">Teams{% if opportunity_form.teams.field.required %}<span
class="error">*</span>{% endif %}</label>
{{ opportunity_form.teams }}
<span class="error" id="id__teams">{{ opportunity_form.teams.errors }}</span>
</div>
</div>
{% endif %}
<div class="filter_col col-md-12">
<div class="form-group">
<label for="exampleInputEmail1">Assigned Users</label>
@ -261,6 +271,7 @@
$('.assigned_users').select2();
$("#id_contacts").select2();
$('#id_currency').select2();
$('#id_teams').select2();
});
$('#id_account').change(function(){

View file

@ -1,6 +1,7 @@
{% extends "sales/base.html" %}
{% load staticfiles %}
{% load paginate %}
{% load thumbnail %}
{% block extralinks %}
<link href="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.6-rc.0/css/select2.min.css" rel="stylesheet" />
{% endblock %}
@ -137,13 +138,21 @@
<td><a href="{% url 'opportunities:opp_view' opportunity.id %}">{{ opportunity.name }}</a></td>
<td>
{% with opportunity_users=opportunity.assigned_to.all %}
{% if opportunity_users %}
{% for user in opportunity_users %}
<span class="text-left">{{ user.email }}</span><br>
{% endfor %}
{% if user.profile_pic %}
{% thumbnail user.profile_pic "40x40" crop="center" as im %}
<a href="{% url 'common:view_user' user.id %}">
<img src="{{ im.url }}" width="{{ im.width }}" height="{{ im.height }}" title="{{ user.email }}">
</a>
{% endthumbnail %}
{% else %}
None
<a href="{% url 'common:view_user' user.id %}">
<img src="{% static 'images/user.png' %}" title="{{ user.email }}" width="40" height="40">
</a>
{% endif %}
{% empty %}
None
{% endfor %}
{% endwith %}
</td>
<td>

View file

@ -22,7 +22,7 @@ from common.tasks import send_email_user_mentions
from opportunity.tasks import send_email_to_assigned_user
from common.access_decorators_mixins import (
sales_access_required, marketing_access_required, SalesAccessRequiredMixin, MarketingAccessRequiredMixin)
from teams.models import Teams
class OpportunityListView(SalesAccessRequiredMixin, LoginRequiredMixin, TemplateView):
model = Opportunity
@ -125,11 +125,11 @@ def create_opportunity(request):
if request.POST.getlist('assigned_to', []):
opportunity_obj.assigned_to.add(
*request.POST.getlist('assigned_to'))
assigned_to_list = request.POST.getlist('assigned_to')
current_site = get_current_site(request)
recipients = assigned_to_list
send_email_to_assigned_user.delay(recipients, opportunity_obj.id, domain=current_site.domain,
protocol=request.scheme)
# assigned_to_list = request.POST.getlist('assigned_to')
# current_site = get_current_site(request)
# recipients = assigned_to_list
# send_email_to_assigned_user.delay(recipients, opportunity_obj.id, domain=current_site.domain,
# protocol=request.scheme)
# for assigned_to_user in assigned_to_list:
# user = get_object_or_404(User, pk=assigned_to_user)
# mail_subject = 'Assigned to opportunity.'
@ -144,6 +144,18 @@ def create_opportunity(request):
# mail_subject, message, to=[user.email])
# email.content_subtype = "html"
# email.send()
if request.POST.getlist('teams', []):
user_ids = Teams.objects.filter(id__in=request.POST.getlist('teams')).values_list('users', flat=True)
assinged_to_users_ids = opportunity_obj.assigned_to.all().values_list('id', flat=True)
for user_id in user_ids:
if user_id not in assinged_to_users_ids:
opportunity_obj.assigned_to.add(user_id)
current_site = get_current_site(request)
recipients = list(opportunity_obj.assigned_to.all().values_list('id', flat=True))
send_email_to_assigned_user.delay(recipients, opportunity_obj.id, domain=current_site.domain,
protocol=request.scheme)
if request.POST.getlist('contacts', []):
opportunity_obj.contacts.add(
*request.POST.getlist('contacts'))
@ -286,10 +298,10 @@ def update_opportunity(request, pk):
all_members_list = list(
set(list(assigned_form_users)) -
set(list(assigned_to_ids)))
current_site = get_current_site(request)
recipients = all_members_list
send_email_to_assigned_user.delay(recipients, opportunity_obj.id, domain=current_site.domain,
protocol=request.scheme)
# current_site = get_current_site(request)
# recipients = all_members_list
# send_email_to_assigned_user.delay(recipients, opportunity_obj.id, domain=current_site.domain,
# protocol=request.scheme)
# if all_members_list:
# for assigned_to_user in all_members_list:
# user = get_object_or_404(User, pk=assigned_to_user)
@ -312,6 +324,18 @@ def update_opportunity(request, pk):
else:
opportunity_obj.assigned_to.clear()
if request.POST.getlist('teams', []):
user_ids = Teams.objects.filter(id__in=request.POST.getlist('teams')).values_list('users', flat=True)
assinged_to_users_ids = opportunity_obj.assigned_to.all().values_list('id', flat=True)
for user_id in user_ids:
if user_id not in assinged_to_users_ids:
opportunity_obj.assigned_to.add(user_id)
current_site = get_current_site(request)
recipients = list(opportunity_obj.assigned_to.all().values_list('id', flat=True))
send_email_to_assigned_user.delay(recipients, opportunity_obj.id, domain=current_site.domain,
protocol=request.scheme)
if request.POST.getlist('contacts', []):
opportunity_obj.contacts.add(
*request.POST.getlist('contacts'))

View file

@ -4,9 +4,12 @@ from accounts.models import Account
from contacts.models import Contact
from common.models import User, Attachments, Comment
from django.db.models import Q
from teams.models import Teams
class TaskForm(forms.ModelForm):
teams_queryset = []
teams = forms.MultipleChoiceField(choices=teams_queryset)
def __init__(self, *args, **kwargs):
# assigned_users = kwargs.pop('assigned_to', [])
@ -27,7 +30,9 @@ class TaskForm(forms.ModelForm):
self.fields["account"].queryset = Account.objects.filter(status="open")
self.fields["contacts"].queryset = Contact.objects.filter()
self.fields["teams"].choices = [(team.get('id'), team.get('name')) for team in Teams.objects.all().values('id', 'name')]
self.fields["teams"].required = False
self.fields['assigned_to'].required = False
# if assigned_users:
# self.fields['assigned_to'].queryset = assigned_users

View file

@ -17,7 +17,7 @@
{% block content %}
<form id="formid" action='' method="POST" novalidate enctype="multipart/form-data">
<div class="overview_form_block row marl justify-content-center">
<div class="col-md-9" >
<div class="col-md-9">
<div class="card">
<div class="card-body">
<div class="card-title text-center">
@ -35,8 +35,8 @@
</div>
<div class="filter_col col-md-12">
<div class="form-group">
<label for="exampleInputEmail1">Status{% if form.status.field.required %}<span
class="error_marker" style="color:red">*</span>{% endif %}</label>
<label for="exampleInputEmail1">Status{% if form.status.field.required %}<span class="error_marker"
style="color:red">*</span>{% endif %}</label>
{{ form.status }}
<span class="error" id="id__status">{{ form.status.errors }}</span>
</div>
@ -80,10 +80,6 @@
<span class="error" id="id__account">{{ form.account.errors }}</span>
</div>
</div>
</div>
</div>
<div class="col-md-4">
<div class="filter_col billing_block col-md-12" style="padding: 0px;">
<div class="filter_col col-md-12">
<div class="form-group ">
<label for="id_contacts" class="required">Contacts{% if form.contacts.field.required %}<span
@ -92,6 +88,20 @@
<span class="error" id="id__contacts">{{ form.contacts.errors }}</span>
</div>
</div>
</div>
</div>
<div class="col-md-4">
<div class="filter_col billing_block col-md-12" style="padding: 0px;">
{% if request.user.is_superuser or request.user.role == 'ADMIN' %}
<div class="filter_col col-12">
<div class="form-group">
<label for="id_sattus">Teams{% if form.teams.field.required %}<span
class="error">*</span>{% endif %}</label>
{{ form.teams }}
<span class="error" id="id__teams">{{ form.teams.errors }}</span>
</div>
</div>
{% endif %}
<div class="filter_col col-md-12">
<div class="form-group ">
<label for="exampleInputEmail1">Assign To</label>
@ -136,6 +146,7 @@
$(document).ready(function () {
$("#id_contacts").select2();
$("#id_assigned_to").select2();
$("#id_teams").select2();
var date = new Date();
var today = new Date(date.getFullYear(), date.getMonth(), date.getDate());
$('#id_due_date').datetimepicker({

View file

@ -101,7 +101,11 @@
<div class="form-group">
<label class="acc_field_label" for="id_website" data-name="name">Assigned To</label>
{% for user in task.assigned_to.all %}
<div class="account_field" id="account_website" data-name="name">{{ user }}</div>
<div class="account_field" id="account_website" data-name="name">
<a href="{% url 'common:view_user' user.id %}">
{{ user }}
</a>
</div>
{% endfor %}
</div>
</div>

View file

@ -145,14 +145,22 @@
{% endif %}
<td>{% with users=task.assigned_to.all %}
{% if users %}
{% for user in users %}
<span class="text-left">{{ user.email }}</span><br>
{% endfor %}
<td>{% with task_users=task.assigned_to.all %}
{% for user in task_users %}
{% if user.profile_pic %}
{% thumbnail user.profile_pic "40x40" crop="center" as im %}
<a href="{% url 'common:view_user' user.id %}">
<img src="{{ im.url }}" width="{{ im.width }}" height="{{ im.height }}" title="{{ user.email }}">
</a>
{% endthumbnail %}
{% else %}
None
<a href="{% url 'common:view_user' user.id %}">
<img src="{% static 'images/user.png' %}" title="{{ user.email }}" width="40" height="40">
</a>
{% endif %}
{% empty %}
None
{% endfor %}
{% endwith %}
</td>
<td class="actions">
@ -196,14 +204,23 @@
{% endif %}
<td>{% with users=task.assigned_to.all %}
{% if users %}
{% for user in users %}
<span class="text-left">{{ user.email }}</span><br>
{% endfor %}
<td>
{% with task_users=task.assigned_to.all %}
{% for user in task_users %}
{% if user.profile_pic %}
{% thumbnail user.profile_pic "40x40" crop="center" as im %}
<a href="{% url 'common:view_user' user.id %}">
<img src="{{ im.url }}" width="{{ im.width }}" height="{{ im.height }}" title="{{ user.email }}">
</a>
{% endthumbnail %}
{% else %}
None
<a href="{% url 'common:view_user' user.id %}">
<img src="{% static 'images/user.png' %}" title="{{ user.email }}" width="40" height="40">
</a>
{% endif %}
{% empty %}
None
{% endfor %}
{% endwith %}
</td>
<td class="actions">
@ -247,14 +264,22 @@
{% endif %}
<td>{% with users=task.assigned_to.all %}
{% if users %}
{% for user in users %}
<span class="text-left">{{ user.email }}</span><br>
{% endfor %}
<td>{% with task_users=task.assigned_to.all %}
{% for user in task_users %}
{% if user.profile_pic %}
{% thumbnail user.profile_pic "40x40" crop="center" as im %}
<a href="{% url 'common:view_user' user.id %}">
<img src="{{ im.url }}" width="{{ im.width }}" height="{{ im.height }}" title="{{ user.email }}">
</a>
{% endthumbnail %}
{% else %}
None
<a href="{% url 'common:view_user' user.id %}">
<img src="{% static 'images/user.png' %}" title="{{ user.email }}" width="40" height="40">
</a>
{% endif %}
{% empty %}
None
{% endfor %}
{% endwith %}
</td>
<td class="actions">

View file

@ -20,6 +20,7 @@ from tasks.models import Task
from tasks.utils import *
from common.access_decorators_mixins import (
sales_access_required, marketing_access_required, SalesAccessRequiredMixin, MarketingAccessRequiredMixin)
from teams.models import Teams
@login_required
@ -79,6 +80,14 @@ def task_create(request):
task.save()
task.assigned_to.add(*request.POST.getlist('assigned_to'))
task.contacts.add(*request.POST.getlist('contacts'))
if request.POST.getlist('teams', []):
user_ids = Teams.objects.filter(id__in=request.POST.getlist('teams')).values_list('users', flat=True)
assinged_to_users_ids = task.assigned_to.all().values_list('id', flat=True)
for user_id in user_ids:
if user_id not in assinged_to_users_ids:
task.assigned_to.add(user_id)
kwargs = {'domain': request.get_host(), 'protocol': request.scheme}
send_email.delay(task.id, **kwargs)
return JsonResponse({'error': False, 'success_url': reverse('tasks:tasks_list')})
@ -141,6 +150,12 @@ def task_edit(request, task_id):
# task.contacts.clear()
# task.assigned_to.add(*request.POST.getlist('assigned_to'))
# task.contacts.add(*request.POST.getlist('contacts'))
if request.POST.getlist('teams', []):
user_ids = Teams.objects.filter(id__in=request.POST.getlist('teams')).values_list('users', flat=True)
assinged_to_users_ids = task.assigned_to.all().values_list('id', flat=True)
for user_id in user_ids:
if user_id not in assinged_to_users_ids:
task.assigned_to.add(user_id)
kwargs = {'domain': request.get_host(), 'protocol': request.scheme}
send_email.delay(task.id, **kwargs)
return JsonResponse({'error': False, 'success_url': reverse('tasks:tasks_list')})

View file

@ -49,12 +49,16 @@
{% if user.profile_pic %}
{% thumbnail user.profile_pic "40x40" crop="center" as im %}
<span>
<img src="{{ im.url }}" width="{{ im.width }}" height="{{ im.height }}" title="{{ user.email }}">
<a href="{% url 'common:view_user' user.id %}">
<img src="{{ im.url }}" width="{{ im.width }}" height="{{ im.height }}" title="{{ user.email }}">
</a>
</span>
{% endthumbnail %}
{% else %}
<span>
<img src="{% static 'images/user.png' %}" title="{{ user.email }}" width="40" height="40">
<a href="{% url 'common:view_user' user.id %}">
<img src="{% static 'images/user.png' %}" title="{{ user.email }}" width="40" height="40">
</a>
</span>
{% endif %}
{% empty %}

View file

@ -28,8 +28,8 @@
<div class="filter_col col-md-2">
<div class="form-group">
<label for="exampleInputEmail1">Team Name</label>
<input type="text" class="form-control" placeholder="Team Name"
name="team_name" value="{{request.POST.team_name}}">
<input type="text" class="form-control" placeholder="Team Name" name="team_name"
value="{{request.POST.team_name}}">
</div>
</div>
<div class="filter_col col-md-2">
@ -128,11 +128,15 @@
{% for user in users %}
{% if user.profile_pic %}
{% thumbnail user.profile_pic "40x40" crop="center" as im %}
<img src="{{ im.url }}" width="{{ im.width }}" height="{{ im.height }}"
title="{{ user.email }}">
<a href="{% url 'common:view_user' user.id %}">
<img src="{{ im.url }}" width="{{ im.width }}" height="{{ im.height }}"
title="{{ user.email }}">
</a>
{% endthumbnail %}
{% else %}
<img src="{% static 'images/user.png' %}" title="{{ user.email }}" width="40" height="40">
<a href="{% url 'common:view_user' user.id %}">
<img src="{% static 'images/user.png' %}" title="{{ user.email }}" width="40" height="40">
</a>
{% endif %}
{% empty %}
None
@ -144,11 +148,11 @@
{% if team.created_by.profile_pic %}
{% thumbnail team.created_by.profile_pic "40x40" crop="center" as im %}
<img src="{{ im.url }}" width="{{ im.width }}" height="{{ im.height }}"
title="{{ team.created_by }}" style="border-radius: 50%" />
title="{{ team.created_by }}" style="border-radius: 50%" />
{% endthumbnail %}
{% else %}
<img src="{% static 'images/user.png' %}"
style="width: 40px;height: 40px;border-radius: 50%;" title="{{ team.created_by }}" />
<img src="{% static 'images/user.png' %}" style="width: 40px;height: 40px;border-radius: 50%;"
title="{{ team.created_by }}" />
{% endif %}
{% else %}
None

View file

@ -95,7 +95,7 @@
<div class="card-body">
<div class="card-title text-right">
<span class="float-left">Last Activity</span>
<a href="#" class="primary_btn text-center"><i class="fas fa-download mar_right_0"></i></a>
<a href="{% url 'marketing:download_links_clicked' campaign.id %}" class="primary_btn text-center"><i class="fas fa-download mar_right_0"></i></a>
</div>
<div class="table-responsive table-bordered">
<table class="table">
@ -104,7 +104,7 @@
<th width="45%">Link(url)</th>
<th width="30%" class="text-center">Unique</th>
<th width="10%" class="text-center">Total</th>
<th width="15%" class="text-center">Export</th>
<!-- <th width="15%" class="text-center">Export</th> -->
</tr>
</thead>
<tbody>
@ -119,9 +119,9 @@
</td>
<td class="text-center">{{ link.unique }}</td>
<td class="text-center">{{ link.clicks }}</td>
<td class="text-center actions">
<!-- <td class="text-center actions">
<a href="#" class="btn btn-success"><i class="fas fa-download mar_right_0"></i></a>
</td>
</td> -->
</tr>
{% endfor %}
</tbody>
@ -171,10 +171,12 @@
{% with contacts=contact.contact_list.all %}
<td>
{% for contact in contacts %}
{% if contact in campaign.contact_lists.all %}
<div>
<a href="{% url 'marketing:contact_list_detail' contact.id %}"
class="anchor">{{contact.name}} </a>
class="anchor">{{contact.name}} </a>
</div>
{% endif %}
{% endfor %}
</td>
{% endwith %}
@ -229,10 +231,12 @@
{% with contacts=contact.contact_list.all %}
<td>
{% for contact in contacts %}
{% if contact in campaign.contact_lists.all %}
<div>
<a href="{% url 'marketing:contact_list_detail' contact.id %}"
class="anchor">{{contact.name}}</a>
</div>
{% endif %}
{% endfor %}
</td>
{% endwith %}
@ -288,10 +292,12 @@
{% with contacts=contact.contact_list.all %}
<td>
{% for contact in contacts %}
{% if contact in campaign.contact_lists.all %}
<div>
<a href="{% url 'marketing:contact_list_detail' contact.id %}"
class="anchor">{{contact.name}}</a>
</div>
{% endif %}
{% endfor %}
</td>
{% endwith %}

View file

@ -197,14 +197,14 @@
<span id="id_html"></span>
<div id="editor-container">
</div>
<span class="hint">Use the following tags in your subject, plain text or HTML code and
<!-- <span class="hint">Use the following tags in your subject, plain text or HTML code and
they'll automatically be formatted when your campaign is sent. For web version and
unsubscribe tags, you can style them with inline CSS.</span>
unsubscribe tags, you can style them with inline CSS.</span> -->
<input type="hidden" name="html" id="html_content">
</div>
<div class="col-md-12 no-padding">
<div class="row help_container">
<div class="col-md-6">
<!-- <div class="row help_container"> -->
<!-- <div class="col-md-6">
<div class="heading">Essential tags (HTML only)</div>
<p class="desc">The following tags can only be used on the HTML version</p>
<ul>
@ -237,42 +237,46 @@
</code>
</li>
</ul>
</div>
<div class="col-md-6">
<div class="heading">Personalization tags</div>
<p class="desc">The following tags can be used on both Plain text or HTML version</p>
<ul>
<li>
<strong>Name: </strong>
<code>[Name,fallback=]</code>
</li>
<li>
<strong>Email: </strong>
<code>[Email]</code>
</li>
<li>
</div> -->
<div class="col-md-12">
<div class="heading">Personalization tags</div>
<p class="desc">The following tags can be used on both Plain text or HTML. Add these tags to customize the email template, these tags will be replaced with the associated contact details while the mails are sent.</p>
<ul>
<li>
<strong>First Name: </strong>
<code>{% templatetag openvariable %} first_name {% templatetag closevariable %}</code>
</li>
<li>
<strong>Last Name: </strong>
<code>{% templatetag openvariable %} last_name {% templatetag closevariable %}</code>
</li>
<li>
<strong>Full Name: </strong>
<code>{% templatetag openvariable %} name {% templatetag closevariable %}</code>
</li>
<li>
<strong>Email: </strong>
<code>{% templatetag openvariable %} email {% templatetag closevariable %}</code>
</li>
<li>
<strong>Company: </strong>
<code>{% templatetag openvariable %} company_name {% templatetag closevariable %}</code>
</li>
<li>
<strong>City: </strong>
<code>{% templatetag openvariable %} city {% templatetag closevariable %}</code>
</li>
<li>
<strong>State: </strong>
<code>{% templatetag openvariable %} state {% templatetag closevariable %}</code>
</li>
<!-- <li>
<strong>Two digit day of the month (eg. 01 to 31):</strong>
<code>[currentdaynumber]</code>
</li>
</ul>
<div class="heading">Essential tags</div>
<p class="desc">The following tags can only be used on the HTML version</p>
<ul>
<li>
<strong>Name: </strong>
<code>[Name,fallback=]</code>
</li>
<li>
<strong>Email: </strong>
<code>[Email]</code>
</li>
<li>
<strong>Two digit day of the month (eg. 01 to 31):</strong>
<code>[currentdaynumber]</code>
</li>
</ul>
</div>
</li> -->
</ul>
</div>
<!-- </div> -->
</div>
</div>
</div>
@ -292,7 +296,8 @@
{% block js_block %}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-tagsinput/1.3.6/jquery.tagsinput.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.6-rc.0/js/select2.min.js"></script>
<script src="https://malsup.github.com/jquery.form.js"></script>
<!-- <script src="https://malsup.github.com/jquery.form.js"></script> -->
<script src="{% static 'js/ajaxForm.js' %}"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.24.0/moment-with-locales.min.js"></script>
<script type="text/javascript"
src="https://cdnjs.cloudflare.com/ajax/libs/tempusdominus-bootstrap-4/5.0.0-alpha14/js/tempusdominus-bootstrap-4.min.js"></script>
@ -350,7 +355,7 @@
[{ header: [1, 2, false] }],
['bold', 'italic', 'underline'],
// ['image', 'code-block']
['code-block']
['code-block', 'link']
]
},
placeholder: 'Compose an epic...',
@ -358,6 +363,7 @@
});
quill.on('text-change', function () {
$('.ql-syntax').css({ "background-color": "#23241f", "color": "#f8f8f2", "overflow": "visible", "border-radius": "3px", "white-space": "pre-wrap", "margin-bottom": "5px", "margin-top": "5px", "padding": "5px 10px" })
var justHtml = quill.root.innerHTML;
$('#html_content').val(justHtml);
});

View file

@ -81,7 +81,7 @@
toolbar: [
[{ header: [1, 2, false] }],
['bold', 'italic', 'underline'],
['code-block']
['code-block', 'link']
]
},
placeholder: 'Compose an epic...',
@ -98,6 +98,7 @@
var justHtmlContent = document.getElementById('justHtml');
quill.on('text-change', function () {
$('.ql-syntax').css({"background-color":"#23241f","color":"#f8f8f2","overflow":"visible","border-radius":"3px","white-space":"pre-wrap","margin-bottom":"5px","margin-top":"5px","padding":"5px 10px"})
var delta = quill.getContents();
var text = quill.getText();
var justHtml = quill.root.innerHTML;
@ -118,6 +119,9 @@
dataType: 'json',
url: $(this).attr('action'),
data: $(this).serialize(),
beforeSend: function (e) {
$('.ql-syntax').css({"background-color":"#23241f","color":"#f8f8f2","overflow":"visible","border-radius":"3px","white-space":"pre-wrap","margin-bottom":"5px","margin-top":"5px","padding":"5px 10px"})
},
success: function (data) {
console.log("data", data)
if (data.error == false) {

View file

@ -44,7 +44,7 @@
<div class="form-group">
<label for="exampleInputEmail1">Email</label>
<input type="text" class="form-control" placeholder="Contact Email" name="contact_email"
value="{{request.POST.contact_email}}">
value="{{request.POST.contact_email}}" minlength="2">
</div>
</div>
<input type="hidden" name="tab_status" id="tab_status">
@ -111,8 +111,8 @@
{% endfor %}
</td>
<td class="actions text-center">
<a href="{% url 'marketing:edit_contact' contact.id %}" class="btn btn-success edit edit_contact"
data-other-contacts-lists='{{contact.contact_list.all|length}}'><i class="fas fa-edit"></i></a>
<!-- <a href="{% url 'marketing:edit_contact' contact.id %}" class="btn btn-success edit edit_contact"
data-other-contacts-lists='{{contact.contact_list.all|length}}'><i class="fas fa-edit"></i></a> -->
<!-- <a href="#" class="sky_blue box"><i class="far fa-copy"></i></a>
<a href="#" class="purple box"><i class="fas fa-upload"></i></a> -->
<a href="{% url 'marketing:delete_contact' contact.id %}"
@ -159,7 +159,7 @@
url = $(this).attr('href')
var contact_lists = parseInt($(this).attr('data-other-contacts-lists'));
if (contact_lists > 1) {
if (!confirm('Are you sure you want to delete? this contact exists in other contact lists, deleting this will delete this contact from other contact lists too!'))
if (!confirm('This contact exists in other contact lists too. Are you sure you want to delete this contact?'))
return;
window.location = $(this).attr('href');
} else {

View file

@ -149,7 +149,7 @@
url = $(this).attr('href')
var contact_lists = parseInt($(this).attr('data-other-contacts-lists'));
if (contact_lists > 1) {
if (!confirm('Are you sure you want to delete? this contact exists in other contact lists, deleting this will delete this contact from other contact lists too!'))
if (!confirm('This contact exists in other contact lists too. Are you sure you want to delete this contact?'))
return;
window.location = $(this).attr('href');
} else {

View file

@ -33,16 +33,44 @@
<nav class="navbar navbar-expand-lg navbar-dark fixed-top">
<!-- <a class="navbar-brand" href="{% url 'common:home' %}">Django CRM</a> -->
<div class="dropdown">
<a class="dropdown-toggle navbar-brand" href="#" role="button" id="dropdownMenuLink" data-toggle="dropdown"
{% if request.user.is_superuser or request.user.role == 'ADMIN' %}
<a class="dropdown-toggle navbar-brand" href="#" role="button" id="dropdownMenuLink" data-toggle="dropdown"
aria-haspopup="true" aria-expanded="false" style="color:#44535c">
Django CRM
</a>
</a>
{% else %}
{% if request.user.has_sales_access and request.user.has_marketing_access %}
<a class="dropdown-toggle navbar-brand" href="#" role="button" id="dropdownMenuLink" data-toggle="dropdown"
aria-haspopup="true" aria-expanded="false" style="color:#44535c">
Django CRM
</a>
{% elif request.user.has_sales_access and not request.user.has_marketing_access %}
<a class="navbar-brand" href="{% url 'common:home' %}" role="button" id="dropdownMenuLink" data-toggle=""
aria-haspopup="true" aria-expanded="false" style="color:#44535c">
Django CRM
</a>
{% elif not request.user.has_sales_access and request.user.has_marketing_access %}
<a class="navbar-brand" href="{% url 'marketing:dashboard' %}" role="button" id="dropdownMenuLink" data-toggle=""
aria-haspopup="true" aria-expanded="false" style="color:#44535c">
Django CRM
</a>
{% else %}
{{''}}
{% endif %}
{% endif %}
<!-- <a class="dropdown-toggle navbar-brand" href="#" role="button" id="dropdownMenuLink" data-toggle="dropdown"
aria-haspopup="true" aria-expanded="false" style="color:#44535c">
Django CRM
</a> -->
<div class="dropdown-menu mt-2" aria-labelledby="dropdownMenuLink">
{% if user.is_superuser or user.role == 'ADMIN' %}
<a class="dropdown-item" href="/">Sales</a>
<a class="dropdown-item" href="{% url 'marketing:dashboard' %}">Marketing</a>
{% elif user.has_sales_access and user.has_marketing_access %}
{% else %}
{% if user.has_sales_access and user.has_marketing_access %}
<a class="dropdown-item" href="/">Sales</a>
<a class="dropdown-item" href="{% url 'marketing:dashboard' %}">Marketing</a>
{% elif user.has_sales_access and not user.has_marketing_access %}
@ -52,6 +80,7 @@
{% else %}
{{''}}
{% endif %}
{% endif %}
<!-- <a class="dropdown-item" href="/">Sales</a>
<a class="dropdown-item" href="{% url 'marketing:dashboard' %}">Marketing</a> -->
</div>

View file

@ -83,7 +83,7 @@
{% with users=account.assigned_to.all %}
{% for user in users|slice:'3' %}
<div>
{{user}}
<a href="{% url 'common:view_user' user.id %}">{{user}}</a>
</div>
{% empty %}
<span class="text-left">None</span>
@ -144,7 +144,7 @@
<td>
{% with users=opportunity.assigned_to.all %}
{% for user in users|slice:'3' %}
<span class="text-left" id="list_opp_users_">{{user}}<span>
<span class="text-left" id="list_opp_users_"><a href="{% url 'common:view_user' user.id %}">{{user}}</a><span>
{% empty %}
<span class="text-left">None</span>
{% endfor %}