I'm creating a site for emails, where a user upon clicking a mailbox (inbox, sent, archived) I will show them all the emails that belong to said mailbox.
Now my problem is the layout, the borders of each email are not displaying the way I want. This is how it should be, where the email with gray background is a read one, while white is not:
This is what code turns up:
I want them separated but I can't get it to work. Help would be appreciated!
inbox.js:
function load_mailbox(mailbox) {
// Show the mailbox and hide other views
document.querySelector('#emails-view').style.display = 'block';
document.querySelector('#compose-view').style.display = 'none';
// Show the mailbox name
document.querySelector('#emails-view').innerHTML = `<h3>${mailbox.charAt(0).toUpperCase() + mailbox.slice(1)}</h3>`;
//get me all the emails in inbox(example)
fetch(`/emails/${mailbox}`)
.then(response => response.json())
.then(emails => {
//for each email
emails.forEach(myFunction);
function myFunction(item) {
//create a new div htmlelement
const element = document.createElement('div');
//give it a class in case i need it
element.setAttribute("class", "email-dv")
//add info to this div
element.innerHTML += item.sender + "<br>";
element.innerHTML += item.subject + "<br>";
element.innerHTML += item.timestamp + "<br>";
//create the borders for the div
//issue here, it is not creating a rectangle for each div
element.style.boder = "groove";
//if email is not read
if (item.read === false) {
element.style.backgroundColor = "white";
}
else {
element.style.backgroundColor = "grey";
}
element.addEventListener('click', function() {
console.log('This element has been clicked!')
});
//add it to the main div for all emails
document.querySelector('#emails-view').append(element);
}
});
inbox.html :
{% extends "mail/layout.html" %}
{% load static %}
{% block body %}
<h2>{{ request.user.email }}</h2>
<button class="btn btn-sm btn-outline-primary" id="inbox">Inbox</button>
<button class="btn btn-sm btn-outline-primary" id="compose">Compose</button>
<button class="btn btn-sm btn-outline-primary" id="sent">Sent</button>
<button class="btn btn-sm btn-outline-primary" id="archived">Archived</button>
<a class="btn btn-sm btn-outline-primary" href="{% url 'logout' %}">Log Out</a>
<hr>
<div id="emails-view" >
</div>
<div id="compose-view">
<h3 id="h">New Email</h3>
<form id="compose-form">
<div class="form-group">
From: <input disabled class="form-control" value="{{ request.user.email }}">
</div>
<div class="form-group">
To: <input id="compose-recipients" class="form-control">
</div>
<div class="form-group">
<input class="form-control" id="compose-subject" placeholder="Subject">
</div>
<textarea class="form-control" id="compose-body" placeholder="Body"></textarea>
<input type="submit" class="btn btn-primary" id="submit-button"/>
</form>
</div>
{% endblock %}
{% block script %}
<script src="{% static 'mail/inbox.js' %}"></script>
{% endblock %}
Well, first of all you have a typo:
element.style.boder you're missing the "r" in border. Can you check that first?
Related
I have this error
invalid literal for int() with base 10: '" + key + "'
I generate the
session['Exit'] is a dictionary inside a dictionary
DictItems = {index:{'foo':foo.foo, ...}}
where index is a int
generated like this
numkey = len(session['Exit'])
ind = int(numkey) + 1
index = str(ind)
The code I was trying to create is
<div class="container-fluid">
<div class="row">
<table class='table table-responsive table-sm w-auto small'>
<tbody>
<div class="col-xs-2">
{% for key, items in session['Exit'].items() %}
{% if key %}
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#new_value" data-key="{{key}}" data-price="{{items.price}}" onclick="updateModal(this)">
{{items.price}}
</button>
{% endif %}
{% endfor %}
</div>
</tbody>
</table>
</div>
</div>
<!--Modal -->
<div class="modal fade" id="new_value" tabindex="-1" role="dialog" aria-labelledby="exampleModalCenterTitle" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLongTitle">New_Value</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<form id="modal-form" action="" method='POST' >
<div class="modal-body">
<p id="modal-text"></p>
<input class="form-control" name="new_value" step="any" required>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
<button class="btn btn-primary" type="submit">Change</button>
</form>
</div>
</div>
</div>
</div>
<!---Modal -->
{% if session['Exit'] %}
<script>
function updateModal(element) {
var key = element.dataset.key;
var price = element.dataset.price;
var form = document.getElementById("modal-form");
form.action = "{{url_for('salidas.change_price', key=" + key + ")}}";
document.getElementById("modal-text").innerHTML = "you are going to change the value $" + price + ", are you sure?";
document.getElementsByName("new_value")[0].value = price;
}
</script>
{% endif %}
I imagine that it coud be because the session['Exit'] could be empty, so i tried a {% if session['Exit'] %} but stop working when session has elements and gives the error
still if session session['Exit'] doesnt exist it shouldnt render
in other: i tried to make the key int
data-key="{{key|int}}
also in the script
var key = parseInt(element.dataset.key);
and in the key
+ parseInt(key) +
still in the url_for because is a string shouldnt give me a problem
so i tried to make the url like this in a triple level
form.action = "\"{{url_for('salidas.change_price', key=" + key + ")}}\"";
i still have the same problem
any idea what else could i try?
EDIT: the solution
basically as Detlef said
"doesn't know about the javascript variable key"
the reason escapes my understanding, because this string
document.getElementById("modal-text").innerHTML
works
so what i did is in the button that calls the data-key, renamed it to data-url and generated the url_for
and from there i just called it, leaving something like this
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#new_value" data-url="{{url_for('salidas.change_price', code=key)}}" data-price="{{items.price}}" onclick="updateModal(this)">
{{items.price}}
</button>
and the javascript
<script>
function updateModal(element) {
var url = element.dataset.url;
var price = element.dataset.price;
var form = document.getElementById("modal-form");
form.action = url;
document.getElementById("modal-text").innerHTML = "you are going to change the value $" + price + ", are you sure?";
document.getElementsByName("new_value")[0].value = price;
}
So idea is Id like the user to click a button, have the page submit through the post method which will populate fields for a form, then return the page with a modal displayed. I have this working, except the issue is that the page is at the top even if the user clicked halfway down. Id like the page to redisplay where it was, with the modal displaying.
I know that there is a fragment parameter, but only for redirecttopage and not page()? Sending it back to get resets everything, so thats not realy ideal. Ive also tried altering the url with javascript which works with setting the page position, but somehow it will not display the modal with that?
Does anyone know how to easily return the page in the post method to a specific spot on the page?
Javascript: (Modal shows up for one second then disappers when it goes to the page position)
function OnLoad() { //Used for redisplaying on error purposes
if ("#TempData["EditingParty"]" == "Yes") {
var loadedURL = window.location.href;
var fragmentPieceOfURL = "#TempData["EndOfURL"]"
location.href = loadedURL + fragmentPieceOfURL;
document.getElementById("EditUsersForm").style.display = "inline-block";
}
else {
document.getElementById("EditUsersForm").style.display = "none";
}
}
Cshtml
Button that goes to post (i is counter to keep track of anchor tag for redisplay location):
<a id="#i"></a>
<button type="submit" style="white-space:nowrap" class="btn btn-secondary btn-sm" formnovalidate asp-page-handler="DisplayEdit" asp-route-id="#Model.UsersOnCaseList.ElementAtOrDefault(i).UserID" asp-route-AttorneyRole="#Model.UsersOnCaseList.ElementAtOrDefault(i).AttorneyRole" asp-route-email="#Model.UsersOnCaseList.ElementAtOrDefault(i).EmailAddress" asp-route-pAttorneyRoleID="#Model.UsersOnCaseList.ElementAtOrDefault(i).AttorneyRoleID" asp-route-PageFragment="#i" asp-route-pEditAttorneyUserID="#Model.UsersOnCaseList.ElementAtOrDefault(i).UserID">Edit <i class="fas fa-ribbon"></i></button>
Modal:
<div class="modal" tabindex="-1" role="dialog" id="EditUsersForm" style="display:none">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Edit User</h5>
<button type="button" onclick="closeEditUsersForm()" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="form-group" style="margin-top:15px;padding-left:15px">
<label asp-for="EditUserEmailInput"></label> <span class="red">*</span>
<input asp-for="EditUserEmailInput" class="form-control" id="EmailInputBox" value="#Model.EditUserEmailInput" style="display:block;width:25em" />
<span style="display:block" asp-validation-for="EditUserEmailInput" class="text-danger" id="AddUserInputValidation"></span>
</div>
<div class="form-group" style="margin-top:15px;padding-left:15px">
<label class="control-label">Role</label> <span class="red">*</span>
<select asp-for="AttorneyRoleIDEditForm" asp-items="#(new SelectList(Model.AttorneyRolesList, "AttorneyRoleID","AttorneyRole"))" name="AttorneyRoleIDEditForm" id="SelectAttorneyRoleIDEditForm" class="form-control" style="width:25em" onchange="DidSelectPlaintiffEdit()">
<option class="form-control" value=-1>Select a Role</option>
</select>
<span asp-validation-for="AttorneyRoleIDEditForm" class="text-danger"></span>
</div>
<div class="form-group" style="margin-top:15px;padding-left:15px">
<label asp-for="EditUserPartyInput"></label> <span class="red">*</span><br />
<input asp-for="EditUserPartyInput" value="#Model.EditUserPartyInput" class="form-control" id="PartyNameInputEdit" style="display:inline-block;width:25em" />
<span style="display:block" asp-validation-for="EditUserPartyInput" class="text-danger" id="PartyNameInputValidation"></span>
</div>
<div class="modal-footer">
<button class="btn btn-primary" style="margin:0 auto" asp-page-handler="SaveUserEdits" asp-route-UserBeingEdited="" id="EditSubmitButton" name="EditUserSubmit" value="Yes">Submit</button>
<button class="btn btn-primary" style="margin:0 auto; display:none" asp-page-handler="SaveUserEdits" disabled id="SubmitButtonDisabled" name="AddUserSubmit" value="Yes">Submit</button>
</div>
</div>
</div>
</div>
CS file:
public IActionResult OnPostDisplayEdit(int id, string email,string AttorneyRole,int pAttorneyRoleID,int pAttorney,int pEditAttorneyUserID,int PageFragment)
{
EditUserEmailInput = email;
string curDictionaryAttorneyRole;
if (AttorneyRole.Contains('('))//Just because in development user didnt always have ability to enter a party
{
curDictionaryAttorneyRole = AttorneyRole.Split(new[] { '(' }, 2)[0].Trim();
EditUserPartyInput = AttorneyRole.Split(new[] { '(' }, 2)[1];
var LastRightParenIndex = EditUserPartyInput.LastIndexOf(')');
EditUserPartyInput = EditUserPartyInput.Substring(0, LastRightParenIndex); //Pulling the right parenthesis out
}
else //Its just the dictionary role
{
curDictionaryAttorneyRole = AttorneyRole;
EditUserPartyInput = null;
}
TempData["EditingParty"] = "Yes";
TempData["EndOfURL"] = PageFragment.ToString() + "&#" + PageFragment.ToString();
SetFileSequenceField();
ModelState.Clear(); //Used to remove the validations
SetAttorneyRoleList();
var selectedIndex = AttorneyRolesList.Where(arl => arl.AttorneyRole == curDictionaryAttorneyRole).Select(arl => arl.AttorneyRoleID).FirstOrDefault();
AttorneyRoleIDEditForm = selectedIndex;
EditAttorneyUserID = pEditAttorneyUserID;
UneditedEmail = email;
UneditedAttorneyRoleID = pAttorneyRoleID;
PopulateUserList();
//return RedirectToPage("AddUsersToCase","GET",fragment:PageFragment.ToString());
return Page();
//var PageURL = Page();
//PageURL = PageURL. + "&#" + PageFragment.ToString();
//return PageURL;
}
You can try to replace
location.href = loadedURL + fragmentPieceOfURL;
to
history.pushState({}, null, loadedURL + fragmentPieceOfURL);
So that the page will not be refreshed with location.href.
Hi there I am fairly new to django and need to add dynamic formsets with autocomplete functions for every from. I am not entirely sure what I am doing wrong i have tried a few approaches and this is my most recent!
I have function called AutoproductComplete which receives the id of the current formset form input that i want to add the auto complete to. It doesnt work, no errors, not sure why. I also did it after the after method so assume the form has been added to the DOM?'
'html'
<form class="form-horizontal" method="POST" action="">
{% csrf_token %}
{{ formset.management_form }}
{% for form in formset %}
<div class="row form-row spacer">
<div class="input-group" style="padding:5px;">
{{form.productName}}
{{form.orderQuantity}}
<div class="input-group-append">
<button class="btn btn-success add-form-row"
style="margin:5px;">+</button>
</div>
</div>
</div>
{% endfor %}
<br>
<div class="row spacer">
<div class="col-12 offset-9">
<button type="submit" class="btn btn-block btn-
dark">Create Order</button>
</div>
</div>
</form>
JavaScript
'''
function AutoproductComplete(id){
const products = [];
console.log("This is working")
console.log(id)
{% for instance in products %}
products.push("{{instance.product_name}}")
{% endfor %}
$(id).autocomplete({
classes: {"ui-autocomplete-input": "highlight"},
source: products,
minLength: 1,
});
};
AutoproductComplete("id_form-0-productName" )
function cloneMore(selector, prefix) {
var newElement = $(selector).clone(true);
var id = ""
var total = $('#id_' + prefix + '-TOTAL_FORMS').val();
`enter code here`newElement.find(
':input:not([type=button]):not([type=submit]):not([type=reset])')
.each(function() {
if ($(this).attr('name')){
var name = $(this).attr('name').replace('-' + (total-1) + '-', '-
' + total + '-');
id = 'id_' + name;
$(this).attr({'name': name, 'id':
id}).val('').removeAttr('checked');
}
});
total++;
$('#id_' + prefix + '-TOTAL_FORMS').val(total);
$(selector).after(newElement);
var conditionRow = $('.form-row:not(:last)');
conditionRow.find('.btn.add-form-row')
.removeClass('btn-success').addClass('btn-danger')
.removeClass('add-form-row').addClass('remove-form-row')
.html('<span class="glyphicon glyphicon-minus" aria-hidden="true" > -
</span>')
AutoproductComplete(id)
return false;
}
$(document).on('click', '.add-form-row', function(e){
e.preventDefault();
cloneMore('.form-row:last', 'form');
return false;
});
'''
You can use DAL
django-autocomplete-light
As it says, its quite lightweight and IMHO easily and highly configurable.
You can find the docs here:
https://django-autocomplete-light.readthedocs.io/en/master/
I am trying to run a function called send mail but it doesn't run at all because the response is supposed to be 201 when it runs but django returns a 200 response like it isn't there. I tried running the function directly in my console and it worked fine so the backend is working as excpected.
Here is the JS code:
document.addEventListener('DOMContentLoaded', function() {
// Use buttons to toggle between views
document.querySelector('#inbox').addEventListener('click', () => load_mailbox('inbox'));
document.querySelector('#sent').addEventListener('click', () => load_mailbox('sent'));
document.querySelector('#archived').addEventListener('click', () => load_mailbox('archive'));
document.querySelector('#compose').addEventListener('click', compose_email);
document.querySelector('#compose-form').addEventListener('submit',send_mail);
// By default, load the inbox
load_mailbox('inbox');
});
function compose_email() {
// Show compose view and hide other views
document.querySelector('#emails-view').style.display = 'none';
document.querySelector('#compose-view').style.display = 'block';
// Clear out composition fields
document.querySelector('#compose-recipients').value = '';
document.querySelector('#compose-subject').value = '';
document.querySelector('#compose-body').value = '';
}
function load_mailbox(mailbox) {
// Show the mailbox and hide other views
document.querySelector('#emails-view').style.display = 'block';
document.querySelector('#compose-view').style.display = 'none';
// Show the mailbox name
document.querySelector('#emails-view').innerHTML = `<h3>${mailbox.charAt(0).toUpperCase() + mailbox.slice(1)}</h3>`;
fetch(`/emails/${mailbox}`)
.then(response => response.json())
.then(emails => {
// Print emails
console.log(emails);
// ... do something else with emails ...
});
}
function send_mail(){
fetch('/emails/', {
method: 'POST',
body: JSON.stringify({
recipients: document.querySelector('#compose-recipients').value,
subject: document.querySelector('#compose-subject').value,
body: document.querySelector('#compose-body').value
})
})
.then(response => response.json())
.then(result => {
// Print result
console.log(result);
});
}
Here is the HTML
{% extends "mail/layout.html" %}
{% load static %}
{% block body %}
<h2>{{ request.user.email }}</h2>
<button class="btn btn-sm btn-outline-primary" id="inbox">Inbox</button>
<button class="btn btn-sm btn-outline-primary" id="compose">Compose</button>
<button class="btn btn-sm btn-outline-primary" id="sent">Sent</button>
<button class="btn btn-sm btn-outline-primary" id="archived">Archived</button>
<a class="btn btn-sm btn-outline-primary" href="{% url 'logout' %}">Log Out</a>
<hr>
<div id="emails-view">
</div>
<div id="compose-view">
<h3>New Email</h3>
<form id="compose-form">
<div class="form-group">
From: <input disabled class="form-control" value="{{ request.user.email }}">
</div>
<div class="form-group">
To: <input id="compose-recipients" class="form-control">
</div>
<div class="form-group">
<input class="form-control" id="compose-subject" placeholder="Subject">
</div>
<textarea class="form-control" id="compose-body" placeholder="Body"></textarea>
<input type="submit" class="btn btn-primary"/>
</form>
</div>
{% endblock %}
{% block script %}
<script src="{% static 'mail/inbox.js' %}"></script>
{% endblock %}
Here the Documentation for the django API:
To send an email, you can send a POST request to the /emails route. The route requires three pieces of data to be submitted: a recipients value (a comma-separated string of all users to send an email to), a subject string, and a body string. For example, you could write JavaScript code like
fetch('/emails', {
method: 'POST',
body: JSON.stringify({
recipients: 'baz#example.com',
subject: 'Meeting time',
body: 'How about we meet tomorrow at 3pm?'
})
})
.then(response => response.json())
.then(result => {
// Print result
console.log(result);
});
If the email is sent successfully, the route will respond with a 201 status code and a JSON response of {"message": "Email sent successfully."}.
Following is the code of my table. In the action column i have a buttons named accept and reject. On click on reject I want to get the values of 2 and 3 "td" present in that "tr".
<table class="w3-table" id="tbl_task" width="100%">
<tr>
{% for ele in d|slice:":1" %} {% for key in ele.keys %}
<th>{{ key }}</th>
{% endfor %} {% endfor %}
<th>Action</th>
</tr>
{% for ele in d %}
<tr class="class_1">
{% for k, v in ele.iteritems %} {% if k in "Assigned_Users" %}
<td>
{% if v|length > 2 %}
<div style="width: 80%;max-height: 37px;overflow:auto;margin-left: 32px;">
{% for ch in v %} {{ ch|linebreaksbr }} {% endfor %}
</div>
{% else %} {% for ch in v %} {{ ch }} {% endfor %} {% endif %}
</td>
{% else %}
<td>
{{ v }}
</td>
{% endif %} {% endfor %}
<td class="noexcel">
<div id="td_button_div">
<button id="status_accepted" class="btn btn-default btn-sm" name="accept">
<span class="glyphicon glyphicon-ok"></span> Approve
</button>
<button id="status_rejected" class="btn btn-default btn-sm" name="reject" data-toggle="modal" data-target="#myModal">
<span class="glyphicon glyphicon-remove"></span> Reject
</button>
<!-- Modal -->
<div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
<h4 class="modal-title" id="myModalLabel">Modal title
</h4>
</div>
<div class="modal-body">
<label>Remarks</label>
<textarea name="textarea" style="color:black;width:100%"></textarea>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close
</button>
<button type="button" class="btn btn-primary" id="save_remarks">Save changes
</button>
</div>
</div>
</div>
</div>
</div>
</td>
</tr>
{% endfor %}
At first time I am getting data properly but at second click only modal is displayed with the existing values.
Following is my JQuery code:
$('#status_rejected').on('click', function(e){
var current_row = ' ';
var task_name = ' ';
var current_status = ' ';
var notes = ' ';
alert("inside reject function");
current_row = $(this).closest('tr');
task_name = current_row.find("td:eq(2)").text();
current_status = current_row.find("td:eq(0)").text();
alert("cstatus--->"+$.trim(current_status)+"\n"+"tname"+$.trim(task_name));
var status = "reject"
$("textarea").val(" ");
$("#save_remarks").on('click',function(){
alert("inside save changes on click");
notes = $.trim($("textarea").val());
alert("cstatus"+$.trim(current_status)+"\n"+"tname"+$.trim(task_name));
});
});// end of show model
Need help with this?
I was able resolve this in the following way:
$('.noexcel #status_rejected').on('click', function(e){
var current_row = ' ';
var task_name = ' ';
var current_status = ' ';
var notes = ' ';
var cnt = 0;
current_row = $(this).closest('tr');
task_name = current_row.find("td:eq(2)").text();
current_status = current_row.find("td:eq(0)").text();
var status = "reject"
$("textarea").val(" ");
$("#save_remarks").on('click',function(){
notes = $.trim($("textarea").val());
if(current_status != ' ' && task_name != ' ' && notes != ' ' && current_row != ' '){
ajax_call(current_row, current_status, task_name, notes, status);
current_row = current_status = task_name = notes = ' ';
}
}); // end of onclick of modal save button
});// end of show model
function ajax_call(current_row, current_status, task_name, notes, status){
$.ajax({
type:'post',
url:'/ajax/change_ftrack_status/',
data:{
currentStatus : current_status,
taskName : task_name,
status : status,
notes : notes
},
success:function(data){
$.each(data, function(key, value){
if (key == "ftrack_status"){
current_row.find("td:eq(0)").html(value);
}
else if (key == "updated_on"){
current_row.find("td:eq(1)").html(value);
}
}); // end of for each
// disable the reject button
current_row.find("td #status_rejected").prop("disabled", true);
}
}); //end of ajax
}