Add JavaScript files and edit profile CSS

1) finished edit profile with delete profile
This commit is contained in:
newtbot 2024-01-23 01:44:11 +08:00
parent d819ac71b2
commit 5b262eb803
14 changed files with 296 additions and 334 deletions

View File

@ -22,12 +22,8 @@ async function getUserID(userid) {
if (!userRes) return false; if (!userRes) return false;
return userRes; return userRes;
} }
//api/v0/auth/register //api/v0/auth/register
/* Registering new user /* Registering new user
1) req.body is taken from html form or wtv 1) req.body is taken from html form or wtv
@ -108,31 +104,53 @@ async function addAPIKey(userId, permission) {
return token.id + "-" + hashtoken; return token.id + "-" + hashtoken;
} }
//api/v0/user/logout //api/v0/user/update
async function deleteUserToken(token) { async function updateProfile(user, body) {
//get row id if (!body.password) {
let splitAuthToken = token.split("-"); let updateUser = await userModel.update(
let rowid = splitAuthToken[0]; {
firstname: body.first_name,
//console.log(rowid); lastname: body.last_name,
username: body.username,
//delete from db email: body.email,
let delRes = await apikeyModel.destroy({ address: body.address,
where: { phone: body.phone,
id: rowid, },
{
where: {
id: user.id,
}, },
});
if (!delRes) return false;
return true;
} }
);
if (!updateUser) return false;
return true;
} else {
let hash = await hashPassword(body.password);
let updateUser = await userModel.update(
{
firstname: body.first_name,
lastname: body.last_name,
username: body.username,
email: body.email,
address: body.address,
phone: body.phone,
password: hash,
},
{
where: {
id: user.id,
},
}
);
if (!updateUser) return false;
return true;
}
}
module.exports = { module.exports = {
getUserID, getUserID,
addUser, addUser,
loginUser, loginUser,
updateProfile,
addAPIKey, addAPIKey,
deleteUserToken,
}; };

View File

@ -12,6 +12,7 @@ async function auth(req, res, next){
//get from db //get from db
let token = await apikeyModel.findByPk(rowid, {include: userModel}); let token = await apikeyModel.findByPk(rowid, {include: userModel});
if (!token) return false;
//compare //compare
let isMatch = await comparePassword(suppliedToken, token.apikey); let isMatch = await comparePassword(suppliedToken, token.apikey);
@ -20,7 +21,7 @@ async function auth(req, res, next){
//else do logic //else do logic
//pass hashed token to req.token (IMPORTANT ITS NOT PASSED TO CLIENT) //pass hashed token to req.token (IMPORTANT ITS NOT PASSED TO CLIENT)
req.token = token req.token = token
req.user = await token.getUser(); req.user = await token.getUser(); //taking user seq obj from usermodel
next(); next();
}catch(error){ }catch(error){
next(error); next(error);

View File

@ -3813,3 +3813,12 @@
.card-text { .card-text {
color: #000000; color: #000000;
} }
/* edit profile */
.profile {
margin: auto;
width: 40%;
border: 1px solid #000000;
padding: 10px;
}

View File

@ -1,100 +0,0 @@
.btn-delete {
background-color: red;
color: white;
}
.ui-w-80 {
width: 80px !important;
height: auto;
}
.btn-default {
border-color: rgba(24,28,33,0.1);
background: rgba(0,0,0,0);
color: #4E5155;
}
label.btn {
margin-bottom: 0;
}
.btn-outline-primary {
border-color: #26B4FF;
background: transparent;
color: #26B4FF;
}
.btn {
cursor: pointer;
}
.text-light {
color: #babbbc !important;
}
.btn-facebook {
border-color: rgba(0,0,0,0);
background: #3B5998;
color: #fff;
}
.btn-instagram {
border-color: rgba(0,0,0,0);
background: #000;
color: #fff;
}
.card {
background-clip: padding-box;
box-shadow: 0 1px 4px rgba(24,28,33,0.012);
}
.row-bordered {
overflow: hidden;
}
.account-settings-fileinput {
position: absolute;
visibility: hidden;
width: 1px;
height: 1px;
opacity: 0;
}
.account-settings-links .list-group-item.active {
font-weight: bold !important;
}
html:not(.dark-style) .account-settings-links .list-group-item.active {
background: transparent !important;
}
.account-settings-multiselect ~ .select2-container {
width: 100% !important;
}
.light-style .account-settings-links .list-group-item {
padding: 0.85rem 1.5rem;
border-color: rgba(24, 28, 33, 0.03) !important;
}
.light-style .account-settings-links .list-group-item.active {
color: #4e5155 !important;
}
.material-style .account-settings-links .list-group-item {
padding: 0.85rem 1.5rem;
border-color: rgba(24, 28, 33, 0.03) !important;
}
.material-style .account-settings-links .list-group-item.active {
color: #4e5155 !important;
}
.dark-style .account-settings-links .list-group-item {
padding: 0.85rem 1.5rem;
border-color: rgba(255, 255, 255, 0.03) !important;
}
.dark-style .account-settings-links .list-group-item.active {
color: #fff !important;
}
.light-style .account-settings-links .list-group-item.active {
color: #4E5155 !important;
}
.light-style .account-settings-links .list-group-item {
padding: 0.85rem 1.5rem;
border-color: rgba(24,28,33,0.03) !important;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.4 KiB

View File

@ -159,7 +159,15 @@ app.auth = (function (app) {
if (getToken()) { if (getToken()) {
return app.api.get("user/me", function (error, data) { return app.api.get("user/me", function (error, data) {
if (!error) app.auth.user = data; if (!error) app.auth.user = data;
//$.scope.getUsername.push(data); //for navbar to show username
$.scope.getUsername.update(data);
//for edit profile to show user details
//if not in edit profile page, it will not show
if (location.pathname === "/profile")
{
$.scope.getUserDetails.update(data);
}
return callback(error, data); return callback(error, data);
}); });
} else { } else {
@ -167,16 +175,6 @@ app.auth = (function (app) {
} }
} }
function showUser(){
app.api.get("user/me", function (error, data) {
if (!error) app.auth.user = data;
$.scope.getUsername.push(data);
});
}
function logOut(callback) { function logOut(callback) {
//call logout route //call logout route
$.ajax({ $.ajax({
@ -217,19 +215,13 @@ app.auth = (function (app) {
} }
function homeRedirect() { function homeRedirect() {
window.location.href = location.href.replace(location.replace(`/`)) || "/"; //window.location.href = location.href.replace(location.replace(`/`)) || "/";
location.replace(`/`);
} }
/*
function redirectIfLoggedIn() { function profileRedirect() {
if (getToken()){ location.replace(`/profile`);
homeRedirect();
} }
logInRedirect();
}
*/
return { return {
getToken: getToken, getToken: getToken,
@ -239,11 +231,33 @@ app.auth = (function (app) {
forceLogin, forceLogin,
logInRedirect, logInRedirect,
homeRedirect, homeRedirect,
showUser, profileRedirect,
//showUser,
//redirectIfLoggedIn, //redirectIfLoggedIn,
}; };
})(app); })(app);
app.user = (function (app) {
//delete profile
function deleteProfile() {
app.api.delete("user/delete", function (error, data) {
if (error) {
app.util.actionMessage(error.message, $("#deleteProfile"), "danger");
} else {
app.auth.logOut(function () {
location.replace(`/login`);
});
}
});
}
return {
deleteProfile,
};
})(app);
//ajax form submit and pass to api //ajax form submit and pass to api
function formAJAX(btn, del) { function formAJAX(btn, del) {
event.preventDefault(); // avoid to execute the actual submit of the form. event.preventDefault(); // avoid to execute the actual submit of the form.
@ -251,11 +265,6 @@ function formAJAX(btn, del) {
var formData = $form.find("[name]").serializeObject(); // builds query formDataing var formData = $form.find("[name]").serializeObject(); // builds query formDataing
var method = $form.attr("method") || "post"; var method = $form.attr("method") || "post";
// if( !$form.validate()) {
// app.util.actionMessage('Please fix the form errors.', $form, 'danger')
// return false;
// }
app.util.actionMessage("Loading...", $form, "info"); app.util.actionMessage("Loading...", $form, "info");
//console.log('Data being sent to', $form.attr('action'), formData) //console.log('Data being sent to', $form.attr('action'), formData)

View File

@ -1,4 +1,4 @@
const { getUserID , deleteUserToken } = require("../functions/apiDatabase.js"); const { getUserID, updateProfile } = require("../functions/apiDatabase.js");
const express = require("express"); const express = require("express");
const router = express.Router(); const router = express.Router();
@ -16,15 +16,13 @@ router.get("/me", async function (req, res, next) {
res.json({ res.json({
user: user, user: user,
}); });
} catch (error) { } catch (error) {
next(error); next(error);
} }
}); });
//logout //logout
router.delete('/logout', async function(req, res, next){ router.delete("/logout", async function (req, res, next) {
try { try {
/* /*
let authToken = req.header('auth-token'); let authToken = req.header('auth-token');
@ -42,16 +40,44 @@ router.delete('/logout', async function(req, res, next){
res.json({ res.json({
message: "User logged out successfully", message: "User logged out successfully",
}); });
} catch (error) { } catch (error) {
next(error); next(error);
} }
}); });
//update //update
router.put("/update", async function (req, res, next) {
try {
if (!req.body.password) {
let updateRes = await updateProfile(req.user, req.body);
if (!updateRes) return next(error);
console.log(updateRes);
res.json({
message: "User updated successfully",
});
} else {
let updateRes = await updateProfile(req.user, req.body);
if (!updateRes) return next(error);
res.json({
message: "User updated successfully",
});
}
} catch (error) {
next(error);
}
});
//delete //delete
router.delete("/delete", async function (req, res, next) {
//https://stackoverflow.com/questions/23128816/sequelize-js-ondelete-cascade-is-not-deleting-records-sequelize
//destroy method call on seq object
req.token.destroy({
onDelete: "cascade",
});
req.user.destroy();
res.json({
message: "User deleted successfully",
});
});
module.exports = router; module.exports = router;

View File

@ -394,5 +394,5 @@
</div> </div>
</body> </body>
<script src="js/api.js"></script>
</html> </html>

View File

@ -81,11 +81,7 @@
</p> </p>
</div> </div>
</footer> </footer>
<script src="js/learnmore.js"></script>
<script src="js/search.js"></script> <script src="js/search.js"></script>
<script src="js/api.js"></script>
</body> </body>
</html> </html>

View File

@ -38,5 +38,7 @@
<br> <br>
<br> <br>
<script src="js/learnmore.js"></script>
<%- include('bot') %> <%- include('bot') %>

View File

@ -6,7 +6,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="description" content=""> <meta name="description" content="">
<meta name="author" content=""> <meta name="author" content="">
<link rel="shortcut icon" type="images/logo.ico" href="images/logo.ico" />
<!-- Bootstrap core CSS --> <!-- Bootstrap core CSS -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet" <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet"
integrity="sha384-T3c6CoIi6uLrA9TneNEoa7RxnatzjcDSCmG1MXxSR1GAsXEV/Dwwykc2MPK8M2HN" crossorigin="anonymous"> integrity="sha384-T3c6CoIi6uLrA9TneNEoa7RxnatzjcDSCmG1MXxSR1GAsXEV/Dwwykc2MPK8M2HN" crossorigin="anonymous">

View File

@ -1,112 +1,111 @@
<%- include('top') %> <%- include('top') %>
<link href="css/profile.css" rel="stylesheet" />
<div class="full-title">
<div class="container">
<h1 class="mt-4 mb-3">Profile
</h1>
</div>
</div>
<br> <br>
<br> <br>
<div class="container light-style flex-grow-1 container-p-y">
<div class="card overflow-hidden">
<div class="row no-gutters row-bordered row-border-light">
<div class="col-md-3 pt-0">
<div class="list-group list-group-flush account-settings-links">
<a class="list-group-item list-group-item-action active" data-toggle="list"
href="#account-general">General</a>
<a class="list-group-item list-group-item-action" data-toggle="list"
href="#account-change-password">Change password</a>
</div>
</div>
<div class="col-md-9">
<div class="tab-content">
<div class="tab-pane fade active show" id="account-general">
<div class="card-body media align-items-center">
<img src="https://bootdey.com/img/Content/avatar/avatar1.png" alt=""
class="d-block ui-w-80">
<br> <br>
<div class="media-body ml-4"> <div class="profile">
<label class="btn btn-outline-primary"> <!-- <li jq-repeat="getUsername" class="nav-item"> -->
Upload new photo <div class="edit_information" jq-repeat="getUserDetails">
<input type="file" class="account-settings-fileinput"> <div class="card-header shadow actionMessage" style="display:none"></div>
</label> &nbsp; <form id="profileForm" action="user/update" method="put" onsubmit="formAJAX(this)"
<div class="text-light small mt-1">Allowed JPG, GIF or PNG. Max size of 800K</div> evalAJAX="app.auth.profileRedirect();">
</div> <h3 class="text-center">Edit Personal Information</h3>
</div>
<hr class="border-light m-0">
<div class="card-body">
<div class="form-group">
<label class="form-label">Username</label>
<input type="text" class="form-control mb-1" value="">
</div>
<div class="form-group">
<label class="form-label">First Name</label>
<input type="text" class="form-control" value="">
</div>
<div class="form-group">
<label class="form-label">Last Name</label>
<input type="text" class="form-control" value="">
</div>
<div class="form-group">
<label class="form-label">E-mail</label>
<input type="text" class="form-control mb-1" value="">
<div class="alert alert-warning mt-3">
Your email is not confirmed. Please check your inbox.<br>
<a href="javascript:void(0)">Resend confirmation</a>
</div>
</div>
<div class="form-group">
<label class="form-label">Phone Number</label>
<input type="text" class="form-control" value="">
</div>
<div class="form-group">
<label class="form-label">Address</label>
<input type="text" class="form-control" value="">
</div>
</div>
</div>
<div class="tab-pane fade" id="account-change-password">
<div class="card-body pb-2">
<div class="form-group">
<label class="form-label">Current password</label>
<input type="password" class="form-control">
</div>
<div class="form-group">
<label class="form-label">New password</label>
<input type="password" class="form-control">
</div>
<div class="form-group">
<label class="form-label">Repeat new password</label>
<input type="password" class="form-control">
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="text-right mt-3">
<button type="button" class="btn btn-primary">Save changes</button>&nbsp;
<button type="button" class="btn btn-default">Cancel</button>
<button type="button" class="btn btn-delete">Delete Account</button>
</div>
</div>
<br> <br>
<div class="row">
<div class="col-lg-12 col-md-12 col-sm-12 col-xs-12">
<div class="form-group">
<label class="profile_details_text">First Name:</label>
<input type="text" name="first_name" value="{{ user.firstname }}" class="form-control"
pattern="^[a-zA-Z\s]+$">
</div>
</div>
</div>
<div class="row">
<div class="col-lg-12 col-md-12 col-sm-12 col-xs-12">
<div class="form-group">
<label class="profile_details_text">Last Name: </label>
<input type="text" name="last_name" value="{{ user.lastname }}" class="form-control"
pattern="^[a-zA-Z\s]+$">
</div>
</div>
</div>
<div class="row">
<div class="col-lg-12 col-md-12 col-sm-12 col-xs-12">
<div class="form-group">
<label class="profile_details_text">Username:</label>
<input type="text" name="username" value="{{ user.username }}" class="form-control"
pattern="^\w+$">
</div>
</div>
</div>
<div class="row">
<div class="col-lg-12 col-md-12 col-sm-12 col-xs-12">
<div class="form-group">
<label class="profile_details_text">Password:</label>
<input type="password" name="password" placeholder="Password" class="form-control" value=""
pattern="^(?=.*[A-Za-z])(?=.*\d)(?=.*[@$!%*#?&])[A-Za-z\d@$!%*#?&]{8,}$">
</div>
</div>
</div>
<div class="row">
<div class="col-lg-12 col-md-12 col-sm-12 col-xs-12">
<div class="form-group">
<label class="profile_details_text">Email Address:</label>
<input type="email" name="email" value="{{user.email}}" class="form-control"
pattern="\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*">
</div>
</div>
</div>
<div class="row">
<div class="col-lg-12 col-md-12 col-sm-12 col-xs-12">
<div class="form-group">
<label class="profile_details_text">Address:</label>
<input type="text" name="address" value="{{ user.address }}" class="form-control"
pattern="^(\d{1,3}.)?.+\s(\d{6})$">
</div>
</div>
</div>
<div class="row">
<div class="col-lg-12 col-md-12 col-sm-12 col-xs-12">
<div class="form-group">
<label class="profile_details_text">Phone Number:</label>
<input type="tel" name="phone" value="{{ user.phone }}" class="form-control" value=""
pattern="^[\+]?[(]?[0-9]{3}[)]?[-\s\.]?[0-9]{3}[-\s\.]?[0-9]{4,8}$">
</div>
</div>
</div>
<br>
<div class="row justify-content-center mt-3">
<div class="col-lg-6 col-md-6 col-sm-6 col-xs-6 submit">
<div class="form-group text-center">
<input type="submit" class="btn btn-success updateButton" value="Update Profile">
</div>
</div>
<div class="col-lg-6 col-md-6 col-sm-6 col-xs-6 text-center">
<button type="button" class="btn btn-danger deleteButton" onclick="return myConfirm();">Delete
Profile</button>
</div>
</div>
</form>
</div>
</div>
<br>
<br>
<br>
<br>
<br>
<br>
<script>
function myConfirm() {
var result = confirm("Do you wish to Delete your Profile");
if (result == true) {
app.user.deleteProfile();
} else {
return false;
}
}
</script>
<%- include('bot') %> <%- include('bot') %>

View File

@ -9,6 +9,7 @@
<div class="form signup iot-card"> <div class="form signup iot-card">
<!--<div class="form signup card" --> <!--<div class="form signup card" -->
<header>Signup</header> <header>Signup</header>
<div class="card-header shadow actionMessage" style="display:none"></div>
<!-- localhost/api/v0/user/register --> <!-- localhost/api/v0/user/register -->
<!-- evalAjax Fires when status 200 is returned --> <!-- evalAjax Fires when status 200 is returned -->
<form action="auth/register" onsubmit="formAJAX(this)" evalAJAX="app.auth.logInRedirect();"> <form action="auth/register" onsubmit="formAJAX(this)" evalAJAX="app.auth.logInRedirect();">
@ -35,7 +36,7 @@
<form action="auth/login" onsubmit="formAJAX(this)" evalAJAX="app.auth.homeRedirect(); <form action="auth/login" onsubmit="formAJAX(this)" evalAJAX="app.auth.homeRedirect();
app.auth.setToken(data.token);"> app.auth.setToken(data.token);">
<input type="text" name="username" placeholder="Email address | Username" required <input type="text" name="username" placeholder="Email address | Username" required
pattern="^\w+$" /> pattern="^(\w+@\w+\.\w+)$|^\w+$"/>
<input type="password" name="password" placeholder="Password" required /> <input type="password" name="password" placeholder="Password" required />
<a href="/forgotpassword">Forgot password?</a> <a href="/forgotpassword">Forgot password?</a>
<input type="submit" value="Login" /> <input type="submit" value="Login" />

View File

@ -10,6 +10,8 @@
<meta http-equiv="cleartype" content="on" /> <meta http-equiv="cleartype" content="on" />
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" /> <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="shortcut icon" type="images/logo.ico" href="images/logo.ico" />
<!-- Bootstrap core CSS --> <!-- Bootstrap core CSS -->
<link <link
@ -58,7 +60,6 @@
//check if user is logged in //check if user is logged in
app.auth.isLoggedIn(function (error, data) { app.auth.isLoggedIn(function (error, data) {
if (data) { if (data) {
app.auth.showUser();
$("#cl-logout-button").show("fast"); $("#cl-logout-button").show("fast");
$("#cl-profile-button").show("fast"); $("#cl-profile-button").show("fast");
$("#cl-login-button").hide("fast"); $("#cl-login-button").hide("fast");