344 lines
14 KiB
HTML
344 lines
14 KiB
HTML
|
|
{% extends 'generic/base.html' %}
|
|
|
|
|
|
{% block content %}
|
|
{% if created_users %}
|
|
<div class="alert alert-success">
|
|
The following users have been created: {{created_users}}
|
|
</div>
|
|
{% endif %}
|
|
|
|
{% if error %}
|
|
<div class="alert alert-warning">
|
|
{{error}}
|
|
</div>
|
|
{% endif %}
|
|
|
|
{% if message %}
|
|
<div class="alert alert-info">
|
|
{{message}}
|
|
</div>
|
|
{% endif %}
|
|
<p>
|
|
Prepare a spreadsheet with the following format.
|
|
|
|
<table>
|
|
|
|
<tr><th>First name</th><th>Last name</th><th>Email</th><th>Grade</th><th>Supervisor</th><th>Supervisor email</th></tr>
|
|
<tr><td>name 1</td><td>last name 1</td><td>email1@email.com</td><td>ST1</td><td>supervisor 1</td><td>Supervisor@email.com</td></tr>
|
|
<tr><td>name 2</td><td>last name 2</td><td>email2@email.com</td><td>ST2</td><td>supervisor 2</td><td>Supervisor2@email.com</td></tr>
|
|
</table>
|
|
|
|
|
|
On your spreadsheet then "copy" the data (not including header), come to this page, put focus on the <textarea> box and "paste" the text in. In some instance (large data sets) this might take a couple of seconds.
|
|
Once there simply click the button and check the users that will be created below.
|
|
|
|
</p>
|
|
<p>Please note users created this way bypass some of the validations so check details such as email addresses are correct</p>
|
|
<div class="mb-2">
|
|
<label for="input-format" class="form-label">Input format</label>
|
|
<select id="input-format" class="form-select" style="width:300px">
|
|
<option value="spreadsheet">First,Last,Email,Grade,Supervisor,SupervisorEmail (spreadsheet)</option>
|
|
<option value="name-supervisor-email-grade">User \t Educational Supervisor \t Email \t Grade</option>
|
|
</select>
|
|
</div>
|
|
|
|
<textarea id="csv" placeholder="Paste users content here" style="width: 300px; height: 100px;"></textarea><br/>
|
|
<input type="button" value="Load Data" _="on click createTable()" >
|
|
|
|
|
|
<div role="alert" id="alert" class="alert alert-info "
|
|
_="on load hide me">
|
|
|
|
</div>
|
|
|
|
|
|
<div>
|
|
<ul id="users-list">
|
|
</ul>
|
|
</div>
|
|
|
|
<form id="user-list-form" method="post">
|
|
{% csrf_token %}
|
|
<input type="text" name="usersjson" id="user-list-json" hidden>
|
|
<input type="submit" id="submit-users" name="submit-users" value="Create Users" style="display: none">
|
|
</form>
|
|
|
|
|
|
<script>
|
|
function createTable() {
|
|
|
|
// Get the data
|
|
var excelData = document.getElementById('csv').value.trim()+"\n";
|
|
|
|
// split into rows
|
|
excelRow = excelData.split(String.fromCharCode(10));
|
|
|
|
// If the first row looks like a header (contains words like 'user', 'email', 'grade', 'supervisor'), drop it
|
|
if (excelRow.length) {
|
|
var firstRowCols = excelRow[0].split(String.fromCharCode(9)).map(function(c){return c.trim().toLowerCase();});
|
|
var headerKeywords = ['user','first name','last name','email','grade','educational supervisor','supervisor','first','last'];
|
|
var isHeader = firstRowCols.some(function(c){
|
|
if (!c) return false;
|
|
if (headerKeywords.indexOf(c) !== -1) return true;
|
|
if (c.indexOf('email') !== -1) return true;
|
|
if (c.indexOf('supervisor') !== -1) return true;
|
|
return false;
|
|
});
|
|
if (isHeader) {
|
|
// remove header row
|
|
excelRow.shift();
|
|
}
|
|
}
|
|
|
|
// split rows into columns
|
|
for (i=0; i<excelRow.length; i++) {
|
|
excelRow[i] = excelRow[i].split(String.fromCharCode(9));
|
|
|
|
}
|
|
|
|
// start to create the HTML table
|
|
var myTable = document.createElement("table");
|
|
var myTbody = document.createElement("tbody");
|
|
|
|
// Loop over the rows
|
|
|
|
var format = document.getElementById('input-format').value;
|
|
var elements = ["first_name", "last_name", "email", "grade", "supervisor_name", "supervisor_email"];
|
|
|
|
// For alternate format: User\tEducational Supervisor\tEmail\tGrade
|
|
// columns: full name, supervisor name, email, grade
|
|
if (format === 'name-supervisor-email-grade') {
|
|
elements = ['full_name', 'supervisor_name', 'email', 'grade'];
|
|
}
|
|
var users = [];
|
|
|
|
$("#users-list").empty();
|
|
$("#users-list").append(`The following users will be created. "undefined" fields will be left blank. Emails will be used as usernames. Supervisors will be created automatically if required. If an incorrect grade is used the user will not be created.`);
|
|
|
|
var emails = [];
|
|
for (i=0; i<excelRow.length - 1; i++) {
|
|
//users[i] = {};
|
|
user = {};
|
|
|
|
// create a row in the HTML table
|
|
var myRow = document.createElement("tr");
|
|
|
|
// Loop over the columns and add TD to the TR
|
|
for (j=0; j<excelRow[i].length; j++) {
|
|
if (excelRow[i][j].length != 0) {
|
|
var myCell = document.createElement("td");
|
|
myCell.innerHTML = excelRow[i][j].trim();
|
|
var key = elements[j] || null;
|
|
if (key) {
|
|
user[key] = excelRow[i][j].trim();
|
|
}
|
|
}
|
|
myRow.appendChild(myCell);
|
|
}
|
|
|
|
// If alternate format, split full_name into first_name/last_name and ensure supervisor_email empty
|
|
if (format === 'name-supervisor-email-grade') {
|
|
var full = user.full_name || '';
|
|
full = full.trim();
|
|
if (full.indexOf(' ') > -1) {
|
|
var parts = full.split(/\s+/);
|
|
user.first_name = parts[0];
|
|
user.last_name = parts.slice(1).join(' ');
|
|
} else {
|
|
user.first_name = full;
|
|
user.last_name = '';
|
|
}
|
|
// supervisor email not provided in this format
|
|
user.supervisor_email = '';
|
|
}
|
|
myTbody.appendChild(myRow);
|
|
users.push(user)
|
|
emails.push(user.email)
|
|
console.log(user)
|
|
$("#users-list").append(`<li data-index="${i}">Name: <span class="name">${user.first_name} ${user.last_name}</span><br/>Email: <span class="email">${user.email}</span><br/>Grade: <span class="grade">${user.grade}</span><br/>Supervisor: <span class="supervisor_name">${user.supervisor_name || ''}</span><br/>
|
|
<form>
|
|
Supervisor email: <input class="supervisor-email-input" name="supervisor_email" type="text" value="${user.supervisor_email || ''}" placeholder="supervisor email" style="width: 320px; display: none;" /> <br/>
|
|
<input type="text" name="first_name" value="${user.first_name}" hidden>
|
|
<input type="text" name="last_name" value="${user.last_name}" hidden>
|
|
<input type="text" name="email" value="${user.email}" hidden>
|
|
<input type="text" name="grade" value="${user.grade}" hidden>
|
|
<input type="text" name="supervisor_name" value="${user.supervisor_name}" hidden>
|
|
<button
|
|
hx-post="{% url 'accounts_bulk_create_check' %}"
|
|
hx-trigger="load"
|
|
hx-target="next span"
|
|
name="user"
|
|
class="hide"
|
|
>CHECK</button>
|
|
</form><span class="check-status"></span></li>`)
|
|
}
|
|
myTable.appendChild(myTbody);
|
|
|
|
$.post("{% url 'accounts_check_users' %}", { csrfmiddlewaretoken: "{{ csrf_token }}",
|
|
user_list: JSON.stringify(emails) }, function(data) {
|
|
console.log("Existing users", data)
|
|
})
|
|
|
|
$("#users-list").append(`${users.length} users to create/update.`)
|
|
|
|
// Make sure the new hyperscript works
|
|
_hyperscript.processNode($("#users-list")[0]);
|
|
htmx.process($("#users-list")[0]);
|
|
$("#user-list-json").val(JSON.stringify(users));
|
|
|
|
// Run the supervisor input toggle once HTMX has processed the checks
|
|
updateSupervisorInputs();
|
|
|
|
$("#user-list-json").val(JSON.stringify(users));
|
|
$("#submit-users").show();
|
|
|
|
// When submit is clicked, rebuild users JSON from current DOM values (to pick up any edited supervisor emails)
|
|
window.prepareAndSubmit = function(){
|
|
var rebuilt = [];
|
|
$("#users-list li").each(function(idx, li){
|
|
var $li = $(li);
|
|
var first_last = $li.find('.name').text().trim();
|
|
var parts = first_last.split(/\s+/);
|
|
var first = parts[0] || '';
|
|
var last = parts.slice(1).join(' ') || '';
|
|
var email = $li.find('.email').text().trim();
|
|
var grade = $li.find('.grade').text().trim();
|
|
var supervisor_name = $li.find('.supervisor_name').text().trim();
|
|
var supervisor_email = $li.find('.supervisor-email-input').val().trim();
|
|
rebuilt.push({
|
|
first_name: first,
|
|
last_name: last,
|
|
email: email,
|
|
grade: grade,
|
|
supervisor_name: supervisor_name,
|
|
supervisor_email: supervisor_email
|
|
});
|
|
});
|
|
$("#user-list-json").val(JSON.stringify(rebuilt));
|
|
// submit the form
|
|
document.getElementById('user-list-form').submit();
|
|
};
|
|
// Attach form submit handler to rebuild JSON just before submit (covers cases where user presses Enter)
|
|
$('#user-list-form').on('submit', function(e){
|
|
e.preventDefault();
|
|
// rebuild
|
|
var rebuilt = [];
|
|
$("#users-list li").each(function(idx, li){
|
|
var $li = $(li);
|
|
var first_last = $li.find('.name').text().trim();
|
|
var parts = first_last.split(/\s+/);
|
|
var first = parts[0] || '';
|
|
var last = parts.slice(1).join(' ') || '';
|
|
var email = $li.find('.email').text().trim();
|
|
var grade = $li.find('.grade').text().trim();
|
|
var supervisor_name = $li.find('.supervisor_name').text().trim();
|
|
var supervisor_email = $li.find('.supervisor-email-input').val().trim();
|
|
rebuilt.push({
|
|
first_name: first,
|
|
last_name: last,
|
|
email: email,
|
|
grade: grade,
|
|
supervisor_name: supervisor_name,
|
|
supervisor_email: supervisor_email
|
|
});
|
|
});
|
|
$("#user-list-json").val(JSON.stringify(rebuilt));
|
|
// submit without triggering this handler again
|
|
$(this).off('submit');
|
|
this.submit();
|
|
});
|
|
|
|
// If we want to show the table
|
|
//document.body.appendChild(myTable);
|
|
|
|
document.addEventListener('htmx:afterRequest', function(evt) {
|
|
updateWarnings();
|
|
updateSupervisorInputs();
|
|
|
|
});
|
|
|
|
|
|
}
|
|
</script>
|
|
<script>
|
|
// Hide the supervisor email input if the server has indicated the supervisor exists
|
|
function updateSupervisorInputs(){
|
|
try {
|
|
document.querySelectorAll('#users-list li').forEach(function(li){
|
|
var statusSpan = li.querySelector('.check-status');
|
|
if (!statusSpan) return;
|
|
var text = statusSpan.textContent.trim().toLowerCase();
|
|
var input = li.querySelector('.supervisor-email-input');
|
|
if (!input) return;
|
|
// If the server response indicates the supervisor exists (and not 'does not exist'), hide the input
|
|
if (text.indexOf('supervisor exists') !== -1 && text.indexOf('does not exist') === -1) {
|
|
input.style.display = 'none';
|
|
} else {
|
|
input.style.display = '';
|
|
}
|
|
});
|
|
} catch (e) {
|
|
console.error('updateSupervisorInputs error', e);
|
|
}
|
|
}
|
|
</script>
|
|
<script type="text/hyperscript">
|
|
def updateWarnings()
|
|
log "test"
|
|
then
|
|
if <#users-list li:has(.error)/> is not empty
|
|
put "Errors<br/>" into #alert
|
|
then for error in<#users-list li:has(.error)/>
|
|
put textContent of .name in error at end of #alert
|
|
then
|
|
put " " + textContent of .error in error at end of #alert
|
|
then make a <br/> then put it at the end of #alert
|
|
then add .alert-warning to #alert
|
|
|
|
end
|
|
|
|
else
|
|
put "No errors" into #alert
|
|
end
|
|
then show #alert
|
|
|
|
end
|
|
</script>
|
|
<style>
|
|
table{
|
|
{% comment %} border-collapse: collapse; {% endcomment %}
|
|
border: 1px solid silver;
|
|
}
|
|
tr{
|
|
border-bottom: 1px solid silver;
|
|
}
|
|
td, th {
|
|
border: 1px solid silver;
|
|
padding: 2px;
|
|
padding-left: 4px;
|
|
padding-right: 4px;
|
|
|
|
}
|
|
|
|
#users-list li {
|
|
border: 1px solid blue;
|
|
margin: 10px;
|
|
padding: 10px;
|
|
}
|
|
|
|
.check-status {
|
|
color: blue;
|
|
}
|
|
|
|
.error {
|
|
color:red;
|
|
}
|
|
|
|
#users-list li:has(.error) {
|
|
border: 1px solid red;
|
|
}
|
|
|
|
</style>
|
|
{% endblock content %} |