towards 0.4 and some fixes
This commit is contained in:
parent
153c8d7deb
commit
15bbb94818
60 changed files with 930 additions and 308 deletions
|
|
@ -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',
|
||||
|
|
|
|||
|
|
@ -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")
|
||||
|
|
|
|||
|
|
@ -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')
|
||||
},
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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',
|
||||
|
|
|
|||
|
|
@ -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(){
|
||||
|
|
|
|||
|
|
@ -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'))
|
||||
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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',
|
||||
|
|
|
|||
|
|
@ -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');
|
||||
|
|
|
|||
|
|
@ -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">
|
||||
|
|
|
|||
|
|
@ -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 %}
|
||||
|
|
@ -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 %}
|
||||
|
|
|
|||
|
|
@ -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'), {
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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!?");
|
||||
|
|
|
|||
|
|
@ -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')
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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')
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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({
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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')})
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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() {
|
||||
|
||||
|
|
|
|||
|
|
@ -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 %}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
|
|
|
|||
|
|
@ -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"),
|
||||
]
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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(){
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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'))
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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({
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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">
|
||||
|
|
|
|||
|
|
@ -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')})
|
||||
|
|
|
|||
|
|
@ -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 %}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 %}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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 %}
|
||||
|
|
|
|||
Loading…
Reference in a new issue