mirror of
https://github.com/Unkn0wnCat/matrix-veles.git
synced 2025-04-28 09:46:51 +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 {graphql} from "babel-plugin-relay/macro";
|
||||
import {RoomDetailQuery, RoomDetailQuery$variables} from "./__generated__/RoomDetailQuery.graphql";
|
||||
import {DisposeFn} from "relay-runtime";
|
||||
import {useParams} from "react-router-dom";
|
||||
import {RoomsSlideOverTitleContext} from "./Rooms";
|
||||
import ToggleButton from "../../form_components/ToggleButton";
|
||||
|
||||
import styles from "./RoomDetail.module.scss";
|
||||
|
@ -46,20 +47,21 @@ const RoomDetailInner = ({initialQueryRef}: PropsFinal) => {
|
|||
initialQueryRef
|
||||
)
|
||||
|
||||
const titleSetContext = useContext(RoomsSlideOverTitleContext)
|
||||
|
||||
titleSetContext && data.room?.name && titleSetContext(data.room.name);
|
||||
|
||||
return <>
|
||||
<span className={styles.title}>
|
||||
<h1>{data.room?.name}</h1>
|
||||
<ToggleButton name={"activeSwitch"} label={"Activate"} labelSrOnly={true} onChange={(ev) => {
|
||||
reconfigureRoom({
|
||||
variables: {
|
||||
reconfigureInput: {
|
||||
id: data.room?.id!,
|
||||
deactivate: !ev.currentTarget.checked
|
||||
}
|
||||
<ToggleButton name={"activeSwitch"} label={"Activate Room"} labelSrOnly={false} onChange={(ev) => {
|
||||
reconfigureRoom({
|
||||
variables: {
|
||||
reconfigureInput: {
|
||||
id: data.room?.id!,
|
||||
deactivate: !ev.currentTarget.checked
|
||||
}
|
||||
})
|
||||
}} disabled={reconfiguringRoom || ((data.room || false) && !data.room.active && !data.room.deactivated)} checked={data.room?.active}/>
|
||||
</span>
|
||||
}
|
||||
})
|
||||
}} disabled={reconfiguringRoom || ((data.room || false) && !data.room.active && !data.room.deactivated)} checked={data.room?.active}/>
|
||||
|
||||
|
||||
<pre>{JSON.stringify(data, null, 2)}</pre>
|
||||
|
@ -77,7 +79,7 @@ const RoomDetail = ({initialQueryRef, fetch, dispose}: Props) => {
|
|||
}
|
||||
}, [id, dispose, fetch])
|
||||
|
||||
return initialQueryRef ? <RoomDetailInner initialQueryRef={initialQueryRef} /> : <>loading...</>
|
||||
return initialQueryRef ? <RoomDetailInner initialQueryRef={initialQueryRef} /> : null
|
||||
}
|
||||
|
||||
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 styles from "./Rooms.module.scss";
|
||||
import {Trans} from "react-i18next";
|
||||
import {Trans, useTranslation} from "react-i18next";
|
||||
import RoomsTable from "./RoomsTable";
|
||||
import {PreloadedQuery, usePreloadedQuery} from "react-relay/hooks";
|
||||
import {graphql} from "babel-plugin-relay/macro";
|
||||
import {RoomsQuery} from "./__generated__/RoomsQuery.graphql";
|
||||
import {X} from "lucide-react";
|
||||
import {LoaderSuspense} from "../../common/Loader";
|
||||
|
||||
type Props = {
|
||||
initialQueryRef: PreloadedQuery<RoomsQuery>,
|
||||
|
@ -16,6 +17,7 @@ type Props = {
|
|||
const Rooms = ({initialQueryRef}: Props) => {
|
||||
const outlet = useOutlet()
|
||||
const navigate = useNavigate()
|
||||
const {t} = useTranslation()
|
||||
|
||||
const data = usePreloadedQuery(
|
||||
graphql`
|
||||
|
@ -26,6 +28,10 @@ const Rooms = ({initialQueryRef}: Props) => {
|
|||
initialQueryRef
|
||||
)
|
||||
|
||||
const defaultTitle = t("rooms.details", "Details")
|
||||
|
||||
const [title, setTitle] = useState(defaultTitle)
|
||||
|
||||
|
||||
return <div className={styles.roomsContainer}>
|
||||
<div className={styles.roomsOverview + (outlet ? " "+styles.leaveSpace : "")}>
|
||||
|
@ -35,15 +41,21 @@ const Rooms = ({initialQueryRef}: Props) => {
|
|||
</div>
|
||||
|
||||
<div className={styles.slideOver + (outlet ? " "+styles.active : "")}>
|
||||
<div className={styles.slideOverHeader}>
|
||||
<span><Trans i18nKey={"rooms.details"}>Details</Trans></span>
|
||||
<button onClick={() => navigate("/rooms")}><X/></button>
|
||||
</div>
|
||||
<div className={styles.slideOverContent}>
|
||||
{outlet}
|
||||
</div>
|
||||
<RoomsSlideOverTitleContext.Provider value={setTitle}>
|
||||
<div className={styles.slideOverHeader}>
|
||||
<span>{title}</span>
|
||||
<button onClick={() => navigate("/rooms")}><X/></button>
|
||||
</div>
|
||||
<div className={styles.slideOverContent}>
|
||||
<LoaderSuspense>
|
||||
{outlet}
|
||||
</LoaderSuspense>
|
||||
</div>
|
||||
</RoomsSlideOverTitleContext.Provider>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
export const RoomsSlideOverTitleContext = React.createContext<React.Dispatch<React.SetStateAction<string>>|null>(null)
|
||||
|
||||
export default Rooms
|
|
@ -41,7 +41,7 @@ const RoomsTable = ({initialQueryRef}: Props) => {
|
|||
<tbody>
|
||||
{
|
||||
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>
|
||||
{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>}
|
||||
|
|
|
@ -12,17 +12,18 @@ import {
|
|||
|
||||
import "./i18n";
|
||||
import RelayEnvironment from "./RelayEnvironment";
|
||||
import {LoaderSuspense} from "./components/common/Loader";
|
||||
|
||||
|
||||
ReactDOM.render(
|
||||
<React.StrictMode>
|
||||
<Provider store={store}>
|
||||
<RelayEnvironmentProvider environment={RelayEnvironment({store})}>
|
||||
<React.Suspense fallback={<h1>Loading...</h1>}>
|
||||
<LoaderSuspense>
|
||||
<BrowserRouter>
|
||||
<App />
|
||||
</BrowserRouter>
|
||||
</React.Suspense>
|
||||
</LoaderSuspense>
|
||||
</RelayEnvironmentProvider>
|
||||
</Provider>
|
||||
</React.StrictMode>,
|
||||
|
|
|
@ -10,6 +10,7 @@ import styles from "./PanelLayout.module.scss";
|
|||
import {Trans, useTranslation} from "react-i18next";
|
||||
import {useAppDispatch} from "../app/hooks";
|
||||
import {logOut} from "../features/auth/authSlice";
|
||||
import {LoaderSuspense} from "../components/common/Loader";
|
||||
|
||||
const PanelLayout = () => {
|
||||
const {t} = useTranslation()
|
||||
|
@ -44,9 +45,9 @@ const PanelLayout = () => {
|
|||
</div>
|
||||
</nav>
|
||||
<main id={"main"}>
|
||||
<React.Suspense fallback={<span>Fetching data...</span>}>
|
||||
<LoaderSuspense>
|
||||
{outlet}
|
||||
</React.Suspense>
|
||||
</LoaderSuspense>
|
||||
</main>
|
||||
</div>
|
||||
</div>
|
||||
|
|
Loading…
Add table
Reference in a new issue