mentions added for all modules comments
This commit is contained in:
parent
1a84d1ca22
commit
918c196ba0
19 changed files with 656 additions and 160 deletions
|
|
@ -12,6 +12,8 @@
|
|||
</nav>
|
||||
<!-- breadcrumb ends here -->
|
||||
{% endblock breadcrumb %}
|
||||
|
||||
|
||||
{% block content %}
|
||||
<!-- ACCOUNTS VIEW STARTS -->
|
||||
<div class="main_container" id="maincontainer">
|
||||
|
|
@ -1833,6 +1835,7 @@
|
|||
<!-- ACCOUNTS VIEW ENDS -->
|
||||
{% endblock content %}
|
||||
{% block js_block %}
|
||||
|
||||
<script type="text/javascript">
|
||||
$("#form_opp").submit(function(e) {
|
||||
e.preventDefault();
|
||||
|
|
@ -2022,6 +2025,16 @@
|
|||
});
|
||||
</script>
|
||||
<script type="text/javascript">
|
||||
|
||||
var assigned_to_list = "{{ assigned_data }}";
|
||||
assigned_to_list = JSON.parse(assigned_to_list.replace(/&(l|g|quo)t;/g, function(a,b){
|
||||
return {
|
||||
l : '<',
|
||||
g : '>',
|
||||
quo : '"'
|
||||
}[b];
|
||||
}));
|
||||
|
||||
/*Comment Add Js Start*/
|
||||
$("#comment_form").submit(function(e){
|
||||
e.preventDefault()
|
||||
|
|
@ -2164,14 +2177,13 @@ $("#attachment_form").submit(function (e) {
|
|||
)
|
||||
|
||||
$("#AttachmentError").html("")
|
||||
$("#id_attachments").val("")
|
||||
alert("Attachment Saved")
|
||||
}
|
||||
$("#id_attachments").val("")
|
||||
alert("Attachment Saved")
|
||||
}
|
||||
})
|
||||
})
|
||||
</script>
|
||||
<script src="{% static 'js/mention.js' %}"></script>
|
||||
|
||||
|
||||
|
||||
</script>
|
||||
{% endblock js_block %}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
import json
|
||||
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||
from django.contrib.sites.shortcuts import get_current_site
|
||||
from django.core.mail import EmailMessage
|
||||
|
|
@ -152,6 +153,14 @@ class AccountDetailView(LoginRequiredMixin, DetailView):
|
|||
comment_permission = True
|
||||
else:
|
||||
comment_permission = False
|
||||
|
||||
assigned_data = []
|
||||
for each in context['account_record'].assigned_to.all():
|
||||
assigned_dict = {}
|
||||
assigned_dict['id'] = each.id
|
||||
assigned_dict['name'] = each.email
|
||||
assigned_data.append(assigned_dict)
|
||||
|
||||
context.update({
|
||||
"comments": account_record.accounts_comments.all(),
|
||||
"attachments": account_record.account_attachment.all(),
|
||||
|
|
@ -168,6 +177,7 @@ class AccountDetailView(LoginRequiredMixin, DetailView):
|
|||
"case_priority": PRIORITY_CHOICE,
|
||||
"case_status": STATUS_CHOICE,
|
||||
'comment_permission': comment_permission,
|
||||
"assigned_data": json.dumps(assigned_data)
|
||||
})
|
||||
return context
|
||||
|
||||
|
|
|
|||
|
|
@ -116,7 +116,6 @@
|
|||
<tr class="case_row{{case.id}}" style="text-align:center;">
|
||||
<td scope="row">{{ forloop.counter }}</td>
|
||||
<td><a href="{% url 'cases:view_case' case.id %}">{{ case.name }}</a></td>
|
||||
<td>{{case.closed_on}}</td>
|
||||
<td>
|
||||
{% if case.account %}
|
||||
<a href="{% url 'accounts:view_account' case.account.id %}">{{ case.account }}</a>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
{% extends 'base.html' %}
|
||||
{% load staticfiles %}
|
||||
|
||||
{% block content %}
|
||||
<!-- CASE VIEW STARTS -->
|
||||
<div class="main_container" id="maincontainer">
|
||||
|
|
@ -118,17 +119,17 @@
|
|||
<input type="hidden" value="{{case_record.id}}" name="caseid">
|
||||
</form>
|
||||
<ul class="list-group" id="attachment_div">
|
||||
{% for attachemnt in attachments %}
|
||||
<li class="list-group-item list-row" id="attachment{{attachemnt.id}}">
|
||||
{% for attachment in attachments %}
|
||||
<li class="list-group-item list-row" id="attachment{{attachment.id}}">
|
||||
<div class="float-right right-container">
|
||||
<div class="list-row-buttons btn-group float-right">
|
||||
<button class="action btn btn-danger" onclick="remove_attachment({{attachemnt.id}})">Remove</button>
|
||||
<button class="action btn btn-danger" onclick="remove_attachment({{attachment.id}})">Remove</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="stream-post-container" id="attachment_name{{attachemnt.id}}"><pre><a href="{{ attachemnt.attachment.url }}">{{ attachemnt.file_name }}</a></pre></div>
|
||||
<div class="stream-post-container" id="attachment_name{{attachment.id}}"><pre><a href="{{ attachment.attachment.url }}">{{ attachment.file_name }}</a></pre></div>
|
||||
<div class="stream-container">
|
||||
<pre class="float-left">{{ attachemnt.created_by }}</pre>
|
||||
<pre class="float-right">{{ attachemnt.created_on }}</pre>
|
||||
<pre class="float-left">{{ attachment.created_by }}</pre>
|
||||
<pre class="float-right">{{ attachment.created_on }}</pre>
|
||||
</div>
|
||||
</li>
|
||||
{% endfor %}
|
||||
|
|
@ -149,7 +150,7 @@
|
|||
<textarea class="form-control" textarea cols="40" rows="3" id="id_comments" name="comment" placeholder="Submit Your Comments Here"></textarea><div><i id="CommentError" style="display:none; color:red"></i></div>
|
||||
</br>
|
||||
<div class="buttons_row">
|
||||
<button class="btn btn-default save" style="text-align: center;" id="comment_submit" type="submit">Submit</button>
|
||||
<button class="btn btn-default save" id="comment_submit" type="submit">Submit</button>
|
||||
</div>
|
||||
</div>
|
||||
<input type="hidden" value="{{case_record.id}}" name="caseid">
|
||||
|
|
@ -345,6 +346,17 @@
|
|||
<script src="{% static 'js/cases/view_case.js' %}"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.6-rc.0/js/select2.min.js"></script>
|
||||
<script type="text/javascript">
|
||||
|
||||
var assigned_to_list = "{{ assigned_data }}";
|
||||
assigned_to_list = JSON.parse(assigned_to_list.replace(/&(l|g|quo)t;/g, function(a,b){
|
||||
return {
|
||||
l : '<',
|
||||
g : '>',
|
||||
quo : '"'
|
||||
}[b];
|
||||
}));
|
||||
|
||||
|
||||
$('#remove_case').click(function(e){
|
||||
var result = confirm("Are You Sure You Want to delete?");
|
||||
if (result==false) {
|
||||
|
|
@ -389,10 +401,9 @@ function remove_attachment(x) {
|
|||
"attachment_id": x
|
||||
}, function (data) {
|
||||
if (data.error) {
|
||||
alert(data.error)
|
||||
alert(data.errors)
|
||||
} else {
|
||||
// $("#attachment" + data.aid).remove()
|
||||
window.location.reload();
|
||||
$("#attachment" + data.attachment_object).remove()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
@ -410,16 +421,23 @@ $("#attachment_form").submit(function (e) {
|
|||
processData: false,
|
||||
success: function (data) {
|
||||
if (data.error) {
|
||||
$("#AttachmentError").html(data.error).show()
|
||||
$("#AttachmentError").html(data.errors).show()
|
||||
} else {
|
||||
alert(data.message)
|
||||
$("#attachment_div").prepend(
|
||||
"<li class='list-group-item list-row' id='attachment" + data.attachment_id + "'>" +
|
||||
"<div class='float-right right-container'><div class='list-row-buttons btn-group float-right'><button class='action btn btn-danger' onclick='remove_attachment("+data.attachment_id+")''>Remove</button></div></div>" +
|
||||
"<div class='stream-post-container' id='comment_name"+data.attachment_id+"'><pre><a href='"+data.attachment_url+"'>"+data.attachment+"</a></pre></div>"+
|
||||
"<div class='stream-container'><pre class='float-left'>"+data.created_by+"</pre><pre class='float-right'>"+data.created_on+"</pre></div>" +
|
||||
"</li>"
|
||||
)
|
||||
$("#AttachmentError").html("")
|
||||
$("#id_attachments").val("")
|
||||
window.location.reload();
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
</script>
|
||||
</script>
|
||||
<script src="{% static 'js/mention.js' %}"></script>
|
||||
|
||||
{% endblock js_block %}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
import json
|
||||
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||
from django.contrib.sites.shortcuts import get_current_site
|
||||
from django.core.mail import EmailMessage
|
||||
|
|
@ -143,8 +144,16 @@ class CaseDetailView(LoginRequiredMixin, DetailView):
|
|||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super(CaseDetailView, self).get_context_data(**kwargs)
|
||||
assigned_data = []
|
||||
for each in context['case_record'].assigned_to.all():
|
||||
assigned_dict = {}
|
||||
assigned_dict['id'] = each.id
|
||||
assigned_dict['name'] = each.email
|
||||
assigned_data.append(assigned_dict)
|
||||
|
||||
context.update({"comments": context["case_record"].cases.all(),
|
||||
"attachments": context['case_record'].case_attachment.all()})
|
||||
"attachments": context['case_record'].case_attachment.all(),
|
||||
"assigned_data": json.dumps(assigned_data)})
|
||||
return context
|
||||
|
||||
|
||||
|
|
@ -292,7 +301,8 @@ class AddCommentView(LoginRequiredMixin, CreateView):
|
|||
self.case = get_object_or_404(Case, id=request.POST.get('caseid'))
|
||||
if (
|
||||
request.user in self.case.assigned_to.all() or
|
||||
request.user == self.case.created_by
|
||||
request.user == self.case.created_by or request.user.is_superuser or
|
||||
request.user.role == 'admin'
|
||||
):
|
||||
form = self.get_form()
|
||||
if form.is_valid():
|
||||
|
|
@ -323,7 +333,8 @@ class UpdateCommentView(LoginRequiredMixin, View):
|
|||
|
||||
def post(self, request, *args, **kwargs):
|
||||
self.comment_obj = get_object_or_404(Comment, id=request.POST.get("commentid"))
|
||||
if request.user == self.comment_obj.commented_by:
|
||||
if (request.user == self.comment_obj.commented_by or request.user.is_superuser or
|
||||
request.user.role == 'admin'):
|
||||
form = CaseCommentForm(request.POST, instance=self.comment_obj)
|
||||
if form.is_valid():
|
||||
return self.form_valid(form)
|
||||
|
|
@ -349,7 +360,8 @@ class DeleteCommentView(LoginRequiredMixin, View):
|
|||
|
||||
def post(self, request, *args, **kwargs):
|
||||
self.object = get_object_or_404(Comment, id=request.POST.get("comment_id"))
|
||||
if request.user == self.object.commented_by:
|
||||
if (request.user == self.object.commented_by or request.user.is_superuser or
|
||||
request.user.role == 'admin'):
|
||||
self.object.delete()
|
||||
data = {"cid": request.POST.get("comment_id")}
|
||||
return JsonResponse(data)
|
||||
|
|
@ -368,7 +380,8 @@ class AddAttachmentView(LoginRequiredMixin, CreateView):
|
|||
self.case = get_object_or_404(Case, id=request.POST.get('caseid'))
|
||||
if (
|
||||
request.user in self.case.assigned_to.all() or
|
||||
request.user == self.case.created_by
|
||||
request.user == self.case.created_by or request.user.is_superuser or
|
||||
request.user.role == 'admin'
|
||||
):
|
||||
form = self.get_form()
|
||||
if form.is_valid():
|
||||
|
|
@ -376,7 +389,7 @@ class AddAttachmentView(LoginRequiredMixin, CreateView):
|
|||
else:
|
||||
return self.form_invalid(form)
|
||||
else:
|
||||
data = {'error': "You don't have permission to add attachment for this case."}
|
||||
data = {"error":True, "errors": "You don't have permission to add attachment for this case."}
|
||||
return JsonResponse(data)
|
||||
|
||||
def form_valid(self, form):
|
||||
|
|
@ -385,22 +398,31 @@ class AddAttachmentView(LoginRequiredMixin, CreateView):
|
|||
attachment.file_name = attachment.attachment.name
|
||||
attachment.case = self.case
|
||||
attachment.save()
|
||||
# return JsonResponse({"error": False, "message": "Attachment Saved"
|
||||
# })
|
||||
return JsonResponse({
|
||||
"message": "Attachment Saved"
|
||||
"attachment_id": attachment.id,
|
||||
"attachment": attachment.file_name,
|
||||
"attachment_url": attachment.attachment.url,
|
||||
"created_on": attachment.created_on,
|
||||
"created_by": attachment.created_by.email,
|
||||
"message": "attachment Created",
|
||||
"error": False
|
||||
})
|
||||
|
||||
def form_invalid(self, form):
|
||||
return JsonResponse({"error": form['attachment'].errors})
|
||||
return JsonResponse({"error":True, "errors": form['attachment'].errors})
|
||||
|
||||
|
||||
class DeleteAttachmentsView(LoginRequiredMixin, View):
|
||||
|
||||
def post(self, request, *args, **kwargs):
|
||||
self.object = get_object_or_404(Attachments, id=request.POST.get("attachment_id"))
|
||||
if request.user == self.object.created_by:
|
||||
if (request.user == self.object.created_by or request.user.is_superuser or
|
||||
request.user.role == 'admin'):
|
||||
self.object.delete()
|
||||
data = {"acd": request.POST.get("attachment_id")}
|
||||
data = {"attachment_object": request.POST.get("attachment_id"), "error": False}
|
||||
return JsonResponse(data)
|
||||
else:
|
||||
data = {'error': "You don't have permission to delete this attachment."}
|
||||
data = {"error":True, "errors": "You don't have permission to delete this attachment."}
|
||||
return JsonResponse(data)
|
||||
|
|
@ -273,4 +273,4 @@ class Document(models.Model):
|
|||
|
||||
|
||||
def __str__(self):
|
||||
return self.title
|
||||
return self.title
|
||||
|
|
@ -2,102 +2,112 @@
|
|||
{% load staticfiles %}
|
||||
{% load paginate %}
|
||||
{% block content %}
|
||||
<!-- main_container starts here -->
|
||||
<div class="main_container">
|
||||
<!-- heading_create starts here -->
|
||||
<div class="row marl heading_create">
|
||||
<div class="heading col-md-12">
|
||||
<div class="no-gutters row">
|
||||
<div class="col-md-6">
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="create_new text-right">
|
||||
<a href="{% url 'common:create_doc'%}"><i class="fa fa-plus"></i> Add New Document</a>
|
||||
</div>
|
||||
</div>
|
||||
<!-- main_container starts here -->
|
||||
<div class="main_container">
|
||||
<!-- heading_create starts here -->
|
||||
<div class="row marl heading_create">
|
||||
<div class="heading col-md-12">
|
||||
<div class="no-gutters row">
|
||||
<div class="col-md-6">
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="create_new text-right">
|
||||
<a href="{% url 'common:create_doc' %}"><i class="fa fa-plus"></i> Add New Document</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- heading_create ends here -->
|
||||
<!-- filter_row starts here -->
|
||||
<div class="filter_row row marl">
|
||||
<div class="col-md-12">
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<div class="card-title">Filters</div>
|
||||
<form id="docs_filter" action="" method="POST">
|
||||
<div class="row marl">
|
||||
<div class="filter_col col-4">
|
||||
<div class="form-group">
|
||||
<label for="exampleInputEmail1">Document Title</label>
|
||||
<input type="text" class="form-control" placeholder="Document Title" name="doc_name" value="{{request.POST.doc_name}}">
|
||||
</div>
|
||||
</div>
|
||||
<br clear="all">
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- filter_row ends here -->
|
||||
<div class="table_container_row row marl">
|
||||
<div class="col-md-12">
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<div class="card-title list">
|
||||
List of Documents
|
||||
<span class="float-right total_count">{% if show_pageitems %} {% show_pageitems %}{% else %}Total Documents {{ documents|length }}{% endif %}</span>
|
||||
</div>
|
||||
<div class="table-responsive ">
|
||||
<table class="table table-bordered table-striped table-condensed">
|
||||
<thead>
|
||||
{% if documents|length > 0 %}
|
||||
|
||||
<tr>
|
||||
<th width="5%" style="text-align:center;">S.No</th>
|
||||
<th width="20%" style="text-align:center;">Document Title</th>
|
||||
<th width="20%" style="text-align:center;">Created_by</th>
|
||||
<th width="20%" style="text-align:center;">Actions</th>
|
||||
</tr>
|
||||
{% endif %}
|
||||
</thead>
|
||||
<tbody>
|
||||
{% if per_page %}
|
||||
{% paginate per_page documents %}
|
||||
{% else %}
|
||||
{% paginate 10 documents %}
|
||||
{% endif %}
|
||||
{% for document in documents %}
|
||||
<tr class="text-center">
|
||||
<td scope="row">{{ forloop.counter }}</td>
|
||||
<td><a href="{% url 'common:view_doc' document.id %}">{{ document.title }}</a></td>
|
||||
<td>{{ document.created_by }}</td>
|
||||
<td class="actions">
|
||||
<a href="{% url 'common:edit_doc' document.id %}" class="btn btn-success edit"><i class="fas fa-pencil-alt"></i>Edit</a>
|
||||
<a href="{% url 'common:remove_doc' document.id %}" class="btn btn-danger trash"><i class="fas fa-trash-alt"></i>Delete</a>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{% ifequal documents|length 0 %}
|
||||
<h6 class="text-center">No Documents Found</h6>
|
||||
{% endifequal %}
|
||||
<div class="marl row text-center">
|
||||
{% show_pages %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- main_container ends here -->
|
||||
<!-- heading_create ends here -->
|
||||
<!-- filter_row starts here -->
|
||||
<div class="filter_row row marl">
|
||||
<div class="col-md-3 col-lg-2 col-xl-2">
|
||||
<div class="card">
|
||||
<form id="docs_filter" method="POST" action="">
|
||||
<div class="card-body">
|
||||
<div class="card-title">Filters</div>
|
||||
<div class="row marl">
|
||||
<div class="filter_col col-md-12">
|
||||
<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%}/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="filter_col text-center col-12">
|
||||
<div class="form-group buttons_row">
|
||||
<button class="btn btn-primary save" type="submit">Search</button>
|
||||
<a href="{% url 'common:doc_list' %}" class="btn btn-default clear">Clear</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-9 col-lg-10 col-xl-10">
|
||||
<div class="table_container_row row marl no-gutters">
|
||||
<div class="col-md-12">
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<div class="panel-heading-list card-title">
|
||||
List of Documents
|
||||
<span class="float-right total_count">{% if show_pageitems %} {% show_pageitems %}{% else %}Total Documents {{documents|length}}{% endif %}</span>
|
||||
</div>
|
||||
<div class="table-responsive">
|
||||
<table class="table ">
|
||||
<thead>
|
||||
{% if documents|length > 0 %}
|
||||
<tr>
|
||||
<th>S.No</th>
|
||||
<th>Title</th>
|
||||
<th>Created By</th>
|
||||
<th>Actions</th>
|
||||
</tr>
|
||||
{% endif %}
|
||||
</thead>
|
||||
<tbody>
|
||||
{% if per_page %}
|
||||
{% paginate per_page documents %}
|
||||
{% else%}
|
||||
{% 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>{{document.created_by}}</td>
|
||||
<td class="actions">
|
||||
<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>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{% ifequal documents|length 0 %}
|
||||
<h6 class="text-center">No Documents Found</h6>
|
||||
{% endifequal %}
|
||||
<div class="text-center row marl">
|
||||
{% show_pages %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<br clear="all">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- filter_row ends here -->
|
||||
<!-- accounts list start -->
|
||||
|
||||
<!-- accounts list end -->
|
||||
</div>
|
||||
<!-- main_container ends here -->
|
||||
{% endblock %}
|
||||
{% block js_block %}
|
||||
<script type="text/javascript">
|
||||
$('.trash').click(function(e){
|
||||
$('.remove_document').click(function(e){
|
||||
e.preventDefault()
|
||||
url = $(this).attr('href')
|
||||
if (!confirm('Are you sure you want to delete?'))
|
||||
|
|
@ -105,10 +115,14 @@
|
|||
window.location = $(this).attr('href')
|
||||
});
|
||||
|
||||
$(".reset").click(function(e){
|
||||
window.location = "{% url 'common:doc_list'%}"
|
||||
});
|
||||
|
||||
$("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 %}
|
||||
|
|
@ -359,4 +359,4 @@ def download_document(request, pk):
|
|||
response = HttpResponse(fh.read(), content_type="application/vnd.ms-excel")
|
||||
response['Content-Disposition'] = 'inline; filename=' + os.path.basename(file_path)
|
||||
return response
|
||||
raise Http404
|
||||
raise Http404
|
||||
|
|
@ -30,18 +30,6 @@ class ContactForm(forms.ModelForm):
|
|||
'assigned_to', 'teams', 'first_name', 'last_name', 'account', 'email', 'phone', 'address', 'description'
|
||||
)
|
||||
|
||||
def clean_phone(self):
|
||||
client_phone = self.cleaned_data.get('phone', None)
|
||||
try:
|
||||
if int(client_phone) and not client_phone.isalpha():
|
||||
ph_length = str(client_phone)
|
||||
if len(ph_length) < 10 or len(ph_length) > 13:
|
||||
raise forms.ValidationError('Phone number must be minimum 10 Digits and maximum of 13 Digits')
|
||||
except (ValueError):
|
||||
raise forms.ValidationError('Phone Number should contain only Numbers')
|
||||
return client_phone
|
||||
|
||||
|
||||
|
||||
|
||||
class ContactCommentForm(forms.ModelForm):
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
{% extends 'base.html' %}
|
||||
{% load staticfiles %}
|
||||
|
||||
{% block breadcrumb %}
|
||||
<nav aria-label="breadcrumb">
|
||||
<ol class="breadcrumb">
|
||||
|
|
@ -203,12 +204,22 @@
|
|||
<!-- CONTACTS VIEW ENDS -->
|
||||
{% endblock%}
|
||||
{% block js_block %}
|
||||
<script type="text/javascript">
|
||||
<script type="text/javascript">
|
||||
|
||||
function resetForm() {
|
||||
$('#CommentEditError').hide()
|
||||
document.getElementById("CommentEditError").reset();
|
||||
}
|
||||
var assigned_to_list = "{{ assigned_data }}";
|
||||
assigned_to_list = JSON.parse(assigned_to_list.replace(/&(l|g|quo)t;/g, function(a,b){
|
||||
return {
|
||||
l : '<',
|
||||
g : '>',
|
||||
quo : '"'
|
||||
}[b];
|
||||
}));
|
||||
|
||||
|
||||
function resetForm() {
|
||||
$('#CommentEditError').hide()
|
||||
document.getElementById("CommentEditError").reset();
|
||||
}
|
||||
|
||||
$("#comment_form").submit(function (e) {
|
||||
e.preventDefault()
|
||||
|
|
@ -306,10 +317,8 @@ $("#attachment_form").submit(function (e) {
|
|||
contentType: false,
|
||||
processData: false,
|
||||
success: function (data) {
|
||||
alert("Attachment Saved")
|
||||
if (data.error) {
|
||||
$("#AttachmentError").html(data.error).show()
|
||||
alert("Attachment Saved")
|
||||
} else {
|
||||
$("#attachment_div").prepend(
|
||||
"<li class='list-group-item list-row' id='attachment" + data.attachment_id + "'>" +
|
||||
|
|
@ -348,4 +357,6 @@ function remove_attachment(x) {
|
|||
});
|
||||
|
||||
</script>
|
||||
<script src="{% static 'js/mention.js' %}"></script>
|
||||
|
||||
{% endblock js_block %}
|
||||
|
|
@ -1,3 +1,4 @@
|
|||
import json
|
||||
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||
from django.contrib.sites.shortcuts import get_current_site
|
||||
from django.core.mail import EmailMessage
|
||||
|
|
@ -144,8 +145,17 @@ class ContactDetailView(LoginRequiredMixin, DetailView):
|
|||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super(ContactDetailView, self).get_context_data(**kwargs)
|
||||
|
||||
assigned_data = []
|
||||
for each in context['contact_record'].assigned_to.all():
|
||||
assigned_dict = {}
|
||||
assigned_dict['id'] = each.id
|
||||
assigned_dict['name'] = each.email
|
||||
assigned_data.append(assigned_dict)
|
||||
|
||||
context.update({"comments": context["contact_record"].contact_comments.all(),
|
||||
'attachments':context["contact_record"].contact_attachment.all()
|
||||
'attachments':context["contact_record"].contact_attachment.all(),
|
||||
"assigned_data": json.dumps(assigned_data)
|
||||
})
|
||||
return context
|
||||
|
||||
|
|
|
|||
|
|
@ -37,17 +37,6 @@ class LeadForm(forms.ModelForm):
|
|||
'phone', 'email', 'status', 'source', 'website', 'address', 'description'
|
||||
)
|
||||
|
||||
def clean_phone(self):
|
||||
client_phone = self.cleaned_data.get('phone', None)
|
||||
try:
|
||||
if int(client_phone) and not client_phone.isalpha():
|
||||
ph_length = str(client_phone)
|
||||
if len(ph_length) < 10 or len(ph_length) > 13:
|
||||
raise forms.ValidationError('Phone number must be minimum 10 Digits and maximum of 13 Digits')
|
||||
except (ValueError):
|
||||
raise forms.ValidationError('Phone Number should contain only Numbers')
|
||||
return client_phone
|
||||
|
||||
|
||||
|
||||
class LeadCommentForm(forms.ModelForm):
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@
|
|||
</nav>
|
||||
|
||||
{%endblock%}
|
||||
|
||||
{% block content %}
|
||||
<div class="main_container" id="maincontainer">
|
||||
<div class="overview_form_block row marl justify-content-center">
|
||||
|
|
@ -241,6 +242,16 @@
|
|||
<script src="{% static 'js/calls.js' %}"></script>
|
||||
<script src="{% static 'js/meetings.js' %}"></script>
|
||||
<script type="text/javascript">
|
||||
|
||||
var assigned_to_list = "{{ assigned_data }}";
|
||||
assigned_to_list = JSON.parse(assigned_to_list.replace(/&(l|g|quo)t;/g, function(a,b){
|
||||
return {
|
||||
l : '<',
|
||||
g : '>',
|
||||
quo : '"'
|
||||
}[b];
|
||||
}));
|
||||
|
||||
function resetForm() {
|
||||
$('#CommentEditError').hide()
|
||||
document.getElementById("CommentEditError").reset();
|
||||
|
|
@ -341,10 +352,8 @@ $("#attachment_form").submit(function (e) {
|
|||
contentType: false,
|
||||
processData: false,
|
||||
success: function (data) {
|
||||
alert("Attachment Saved")
|
||||
if (data.error) {
|
||||
$("#AttachmentError").html(data.error).show()
|
||||
alert("Attachment Saved")
|
||||
} else {
|
||||
$("#attachment_div").prepend(
|
||||
"<li class='list-group-item list-row' id='attachment" + data.attachment_id + "'>" +
|
||||
|
|
@ -378,4 +387,6 @@ function remove_attachment(x) {
|
|||
}
|
||||
|
||||
</script>
|
||||
<script src="{% static 'js/mention.js' %}"></script>
|
||||
|
||||
{% endblock js_block %}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
import json
|
||||
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||
from django.contrib.sites.shortcuts import get_current_site
|
||||
from django.core.mail import EmailMessage
|
||||
|
|
@ -177,9 +178,18 @@ class LeadDetailView(LoginRequiredMixin, DetailView):
|
|||
'form-INITIAL_FORMS': '0',
|
||||
'form-MAX_NUM_FORMS': '10',
|
||||
})
|
||||
|
||||
assigned_data = []
|
||||
for each in context['lead_record'].assigned_to.all():
|
||||
assigned_dict = {}
|
||||
assigned_dict['id'] = each.id
|
||||
assigned_dict['name'] = each.email
|
||||
assigned_data.append(assigned_dict)
|
||||
|
||||
context.update({
|
||||
"attachments": attachments, "comments": comments, "status": LEAD_STATUS, "countries": COUNTRIES,
|
||||
"reminder_form_set": reminder_form_set, "meetings": meetings, "calls": calls})
|
||||
"reminder_form_set": reminder_form_set, "meetings": meetings, "calls": calls,
|
||||
"assigned_data": json.dumps(assigned_data)})
|
||||
return context
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@
|
|||
</nav>
|
||||
<!-- Breadcrumb Ends Here -->
|
||||
{% endblock%}
|
||||
|
||||
{% block content%}
|
||||
<!-- OPPORTUNITY VIEW STARTS -->
|
||||
<div class="main_container" id="maincontainer">
|
||||
|
|
@ -235,6 +236,16 @@
|
|||
{% endblock %}
|
||||
{% block js_block %}
|
||||
<script type="text/javascript">
|
||||
|
||||
var assigned_to_list = "{{ assigned_data }}";
|
||||
assigned_to_list = JSON.parse(assigned_to_list.replace(/&(l|g|quo)t;/g, function(a,b){
|
||||
return {
|
||||
l : '<',
|
||||
g : '>',
|
||||
quo : '"'
|
||||
}[b];
|
||||
}));
|
||||
|
||||
$(function () {
|
||||
$('#datetimepicker1').datetimepicker({
|
||||
'format': 'YYYY-MM-DD',
|
||||
|
|
@ -358,10 +369,8 @@ $("#attachment_form").submit(function (e) {
|
|||
contentType: false,
|
||||
processData: false,
|
||||
success: function (data) {
|
||||
alert("Attachment Saved")
|
||||
if (data.error) {
|
||||
$("#AttachmentError").html(data.error).show()
|
||||
alert("Attachment Saved")
|
||||
} else {
|
||||
$("#attachment_div").prepend(
|
||||
"<li class='list-group-item list-row' id='attachment" + data.attachment_id + "'>" +
|
||||
|
|
@ -378,5 +387,9 @@ $("#attachment_form").submit(function (e) {
|
|||
})
|
||||
});
|
||||
|
||||
|
||||
|
||||
</script>
|
||||
<script src="{% static 'js/mention.js' %}"></script>
|
||||
{% endblock js_block %}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
import json
|
||||
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||
from django.contrib.sites.shortcuts import get_current_site
|
||||
from django.core.mail import EmailMessage
|
||||
|
|
@ -143,8 +144,18 @@ class OpportunityDetailView(LoginRequiredMixin, DetailView):
|
|||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super(OpportunityDetailView, self).get_context_data(**kwargs)
|
||||
|
||||
assigned_data = []
|
||||
for each in context['opportunity_record'].assigned_to.all():
|
||||
assigned_dict = {}
|
||||
assigned_dict['id'] = each.id
|
||||
assigned_dict['name'] = each.email
|
||||
assigned_data.append(assigned_dict)
|
||||
|
||||
comments = context["opportunity_record"].opportunity_comments.all()
|
||||
context.update({"comments": comments, 'attachments': context["opportunity_record"].opportunity_attachment.all()})
|
||||
context.update({
|
||||
"comments": comments, 'attachments': context["opportunity_record"].opportunity_attachment.all(),
|
||||
"assigned_data": json.dumps(assigned_data)})
|
||||
return context
|
||||
|
||||
|
||||
|
|
|
|||
70
static/css/mention.scss
Normal file
70
static/css/mention.scss
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
.mention-wrapper {
|
||||
position: relative;
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.mention-wrapper textarea { color: rgba(0, 0, 0, 0.1); }
|
||||
|
||||
.mention-display {
|
||||
color: rgba(0, 0, 0, 0.9);
|
||||
position: absolute;
|
||||
display: inline-block;
|
||||
box-sizing: border-box;
|
||||
pointer-events: none;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
top: 0px;
|
||||
left: 0px;
|
||||
border-radius: 4px;
|
||||
word-break: break-word;
|
||||
-moz-appearance: textfield-multiline;
|
||||
-webkit-appearance: textarea;
|
||||
font: medium -moz-fixed;
|
||||
font: -webkit-small-control;
|
||||
border: 3px solid transparent;
|
||||
padding: 10px;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.mention-options {
|
||||
position: absolute;
|
||||
pointer-events: none;
|
||||
opacity: 0;
|
||||
color: rgba(0, 0, 0, 0.9);
|
||||
width: 100%;
|
||||
border: 3px solid transparent;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.mention-options.show {
|
||||
pointer-events: initial;
|
||||
opacity: 1;
|
||||
z-index: 9999;
|
||||
border: 2px solid #ddd;
|
||||
background: #ddd;
|
||||
}
|
||||
|
||||
|
||||
.mention-options .mention-option {
|
||||
padding: 5px 10px;
|
||||
background: #FFF;
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.mention-options .mention-option:hover:after, .mention-options .mention-option.active:after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
left: 0px;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: rgba(0, 0, 0, 0.1);
|
||||
pointer-events: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.mention-options .mention-option.show { display: block; }
|
||||
306
static/js/mention.js
Normal file
306
static/js/mention.js
Normal file
|
|
@ -0,0 +1,306 @@
|
|||
class Mention {
|
||||
/**
|
||||
* @class Mention
|
||||
* @classdesc Allows using a symbol to display options
|
||||
*
|
||||
* @param {Object} settings - Options to initialize the component with
|
||||
* @param {HTMLElement} settings.input - The textarea to watch {@link Component#input}
|
||||
* @param {HTMLElement} settings.optionList - Element to display options when matched {@link Component#optionList}
|
||||
* @param {Array} settings.options - Array of options. Options can have properties {@link Component#options}
|
||||
* @param {String} [settings.symbol="@"] - The symbol that initials the option list {@link Component#symbol}
|
||||
* @param {Function} [settings.match] - The function used to match options {@link Component#match}
|
||||
* @param {Function} [settings.template] - The template function outputs the innerHTML of the optionlist {@link Component#template}
|
||||
*/
|
||||
constructor(settings) {
|
||||
this.options = settings.options || []
|
||||
this.input = settings.input
|
||||
this.reverse = settings.reverse
|
||||
|
||||
this.symbol = settings.symbol || '@'
|
||||
this.cursorPosition = 0
|
||||
this.hover = 0
|
||||
this.showingOptions = false
|
||||
this.upDownStay = 0
|
||||
this.wordAtCursor = {}
|
||||
this.update = settings.update || function(){}
|
||||
this.match = settings.match || this.match
|
||||
this.template = settings.template || this.template
|
||||
this.startsWith = settings.startsWith || this.startsWith
|
||||
this.html = {
|
||||
input: undefined,
|
||||
display: undefined,
|
||||
wrapper: undefined,
|
||||
optionsList: undefined,
|
||||
options: [],
|
||||
spans: [] }
|
||||
this.setupHTML()
|
||||
this.listen()
|
||||
}
|
||||
|
||||
/**
|
||||
* Function used to match options based on the word
|
||||
* @param {String} [word] - The current word ex. @test
|
||||
* @param {String} [option] - The options being looped
|
||||
* @return {boolean} - If the word matches the option
|
||||
*/
|
||||
match(word, option) {
|
||||
var optionText = option.name || option
|
||||
return optionText.toLowerCase() == word.toLowerCase()
|
||||
}
|
||||
|
||||
/**
|
||||
* Called to see if option starts with the word
|
||||
* @param {String} [word] - The current word ex. @test
|
||||
* @param {String} [option] - The options being looped
|
||||
* @return {boolean} - If the word starts with the option
|
||||
*/
|
||||
startsWith(word, option) {
|
||||
var optionText = option.name || option
|
||||
return optionText.toLowerCase().startsWith(word.toLowerCase())
|
||||
}
|
||||
|
||||
/**
|
||||
* Function returns the template (innerHTML) that will be used for each option
|
||||
* @param {String} [option] - The options being looped
|
||||
* @return {String} - The innerHTM
|
||||
*/
|
||||
template(option) {
|
||||
return option.name || option
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets up the HTML. Wrapper, Display, OptionsList, Options
|
||||
*/
|
||||
setupHTML() {
|
||||
this.html.input = this.input
|
||||
|
||||
// Global wrapper
|
||||
this.html.wrapper = document.createElement('div')
|
||||
this.html.wrapper.classList.add('mention-wrapper')
|
||||
this.html.input.parentElement.insertBefore(this.html.wrapper, this.html.input)
|
||||
this.html.wrapper.appendChild(this.html.input)
|
||||
|
||||
// Options
|
||||
this.html.optionsList = document.createElement('div')
|
||||
this.html.optionsList.classList.add('mention-options')
|
||||
this.html.wrapper.appendChild(this.html.optionsList)
|
||||
if(this.reverse) {
|
||||
this.html.optionsList.classList.add('mention-options-reverse')
|
||||
this.html.wrapper.insertBefore(this.html.optionsList, this.html.wrapper.firstChild)
|
||||
}
|
||||
|
||||
for(var option of this.options) {
|
||||
var optionElement = document.createElement('div')
|
||||
optionElement.classList.add('mention-option')
|
||||
optionElement.innerHTML = this.template(option)
|
||||
optionElement.setAttribute('mentiondata', JSON.stringify(option))
|
||||
this.html.options.push(optionElement)
|
||||
this.html.optionsList.appendChild(optionElement)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Begins listening for events on the input and options
|
||||
*/
|
||||
listen() {
|
||||
this.html.input.addEventListener('input', () => { this.onEventInput() })
|
||||
this.html.input.addEventListener('keydown', (e) => { this.onEventKeyDown(e) })
|
||||
this.html.input.addEventListener('keyup', (e) => { this.onEventKeyUp(e) })
|
||||
this.html.options.forEach((o) => {
|
||||
o.addEventListener('click', (e) => { this.onEventOptionClick(e.target) })
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when on input.addEventListener('input')
|
||||
* @param {Event} e - the event passed
|
||||
*/
|
||||
onEventInput() {
|
||||
this.update()
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when on input.addEventListener('keyup')
|
||||
* @param {Event} e - the keyboard event passed
|
||||
*/
|
||||
onEventKeyDown(e) {
|
||||
this.upDownStay = e.keyCode == 40 ? 1 : e.keyCode == 38 ? -1 : 0
|
||||
if(this.reverse) this.upDownStay *= -1
|
||||
if(this.upDownStay && this.showingOptions) e.preventDefault()
|
||||
if(e.keyCode == 13 && this.showingOptions) {
|
||||
e.preventDefault()
|
||||
var option = this.html.options.find((e) => e.classList.contains('hover'))
|
||||
if(option) this.onEventOptionClick(option)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when on input.addEventListener('keydown')
|
||||
* @param {Event} e - the event passed
|
||||
*/
|
||||
onEventKeyUp() {
|
||||
this.cursorPositionChanged()
|
||||
this.setHoverOption()
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when option input.addEventListener('click')
|
||||
*/
|
||||
onEventOptionClick(optionEle) {
|
||||
var word = this.symbol + JSON.parse(optionEle.getAttribute('mentiondata')).name + ' '
|
||||
var splitInputValue = this.html.input.value.split('')
|
||||
splitInputValue.splice(this.wordAtCursor.index, this.wordAtCursor.word.length, word)
|
||||
this.html.input.value = splitInputValue.join('')
|
||||
this.html.input.focus()
|
||||
this.setCursorPosition(this.wordAtCursor.index + word.length + 1)
|
||||
this.toggleOptionList(false)
|
||||
this.update()
|
||||
}
|
||||
|
||||
/**
|
||||
* Cursor position changed. Check for input data and toggle options
|
||||
*/
|
||||
cursorPositionChanged() {
|
||||
this.cursorPosition = this.html.input.selectionStart
|
||||
this.wordAtCursor = this.readWordAtCursor({ cursorPosition: this.cursorPosition, value: this.input.value })
|
||||
this.toggleOptionList(this.wordAtCursor.word.length && this.wordAtCursor.word[0] == this.symbol)
|
||||
this.showHideOptions()
|
||||
}
|
||||
|
||||
/**
|
||||
* Show/Hide the options list
|
||||
* @param {Boolean} toggle - show or hide
|
||||
*/
|
||||
toggleOptionList(toggle) {
|
||||
this.html.optionsList.classList.remove('show')
|
||||
if(toggle) this.html.optionsList.classList.add('show')
|
||||
this.showingOptions = toggle
|
||||
}
|
||||
|
||||
/**
|
||||
* Loop the options and show/hide options based on match function
|
||||
*/
|
||||
showHideOptions() {
|
||||
for(var option in this.options) {
|
||||
var word = this.wordAtCursor.word.replace(this.symbol, '')
|
||||
this.html.options[option].classList.remove('show')
|
||||
if(this.startsWith(word, this.options[option])) this.html.options[option].classList.add('show')
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Using up/down arrow selects the next option
|
||||
*/
|
||||
setHoverOption() {
|
||||
var viewableOptions = this.html.options.filter((e) => {
|
||||
e.classList.remove('hover')
|
||||
return e.classList.contains('show')
|
||||
})
|
||||
if(!viewableOptions.length){
|
||||
this.toggleOptionList(false)
|
||||
return
|
||||
}
|
||||
|
||||
this.hover = this.upDownStay ? this.hover + this.upDownStay : 0
|
||||
if(this.hover < 0){ this.hover = viewableOptions.length - 1 }
|
||||
if(this.hover == viewableOptions.length) { this.hover = 0}
|
||||
viewableOptions[this.hover].classList.add('hover')
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the cursor position in the text area
|
||||
* @param {Number} position - the position
|
||||
*/
|
||||
setCursorPosition(position) {
|
||||
this.cursorPosition = position
|
||||
this.html.input.setSelectionRange(position, position);
|
||||
}
|
||||
|
||||
/**
|
||||
* From the cursor positoin looks back to match the work and start/end position
|
||||
* @param {Object} data - Options to initialize the component with
|
||||
* @param {String} [data.value] - the string to search through
|
||||
* @param {Number} [data.cursorPosition] - The position of the cursor in the string
|
||||
*/
|
||||
readWordAtCursor(data) {
|
||||
var word = '', index = data.cursorPosition
|
||||
var valueWithReplacedSpecial = data.value.replace(/\n/g, ' ');
|
||||
|
||||
while(index--){
|
||||
var previousCharacter = valueWithReplacedSpecial[index]
|
||||
if(previousCharacter == ' ' || index < 0) break
|
||||
}
|
||||
|
||||
while(index++ < valueWithReplacedSpecial.length-1) {
|
||||
var nextCharacter = valueWithReplacedSpecial[index]
|
||||
if(nextCharacter == ' ') break
|
||||
word += nextCharacter
|
||||
}
|
||||
|
||||
return { index: Math.max(index-word.length, 0), word: word }
|
||||
}
|
||||
|
||||
/**
|
||||
* Loops over the input value.
|
||||
* @return {matches[]} - Array of matches { word: word, index: index word is at}
|
||||
*/
|
||||
findMatches() {
|
||||
var inputValue = this.html.input.value.split('').concat([' '])
|
||||
var words = []
|
||||
|
||||
var currentWord = ''
|
||||
for(var index in inputValue) {
|
||||
var letter = inputValue[index]
|
||||
var lastLetter = inputValue[index-1] || ' '
|
||||
var lastLetterIsSpace = [' ', '\\n'].indexOf(lastLetter) > -1 || lastLetter.charCodeAt(0) == 10
|
||||
var canStartWord = letter == this.symbol && lastLetterIsSpace
|
||||
|
||||
if((canStartWord || currentWord.length) && letter != ' ') currentWord += letter
|
||||
|
||||
if(currentWord.length && letter == ' '){
|
||||
words.push({ word: currentWord, index: Math.max(index-currentWord.length, 0) })
|
||||
currentWord = ''
|
||||
}
|
||||
}
|
||||
|
||||
return words;
|
||||
}
|
||||
|
||||
/**
|
||||
* Collects all the real matches
|
||||
*/
|
||||
collect() {
|
||||
return this.findMatches().filter((word) => {
|
||||
return this.options.some((option) => {
|
||||
return this.match(word.word.replace(this.symbol, ''), option)
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
if(typeof module != 'undefined') module.exports = Mention
|
||||
|
||||
|
||||
var myMention = new Mention({
|
||||
input: document.querySelector('#id_comments'),
|
||||
options: assigned_to_list,
|
||||
|
||||
|
||||
template: function(option) {
|
||||
return '@' + option.name
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
var myMention = new Mention({
|
||||
input: document.querySelector('#id_editcomment'),
|
||||
options: assigned_to_list,
|
||||
|
||||
// match: function(word, option) {
|
||||
// return option.name.startsWith(word)
|
||||
// || option.description.toLowerCase().indexOf(word.toLowerCase()) >= 0
|
||||
// },
|
||||
template: function(option) {
|
||||
return '@' + option.name
|
||||
}
|
||||
})
|
||||
|
|
@ -14,6 +14,8 @@
|
|||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datetimepicker/4.17.47/css/bootstrap-datetimepicker.min.css" />
|
||||
{% compress css %}
|
||||
<link href="{% static 'css/main.scss' %}" type="text/x-scss" rel="stylesheet">
|
||||
<link href="{% static 'css/mention.scss' %}" type="text/x-scss" rel="stylesheet">
|
||||
|
||||
{% endcompress %}
|
||||
{% block extralinks %} {% endblock %}
|
||||
</head>
|
||||
|
|
|
|||
Loading…
Reference in a new issue