diff --git a/README.md b/README.md index 590d978..f4a1a0a 100644 --- a/README.md +++ b/README.md @@ -122,6 +122,7 @@ The following list contains such features - they are only available for [etke.cc * 📊 [Server Status indicator and page](https://github.com/etkecc/synapse-admin/pull/182) * 📬 [Server Notifications indicator and page](https://github.com/etkecc/synapse-admin/pull/240) * 🛠️ [Server Commands panel](https://github.com/etkecc/synapse-admin/pull/365) +* 🚀 [Server Actions page](https://github.com/etkecc/synapse-admin/pull/457) ### Development diff --git a/screenshots/etke.cc/server-actions/page.webp b/screenshots/etke.cc/server-actions/page.webp new file mode 100644 index 0000000..0b8f335 Binary files /dev/null and b/screenshots/etke.cc/server-actions/page.webp differ diff --git a/src/App.tsx b/src/App.tsx index 2b5ed3b..65709d8 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -5,8 +5,12 @@ import { Admin, CustomRoutes, Resource, resolveBrowserLocale } from "react-admin import { Route } from "react-router-dom"; import AdminLayout from "./components/AdminLayout"; +import ServerActionsPage from "./components/etke.cc/ServerActionsPage"; import ServerNotificationsPage from "./components/etke.cc/ServerNotificationsPage"; import ServerStatusPage from "./components/etke.cc/ServerStatusPage"; +import RecurringCommandEdit from "./components/etke.cc/schedules/components/recurring/RecurringCommandEdit"; +import ScheduledCommandEdit from "./components/etke.cc/schedules/components/scheduled/ScheduledCommandEdit"; +import ScheduledCommandShow from "./components/etke.cc/schedules/components/scheduled/ScheduledCommandShow"; import UserImport from "./components/user-import/UserImport"; import germanMessages from "./i18n/de"; import englishMessages from "./i18n/en"; @@ -64,6 +68,12 @@ export const App = () => ( } /> } /> + } /> + } /> + } /> + } /> + } /> + } /> } /> diff --git a/src/components/AdminLayout.tsx b/src/components/AdminLayout.tsx index e199198..0446f7f 100644 --- a/src/components/AdminLayout.tsx +++ b/src/components/AdminLayout.tsx @@ -1,3 +1,4 @@ +import ManageHistoryIcon from "@mui/icons-material/ManageHistory"; import { useEffect, useState, Suspense } from "react"; import { CheckForApplicationUpdate, @@ -75,11 +76,11 @@ const AdminAppBar = () => { const AdminMenu = props => { const [menu, setMenu] = useState([] as MenuItem[]); - const [serverStatusEnabled, setServerStatusEnabled] = useState(false); + const [etkeRoutesEnabled, setEtkeRoutesEnabled] = useState(false); useEffect(() => { setMenu(GetConfig().menu); if (GetConfig().etkeccAdmin) { - setServerStatusEnabled(true); + setEtkeRoutesEnabled(true); } }, []); const [serverProcess, setServerProcess] = useStore("serverProcess", { @@ -95,8 +96,9 @@ const AdminMenu = props => { return ( - {serverStatusEnabled && ( + {etkeRoutesEnabled && ( { command={serverProcess.command} locked_at={serverProcess.locked_at} isOkay={serverStatus.ok} + isLoaded={serverStatus.success} /> } primaryText="Server Status" /> )} + {etkeRoutesEnabled && ( + } + primaryText="Server Actions" + /> + )} {menu && menu.map((item, index) => { diff --git a/src/components/etke.cc/CurrentlyRunningCommand.tsx b/src/components/etke.cc/CurrentlyRunningCommand.tsx new file mode 100644 index 0000000..44b4d98 --- /dev/null +++ b/src/components/etke.cc/CurrentlyRunningCommand.tsx @@ -0,0 +1,37 @@ +import { Stack, Tooltip, Typography, Box, Link } from "@mui/material"; +import { useStore } from "react-admin"; + +import { ServerProcessResponse } from "../../synapse/dataProvider"; +import { getTimeSince } from "../../utils/date"; + +const CurrentlyRunningCommand = () => { + const [serverProcess, setServerProcess] = useStore("serverProcess", { + command: "", + locked_at: "", + }); + const { command, locked_at } = serverProcess; + + if (!command || !locked_at) { + return null; + } + + return ( + + + Currently running: + + + {command} + + + + (started {getTimeSince(locked_at)} ago) + + + + + + ); +}; + +export default CurrentlyRunningCommand; diff --git a/src/components/etke.cc/README.md b/src/components/etke.cc/README.md index 5965915..88bc0b7 100644 --- a/src/components/etke.cc/README.md +++ b/src/components/etke.cc/README.md @@ -47,10 +47,21 @@ In the application bar the new notifications icon is displayed that shows the nu When you click on a notification from the [Server Notifications icon](#server-notifications-icon)'s list in the application bar, you will be redirected to the Server Notifications page. This page contains the full text of all the notifications you have about your server. +### Server Actions Page + +![Server Actions Page](../../../screenshots/etke.cc/server-actions/page.webp) + +When you click on the `Server Actions` sidebar menu item, you will be redirected to the Server Actions page. +On this page you can do the following: + +* [Run a command](#server-commands-panel) on your server immediately +* [Schedule a command](https://etke.cc/help/extras/scheduler/#schedule) to run at a specific date and time +* [Configure a recurring schedule](https://etke.cc/help/extras/scheduler/#recurring) for a command to run at a specific time every week + ### Server Commands Panel ![Server Commands Panel](../../../screenshots/etke.cc/server-commands/panel.webp) -When you open [Server Status page](#server-status-page), you will see the Server Commands panel. This panel contains all -[the commands](https://etke.cc/help/extras/scheduler/#commands) you can run on your server in 1 click. Once command is finished, you will get a notification about the -result. +When you open [Server Actions page](#server-status-page), you will see the Server Commands panel. +This panel contains all [the commands](https://etke.cc/help/extras/scheduler/#commands) you can run on your server in 1 click. +Once command is finished, you will get a notification about the result. diff --git a/src/components/etke.cc/ServerActionsPage.tsx b/src/components/etke.cc/ServerActionsPage.tsx new file mode 100644 index 0000000..b74af6f --- /dev/null +++ b/src/components/etke.cc/ServerActionsPage.tsx @@ -0,0 +1,51 @@ +import RestoreIcon from "@mui/icons-material/Restore"; +import ScheduleIcon from "@mui/icons-material/Schedule"; +import { Box, Typography, Link, Divider } from "@mui/material"; +import { Stack } from "@mui/material"; + +import CurrentlyRunningCommand from "./CurrentlyRunningCommand"; +import ServerCommandsPanel from "./ServerCommandsPanel"; +import RecurringCommandsList from "./schedules/components/recurring/RecurringCommandsList"; +import ScheduledCommandsList from "./schedules/components/scheduled/ScheduledCommandsList"; +const ServerActionsPage = () => { + return ( + + + + + + + + + Scheduled commands + + + The following commands are scheduled to run at specific times. You can view their details and modify them as + needed. More details about the mode can be found{" "} + + here + + . + + + + + + + Recurring commands + + + The following commands are set to run at specific weekday and time (weekly). You can view their details and + modify them as needed. More details about the mode can be found{" "} + + here + + . + + + + + ); +}; + +export default ServerActionsPage; diff --git a/src/components/etke.cc/ServerCommandsPanel.tsx b/src/components/etke.cc/ServerCommandsPanel.tsx index 02e9835..dd940b2 100644 --- a/src/components/etke.cc/ServerCommandsPanel.tsx +++ b/src/components/etke.cc/ServerCommandsPanel.tsx @@ -1,4 +1,4 @@ -import { PlayArrow, CheckCircle } from "@mui/icons-material"; +import { PlayArrow, CheckCircle, HelpCenter, Construction } from "@mui/icons-material"; import { Table, TableBody, @@ -10,12 +10,15 @@ import { Alert, TextField, Box, + Link, + Typography, } from "@mui/material"; import { useEffect, useState } from "react"; import { Button, Loading, useDataProvider, useCreatePath, useStore } from "react-admin"; -import { Link } from "react-router-dom"; +import { Link as RouterLink } from "react-router-dom"; import { useAppContext } from "../../Context"; +import { useServerCommands } from "./hooks/useServerCommands"; import { ServerCommand, ServerProcessResponse } from "../../synapse/dataProvider"; import { Icons } from "../../utils/icons"; @@ -26,34 +29,20 @@ const renderIcon = (icon: string) => { const ServerCommandsPanel = () => { const { etkeccAdmin } = useAppContext(); - const createPath = useCreatePath(); + if (!etkeccAdmin) { + return null; + } - const [isLoading, setLoading] = useState(true); - const [serverCommands, setServerCommands] = useState>({}); + const createPath = useCreatePath(); + const { isLoading, serverCommands, setServerCommands } = useServerCommands(); const [serverProcess, setServerProcess] = useStore("serverProcess", { command: "", locked_at: "", }); const [commandIsRunning, setCommandIsRunning] = useState(serverProcess.command !== ""); - const [commandResult, setCommandResult] = useState([]); - + const [commandResult, setCommandResult] = useState([]); const dataProvider = useDataProvider(); - useEffect(() => { - const fetchIsAdmin = async () => { - const serverCommandsResponse = await dataProvider.getServerCommands(etkeccAdmin); - if (serverCommandsResponse) { - const serverCommands = serverCommandsResponse; - Object.keys(serverCommandsResponse).forEach((command: string) => { - serverCommands[command].additionalArgs = ""; - }); - setServerCommands(serverCommands); - } - setLoading(false); - }; - fetchIsAdmin(); - }, []); - useEffect(() => { if (serverProcess.command === "") { setCommandIsRunning(false); @@ -103,11 +92,12 @@ const ServerCommandsPanel = () => { commandScheduledText += `, with additional args: ${additionalArgs}`; } - results.push({commandScheduledText}); + results.push({commandScheduledText}); results.push( - + Expect your result in the{" "} - Notifications page soon. + Notifications page + soon. ); @@ -138,25 +128,40 @@ const ServerCommandsPanel = () => { return ( <> -

Server Commands

- + + Available Commands + + + The following commands are available to run. More details about each of them can be found{" "} + + here + + . + + Command + Description {Object.entries(serverCommands).map(([command, { icon, args, description, additionalArgs }]) => ( - + {renderIcon(icon)} {command} + + +