diff --git a/ui/src/App.vue b/ui/src/App.vue index a86fe85c7..2df7bcbbb 100644 --- a/ui/src/App.vue +++ b/ui/src/App.vue @@ -10,6 +10,9 @@
+ + {{ diskSpaceMessage }} +
@@ -23,10 +26,12 @@ import Navbar from "@/components/Navbar.vue"; import Tabs from "@/components/Tabs.vue"; import Login from "@/views/Login.vue"; +import Alert from "@/components/Alert.vue"; import { defineComponent, onMounted, ref, Ref } from "vue"; -import { getPrincipal, getVersion, logout } from "@/api/api"; +import { getPrincipal, getVersion, logout, getFreeDiskSpace } from "@/api/api"; import { useRouter } from "vue-router"; import { ApiError } from "@/helpers/errors"; +import { diskSpaceBelowThreshold, convertBytes } from "@/helpers/utils"; export default defineComponent({ name: "ArmadilloPortal", @@ -34,16 +39,19 @@ export default defineComponent({ Navbar, Tabs, Login, + Alert, }, setup() { const isAuthenticated: Ref = ref(false); const username: Ref = ref(""); const version: Ref = ref(""); const router = useRouter(); + const diskSpace: Ref = ref(""); onMounted(() => { loadUser(); loadVersion(); + loadFreeDiskSpace(); }); const loadUser = async () => { @@ -67,13 +75,16 @@ export default defineComponent({ const loadVersion = async () => { version.value = await getVersion(); }; - + const loadFreeDiskSpace = async () => { + diskSpace.value = await getFreeDiskSpace(); + }; return { username, isAuthenticated, version, loadUser, loadVersion, + diskSpace, }; }, data() { @@ -88,6 +99,16 @@ export default defineComponent({ ], }; }, + computed: { + diskNearFull() { + return diskSpaceBelowThreshold(this.diskSpace); + }, + diskSpaceMessage() { + return `Disk space low (${ + this.diskSpace === "" ? "" : convertBytes(this.diskSpace) + } remaining). Saving workspaces may not be possible and users risk losing workspace data. Either allocate more space or remove saved workspaces.`; + }, + }, methods: { logoutUser() { logout().then(() => { diff --git a/ui/src/api/api.ts b/ui/src/api/api.ts index a467584d5..c16aee327 100644 --- a/ui/src/api/api.ts +++ b/ui/src/api/api.ts @@ -318,3 +318,9 @@ export async function createLinkFile( }; return postJson(`/storage/projects/${viewProject}/objects/link`, data); } + +export async function getFreeDiskSpace() { + return get("/actuator/metrics/disk.free").then((data) => { + return data.measurements[0].value; + }); +} diff --git a/ui/src/components/ActuatorItem.vue b/ui/src/components/ActuatorItem.vue index 241817a21..25b56f7b3 100644 --- a/ui/src/components/ActuatorItem.vue +++ b/ui/src/components/ActuatorItem.vue @@ -27,30 +27,18 @@ diff --git a/ui/src/components/Alert.vue b/ui/src/components/Alert.vue index 0d593f328..2a220d6c1 100644 --- a/ui/src/components/Alert.vue +++ b/ui/src/components/Alert.vue @@ -10,6 +10,7 @@