Add email templates for user notifications and account management

- Created a base email template (base.html) for consistent styling across all emails.
- Added moderation approval email template (moderation_approved.html) to notify users of approved submissions.
- Added moderation rejection email template (moderation_rejected.html) to inform users of required changes for their submissions.
- Created password reset email template (password_reset.html) for users requesting to reset their passwords.
- Developed a welcome email template (welcome.html) to greet new users and provide account details and tips for using ThrillWiki.
This commit is contained in:
pacnpal
2025-11-08 15:34:04 -05:00
parent 9c46ef8b03
commit d6ff4cc3a3
335 changed files with 61926 additions and 73 deletions

View File

@@ -0,0 +1,7 @@
.selectable-field-export-row {
padding-left: 10px;
}
.selectable-field-export-row > label{
padding-left: 5px;
}

View File

@@ -0,0 +1,45 @@
function hideUnselectedResourceFields(selectedResourceIndex) {
const fields = document.querySelectorAll("[resource-index]");
fields.forEach((field) => {
if (field.getAttribute("resource-index") !== selectedResourceIndex.toString()) {
// field is wrapped by div, change visibility on wrapper
field.style.display = "none";
}
});
}
function showSelectedResourceFields(resourceIndex) {
const fields = document.querySelectorAll(`[resource-index="${resourceIndex}"]`);
fields.forEach((field) => {
// field is wrapped by div, change visibility on wrapper
field.style.display = "block";
});
}
function onResourceSelected(e) {
const resourceIndex = e.target.value;
showSelectedResourceFields(resourceIndex);
hideUnselectedResourceFields(resourceIndex);
}
document.addEventListener("DOMContentLoaded", () => {
const resourceSelector = document.querySelector("#id_resource");
if (!resourceSelector) {
console.error("resource select input not found");
return;
}
// If selector is actually select input, get selected option.
// else selected resource index is 0
const selectedResourceIndex = resourceSelector.tagName === "SELECT" ? resourceSelector.value : 0;
resourceSelector.addEventListener("input", onResourceSelected);
// initially hide unselected resource fields
hideUnselectedResourceFields(selectedResourceIndex);
});

View File

@@ -0,0 +1,21 @@
(function($) {
$().ready(function () {
$('input.guess_format[type="file"]').change(function () {
var files = this.files;
var dropdowns = $(this.form).find('select.guess_format');
if(files.length > 0) {
var extension = files[0].name.split('.').pop().trim().toLowerCase();
for(var i = 0; i < dropdowns.length; i++) {
var dropdown = dropdowns[i];
dropdown.selectedIndex = 0;
for(var j = 0; j < dropdown.options.length; j++) {
if(extension === dropdown.options[j].text.trim().toLowerCase()) {
dropdown.selectedIndex = j;
break;
}
}
}
}
});
});
})(django.jQuery);

View File

@@ -0,0 +1,159 @@
.import-preview .errors {
position: relative;
}
.validation-error-count {
display: inline-block;
background-color: #e40000;
border-radius: 6px;
color: white;
font-size: 0.9em;
position: relative;
font-weight: bold;
margin-top: -2px;
padding: 0.2em 0.4em;
}
.validation-error-container {
position: absolute;
opacity: 0;
pointer-events: none;
background-color: #ffc1c1;
padding: 14px 15px 10px;
top: 25px;
margin: 0 0 20px 0;
width: 200px;
z-index: 2;
}
html[data-theme="light"] .validation-error-container {
background-color: #ffc1c1;
}
table.import-preview tr.skip, html[data-theme="light"] table.import-preview tr.skip {
background-color: #d2d2d2;
}
table.import-preview tr.new, html[data-theme="light"] table.import-preview tr.new {
background-color: #bdd8b2;
}
table.import-preview tr.delete, html[data-theme="light"] table.import-preview tr.delete {
background-color: #f9bebf;
}
table.import-preview tr.update, html[data-theme="light"] table.import-preview tr.update {
background-color: #fdfdcf;
}
table.import-preview td ins, html[data-theme="light"] table.import-preview td ins {
background-color: #e6ffe6 !important;
}
html[data-theme="light"] table.import-preview td del {
background-color: #ffe6e6 !important;
}
.import-preview td:hover .validation-error-count {
z-index: 3;
}
.import-preview td:hover .validation-error-container {
opacity: 1;
pointer-events: auto;
}
.validation-error-list {
margin: 0;
padding: 0;
}
.validation-error-list li {
list-style: none;
margin: 0;
}
.validation-error-list > li > ul {
margin: 8px 0;
padding: 0;
}
.validation-error-list > li > ul > li {
padding: 0;
margin: 0 0 10px;
line-height: 1.28em;
}
.validation-error-field-label {
display: block;
border-bottom: 1px solid #e40000;
color: #e40000;
text-transform: uppercase;
font-weight: bold;
font-size: 0.85em;
}
@media (prefers-color-scheme: dark) {
table.import-preview tr.skip {
background-color: #2d2d2d;
}
table.import-preview tr.new {
background-color: #42274d;
}
table.import-preview tr.delete {
background-color: #064140;
}
table.import-preview tr.update {
background-color: #020230;
}
.validation-error-container {
background-color: #003e3e;
}
/*
these declarations are necessary to forcibly override the
formatting applied by the diff-match-patch python library
*/
table.import-preview td ins {
background-color: #190019 !important;
}
table.import-preview td del {
background-color: #001919 !important;
}
}
html[data-theme="dark"] table.import-preview tr.skip {
background-color: #2d2d2d;
}
html[data-theme="dark"] table.import-preview tr.new {
background-color: #42274d;
}
html[data-theme="dark"] table.import-preview tr.delete {
background-color: #064140;
}
html[data-theme="dark"] table.import-preview tr.update {
background-color: #020230;
}
html[data-theme="dark"] .validation-error-container {
background-color: #003e3e;
}
/*
these declarations are necessary to forcibly override the
formatting applied by the diff-match-patch python library
*/
html[data-theme="dark"] table.import-preview td ins {
background-color: #190019 !important;
}
html[data-theme="dark"] table.import-preview td del {
background-color: #001919 !important;
}