diff --git a/client/src/Components/v2/common/controls/HeaderCreate.tsx b/client/src/Components/v2/common/controls/HeaderCreate.tsx index 36c60c3d4..8234cc8ed 100644 --- a/client/src/Components/v2/common/controls/HeaderCreate.tsx +++ b/client/src/Components/v2/common/controls/HeaderCreate.tsx @@ -1,14 +1,27 @@ import { Stack } from "@mui/material"; import { useNavigate } from "react-router-dom"; import { ButtonInput } from "../../inputs/Button"; +import { useTranslation } from "react-i18next"; interface HeaderCreateProps { label?: string; path: string; + isLoading?: boolean; + isAdmin?: boolean; } -export const HeaderCreate = ({ label = "Create", path }: HeaderCreateProps) => { +export const HeaderCreate = ({ + label, + path, + isLoading = false, + isAdmin = false, +}: HeaderCreateProps) => { const navigate = useNavigate(); + const { t } = useTranslation(); + + if (!isAdmin) { + return null; + } const handleClick = () => { navigate(path); @@ -25,8 +38,9 @@ export const HeaderCreate = ({ label = "Create", path }: HeaderCreateProps) => { variant="contained" color="primary" onClick={handleClick} + loading={isLoading} > - {label} + {label || t("common.buttons.create")} ); diff --git a/client/src/Pages/Uptime/Monitors/index.tsx b/client/src/Pages/Uptime/Monitors/index.tsx index 6ee400562..630fc67f1 100644 --- a/client/src/Pages/Uptime/Monitors/index.tsx +++ b/client/src/Pages/Uptime/Monitors/index.tsx @@ -8,6 +8,8 @@ import { import { TextField } from "@/Components/v2/inputs"; import Stack from "@mui/material/Stack"; import { MonitorTable } from "@/Pages/Uptime/Monitors/Components/UptimeMonitorsTable"; +import { HeaderCreate } from "@/Components/v2/common"; + import { useTranslation } from "react-i18next"; import useMediaQuery from "@mui/material/useMediaQuery"; import { useGet } from "@/Hooks/UseApi"; @@ -15,7 +17,7 @@ import type { Monitor, MonitorType, MonitorsWithChecksResponse } from "@/Types/M import { useState, useMemo, useCallback } from "react"; import { useSelector, useDispatch } from "react-redux"; import { setRowsPerPage } from "@/Features/UI/uiSlice.js"; - +import { useIsAdmin } from "@/Hooks/useIsAdmin"; import type { RootState } from "@/Types/state"; import { useTheme } from "@mui/material"; @@ -24,7 +26,7 @@ const UptimeMonitorsPage = () => { const theme = useTheme(); const isSmall = useMediaQuery(theme.breakpoints.down("md")); const dispatch = useDispatch(); - + const isAdmin = useIsAdmin(); // Redux state const rowsPerPage = useSelector( (state: RootState) => state.ui?.monitors?.rowsPerPage ?? 10 @@ -84,7 +86,7 @@ const UptimeMonitorsPage = () => { // Data fetching const { data: monitors, - isLoading, + isLoading: monitorsLoading, error, } = useGet("/monitors/team?type=http&type=ping&type=port&type=docker"); @@ -109,14 +111,21 @@ const UptimeMonitorsPage = () => { setSearch(""); }, []); + const isLoading = monitorsLoading || monitorsWithChecksLoading; + return ( + {}; class Logger { constructor() { let logLevel = LOG_LEVEL; - this.unsubscribe = store.subscribe(() => { - logLevel = "debug"; - this.updateLogLevel(logLevel); - }); + this.updateLogLevel(logLevel); + // Defer store subscription to avoid circular dependency during HMR + setTimeout(() => { + try { + import("../store").then(({ default: store }) => { + if (store) { + this.unsubscribe = store.subscribe(() => { + logLevel = "debug"; + this.updateLogLevel(logLevel); + }); + } + }); + } catch (e) { + // Store not ready yet, ignore + } + }, 0); } updateLogLevel(logLevel) { diff --git a/client/src/locales/en.json b/client/src/locales/en.json index da4225c2e..de02815b1 100644 --- a/client/src/locales/en.json +++ b/client/src/locales/en.json @@ -3,7 +3,8 @@ "appName": "Checkmate", "monitoringAgentName": "Capture", "buttons": { - "toggleTheme": "Toggles light & dark" + "toggleTheme": "Toggles light & dark", + "create": "Create" }, "toasts": { "networkError": "Network error",