Gave profile page a facelift in perperation for email/password update pop-ups.

This commit is contained in:
rainbow napkin 2024-12-31 06:50:34 -05:00
parent a51152a89d
commit c32f3df3f3
16 changed files with 316 additions and 157 deletions

View file

@ -14,104 +14,125 @@ 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/>.*/
//Base Class
class profileEditPrompt{
constructor(field, content, useTextArea = false){
class profileUpdatePrompt{
constructor(field){
this.field = field;
this.useTextArea = useTextArea;
this.content = content;
this.link = document.querySelector(`#profile-${field}-edit`);
this.contentNode = document.querySelector(`#profile-${field}-content`);
this.promptNode = document.querySelector(`#profile-${field}-prompt`);
//Bail out if something ain't right
if(!this.link || !this.content){
return;
}
this.setupPrompt();
}
setupPrompt(){
if(this.link != null){
this.link.addEventListener("click", this.prompt.bind(this));
if(this.promptNode != null){
this.setupInput();
}
}
setupInput(){
this.contentNode.addEventListener('click', this.popPrompt.bind(this));
this.promptNode.addEventListener('keydown', this.closePrompt.bind(this));
}
prompt(){
//Create input element
if(this.useTextArea){
this.prompt = document.createElement("textArea");
popPrompt(){
this.promptNode.style.display = 'inline';
this.promptNode.focus();
}
closePrompt(event){
//Check if we're finished
const fin = event.key == "Escape" || event.key == "Enter";
//IF we are
if(fin){
//Display the prompt
this.promptNode.style.display = 'none';
}
//Return whether or not we're done
return fin;
}
}
class profileUpdateTextPrompt extends profileUpdatePrompt{
constructor(field, fillPrompt = false){
//call derived constructor
super(field);
//Set fill prompt
this.fillPrompt = fillPrompt;
}
popPrompt(){
//Call derived method
super.popPrompt();
//If we're filling the prompt
if(this.fillPrompt){
//Fill the prompt content and placeholder
this.promptNode.value = this.contentNode.textContent;
this.promptNode.placeholder = this.field;
//otherwise
}else{
this.prompt = document.createElement("input");
//Just fill the placeholder
this.promptNode.placeholder = this.contentNode.textContent;
}
//Setup properties
this.prompt.id = `profile-${this.field}-prompt`;
this.prompt.classList.add("profile-edit-prompt");
if(this.field == "img"){
this.prompt.placeholder = this.content.src;
}else{
this.prompt.placeholder = this.content.innerHTML;
}
//Setup event listener
this.prompt.addEventListener("keydown", this.update.bind(this));
//replace label
this.content.replaceWith(this.prompt);
//Hide content
this.contentNode.style.display = 'none';
}
async update(event){
if((!event || event.key == "Enter") && this.prompt.value){
//setup object
var updateObj = {};
updateObj[this.field] = this.prompt.value;
async closePrompt(event){
//Call derived constructor and check if we're finished, assuming we're finished...
if(super.closePrompt(event)){
//Display
this.contentNode.style.display = 'inline-block';
//contact server, and collect response
var updated_content = (await utils.ajax.updateProfile(updateObj))[this.field];
//If we're not cancelling
if(event.key == "Enter"){
//Create empty update object
let updateObj = {};
//Update label
if(updated_content != null){
if(this.field == "img"){
this.content.src = updated_content;
}else{
this.content.innerHTML = updated_content;
}
//Fill field
updateObj[this.field] = this.promptNode.value;
//Send er' off
const update = await utils.ajax.updateProfile(updateObj);
//Fill content from update
this.contentNode.innerHTML = update[this.field];
}
this.finish();
}else if(event.key == "Escape" || event.key == "Enter"){
this.finish();
}
}
finish(){
this.prompt.replaceWith(this.content);
}
}
class profileTextEditPrompt extends profileEditPrompt{
constructor(field, useTextArea = false){
//Get content based on field name
var content = document.querySelector(`#profile-${field}-content`);
//Derived Constructor
super(field, content, useTextArea);
}
prompt(){
super.prompt();
}
async update(event){
await super.update(event)
}
}
//Child Classes
class profileImgEditPrompt extends profileEditPrompt{
class profileUpdateImagePrompt extends profileUpdatePrompt{
constructor(){
//Get content based on field name
var content = document.querySelector(`#profile-img`);
//Derived constructor
super("img", content, false);
//call derived constructor
super('img');
}
popPrompt(){
//Call derived method
super.popPrompt();
this.promptNode.placeholder = this.contentNode.src;
}
async closePrompt(event){
//Call derived constructor
super.closePrompt(event);
//If we're not cancelling
if(event.key == "Enter"){
//Create empty update object
let updateObj = {};
//Fill field
updateObj[this.field] = this.promptNode.value;
//Send er' off
const update = await utils.ajax.updateProfile(updateObj);
//Fill content from update
this.contentNode.src = update[this.field];
}
}
}
@ -169,11 +190,11 @@ class tokeList{
}
toggleTokeList(){
if(this.tokeList.checkVisibility()){
this.tokeList.style.display = "none";
if(this.tokeList.style.visibility == "visible"){
this.tokeList.style.visibility = "collapse";
this.tokeListToggleIcon.classList.replace("bi-caret-down-fill","bi-caret-left-fill");
}else{
this.tokeList.style.display = "block";
this.tokeList.style.visibility = "visible";
this.tokeListToggleIcon.classList.replace("bi-caret-left-fill","bi-caret-down-fill");
}
}
@ -183,7 +204,9 @@ class deleteAccountButton{
constructor(){
this.deleteLink = document.querySelector('#account-settings-delete-button');
this.setupInput();
if(this.deleteLink != null){
this.setupInput();
}
}
setupInput(){
@ -218,9 +241,10 @@ class deleteAccountPopup{
}
//Object Instantiation
new profileTextEditPrompt("signature");
new profileTextEditPrompt("bio", true);
new profileImgEditPrompt();
new tokeList();
new passwordResetPrompt();
new deleteAccountButton();
const imgPrompt = new profileUpdateImagePrompt();
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();