mirror of
https://github.com/Unkn0wnCat/matrix-veles.git
synced 2025-04-30 10:46:53 +02:00
webui: Merge changes
This commit is contained in:
parent
5bcfe39d84
commit
dc997e240e
8 changed files with 95 additions and 36 deletions
8
.idea/misc.xml
generated
8
.idea/misc.xml
generated
|
@ -1,8 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="SwUserDefinedSpecifications">
|
|
||||||
<option name="specTypeByUrl">
|
|
||||||
<map />
|
|
||||||
</option>
|
|
||||||
</component>
|
|
||||||
</project>
|
|
33
webui/src/components/common/Loader.module.scss
Normal file
33
webui/src/components/common/Loader.module.scss
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
@import "../../globals";
|
||||||
|
|
||||||
|
.loader {
|
||||||
|
width: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
|
> svg {
|
||||||
|
animation-name: spinny-spin;
|
||||||
|
animation-duration: 2s;
|
||||||
|
animation-timing-function: linear;
|
||||||
|
animation-iteration-count: infinite;
|
||||||
|
|
||||||
|
width: 80px;
|
||||||
|
height: 80px;
|
||||||
|
|
||||||
|
stroke-width: 1.5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
> span {
|
||||||
|
margin-top: var(--veles-layout-padding);
|
||||||
|
font-size: 1.5em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes spinny-spin {
|
||||||
|
0% {transform: rotate(0turn)}
|
||||||
|
100% {transform: rotate(1turn)}
|
||||||
|
}
|
18
webui/src/components/common/Loader.tsx
Normal file
18
webui/src/components/common/Loader.tsx
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
import React from "react";
|
||||||
|
import {Loader as LoaderIcon} from "lucide-react";
|
||||||
|
|
||||||
|
import styles from "./Loader.module.scss";
|
||||||
|
import {Trans} from "react-i18next";
|
||||||
|
|
||||||
|
const Loader = () => {
|
||||||
|
return <div className={styles.loader}>
|
||||||
|
<LoaderIcon/>
|
||||||
|
<span><Trans i18nKey={"common.loading"}>Loading...</Trans></span>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
|
||||||
|
export const LoaderSuspense = (props: React.PropsWithChildren<{}>) => <React.Suspense fallback={<Loader/>} children={props.children} />
|
||||||
|
|
||||||
|
//export const LoaderSuspense = (props: React.PropsWithChildren<{}>) => <Loader/>
|
||||||
|
|
||||||
|
export default Loader;
|
|
@ -1,9 +1,10 @@
|
||||||
import React, {useEffect} from "react";
|
import React, {useContext, useEffect} from "react";
|
||||||
import {PreloadedQuery, usePreloadedQuery} from "react-relay/hooks";
|
import {PreloadedQuery, usePreloadedQuery} from "react-relay/hooks";
|
||||||
import {graphql} from "babel-plugin-relay/macro";
|
import {graphql} from "babel-plugin-relay/macro";
|
||||||
import {RoomDetailQuery, RoomDetailQuery$variables} from "./__generated__/RoomDetailQuery.graphql";
|
import {RoomDetailQuery, RoomDetailQuery$variables} from "./__generated__/RoomDetailQuery.graphql";
|
||||||
import {DisposeFn} from "relay-runtime";
|
import {DisposeFn} from "relay-runtime";
|
||||||
import {useParams} from "react-router-dom";
|
import {useParams} from "react-router-dom";
|
||||||
|
import {RoomsSlideOverTitleContext} from "./Rooms";
|
||||||
import ToggleButton from "../../form_components/ToggleButton";
|
import ToggleButton from "../../form_components/ToggleButton";
|
||||||
|
|
||||||
import styles from "./RoomDetail.module.scss";
|
import styles from "./RoomDetail.module.scss";
|
||||||
|
@ -46,10 +47,12 @@ const RoomDetailInner = ({initialQueryRef}: PropsFinal) => {
|
||||||
initialQueryRef
|
initialQueryRef
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const titleSetContext = useContext(RoomsSlideOverTitleContext)
|
||||||
|
|
||||||
|
titleSetContext && data.room?.name && titleSetContext(data.room.name);
|
||||||
|
|
||||||
return <>
|
return <>
|
||||||
<span className={styles.title}>
|
<ToggleButton name={"activeSwitch"} label={"Activate Room"} labelSrOnly={false} onChange={(ev) => {
|
||||||
<h1>{data.room?.name}</h1>
|
|
||||||
<ToggleButton name={"activeSwitch"} label={"Activate"} labelSrOnly={true} onChange={(ev) => {
|
|
||||||
reconfigureRoom({
|
reconfigureRoom({
|
||||||
variables: {
|
variables: {
|
||||||
reconfigureInput: {
|
reconfigureInput: {
|
||||||
|
@ -59,7 +62,6 @@ const RoomDetailInner = ({initialQueryRef}: PropsFinal) => {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}} disabled={reconfiguringRoom || ((data.room || false) && !data.room.active && !data.room.deactivated)} checked={data.room?.active}/>
|
}} disabled={reconfiguringRoom || ((data.room || false) && !data.room.active && !data.room.deactivated)} checked={data.room?.active}/>
|
||||||
</span>
|
|
||||||
|
|
||||||
|
|
||||||
<pre>{JSON.stringify(data, null, 2)}</pre>
|
<pre>{JSON.stringify(data, null, 2)}</pre>
|
||||||
|
@ -77,7 +79,7 @@ const RoomDetail = ({initialQueryRef, fetch, dispose}: Props) => {
|
||||||
}
|
}
|
||||||
}, [id, dispose, fetch])
|
}, [id, dispose, fetch])
|
||||||
|
|
||||||
return initialQueryRef ? <RoomDetailInner initialQueryRef={initialQueryRef} /> : <>loading...</>
|
return initialQueryRef ? <RoomDetailInner initialQueryRef={initialQueryRef} /> : null
|
||||||
}
|
}
|
||||||
|
|
||||||
export default RoomDetail;
|
export default RoomDetail;
|
|
@ -1,13 +1,14 @@
|
||||||
import React from "react";
|
import React, {useContext, useState} from "react";
|
||||||
import {useNavigate, useOutlet} from "react-router-dom";
|
import {useNavigate, useOutlet} from "react-router-dom";
|
||||||
|
|
||||||
import styles from "./Rooms.module.scss";
|
import styles from "./Rooms.module.scss";
|
||||||
import {Trans} from "react-i18next";
|
import {Trans, useTranslation} from "react-i18next";
|
||||||
import RoomsTable from "./RoomsTable";
|
import RoomsTable from "./RoomsTable";
|
||||||
import {PreloadedQuery, usePreloadedQuery} from "react-relay/hooks";
|
import {PreloadedQuery, usePreloadedQuery} from "react-relay/hooks";
|
||||||
import {graphql} from "babel-plugin-relay/macro";
|
import {graphql} from "babel-plugin-relay/macro";
|
||||||
import {RoomsQuery} from "./__generated__/RoomsQuery.graphql";
|
import {RoomsQuery} from "./__generated__/RoomsQuery.graphql";
|
||||||
import {X} from "lucide-react";
|
import {X} from "lucide-react";
|
||||||
|
import {LoaderSuspense} from "../../common/Loader";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
initialQueryRef: PreloadedQuery<RoomsQuery>,
|
initialQueryRef: PreloadedQuery<RoomsQuery>,
|
||||||
|
@ -16,6 +17,7 @@ type Props = {
|
||||||
const Rooms = ({initialQueryRef}: Props) => {
|
const Rooms = ({initialQueryRef}: Props) => {
|
||||||
const outlet = useOutlet()
|
const outlet = useOutlet()
|
||||||
const navigate = useNavigate()
|
const navigate = useNavigate()
|
||||||
|
const {t} = useTranslation()
|
||||||
|
|
||||||
const data = usePreloadedQuery(
|
const data = usePreloadedQuery(
|
||||||
graphql`
|
graphql`
|
||||||
|
@ -26,6 +28,10 @@ const Rooms = ({initialQueryRef}: Props) => {
|
||||||
initialQueryRef
|
initialQueryRef
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const defaultTitle = t("rooms.details", "Details")
|
||||||
|
|
||||||
|
const [title, setTitle] = useState(defaultTitle)
|
||||||
|
|
||||||
|
|
||||||
return <div className={styles.roomsContainer}>
|
return <div className={styles.roomsContainer}>
|
||||||
<div className={styles.roomsOverview + (outlet ? " "+styles.leaveSpace : "")}>
|
<div className={styles.roomsOverview + (outlet ? " "+styles.leaveSpace : "")}>
|
||||||
|
@ -35,15 +41,21 @@ const Rooms = ({initialQueryRef}: Props) => {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className={styles.slideOver + (outlet ? " "+styles.active : "")}>
|
<div className={styles.slideOver + (outlet ? " "+styles.active : "")}>
|
||||||
|
<RoomsSlideOverTitleContext.Provider value={setTitle}>
|
||||||
<div className={styles.slideOverHeader}>
|
<div className={styles.slideOverHeader}>
|
||||||
<span><Trans i18nKey={"rooms.details"}>Details</Trans></span>
|
<span>{title}</span>
|
||||||
<button onClick={() => navigate("/rooms")}><X/></button>
|
<button onClick={() => navigate("/rooms")}><X/></button>
|
||||||
</div>
|
</div>
|
||||||
<div className={styles.slideOverContent}>
|
<div className={styles.slideOverContent}>
|
||||||
|
<LoaderSuspense>
|
||||||
{outlet}
|
{outlet}
|
||||||
|
</LoaderSuspense>
|
||||||
</div>
|
</div>
|
||||||
|
</RoomsSlideOverTitleContext.Provider>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const RoomsSlideOverTitleContext = React.createContext<React.Dispatch<React.SetStateAction<string>>|null>(null)
|
||||||
|
|
||||||
export default Rooms
|
export default Rooms
|
|
@ -41,7 +41,7 @@ const RoomsTable = ({initialQueryRef}: Props) => {
|
||||||
<tbody>
|
<tbody>
|
||||||
{
|
{
|
||||||
data.rooms?.edges.map((edge) => {
|
data.rooms?.edges.map((edge) => {
|
||||||
return <tr onClick={() => {navigate("/rooms/"+edge.node.id)}}>
|
return <tr onClick={() => {navigate("/rooms/"+edge.node.id)}} key={edge.node.id}>
|
||||||
<td>
|
<td>
|
||||||
{edge.node.debug && <span className={styles.badge + " " + styles.blue}><Trans i18nKey={"rooms.debug"}>Debug</Trans></span>}
|
{edge.node.debug && <span className={styles.badge + " " + styles.blue}><Trans i18nKey={"rooms.debug"}>Debug</Trans></span>}
|
||||||
{!edge.node.active && <span className={styles.badge + " " + styles.red}><Trans i18nKey={"rooms.inactive"}>Inactive</Trans></span>}
|
{!edge.node.active && <span className={styles.badge + " " + styles.red}><Trans i18nKey={"rooms.inactive"}>Inactive</Trans></span>}
|
||||||
|
|
|
@ -12,17 +12,18 @@ import {
|
||||||
|
|
||||||
import "./i18n";
|
import "./i18n";
|
||||||
import RelayEnvironment from "./RelayEnvironment";
|
import RelayEnvironment from "./RelayEnvironment";
|
||||||
|
import {LoaderSuspense} from "./components/common/Loader";
|
||||||
|
|
||||||
|
|
||||||
ReactDOM.render(
|
ReactDOM.render(
|
||||||
<React.StrictMode>
|
<React.StrictMode>
|
||||||
<Provider store={store}>
|
<Provider store={store}>
|
||||||
<RelayEnvironmentProvider environment={RelayEnvironment({store})}>
|
<RelayEnvironmentProvider environment={RelayEnvironment({store})}>
|
||||||
<React.Suspense fallback={<h1>Loading...</h1>}>
|
<LoaderSuspense>
|
||||||
<BrowserRouter>
|
<BrowserRouter>
|
||||||
<App />
|
<App />
|
||||||
</BrowserRouter>
|
</BrowserRouter>
|
||||||
</React.Suspense>
|
</LoaderSuspense>
|
||||||
</RelayEnvironmentProvider>
|
</RelayEnvironmentProvider>
|
||||||
</Provider>
|
</Provider>
|
||||||
</React.StrictMode>,
|
</React.StrictMode>,
|
||||||
|
|
|
@ -10,6 +10,7 @@ import styles from "./PanelLayout.module.scss";
|
||||||
import {Trans, useTranslation} from "react-i18next";
|
import {Trans, useTranslation} from "react-i18next";
|
||||||
import {useAppDispatch} from "../app/hooks";
|
import {useAppDispatch} from "../app/hooks";
|
||||||
import {logOut} from "../features/auth/authSlice";
|
import {logOut} from "../features/auth/authSlice";
|
||||||
|
import {LoaderSuspense} from "../components/common/Loader";
|
||||||
|
|
||||||
const PanelLayout = () => {
|
const PanelLayout = () => {
|
||||||
const {t} = useTranslation()
|
const {t} = useTranslation()
|
||||||
|
@ -44,9 +45,9 @@ const PanelLayout = () => {
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
<main id={"main"}>
|
<main id={"main"}>
|
||||||
<React.Suspense fallback={<span>Fetching data...</span>}>
|
<LoaderSuspense>
|
||||||
{outlet}
|
{outlet}
|
||||||
</React.Suspense>
|
</LoaderSuspense>
|
||||||
</main>
|
</main>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
Loading…
Add table
Reference in a new issue