Finished up with email verification system and profile page redux.
This commit is contained in:
parent
c32f3df3f3
commit
40c004795b
15 changed files with 275 additions and 58 deletions
32
www/css/popup/changeEmail.css
Normal file
32
www/css/popup/changeEmail.css
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
/*Canopy - The next generation of stoner streaming software
|
||||
Copyright (C) 2024-2025 Rainbownapkin and the TTN Community
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.*/
|
||||
|
||||
#email-change-popup-content{
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
#email-change-popup-title{
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
#email-change-popup-caption{
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
#email-change-popup-content input{
|
||||
margin: 0.5em 0;
|
||||
}
|
||||
32
www/css/popup/changePassword.css
Normal file
32
www/css/popup/changePassword.css
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
/*Canopy - The next generation of stoner streaming software
|
||||
Copyright (C) 2024-2025 Rainbownapkin and the TTN Community
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.*/
|
||||
|
||||
#password-change-popup-content{
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
#password-change-popup-title{
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
#password-change-popup-caption{
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
#password-change-popup-content input{
|
||||
margin: 0.5em 0;
|
||||
}
|
||||
|
|
@ -41,6 +41,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.*/
|
|||
#account-settings-div{
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding: 1em;
|
||||
}
|
||||
|
||||
|
|
@ -57,16 +58,24 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.*/
|
|||
|
||||
#profile-img{
|
||||
position: relative;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
height: 14em;
|
||||
width: 14em;
|
||||
margin: 1em 0;
|
||||
}
|
||||
|
||||
#profile-img-content{
|
||||
margin: 1em 0;
|
||||
cursor: pointer;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
#profile-img-prompt{
|
||||
position: absolute;
|
||||
left: -2em;
|
||||
right: -2em;
|
||||
left: -1.5em;
|
||||
right: -1.5em;
|
||||
top: calc(50% - 1.3em);
|
||||
}
|
||||
|
||||
|
|
@ -85,7 +94,7 @@ p.profile-item{
|
|||
margin: 0;
|
||||
}
|
||||
|
||||
span.profile-item-oneliner{
|
||||
.profile-item-oneliner{
|
||||
text-wrap: nowrap
|
||||
}
|
||||
|
||||
|
|
@ -99,7 +108,7 @@ span.profile-item-oneliner{
|
|||
height: fit-content;
|
||||
min-height: 1.5em;
|
||||
max-height: 5.8em;
|
||||
padding: 0.5em 0;
|
||||
padding: 0.5em 0.2em;
|
||||
border-bottom-right-radius: 0;
|
||||
text-wrap: nowrap;
|
||||
visibility: collapse;
|
||||
|
|
@ -124,11 +133,14 @@ span.profile-item-oneliner{
|
|||
|
||||
#profile-bio-prompt{
|
||||
width: 30VW;
|
||||
height: 11em;
|
||||
height: 19.4em;
|
||||
resize: vertical;
|
||||
}
|
||||
|
||||
/* temp */
|
||||
input:not([type="checkbox"]):not(.navbar-item):not(.profile-item-prompt){
|
||||
display: block;
|
||||
#account-email-label{
|
||||
margin: 0.2em 0;
|
||||
}
|
||||
|
||||
#account-email-address{
|
||||
margin-top: 0.2em
|
||||
}
|
||||
|
|
@ -37,7 +37,7 @@ class profileUpdatePrompt{
|
|||
|
||||
closePrompt(event){
|
||||
//Check if we're finished
|
||||
const fin = event.key == "Escape" || event.key == "Enter";
|
||||
const fin = event.key == "Escape" || (event.key == "Enter" && !event.shiftKey);
|
||||
|
||||
//IF we are
|
||||
if(fin){
|
||||
|
|
@ -63,6 +63,12 @@ class profileUpdateTextPrompt extends profileUpdatePrompt{
|
|||
//Call derived method
|
||||
super.popPrompt();
|
||||
|
||||
//For each line break
|
||||
this.contentNode.querySelectorAll('br').forEach((br)=>{
|
||||
//Replace the linenreaks with newlines to get the text area to play nice
|
||||
br.outerHTML = "\n"
|
||||
});
|
||||
|
||||
//If we're filling the prompt
|
||||
if(this.fillPrompt){
|
||||
//Fill the prompt content and placeholder
|
||||
|
|
@ -85,7 +91,7 @@ class profileUpdateTextPrompt extends profileUpdatePrompt{
|
|||
this.contentNode.style.display = 'inline-block';
|
||||
|
||||
//If we're not cancelling
|
||||
if(event.key == "Enter"){
|
||||
if(event.key == "Enter" && !event.shiftKey){
|
||||
//Create empty update object
|
||||
let updateObj = {};
|
||||
|
||||
|
|
@ -95,8 +101,8 @@ class profileUpdateTextPrompt extends profileUpdatePrompt{
|
|||
//Send er' off
|
||||
const update = await utils.ajax.updateProfile(updateObj);
|
||||
|
||||
//Fill content from update
|
||||
this.contentNode.innerHTML = update[this.field];
|
||||
//Fill content from update, make sure to add line breaks for the bio
|
||||
this.contentNode.innerHTML = update[this.field].replaceAll('\n','<br>');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -200,9 +206,10 @@ class tokeList{
|
|||
}
|
||||
}
|
||||
|
||||
class deleteAccountButton{
|
||||
constructor(){
|
||||
this.deleteLink = document.querySelector('#account-settings-delete-button');
|
||||
class accountSettingsButton{
|
||||
constructor(field, popupClass){
|
||||
this.deleteLink = document.querySelector(`#account-settings-${field}-button`);
|
||||
this.popupClass = popupClass;
|
||||
|
||||
if(this.deleteLink != null){
|
||||
this.setupInput();
|
||||
|
|
@ -210,11 +217,74 @@ class deleteAccountButton{
|
|||
}
|
||||
|
||||
setupInput(){
|
||||
this.deleteLink.addEventListener("click",this.deletePrompt.bind(this));
|
||||
this.deleteLink.addEventListener("click",this.showPopup.bind(this));
|
||||
}
|
||||
|
||||
async deletePrompt(event){
|
||||
this.popup = new deleteAccountPopup();
|
||||
async showPopup(event){
|
||||
this.popup = new this.popupClass();
|
||||
}
|
||||
}
|
||||
|
||||
class changeEmailPopup{
|
||||
constructor(){
|
||||
this.popup = new canopyUXUtils.popup("changeEmail", true, this.asyncConstructor.bind(this), this.asyncConstructor);
|
||||
}
|
||||
|
||||
asyncConstructor(){
|
||||
this.emailPrompt = document.querySelector('#email-change-popup-email');
|
||||
this.passPrompt = document.querySelector('#email-change-popup-password');
|
||||
|
||||
this.setupInput();
|
||||
}
|
||||
|
||||
setupInput(){
|
||||
this.emailPrompt.addEventListener('keydown', this.emailRequest.bind(this));
|
||||
this.passPrompt.addEventListener('keydown', this.emailRequest.bind(this));
|
||||
}
|
||||
|
||||
async emailRequest(event){
|
||||
if(event.key == "Enter"){
|
||||
await utils.ajax.requestEmailChange(this.emailPrompt.value, this.passPrompt.value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class changePasswordPopup{
|
||||
constructor(){
|
||||
this.popup = new canopyUXUtils.popup("changePassword", true, this.asyncConstructor.bind(this), this.asyncConstructor);
|
||||
}
|
||||
|
||||
asyncConstructor(){
|
||||
this.oldPassPrompt = document.querySelector('#password-change-popup-old-password');
|
||||
this.newPassPrompt = document.querySelector('#password-change-popup-new-password');
|
||||
this.confirmPassPrompt = document.querySelector('#password-change-popup-confirm-new-password');
|
||||
|
||||
this.setupInput();
|
||||
}
|
||||
|
||||
setupInput(){
|
||||
this.oldPassPrompt.addEventListener('keydown', this.emailRequest.bind(this));
|
||||
this.newPassPrompt.addEventListener('keydown', this.emailRequest.bind(this));
|
||||
this.confirmPassPrompt.addEventListener('keydown', this.emailRequest.bind(this));
|
||||
}
|
||||
|
||||
async emailRequest(event){
|
||||
if(event.key == "Enter"){
|
||||
const updateObj = {};
|
||||
|
||||
updateObj.passChange = {
|
||||
oldPass: this.oldPassPrompt.value,
|
||||
newPass: this.newPassPrompt.value,
|
||||
confirmPass: this.confirmPassPrompt.value
|
||||
};
|
||||
|
||||
const response = await utils.ajax.updateProfile(updateObj);
|
||||
|
||||
if(response != null){
|
||||
//Return user homepage after good pass change, as we've probably been logged out by the server for security.
|
||||
window.location.pathname = '/';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -246,5 +316,6 @@ const pronounsPrompt = new profileUpdateTextPrompt('pronouns');
|
|||
const signaturePrompt = new profileUpdateTextPrompt('signature');
|
||||
const bioPrompt = new profileUpdateTextPrompt('bio', true);
|
||||
const profileTokeList = new tokeList();
|
||||
const accountPassResetPrompt = new passwordResetPrompt();
|
||||
const accountDeleteButton = new deleteAccountButton();
|
||||
const accountEmailChange = new accountSettingsButton('update-email', changeEmailPopup);
|
||||
const accountPasswordChange = new accountSettingsButton('change-password', changePasswordPopup);
|
||||
const accountDeleteButton = new accountSettingsButton('delete', deleteAccountPopup);
|
||||
Loading…
Add table
Add a link
Reference in a new issue