diff --git a/src/lib.rs b/src/lib.rs index 91c01fe..f56fa68 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1794,7 +1794,7 @@ async fn software_version() -> Json { let version = env::var("MAIN_PKG_VERSION").unwrap(); let response = SoftwareVersionResponse { server: Some(version), - client: None, + client: Some(extract_version().await.unwrap_or("0.0.0".to_string())), }; Json(response) } diff --git a/webconsole/package.json b/webconsole/package.json index dd6b131..c93e9e2 100644 --- a/webconsole/package.json +++ b/webconsole/package.json @@ -1,46 +1,46 @@ { "name": "template-vitejs-vue3-tailwindcss-fontawesome", "private": true, - "version": "1.1.99-31", + "version": "1.1.99-32", "type": "module", "scripts": { - "build": "vite build && gulp licenses", - "dev": "vite", - "create-cert": "openssl req -x509 -newkey rsa:4096 -keyout localhost.key -out localhost.pem -sha256 -nodes -days 365", "devserver": "npx nodemon -V -w ./src -e js,vue,ts,css,html --exec 'npm run build && node devserver.js'", - "preview": "vite preview" + "preview": "vite preview", + "create-cert": "openssl req -x509 -newkey rsa:4096 -keyout localhost.key -out localhost.pem -sha256 -nodes -days 365", + "dev": "vite", + "build": "vite build && gulp licenses" }, "dependencies": { - "pinia": "^2.1.7", + "@heroicons/vue": "^2.1.3", "vue": "^3.4.27", + "@pqina/flip": "^1.8.3", + "pinia": "^2.1.7", "@headlessui/vue": "^1.7.22", + "axios": "^1.7.2", "jdenticon": "^3.3.0", - "@pqina/flip": "^1.8.3", - "@heroicons/vue": "^2.1.3", - "vue-router": "^4.3.2", - "axios": "^1.7.2" + "vue-router": "^4.3.3" }, "devDependencies": { - "sass": "^1.77.2", - "gulp": "^5.0.0", - "@vitejs/plugin-vue": "^5.0.4", - "@types/glob": "^8.1.0", + "ts-node": "^10.9.2", "glob": "10.4.1", - "nodemon": "^3.1.0", + "gulp": "^5.0.0", + "@tailwindcss/typography": "^0.5.13", + "sass": "^1.77.5", + "gulp-append-prepend": "^1.0.9", "vite-plugin-static-copy": "^1.0.5", "postcss-purgefonts": "^1.0.2", - "@fullhuman/postcss-purgecss": "^6.0.0", "gulp-if": "^3.0.0", - "gulp-append-prepend": "^1.0.9", - "typescript": "^5.4.5", + "postcss": "^8.4.38", "express": "^4.19.2", + "nodemon": "^3.1.3", + "@vitejs/plugin-vue": "^5.0.5", + "@fullhuman/postcss-purgecss": "^6.0.0", + "@types/glob": "^8.1.0", + "vite": "^5.2.13", + "tailwindcss": "^3.4.4", + "@tailwindcss/forms": "^0.5.7", "autoprefixer": "^10.4.19", - "ts-node": "^10.9.2", - "postcss": "^8.4.38", "npm-check-updates": "^16.14.20", - "@tailwindcss/forms": "^0.5.7", - "tailwindcss": "^3.4.3", - "@tailwindcss/typography": "^0.5.13", - "vite": "^5.2.11" + "typescript": "^5.4.5" } } \ No newline at end of file diff --git a/webconsole/src/footers/mainfooter.vue b/webconsole/src/footers/mainfooter.vue index c3750fd..bcc4649 100644 --- a/webconsole/src/footers/mainfooter.vue +++ b/webconsole/src/footers/mainfooter.vue @@ -5,12 +5,14 @@ >

- © 2024 Ronan LE MEILLAT for SCTG Development - sctgdesk-api-server v{{ version }} + © 2024 Ronan LE MEILLAT for SCTG Development - sctgdesk-api-server v{{ serverVersion }} - latest client version: v{{ clientVersion }}

\ No newline at end of file diff --git a/webconsole/src/main.ts b/webconsole/src/main.ts index b4680bd..44f9a37 100644 --- a/webconsole/src/main.ts +++ b/webconsole/src/main.ts @@ -14,6 +14,7 @@ import { addJsonLD } from "./config/StructuredLDJson" import { useUserStore } from '@/stores/sctgDeskStore'; import '@/index.scss' import { RouteLocationNormalized } from 'vue-router' +import { useVersionsStore } from '@/stores/versionsStore'; const baseUrl = import.meta.url; // const useImage = (url: string) => { @@ -74,3 +75,4 @@ createApp(App).use(router) .use(pinia) .mount('#app') addJsonLD(); +useVersionsStore().fetchVersions(); \ No newline at end of file diff --git a/webconsole/src/stores/sctgDeskStore.ts b/webconsole/src/stores/sctgDeskStore.ts index d7801d2..9d2a793 100644 --- a/webconsole/src/stores/sctgDeskStore.ts +++ b/webconsole/src/stores/sctgDeskStore.ts @@ -1,15 +1,34 @@ -import { Token, UserInfo,Configuration } from "@/api"; -import { defineStore } from "pinia"; -export const useUserStore = defineStore('user', { - state: () => { - return { - user: null as UserInfo | null, - api_configuration: null as Configuration | null, - id: null as string | null, - uuid_base64: null as string | null, - oidc_code: null as string | null, - oidc_provider: null as string | null, - } - }, - }) - \ No newline at end of file +import { Token, UserInfo, Configuration } from "@/api"; +import { StoreDefinition, defineStore } from "pinia"; + +/** + * The user store. + * + * @export + * @type {StoreDefinition<"user", { user: UserInfo; api_configuration: Configuration; id: string; uuid_base64: string; oidc_code: string; oidc_provider: string; }, {}, {}>} + * @property {UserInfo | null} user The user information. + * @property {Configuration | null} api_configuration The API configuration. + * @property {string | null} id The user ID. + * @property {string | null} uuid_base64 The user UUID in base64. + * @property {string | null} oidc_code The OIDC code. + * @property {string | null} oidc_provider The OIDC provider. + **/ +export const useUserStore: StoreDefinition<"user", { + user: UserInfo; + api_configuration: Configuration; + id: string; + uuid_base64: string; + oidc_code: string; + oidc_provider: string; +}, {}, {}> = defineStore('user', { + state: () => { + return { + user: null as UserInfo | null, + api_configuration: null as Configuration | null, + id: null as string | null, + uuid_base64: null as string | null, + oidc_code: null as string | null, + oidc_provider: null as string | null, + } + }, +}) diff --git a/webconsole/src/stores/versionsStore.ts b/webconsole/src/stores/versionsStore.ts new file mode 100644 index 0000000..07e0fb7 --- /dev/null +++ b/webconsole/src/stores/versionsStore.ts @@ -0,0 +1,33 @@ +import { getClientVersion, getServerVersion } from "@/utilities/api"; +import { StoreDefinition, defineStore } from "pinia"; + +/** + * The versions store. + * + * @export + * @type {StoreDefinition<"versions", { serverVersion: string; clientVersion: string; }, {}, { fetchVersion(): Promise; }>} + * @property {string} serverVersion The server version. + * @property {string} clientVersion The client version. + */ +export const useVersionsStore: StoreDefinition<"versions", { + serverVersion: string | null; + clientVersion: string | null; +}, {}, { + fetchVersions(): Promise; +}> = defineStore('versions', { + state: () => ({ + serverVersion: null as string, + clientVersion: null as string, + }), + actions: { + async fetchVersions() { + // console.log("Fetching versions"); + if (!this.serverVersion) { + this.serverVersion = await getServerVersion(); + } + if (!this.clientVersion) { + this.clientVersion = await getClientVersion(); + } + } + } +}); \ No newline at end of file diff --git a/webconsole/src/utilities/api.ts b/webconsole/src/utilities/api.ts index 43e29f9..b0f0c08 100644 --- a/webconsole/src/utilities/api.ts +++ b/webconsole/src/utilities/api.ts @@ -1,7 +1,14 @@ -import { UserApi, UserListResponse } from "@/api"; +import { Configuration, SoftwareApi, UserApi, UserListResponse } from "@/api"; import { GroupApi, Group } from '@/api'; import { useUserStore } from "@/stores/sctgDeskStore"; +/** + * The base path for the API. + * This is the origin of the current window if it is localhost, otherwise it is the origin of the current window. + * This is need for development purposes. + */ +export const basePath = window.location.origin == "http://localhost:5173" ? "http://127.0.0.1:21114" : window.location.origin; + /** * Retrieves the list of users from the API. * @@ -47,4 +54,50 @@ export function getGroups(): Promise { }); } ); +} + +/** + * Retrieves the server version. + * + * @return {Promise} A promise that resolves with the server version. + */ +export function getServerVersion(): Promise { + const configuration = new Configuration({ basePath: basePath }); + const softwareApi = new SoftwareApi(configuration); + return new Promise((resolve, reject) => { + softwareApi.softwareVersion().then((response) => { + if (response.status == 200) { + resolve(response.data.server); + } + else { + resolve(""); + } + }).catch((error) => { + console.error(error); + resolve(""); + }); + }); +} + +/** + * Retrieves the client version. + * + * @return {Promise} A promise that resolves with the client version. + */ +export function getClientVersion(): Promise { + const configuration = new Configuration({ basePath: basePath }); + const softwareApi = new SoftwareApi(configuration); + return new Promise((resolve, reject) => { + softwareApi.softwareVersion().then((response) => { + if (response.status == 200) { + resolve(response.data.client); + } + else { + resolve(""); + } + }).catch((error) => { + console.error(error); + resolve(""); + }); + }); } \ No newline at end of file diff --git a/webconsole/src/views/LoginPage.vue b/webconsole/src/views/LoginPage.vue index e4f0de6..5ec0024 100644 --- a/webconsole/src/views/LoginPage.vue +++ b/webconsole/src/views/LoginPage.vue @@ -10,7 +10,8 @@ This website use:
Your Company -

SCTGDesk server v{{ version }}

+

SCTGDesk server v{{ + serverVersion }}

@@ -58,15 +59,17 @@ import { useUserStore } from '@/stores/sctgDeskStore'; import { useRouter } from 'vue-router'; import { onMounted, ref } from 'vue'; import { LoginApi, Configuration } from '@/api'; -import packageJson from '../../package.json'; -const version = packageJson.version; +import { useVersionsStore } from '@/stores/versionsStore'; +import { basePath } from '@/utilities/api'; + +const serverVersion = ref(""); const userStore = useUserStore(); const router = useRouter(); const name = ref(""); const password = ref(""); -const basePath = window.location.origin == "http://localhost:5173" ? "http://127.0.0.1:21114" : window.location.origin; + const oidc_link = ref(null as HTMLAnchorElement | null); type OauthProvider = { @@ -82,7 +85,7 @@ const oauthproviders = ref([] as OauthProvider[]); * @param {SubmitEvent} e - The submit event object. * @return {void} This function does not return a value. */ -function handleLogin(e: SubmitEvent) { +function handleLogin(e: SubmitEvent): void { e.preventDefault(); const configuration = new Configuration({ // Workaround for development environment @@ -146,7 +149,7 @@ function oidcAuth_step1(provider: OauthProvider) { loginApi.oidcAuth(oidcAuthRequest).then(async (response) => { console.log(response); userStore.oidc_code = response.data.code; - + oidc_link.value.href = response.data.url; oidc_link.value.innerText = `Please authenticate with ${userStore.oidc_provider}...`; oidc_link.value.target = "_blank"; @@ -171,7 +174,7 @@ function oidcAuth_step1(provider: OauthProvider) { * @return {Promise} A promise that resolves to true if the authentication is successful, * or false otherwise. */ -function oidcAuth_step2():Promise { +function oidcAuth_step2(): Promise { const configuration = new Configuration({ basePath: basePath, username: name.value, @@ -206,11 +209,14 @@ function oidcAuth_step2():Promise { * @param {string} string - The string to capitalize. * @return {string} The capitalized string. */ -function capitalizeFirstLetter(string: string): string{ +function capitalizeFirstLetter(string: string): string { return string.charAt(0).toUpperCase() + string.slice(1); } onMounted(() => { + useVersionsStore().fetchVersions().then(() => { + serverVersion.value = useVersionsStore().serverVersion; + }) userStore.uuid_base64 = generateUUIDBase64Encoded(); userStore.id = Math.random().toString(36).substring(2, 15); const configuration = new Configuration({