From 72b9bb1383879c609e84e7ee4a9d8fdc33c7c3d1 Mon Sep 17 00:00:00 2001
From: samaradel
Date: Tue, 11 Feb 2025 19:56:33 +0200
Subject: [PATCH 01/11] init Admin page
---
client/src/router/index.js | 24 +-
client/src/services/userService.js | 10 +-
client/src/store/UserStore.js | 14 +-
client/src/views/Admin.vue | 717 ++++++++----------
.../{tabs => accManagemenTabs}/AuditLogs.vue | 0
.../ChangePassword.vue | 0
.../DeleteAccount.vue | 0
.../{tabs => accManagemenTabs}/Invoices.vue | 0
.../{tabs => accManagemenTabs}/Payments.vue | 0
.../{tabs => accManagemenTabs}/Profile.vue | 0
client/src/views/adminTabs/History.vue | 5 +
client/src/views/adminTabs/Requests.vue | 260 +++++++
12 files changed, 625 insertions(+), 405 deletions(-)
rename client/src/views/{tabs => accManagemenTabs}/AuditLogs.vue (100%)
rename client/src/views/{tabs => accManagemenTabs}/ChangePassword.vue (100%)
rename client/src/views/{tabs => accManagemenTabs}/DeleteAccount.vue (100%)
rename client/src/views/{tabs => accManagemenTabs}/Invoices.vue (100%)
rename client/src/views/{tabs => accManagemenTabs}/Payments.vue (100%)
rename client/src/views/{tabs => accManagemenTabs}/Profile.vue (100%)
create mode 100644 client/src/views/adminTabs/History.vue
create mode 100644 client/src/views/adminTabs/Requests.vue
diff --git a/client/src/router/index.js b/client/src/router/index.js
index 2dc44db3..dba083c8 100644
--- a/client/src/router/index.js
+++ b/client/src/router/index.js
@@ -5,14 +5,16 @@ import Account from "@/views/Account.vue";
import VM from "@/views/VM.vue";
import Admin from "@/views/Admin.vue";
import NewPassword from "@/views/Newpassword.vue";
-import ProfileTab from "@/views/tabs/Profile.vue";
-import PaymentsTab from "@/views/tabs/Payments.vue";
-import Invoices from "@/views/tabs/Invoices.vue";
-import ChangePassword from "@/views/tabs/ChangePassword.vue";
-import AuditLogs from "@/views/tabs/AuditLogs.vue";
-import DeleteAccount from "@/views/tabs/DeleteAccount.vue";
+import ProfileTab from "@/views/accManagemenTabs/Profile.vue";
+import PaymentsTab from "@/views/accManagemenTabs/Payments.vue";
+import Invoices from "@/views/accManagemenTabs/Invoices.vue";
+import ChangePassword from "@/views/accManagemenTabs/ChangePassword.vue";
+import AuditLogs from "@/views/accManagemenTabs/AuditLogs.vue";
+import DeleteAccount from "@/views/accManagemenTabs/DeleteAccount.vue";
import Deploy from "@/views/Deploy.vue";
import Home from "@/views/HomeWrapper.vue";
+import Requests from "@/views/adminTabs/Requests.vue";
+import History from "@/views/adminTabs/History.vue";
const routes = [
{
@@ -149,6 +151,16 @@ const routes = [
layout: "Default",
requiresAuth: true,
},
+ children: [
+ {
+ path: "",
+ component: Requests,
+ },
+ {
+ path: "history",
+ component: History,
+ },
+ ],
},
{
path: "/logout",
diff --git a/client/src/services/userService.js b/client/src/services/userService.js
index 37121d18..f1f7be7a 100644
--- a/client/src/services/userService.js
+++ b/client/src/services/userService.js
@@ -255,7 +255,7 @@ export default {
// Deployments
async getDeploymentsCount() {
- return await authClient().get("/deployment/count");
+ return await authClient().get("/deployments/count");
},
// Vouchers
@@ -271,8 +271,8 @@ export default {
return await authClient().put("/voucher");
},
- async generateVoucher(length, vms, public_ips) {
- return await authClient().post("/voucher", { length, vms, public_ips });
+ async generateVoucher(balance, length) {
+ return await authClient().post("/voucher", { balance, length });
},
async getAuditEvents() {
@@ -323,8 +323,6 @@ export default {
// setting next launch value
async setNextLaunch(value) {
- return await authClient().put("/nextlaunch", {
- launched: value,
- });
+ return await authClient().put("/nextlaunch", { launched: value });
},
};
diff --git a/client/src/store/UserStore.js b/client/src/store/UserStore.js
index d0abd886..e4a1e031 100644
--- a/client/src/store/UserStore.js
+++ b/client/src/store/UserStore.js
@@ -9,8 +9,7 @@ export const useUserStore = defineStore("userStore", {
isLoaded: false,
notifications: [],
maintenance: false,
- next_launch: false,
- next_launch_admin: false,
+ next_launch_admin: true,
isAuthenticated: localStorage.getItem("token"),
}),
actions: {
@@ -60,13 +59,21 @@ export const useUserStore = defineStore("userStore", {
try {
const response = await userService.nextLaunch();
const { launched } = response.data.data;
- this.next_launch = launched;
this.next_launch_admin = launched;
} catch (error) {
return error;
}
},
+ async setNextLaunch(value) {
+ try {
+ const response = await userService.setNextLaunch(value);
+ return response
+ } catch (error) {
+ return error;
+ }
+ },
+
async checkMaintenance() {
try {
const response = await userService.maintenance();
@@ -79,5 +86,6 @@ export const useUserStore = defineStore("userStore", {
},
getters: {
isUserLoaded: (state) => state.isLoaded,
+ isNextLaunchEnabled: (state) => state.next_launch_admin,
},
});
diff --git a/client/src/views/Admin.vue b/client/src/views/Admin.vue
index 5a1c1e22..6682e63d 100644
--- a/client/src/views/Admin.vue
+++ b/client/src/views/Admin.vue
@@ -1,15 +1,74 @@
-
+
+ Admin Panel
+
+
-
-
- Admin Panel
-
+
+
+
+
+ Balance: {{ balance }} TFT
+
+
+ mdi-server
+
+ Used VMs: {{ usedResources }}
+ Deployed VMs: {{ deployedResources }}
+
+
+
+
+ mdi-ip
+
+ Used IPs: {{ usedIPs }}
+ Reserved IPs: {{ reservedIPs }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{
+ tab.name
+ }}
+
+
+
+
+
+
+ x``
+
+
+
+
+
-
-
+ -->
diff --git a/client/src/views/tabs/AuditLogs.vue b/client/src/views/accManagemenTabs/AuditLogs.vue
similarity index 100%
rename from client/src/views/tabs/AuditLogs.vue
rename to client/src/views/accManagemenTabs/AuditLogs.vue
diff --git a/client/src/views/tabs/ChangePassword.vue b/client/src/views/accManagemenTabs/ChangePassword.vue
similarity index 100%
rename from client/src/views/tabs/ChangePassword.vue
rename to client/src/views/accManagemenTabs/ChangePassword.vue
diff --git a/client/src/views/tabs/DeleteAccount.vue b/client/src/views/accManagemenTabs/DeleteAccount.vue
similarity index 100%
rename from client/src/views/tabs/DeleteAccount.vue
rename to client/src/views/accManagemenTabs/DeleteAccount.vue
diff --git a/client/src/views/tabs/Invoices.vue b/client/src/views/accManagemenTabs/Invoices.vue
similarity index 100%
rename from client/src/views/tabs/Invoices.vue
rename to client/src/views/accManagemenTabs/Invoices.vue
diff --git a/client/src/views/tabs/Payments.vue b/client/src/views/accManagemenTabs/Payments.vue
similarity index 100%
rename from client/src/views/tabs/Payments.vue
rename to client/src/views/accManagemenTabs/Payments.vue
diff --git a/client/src/views/tabs/Profile.vue b/client/src/views/accManagemenTabs/Profile.vue
similarity index 100%
rename from client/src/views/tabs/Profile.vue
rename to client/src/views/accManagemenTabs/Profile.vue
diff --git a/client/src/views/adminTabs/History.vue b/client/src/views/adminTabs/History.vue
new file mode 100644
index 00000000..26f8bd91
--- /dev/null
+++ b/client/src/views/adminTabs/History.vue
@@ -0,0 +1,5 @@
+
+ History
+
+
+
diff --git a/client/src/views/adminTabs/Requests.vue b/client/src/views/adminTabs/Requests.vue
new file mode 100644
index 00000000..b21a32c7
--- /dev/null
+++ b/client/src/views/adminTabs/Requests.vue
@@ -0,0 +1,260 @@
+
+
+
+
+
+ {{ index + 1 }}
+
+
+
+
+ {{ userAvatar(item.name) }}
+
+
+
{{ item.name }}
+
+ {{ item.email }}
+
+
+
+
+
+ A
+
+
+
Voucher generated by Admin
+
+
+
+
+ {{ formatDate(item.created_at) }}
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ index + 1 }}
+
+
+
+
+ {{ userAvatar(item.name) }}
+
+
+
{{ item.name }}
+
+ {{ item.email }}
+
+
+
+
+
+ A
+
+
+
Voucher generated by Admin
+
+
+
+
+ {{ formatDate(item.created_at) }}
+
+
+ mdi-information
+ mdi-account-lock
+
+
+
+
+
+
+
+
From 3accb0a66c07c570d4dab837083a972dec5fe9a6 Mon Sep 17 00:00:00 2001
From: samaradel
Date: Wed, 12 Feb 2025 17:15:25 +0200
Subject: [PATCH 02/11] Add javascript-time-ago package
---
client/package.json | 1 +
1 file changed, 1 insertion(+)
diff --git a/client/package.json b/client/package.json
index 2ec624ff..7c864cd4 100644
--- a/client/package.json
+++ b/client/package.json
@@ -15,6 +15,7 @@
"axios": "^1.7.2",
"core-js": "^3.33.2",
"file-saver": "^2.0.5",
+ "javascript-time-ago": "^2.5.11",
"jszip": "^3.10.1",
"mosha-vue-toastify": "^1.0.23",
"pinia": "^2.3.1",
From 83e13fd9a9b9f09e0617ae2d4c1daa5d611cce5e Mon Sep 17 00:00:00 2001
From: samaradel
Date: Wed, 12 Feb 2025 17:16:45 +0200
Subject: [PATCH 03/11] Calculate balance with voucher balance and display it
---
client/src/components/TopupPayment.vue | 17 +++--------------
client/src/layouts/default/AppBar.vue | 4 ++--
client/src/store/UserStore.js | 6 ++++--
3 files changed, 9 insertions(+), 18 deletions(-)
diff --git a/client/src/components/TopupPayment.vue b/client/src/components/TopupPayment.vue
index 7dc643e5..187f770c 100644
--- a/client/src/components/TopupPayment.vue
+++ b/client/src/components/TopupPayment.vue
@@ -14,7 +14,7 @@
- ${{ balance }}
+ ${{ getTotalBalance }}
current balance
@@ -111,7 +111,7 @@
diff --git a/client/src/layouts/default/AppBar.vue b/client/src/layouts/default/AppBar.vue
index eb253ab6..f49b5346 100644
--- a/client/src/layouts/default/AppBar.vue
+++ b/client/src/layouts/default/AppBar.vue
@@ -43,7 +43,7 @@
- Balance: ${{ user?.balance }}
+ Balance: ${{ getTotalBalance }}
@@ -133,7 +133,7 @@ const drawer = ref(false);
const isActive = ref(0);
const toast = ref(null);
const store = useUserStore();
-const { user, isLoading, notifications } = storeToRefs(store);
+const { user, isLoading, notifications, getTotalBalance } = storeToRefs(store);
const navItems = ref([
{ title: "Home", path: "/" },
diff --git a/client/src/store/UserStore.js b/client/src/store/UserStore.js
index e4a1e031..a9a500ea 100644
--- a/client/src/store/UserStore.js
+++ b/client/src/store/UserStore.js
@@ -32,7 +32,7 @@ export const useUserStore = defineStore("userStore", {
} catch (error) {
if (error.response.status == 401) {
localStorage.removeItem("token");
- router.push("/login");
+ router.push("/");
return error;
}
return error;
@@ -68,7 +68,7 @@ export const useUserStore = defineStore("userStore", {
async setNextLaunch(value) {
try {
const response = await userService.setNextLaunch(value);
- return response
+ return response;
} catch (error) {
return error;
}
@@ -87,5 +87,7 @@ export const useUserStore = defineStore("userStore", {
getters: {
isUserLoaded: (state) => state.isLoaded,
isNextLaunchEnabled: (state) => state.next_launch_admin,
+ getTotalBalance: (state) => state.user.balance + state.user.voucher_balance,
+ isAdmin: (state) => state.user.admin,
},
});
From 7e27161370fa8f7bd6d362e3bc9a2e92c13779ed Mon Sep 17 00:00:00 2001
From: samaradel
Date: Wed, 12 Feb 2025 17:17:31 +0200
Subject: [PATCH 04/11] Update timestamp format using time-ago package
---
.../src/views/accManagemenTabs/AuditLogs.vue | 22 ++++++++-----------
.../src/views/accManagemenTabs/Invoices.vue | 18 ++++++---------
2 files changed, 16 insertions(+), 24 deletions(-)
diff --git a/client/src/views/accManagemenTabs/AuditLogs.vue b/client/src/views/accManagemenTabs/AuditLogs.vue
index 3dd97eb0..885bdea1 100644
--- a/client/src/views/accManagemenTabs/AuditLogs.vue
+++ b/client/src/views/accManagemenTabs/AuditLogs.vue
@@ -14,7 +14,7 @@
- {{ formatDate(item.timestamp) }}
+ {{ timeAgo.format(convertDate(item.timestamp)) }}
@@ -26,7 +26,11 @@
import { ref, onMounted } from "vue";
import userService from "@/services/userService";
import Toast from "@/components/Toast.vue";
+import TimeAgo from "javascript-time-ago";
+import en from "javascript-time-ago/locale/en";
+TimeAgo.addLocale(en)
+const timeAgo = ref(new TimeAgo("en-US"));
const events = ref([]);
const toast = ref(null);
const loading = ref(false);
@@ -41,6 +45,10 @@ const headers = ref([
},
]);
+function convertDate(date) {
+ return new Date(date);
+}
+
async function getAuditEvents() {
loading.value = true;
await userService
@@ -58,18 +66,6 @@ async function getAuditEvents() {
});
}
-function formatDate(date) {
- var d = new Date(date),
- month = "" + (d.getMonth() + 1),
- day = "" + d.getDate(),
- year = d.getFullYear();
-
- if (month.length < 2) month = "0" + month;
- if (day.length < 2) day = "0" + day;
-
- return [day, month, year].join("-");
-}
-
onMounted(async () => {
await getAuditEvents();
});
diff --git a/client/src/views/accManagemenTabs/Invoices.vue b/client/src/views/accManagemenTabs/Invoices.vue
index 4f297079..5978b08f 100644
--- a/client/src/views/accManagemenTabs/Invoices.vue
+++ b/client/src/views/accManagemenTabs/Invoices.vue
@@ -19,7 +19,7 @@
:hide-default-footer="invoices == 0"
>
- {{ formatDate(item.created_at) }}
+ {{ timeAgo.format(convertDate(item.created_at)) }}
@@ -52,7 +52,11 @@ import userService from "@/services/userService";
import Toast from "@/components/Toast.vue";
import { storeToRefs } from "pinia";
import { useUserStore } from "@/store/UserStore";
+import TimeAgo from "javascript-time-ago";
+import en from "javascript-time-ago/locale/en";
+TimeAgo.addLocale(en);
+const timeAgo = ref(new TimeAgo("en-US"));
const invoices = ref();
const toast = ref(null);
const message = ref();
@@ -75,16 +79,8 @@ const headers = ref([
},
]);
-function formatDate(date) {
- var d = new Date(date),
- month = "" + (d.getMonth() + 1),
- day = "" + d.getDate(),
- year = d.getFullYear();
-
- if (month.length < 2) month = "0" + month;
- if (day.length < 2) day = "0" + day;
-
- return [day, month, year].join("-");
+function convertDate(date) {
+ return new Date(date);
}
// TODO handle invoices InvoiceID
From 342534092ad41d92ef7b1d3f37b03fb45fe09371 Mon Sep 17 00:00:00 2001
From: samaradel
Date: Wed, 12 Feb 2025 17:33:05 +0200
Subject: [PATCH 05/11] Fix !user
---
client/src/store/UserStore.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/client/src/store/UserStore.js b/client/src/store/UserStore.js
index a9a500ea..d9aa05a9 100644
--- a/client/src/store/UserStore.js
+++ b/client/src/store/UserStore.js
@@ -87,7 +87,7 @@ export const useUserStore = defineStore("userStore", {
getters: {
isUserLoaded: (state) => state.isLoaded,
isNextLaunchEnabled: (state) => state.next_launch_admin,
- getTotalBalance: (state) => state.user.balance + state.user.voucher_balance,
+ getTotalBalance: (state) => state.user? state.user.balance + state.user.voucher_balance : 0,
isAdmin: (state) => state.user.admin,
},
});
From 1616493461345b962490207d7e81562a54c9460a Mon Sep 17 00:00:00 2001
From: samaradel
Date: Wed, 12 Feb 2025 17:34:15 +0200
Subject: [PATCH 06/11] Request tab improvments
---
client/src/views/Admin.vue | 14 +-
client/src/views/adminTabs/Requests.vue | 165 +++++++++++++++---------
2 files changed, 108 insertions(+), 71 deletions(-)
diff --git a/client/src/views/Admin.vue b/client/src/views/Admin.vue
index 6682e63d..70447fbb 100644
--- a/client/src/views/Admin.vue
+++ b/client/src/views/Admin.vue
@@ -14,18 +14,12 @@
mdi-server
-
- Used VMs: {{ usedResources }}
- Deployed VMs: {{ deployedResources }}
-
+ Deployed VMs: {{ deployedResources }}
- mdi-ip
-
- Used IPs: {{ usedIPs }}
- Reserved IPs: {{ reservedIPs }}
-
+ mdi-ip
+ Reserved IPs: {{ reservedIPs }}
@@ -64,7 +58,7 @@
- x``
+
diff --git a/client/src/views/adminTabs/Requests.vue b/client/src/views/adminTabs/Requests.vue
index b21a32c7..643e3076 100644
--- a/client/src/views/adminTabs/Requests.vue
+++ b/client/src/views/adminTabs/Requests.vue
@@ -23,7 +23,7 @@
-
+
A
@@ -33,7 +33,10 @@
- {{ formatDate(item.created_at) }}
+ {{ timeAgo.format(convertDate(item.created_at)) }}
+
+
+ {{ item.balance > 0 ? `$${item.balance}` : item.balance }}
{{ index + 1 }}
-
-
+
+
- {{ userAvatar(item.name) }}
+ {{
+ userAvatar(item.first_name)
+ }}
-
{{ item.name }}
+
{{ item.first_name }}
{{ item.email }}
@@ -93,12 +97,26 @@
+
+ {{ item.count.vms }}
+
+
+ {{ item.count.ips }}
+
+
- {{ formatDate(item.created_at) }}
+
- mdi-information
- mdi-account-lock
+ mdi-information
+ mdi-account-key
+ mdi-account-lock
@@ -108,10 +126,17 @@
-->
diff --git a/client/src/views/adminTabs/Requests.vue b/client/src/views/adminTabs/Requests.vue
index 77a28958..8bc71270 100644
--- a/client/src/views/adminTabs/Requests.vue
+++ b/client/src/views/adminTabs/Requests.vue
@@ -133,12 +133,15 @@ import en from "javascript-time-ago/locale/en";
import { storeToRefs } from "pinia";
import { useUserStore } from "@/store/UserStore";
+defineProps({
+ pendingVouchers: {
+ type: Array,
+ },
+});
+const emit = defineEmits("updateVouchers");
+
TimeAgo.addLocale(en);
const timeAgo = ref(new TimeAgo("en-US"));
-const vouchers = ref([]);
-const pendingVouchers = ref([]);
-const approveAllCount = ref(0);
-const userInfo = ref(null);
const users = ref([]);
const toast = ref(null);
const loading = ref(false);
@@ -163,54 +166,6 @@ const usersHeaders = ref([
{ title: "Actions", key: "actions", sortable: false },
]);
-async function getVouchers() {
- loading.value = true;
-
- try {
- const response = await userService.getVouchers();
- const { data } = response.data;
-
- approveAllCount.value = 0;
-
- await updateVouchers(data);
-
- vouchers.value = data.filter(
- (voucher) => voucher.approved || voucher.rejected
- );
- pendingVouchers.value = data.filter(
- (voucher) => !voucher.approved && !voucher.rejected
- );
- } catch (error) {
- const { err } = error.response.data;
- toast.value.toast(err, "#FF5252");
- } finally {
- loading.value = false;
- }
-}
-
-async function updateVouchers(data) {
- const updatePromises = data.map(async (voucher) => {
- await new Promise((resolve) => setTimeout(resolve, 10));
-
- if (voucher.approved && voucher.rejected) {
- approveAllCount.value++;
- }
-
- if (users.value && voucher.user_id) {
- userInfo.value = users.value.find((user) => user.ID === voucher.user_id);
-
- if (userInfo.value && voucher.user_id === userInfo.value.ID) {
- Object.assign(voucher, {
- email: userInfo.value.email,
- name: userInfo.value.first_name,
- });
- }
- }
- });
-
- await Promise.all(updatePromises);
-}
-
function convertDate(date) {
return new Date(date);
}
@@ -241,12 +196,12 @@ async function approveVoucher(id, approved) {
.approveVoucher(id, approved)
.then(async (response) => {
toast.value.toast(response.data.msg, "#388E3C");
- await getVouchers();
})
.catch((response) => {
const { err } = response.response.data;
toast.value.toast(err, "#FF5252");
- });
+ })
+ .finally(() => emit("updateData"));
}
async function approveAllVouchers() {
@@ -254,12 +209,12 @@ async function approveAllVouchers() {
.approveAllVouchers()
.then(async (response) => {
toast.value.toast(response.data.msg, "#388E3C");
- await getVouchers();
})
.catch((response) => {
const { err } = response.response.data;
toast.value.toast(err, "#FF5252");
- });
+ })
+ .finally(() => emit("updateData"));
}
async function setAdmin(email, admin) {
@@ -280,7 +235,6 @@ async function setAdmin(email, admin) {
onMounted(async () => {
await getUsers();
- await getVouchers();
});