summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--public/js/util.js34
-rwxr-xr-xviews/event.handlebars110
-rwxr-xr-xviews/eventgroup.handlebars114
-rwxr-xr-xviews/layouts/main.handlebars1
-rw-r--r--views/partials/editeventgroupmodal.handlebars14
-rw-r--r--views/partials/editeventmodal.handlebars11
6 files changed, 263 insertions, 21 deletions
diff --git a/public/js/util.js b/public/js/util.js
new file mode 100644
index 0000000..e2e9938
--- /dev/null
+++ b/public/js/util.js
@@ -0,0 +1,34 @@
+const getStoredToken = function(eventID) {
+ try {
+ let editTokens = JSON.parse(localStorage.getItem('editTokens'));
+ return editTokens[eventID];
+ } catch(e) {
+ console.error(e);
+ localStorage.setItem('editTokens', JSON.stringify({}));
+ return false;
+ }
+}
+
+const addStoredToken = function(eventID, token) {
+ try {
+ let editTokens = JSON.parse(localStorage.getItem('editTokens'));
+ editTokens[eventID] = token;
+ localStorage.setItem('editTokens', JSON.stringify(editTokens));
+ } catch(e) {
+ console.error(e);
+ localStorage.setItem('editTokens', JSON.stringify({ [eventID]: token }));
+ return false;
+ }
+}
+
+const removeStoredToken = function(eventID) {
+ try {
+ let editTokens = JSON.parse(localStorage.getItem('editTokens'));
+ delete editTokens[eventID];
+ localStorage.setItem('editTokens', JSON.stringify(editTokens));
+ } catch(e) {
+ console.error(e);
+ localStorage.setItem('editTokens', JSON.stringify({}));
+ return false;
+ }
+}
diff --git a/views/event.handlebars b/views/event.handlebars
index 6a65f07..4fb1a46 100755
--- a/views/event.handlebars
+++ b/views/event.handlebars
@@ -5,16 +5,15 @@
{{/if}}
<div class="row">
<div class="col-lg">
- <h3 id="eventName">{{eventData.name}}</h3>
+ <h3 id="eventName" data-event-id="{{eventData.id}}">{{eventData.name}}</h3>
</div>
- {{#if editingEnabled}}
<div class="col-lg-3 ml-2 edit-buttons">
- <div class="btn-group" role="group" aria-label="Event controls">
- <button type="button" id="editEvent" class="btn btn-success" data-toggle="modal" data-target="#editModal" {{#if eventHasConcluded}}disabled{{/if}}><i class="fas fa-edit"></i> Edit</button>
- <button type="button" id="deleteEvent" class="btn btn-danger" data-toggle="modal" data-target="#deleteModal"><i class="fas fa-trash"></i> Delete</button>
- </div>
+ {{#if editingEnabled}}
+ <button type="button" id="editEvent" class="btn btn-success" {{#if eventHasConcluded}}disabled{{/if}} data-event-id="{{eventData.id}}" data-toggle="modal" data-target="#editModal"><i class="fas fa-edit"></i> Edit event</button>
+ {{else}}
+ <button type="button" id="editEvent" class="btn btn-success" {{#if eventHasConcluded}}disabled{{/if}} data-event-id="{{eventData.id}}" data-toggle="modal" data-target="#editTokenModal"><i class="fas fa-edit"></i> Edit event</button>
+ {{/if}}
</div>
- {{/if}}
</div>
<div class="container my-4 pr-0">
<div class="row">
@@ -324,6 +323,36 @@
</div>
{{/if}}
+<div class="modal fade" id="editTokenModal" tabindex="-1" role="dialog" aria-labelledby="editTokenModalLabel" aria-hidden="true">
+ <div class="modal-dialog" role="document">
+ <div class="modal-content">
+ <div class="modal-header">
+ <h5 class="modal-title" id="editTokenModalLabel">Enter editing password</h5>
+ <button type="button" class="close" data-dismiss="modal" aria-label="Close">
+ <span aria-hidden="true">&times;</span>
+ </button>
+ </div>
+ <form id="verifyTokenForm" action="/verifytoken/event/{{eventData.id}}" method="post">
+ <div class="modal-body">
+ <div class="form-group">
+ <p class="form-text small">Enter the editing password you received by email or were shown when the event was created.</p>
+ <div class="form-group">
+ <input type="text" class="form-control" id="editToken" name="editToken" placeholder="Get it right!" data-validation="required">
+ </div>
+ <div class="form-group">
+ <div class="alert alert-danger" style="display:none;"></div>
+ </div>
+ </div>
+ </div>
+ <div class="modal-footer">
+ <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
+ <button type="submit" class="btn btn-primary">Edit event</button>
+ </div>
+ </form>
+ </div>
+ </div>
+</div>
+
{{#if editingEnabled}}
{{#unless eventHasConcluded}}
{{> editeventmodal }}
@@ -338,7 +367,7 @@
<span aria-hidden="true">&times;</span>
</button>
</div>
- <form id="editEventForm" action="/deleteevent/{{eventData.id}}/{{eventData.editToken}}" method="post">
+ <form id="deleteEventForm" action="/deleteevent/{{eventData.id}}" method="post">
<div class="modal-body">
<p>Are you sure you want to delete this event? This action cannot be undone.</p>
</div>
@@ -403,6 +432,47 @@
})
$(document).ready(function() {
+ // Save the editing token from the URL, if it is valid
+ const eventID = $('#eventName').attr('data-event-id');
+ const urlParams = new URLSearchParams(window.location.search);
+ if (urlParams.has('e')) {
+ $.ajax({
+ type: "POST",
+ url: `/verifytoken/event/${eventID}`,
+ data: { editToken: urlParams.get('e') },
+ success: function(response, status, xhr) {
+ if (xhr.status === 200) {
+ addStoredToken(eventID, urlParams.get('e'));
+ }
+ },
+ error: function(response, status, xhr) {
+ // The editing token is wrong - remove it
+ removeStoredToken(eventID);
+ window.location = window.location.pathname;
+ }
+ });
+ } else if (getStoredToken(eventID)) {
+ const editToken = getStoredToken(eventID);
+ $.ajax({
+ type: "POST",
+ url: `/verifytoken/event/${eventID}`,
+ data: { editToken },
+ success: function(response, status, xhr) {
+ if (xhr.status === 200) {
+ window.location.search = `?e=${editToken}`;
+ }
+ },
+ error: function(response, status, xhr) {
+ // The editing token is wrong - remove it
+ removeStoredToken(eventID);
+ }
+ });
+ }
+
+ if (urlParams.has('show_edit')) {
+ $('#editModal').modal('show');
+ }
+
// From https://davidwalsh.name/javascript-download
function downloadFile(data, fileName, type="text/plain") {
// Create an invisible A element
@@ -502,6 +572,30 @@
const passphrase = window.niceware.generatePassphrase(6).join('-');
modal.find('#removeAttendancePassword').val(passphrase);
});
+
+ $('#verifyTokenForm').on('submit', function(e) {
+ e.preventDefault();
+ let form = $(this);
+ $.ajax({
+ type: "POST",
+ url: form.attr('action'),
+ data: form.serialize(),
+ success: function(response, status, xhr) {
+ if (xhr.status === 200) {
+ // Save the token to localStorage for later
+ addStoredToken($('#eventName').attr('data-event-id'), new FormData(form[0]).get('editToken'));
+ window.location.search = `?e=${new FormData(form[0]).get('editToken')}&show_edit=true`;
+ }
+ },
+ error: function(response, status, xhr) {
+ form.find('.alert').text('That editing password is incorrect. Try again.').show();
+ }
+ });
+ });
+
+ $('#deleteEvent').on('click', function() {
+ $('#editModal').modal('hide');
+ })
});
</script>
diff --git a/views/eventgroup.handlebars b/views/eventgroup.handlebars
index 03a5b27..d7726bd 100755
--- a/views/eventgroup.handlebars
+++ b/views/eventgroup.handlebars
@@ -5,16 +5,15 @@
{{/if}}
<div class="row">
<div class="col-lg">
- <h3 id="eventName">{{eventGroupData.name}}</h3>
+ <h3 id="eventName" data-event-id="{{eventGroupData.id}}">{{eventGroupData.name}}</h3>
</div>
- {{#if editingEnabled}}
<div class="col-lg-2 ml-2 edit-buttons">
- <div class="btn-group" role="group" aria-label="Event controls">
- <button type="button" id="editEvent" class="btn btn-success" data-toggle="modal" data-target="#editModal" ><i class="fas fa-edit"></i></button>
- <button type="button" id="deleteEvent" class="btn btn-danger" data-toggle="modal" data-target="#deleteModal"><i class="fas fa-trash"></i></button>
- </div>
+ {{#if editingEnabled}}
+ <button type="button" id="editEvent" class="btn btn-success text-nowrap" data-event-id="{{eventGroupData.id}}" data-toggle="modal" data-target="#editModal"><i class="fas fa-edit"></i> Edit group</button>
+ {{else}}
+ <button type="button" id="editEvent" class="btn btn-success text-nowrap" data-event-id="{{eventGroupData.id}}" data-toggle="modal" data-target="#editTokenModal"><i class="fas fa-edit"></i> Edit group</button>
+ {{/if}}
</div>
- {{/if}}
</div>
{{#if firstLoad}}
<div class="alert alert-success alert-dismissible fade show" role="alert">
@@ -70,7 +69,7 @@
<td><span class="code">{{eventGroupData.id}}</span></td>
</tr>
<tr>
- <td><strong>Event group secret editing code</strong></td>
+ <td><strong>Event group editing password</strong></td>
<td><span class="code">{{eventGroupData.editToken}}</span></td>
</tr>
</table>
@@ -116,7 +115,7 @@
<span aria-hidden="true">&times;</span>
</button>
</div>
- <form action="/deleteeventgroup/{{eventGroupData.id}}/{{eventGroupData.editToken}}" method="post">
+ <form id="deleteEventGroupForm" action="/deleteeventgroup/{{eventGroupData.id}}/{{eventGroupData.editToken}}" method="post">
<div class="modal-body">
<p>Are you sure you want to delete this event group? This action cannot be undone.</p>
<p>This will <strong>not</strong> delete the individual events contained in this group. They can be linked to another group later.</p>
@@ -132,6 +131,37 @@
{{/if}}
+<div class="modal fade" id="editTokenModal" tabindex="-1" role="dialog" aria-labelledby="editTokenModalLabel" aria-hidden="true">
+ <div class="modal-dialog" role="document">
+ <div class="modal-content">
+ <div class="modal-header">
+ <h5 class="modal-title" id="editTokenModalLabel">Enter editing password</h5>
+ <button type="button" class="close" data-dismiss="modal" aria-label="Close">
+ <span aria-hidden="true">&times;</span>
+ </button>
+ </div>
+ <form id="verifyTokenForm" action="/verifytoken/group/{{eventGroupData.id}}" method="post">
+ <div class="modal-body">
+ <div class="form-group">
+ <p class="form-text small">Enter the editing password you received by email or were shown when the event was created.</p>
+ <div class="form-group">
+ <input type="text" class="form-control" id="editToken" name="editToken" placeholder="Get it right!" data-validation="required">
+ </div>
+ <div class="form-group">
+ <div class="alert alert-danger" style="display:none;"></div>
+ </div>
+ </div>
+ </div>
+ <div class="modal-footer">
+ <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
+ <button type="submit" class="btn btn-primary">Edit group</button>
+ </div>
+ </form>
+ </div>
+ </div>
+</div>
+
+
<script>
$.validate({
lang: 'en',
@@ -141,6 +171,47 @@
});
$(document).ready(function() {
+ // Save the editing token from the URL, if it is valid
+ const eventID = $('#eventName').attr('data-event-id');
+ const urlParams = new URLSearchParams(window.location.search);
+ if (urlParams.has('e')) {
+ $.ajax({
+ type: "POST",
+ url: `/verifytoken/group/${eventID}`,
+ data: { editToken: urlParams.get('e') },
+ success: function(response, status, xhr) {
+ if (xhr.status === 200) {
+ addStoredToken(eventID, urlParams.get('e'));
+ }
+ },
+ error: function(response, status, xhr) {
+ // The editing token is wrong - remove it
+ removeStoredToken(eventID);
+ window.location = window.location.pathname;
+ }
+ });
+ } else if (getStoredToken(eventID)) {
+ const editToken = getStoredToken(eventID);
+ $.ajax({
+ type: "POST",
+ url: `/verifytoken/group/${eventID}`,
+ data: { editToken },
+ success: function(response, status, xhr) {
+ if (xhr.status === 200) {
+ window.location.search = `?e=${editToken}`;
+ }
+ },
+ error: function(response, status, xhr) {
+ // The editing token is wrong - remove it
+ removeStoredToken(eventID);
+ }
+ });
+ }
+
+ if (urlParams.has('show_edit')) {
+ $('#editModal').modal('show');
+ }
+
$.uploadPreview({
input_field: "#eventGroupImageUpload",
preview_box: "#eventGroupImagePreview",
@@ -157,6 +228,31 @@
$("#copyEventLink").click(function(){
$(this).html('<i class="fas fa-copy"></i> Copied!');
setTimeout(function(){ $("#copyEventLink").html('<i class="fas fa-copy"></i> Copy');}, 5000);
+ });
+
+ $('#verifyTokenForm').on('submit', function(e) {
+ e.preventDefault();
+ let form = $(this);
+ $.ajax({
+ type: "POST",
+ url: form.attr('action'),
+ data: form.serialize(),
+ success: function(response, status, xhr) {
+ if (xhr.status === 200) {
+ // Save the token to localStorage for later
+ addStoredToken($('#eventName').attr('data-event-id'), new FormData(form[0]).get('editToken'));
+ window.location.search = `?e=${new FormData(form[0]).get('editToken')}&show_edit=true`;
+ }
+ },
+ error: function(response, status, xhr) {
+ form.find('.alert').text('That editing password is incorrect. Try again.').show();
+ }
+ });
+ });
+
+ $('#deleteEvent').on('click', function() {
+ $('#editModal').modal('hide');
})
+
});
</script>
diff --git a/views/layouts/main.handlebars b/views/layouts/main.handlebars
index 029e761..7e44810 100755
--- a/views/layouts/main.handlebars
+++ b/views/layouts/main.handlebars
@@ -51,6 +51,7 @@
<script src="/js/i18n/datepicker.en.js"></script>
<script src="/js/select2.min.js"></script>
<script src="/js/moment-timezone.js"></script>
+ <script src="/js/util.js"></script>
</head>
diff --git a/views/partials/editeventgroupmodal.handlebars b/views/partials/editeventgroupmodal.handlebars
index a6102fa..3b8f55a 100644
--- a/views/partials/editeventgroupmodal.handlebars
+++ b/views/partials/editeventgroupmodal.handlebars
@@ -1,5 +1,5 @@
<div class="modal fade" id="editModal" tabindex="-1" role="dialog" aria-labelledby="editModalLabel" aria-hidden="true">
- <div class="modal-dialog" role="document">
+ <div class="modal-dialog modal-xl modal-dialog-scrollable" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="editModalLabel">Edit '{{eventGroupData.name}}'</h5>
@@ -7,8 +7,8 @@
<span aria-hidden="true">&times;</span>
</button>
</div>
- <form id="editEventForm" action="/editeventgroup/{{eventGroupData.id}}/{{eventGroupData.editToken}}" method="post" enctype="multipart/form-data" autocomplete="off">
<div class="modal-body">
+ <form id="editEventForm" action="/editeventgroup/{{eventGroupData.id}}/{{eventGroupData.editToken}}" method="post" enctype="multipart/form-data" autocomplete="off">
<div class="form-group">
<label for="eventGroupName" >Name</label>
<input type="text" class="form-control" id="eventGroupName" name="eventGroupName" placeholder="Make it snappy." value="{{eventGroupData.name}}" data-validation="required length" data-validation-length="3-120">
@@ -34,12 +34,20 @@
</div>
<small class="form-text">Recommended dimensions (w x h): 920px by 300px.</small>
</div>
+ <div class="form-group">
+ <div class="card border-danger mb-3">
+ <div class="card-header text-danger">Delete this event group</div>
+ <div class="card-body text-danger">
+ <button type="button" id="deleteEvent" class="btn btn-danger" data-toggle="modal" data-target="#deleteModal"><i class="fas fa-trash"></i> Delete event group</button>
+ </div>
+ </div>
+ </div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
<button type="submit" class="btn btn-primary">Save changes</button>
- </div>
</form>
+ </div>
</div>
</div>
</div>
diff --git a/views/partials/editeventmodal.handlebars b/views/partials/editeventmodal.handlebars
index a1ccd83..b4b0ea6 100644
--- a/views/partials/editeventmodal.handlebars
+++ b/views/partials/editeventmodal.handlebars
@@ -1,5 +1,5 @@
<div class="modal fade" id="editModal" tabindex="-1" role="dialog" aria-labelledby="editModalLabel" aria-hidden="true">
- <div class="modal-dialog" role="document">
+ <div class="modal-dialog modal-xl modal-dialog-scrollable" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="editModalLabel">Edit '{{eventData.name}}'</h5>
@@ -133,6 +133,15 @@
placeholder="Enter a number." data-validation="number" data-validation-optional="true"
value="{{eventData.maxAttendees}}">
</div>
+
+ <div class="form-group">
+ <div class="card border-danger mb-3">
+ <div class="card-header text-danger">Delete this event</div>
+ <div class="card-body text-danger">
+ <button type="button" id="deleteEvent" class="btn btn-danger" data-toggle="modal" data-target="#deleteModal" data-event-id="{{eventData.id}}"><i class="fas fa-trash"></i> Delete</button>
+ </div>
+ </div>
+ </div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>