Change password dialog layout finished

This commit is contained in:
Martin Araneda 2023-02-09 23:38:39 -03:00 committed by Chris Cromer
parent 4d6050b394
commit fbb6c0c265
Signed by: cromer
GPG Key ID: FA91071797BEEEC2
11 changed files with 196 additions and 144 deletions

View File

@ -11,7 +11,9 @@
"lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs --fix --ignore-path .gitignore"
},
"dependencies": {
"axios": "^1.3.2",
"chart.js": "^4.2.0",
"file-saver": "^2.0.5",
"pinia": "^2.0.28",
"primeflex": "^3.3.0",
"primeicons": "^6.0.1",
@ -22,6 +24,7 @@
"devDependencies": {
"@playwright/test": "^1.28.1",
"@rushstack/eslint-patch": "^1.1.4",
"@types/file-saver": "^2.0.5",
"@vitejs/plugin-vue": "^4.0.0",
"@vue/eslint-config-prettier": "^7.0.0",
"@vue/test-utils": "^2.2.6",

Binary file not shown.

Binary file not shown.

View File

@ -1,104 +1,141 @@
<script setup>
import { ref, computed, onMounted, onBeforeUnmount } from 'vue';
import { useLayout } from '@/layout/composables/layout';
import { useRouter } from 'vue-router';
import { ref, computed, onMounted, onBeforeUnmount } from 'vue';
import { useLayout } from '@/layout/composables/layout';
import { useRouter } from 'vue-router';
import { useToast } from 'primevue/usetoast';
const { onMenuToggle } = useLayout();
const { onMenuToggle } = useLayout();
const outsideClickListener = ref(null);
const topbarMenuActive = ref(false);
const router = useRouter();
const outsideClickListener = ref(null);
const topbarMenuActive = ref(false);
const changePasswordDialog = ref(false);
const router = useRouter();
const user = ref({});
const submitted = ref(false);
const toast = useToast();
const menu = ref();
const items = ref([
{
label: 'Log out',
icon: 'pi pi-sign-out',
command: () => {
toast.add({ severity: 'warn', summary: 'Delete', detail: 'Data Deleted', life: 3000 });
localStorage.removeItem('token');
router.push('/');
}
},
{
label: 'Change password',
icon: 'pi pi-key',
command: () => {
changePasswordDialog.value = true;
submitted.value = false;
user.value = {};
}
}
]);
onMounted(() => {
bindOutsideClickListener();
});
const toggle = (event) => {
menu.value.toggle(event);
};
onBeforeUnmount(() => {
unbindOutsideClickListener();
});
onMounted(() => {
bindOutsideClickListener();
});
const onTopBarMenuButton = () => {
topbarMenuActive.value = !topbarMenuActive.value;
onBeforeUnmount(() => {
unbindOutsideClickListener();
});
const onClickPasswordChange = () => {
submitted.value = true;
}
const onTopBarMenuButton = () => {
topbarMenuActive.value = !topbarMenuActive.value;
};
const topbarMenuClasses = computed(() => {
return {
'layout-topbar-menu-mobile-active': topbarMenuActive.value
};
const onSettingsClick = () => {
topbarMenuActive.value = false;
router.push('/documentation');
};
const topbarMenuClasses = computed(() => {
return {
'layout-topbar-menu-mobile-active': topbarMenuActive.value
});
const bindOutsideClickListener = () => {
if (!outsideClickListener.value) {
outsideClickListener.value = (event) => {
if (isOutsideClicked(event)) {
topbarMenuActive.value = false;
}
};
});
document.addEventListener('click', outsideClickListener.value);
}
};
const unbindOutsideClickListener = () => {
if (outsideClickListener.value) {
document.removeEventListener('click', outsideClickListener);
outsideClickListener.value = null;
}
};
const isOutsideClicked = (event) => {
if (!topbarMenuActive.value) return;
const bindOutsideClickListener = () => {
if (!outsideClickListener.value) {
outsideClickListener.value = (event) => {
if (isOutsideClicked(event)) {
topbarMenuActive.value = false;
}
};
document.addEventListener('click', outsideClickListener.value);
}
};
const unbindOutsideClickListener = () => {
if (outsideClickListener.value) {
document.removeEventListener('click', outsideClickListener);
outsideClickListener.value = null;
}
};
const isOutsideClicked = (event) => {
if (!topbarMenuActive.value) return;
const sidebarEl = document.querySelector('.layout-topbar-menu');
const topbarEl = document.querySelector('.layout-topbar-menu-button');
const sidebarEl = document.querySelector('.layout-topbar-menu');
const topbarEl = document.querySelector('.layout-topbar-menu-button');
return !(sidebarEl.isSameNode(event.target) || sidebarEl.contains(event.target) || topbarEl.isSameNode(event.target) || topbarEl.contains(event.target));
};
return !(sidebarEl.isSameNode(event.target) || sidebarEl.contains(event.target) || topbarEl.isSameNode(event.target) || topbarEl.contains(event.target));
};
</script>
<template>
<div class="layout-topbar">
<button
class="p-link layout-menu-button layout-topbar-button"
@click="onMenuToggle()"
>
<button class="p-link layout-menu-button layout-topbar-button" @click="onMenuToggle()">
<i class="pi pi-bars"></i>
</button>
<button
class="p-link layout-topbar-menu-button layout-topbar-button"
@click="onTopBarMenuButton()"
>
<button class="p-link layout-topbar-menu-button layout-topbar-button" @click="onTopBarMenuButton()">
<i class="pi pi-ellipsis-v"></i>
</button>
<div
class="layout-topbar-menu"
:class="topbarMenuClasses"
>
<button
@click="onTopBarMenuButton()"
class="p-link layout-topbar-button"
>
<i class="pi pi-calendar"></i>
<span>Calendar</span>
</button>
<button
@click="onTopBarMenuButton()"
class="p-link layout-topbar-button"
>
<div class="layout-topbar-menu" :class="topbarMenuClasses">
<button @click="toggle" class="p-link layout-topbar-button">
<i class="pi pi-user"></i>
<span>Profile</span>
</button>
<button
@click="onSettingsClick()"
class="p-link layout-topbar-button"
>
<i class="pi pi-cog"></i>
<span>Settings</span>
</button>
<Menu id="overlay_menu" ref="menu" :model="items" :popup="true" />
</div>
<Dialog v-model:visible="changePasswordDialog" :style="{ width: '450px' }" header="Change Password"
:modal="true" class="p-fluid">
<div class="field">
<label for="current_password">Current Password</label>
<InputText id="current_password" v-model.trim="user.current_password" required="true" autofocus
:class="{ 'p-invalid': submitted && !user.current_password }" />
<small class="p-invalid" v-if="submitted && !user.current_password">Actual password is required.</small>
</div>
<div class="field">
<label for="new_password">New Password</label>
<InputText id="new_password" v-model.trim="user.new_password" required="true" autofocus
:class="{ 'p-invalid': submitted && !user.new_password }" />
<small class="p-invalid" v-if="submitted && !user.new_password">New password is required.</small>
</div>
<div class="field">
<label for="confirm_new_password">Confirm new Password</label>
<InputText id="confirm_new_password" v-model.trim="user.confirm_new_password" required="true" autofocus
:class="{ 'p-invalid': submitted && !user.confirm_new_password }" />
<small class="p-invalid" v-if="submitted && !user.confirm_new_password">Confirm the new password is
required.</small>
</div>
<template #footer>
<Button label="Cancel" icon="pi pi-times" class="p-button-text" @click="hideDialog" />
<Button label="Save" icon="pi pi-check" class="p-button-text" @click="onClickPasswordChange" />
</template>
</Dialog>
</div>
</template>
<style lang="scss" scoped></style>
<style lang="scss" scoped>
</style>

View File

@ -21,6 +21,7 @@ import Textarea from 'primevue/textarea';
import RadioButton from 'primevue/radiobutton';
import InputNumber from 'primevue/inputnumber';
import Dialog from 'primevue/dialog';
import Menu from 'primevue/menu';
import '@/assets/styles.scss';
@ -49,6 +50,7 @@ app.component('Textarea', Textarea);
app.component('RadioButton', RadioButton);
app.component('InputNumber', InputNumber);
app.component('Dialog', Dialog);
app.component('Menu', Menu);
app.mount('#app');

View File

@ -1,11 +1,18 @@
<script setup>
import { saveAs } from 'file-saver';
const smoothScroll = (id) => {
document.querySelector(id).scrollIntoView({
behavior: 'smooth'
});
};
const onClickWindows = () => {
saveAs("/game/alai-1.0.0.zip", "alai-1.0.0.zip");
}
const onClickLinux = () => {
saveAs("/game/alai-1.0.0.tar.gz", "alai-1.0.0.tar.gz");
}
</script>
<template>
@ -23,7 +30,7 @@ const smoothScroll = (id) => {
<ul
class="list-none p-0 m-0 flex lg:align-items-center select-none flex-column lg:flex-row cursor-pointer">
<li>
<router-link to="/home"
<router-link to="/"
class="flex m-0 md:ml-5 px-0 py-3 text-900 font-medium line-height-3 p-ripple" v-ripple>
<span>Home</span>
</router-link>
@ -116,6 +123,31 @@ const smoothScroll = (id) => {
</div>
</div>
<div id="downloads" class="py-4 px-4 lg:px-8 mx-0 my-6 lg:mx-8">
<div class="text-center">
<h2 class="text-900 font-normal mb-6">Downloads</h2>
</div>
<div class="flex justify-content-center p-4 flex-order-1 lg:flex-order-0" style="border-radius: 8px">
<Button @click="onClickWindows()" class="flex justify-content-center p-button-lg px-0 w-2 mr-4">
<i class="pi pi-microsoft px-1"></i>
<span class="px-2">
Windows
</span>
</Button>
<Button @click="onClickLinux()" class="flex justify-content-center p-button-lg px-0 w-2 ml-4">
<i class="pi pi-globe px-1"></i>
<span class="px-2">
Linux
</span>
</Button>
</div>
</div>
<div class="py-4 px-4 mx-0 mt-8 lg:mx-8">

View File

@ -32,6 +32,10 @@ async function onShowClick() {
}
async function onCreateClick() {
submitted.value = true;
if (os.value.name === "") {
throw new Error("name empty");
}
var newOS =
{
name: os.value.name

View File

@ -32,6 +32,16 @@ async function onShowClick() {
}
async function onCreateClick() {
submitted.value = true;
if (user.value.name === "") {
throw new Error("name empty");
}
else if (user.value.username === "") {
throw new Error("username empty");
}
else if (user.value.email === "") {
throw new Error("email empty");
}
var newUser =
{
name: user.value.name,

View File

@ -207,6 +207,11 @@
resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.3.4.tgz#e913e8175db8307d78b4e8fa690408ba6b65dee4"
integrity sha512-KnRanxnpfpjUTqTCXslZSEdLfXExwgNxYPdiO2WGUj8+HDjFi8R3k5RVKPeSCzLjCcshCAtVO2QBbVuAV4kTnw==
"@types/file-saver@^2.0.5":
version "2.0.5"
resolved "https://registry.yarnpkg.com/@types/file-saver/-/file-saver-2.0.5.tgz#9ee342a5d1314bb0928375424a2f162f97c310c7"
integrity sha512-zv9kNf3keYegP5oThGLaPk8E081DFDuwfqjtiTzm6PoxChdJ1raSuADf2YGCVIyrSynLrgc8JWv296s7Q7pQSQ==
"@types/node@*":
version "18.11.18"
resolved "https://registry.yarnpkg.com/@types/node/-/node-18.11.18.tgz#8dfb97f0da23c2293e554c5a50d61ef134d7697f"
@ -405,6 +410,15 @@ asynckit@^0.4.0:
resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==
axios@^1.3.2:
version "1.3.2"
resolved "https://registry.yarnpkg.com/axios/-/axios-1.3.2.tgz#7ac517f0fa3ec46e0e636223fd973713a09c72b3"
integrity sha512-1M3O703bYqYuPhbHeya5bnhpYVsDDRyQSabNja04mZtboLNSuZ4YrltestrLXfHgmzua4TpUqRiVKbiQuo2epw==
dependencies:
follow-redirects "^1.15.0"
form-data "^4.0.0"
proxy-from-env "^1.1.0"
balanced-match@^1.0.0:
version "1.0.2"
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee"
@ -822,6 +836,11 @@ file-entry-cache@^6.0.1:
dependencies:
flat-cache "^3.0.4"
file-saver@^2.0.5:
version "2.0.5"
resolved "https://registry.yarnpkg.com/file-saver/-/file-saver-2.0.5.tgz#d61cfe2ce059f414d899e9dd6d4107ee25670c38"
integrity sha512-P9bmyZ3h/PRG+Nzga+rbdI4OEpNDzAVyy74uVO9ATgzLK6VtAsYybF/+TOCvrc0MO793d6+42lLyZTw7/ArVzA==
fill-range@^7.0.1:
version "7.0.1"
resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40"
@ -850,6 +869,11 @@ flatted@^3.1.0:
resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.7.tgz#609f39207cb614b89d0765b477cb2d437fbf9787"
integrity sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==
follow-redirects@^1.15.0:
version "1.15.2"
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.2.tgz#b460864144ba63f2681096f274c4e57026da2c13"
integrity sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==
form-data@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452"
@ -1374,6 +1398,11 @@ primevue@^3.22.3:
resolved "https://registry.yarnpkg.com/primevue/-/primevue-3.22.3.tgz#62253c8477fec090e86b0ca74493b34b48a3b5a0"
integrity sha512-0s40+wc7YvuGzx0giT9/xxJctV2OXwgSdu3+LEa21CIg5+IWmTIlKXwaPaWKuFVuO8tKz8BrQr0Va0j4SObYKw==
proxy-from-env@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2"
integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==
psl@^1.1.33:
version "1.9.0"
resolved "https://registry.yarnpkg.com/psl/-/psl-1.9.0.tgz#d0df2a137f00794565fcaf3b2c00cd09f8d5a5a7"

View File

@ -1,5 +0,0 @@
{
"dependencies": {
"axios": "^1.2.6"
}
}

View File

@ -1,60 +0,0 @@
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1
asynckit@^0.4.0:
version "0.4.0"
resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==
axios@^1.2.6:
version "1.2.6"
resolved "https://registry.yarnpkg.com/axios/-/axios-1.2.6.tgz#eacb6d065baa11bad5959e7ffa0cb6745c65f392"
integrity sha512-rC/7F08XxZwjMV4iuWv+JpD3E0Ksqg9nac4IIg6RwNuF0JTeWoCo/mBNG54+tNhhI11G3/VDRbdDQTs9hGp4pQ==
dependencies:
follow-redirects "^1.15.0"
form-data "^4.0.0"
proxy-from-env "^1.1.0"
combined-stream@^1.0.8:
version "1.0.8"
resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f"
integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==
dependencies:
delayed-stream "~1.0.0"
delayed-stream@~1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619"
integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==
follow-redirects@^1.15.0:
version "1.15.2"
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.2.tgz#b460864144ba63f2681096f274c4e57026da2c13"
integrity sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==
form-data@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452"
integrity sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==
dependencies:
asynckit "^0.4.0"
combined-stream "^1.0.8"
mime-types "^2.1.12"
mime-db@1.52.0:
version "1.52.0"
resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70"
integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==
mime-types@^2.1.12:
version "2.1.35"
resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a"
integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==
dependencies:
mime-db "1.52.0"
proxy-from-env@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2"
integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==