Initial api requests + stores + basic layout
This commit is contained in:
93
web/components/layouts/main.tsx
Normal file
93
web/components/layouts/main.tsx
Normal file
@@ -0,0 +1,93 @@
|
||||
import { useRecoilValue } from 'recoil';
|
||||
import { Layout, Row, Col } from 'antd';
|
||||
import { useState } from 'react';
|
||||
import { ServerStatus } from '../../models/ServerStatus';
|
||||
import { ServerStatusStore, serverStatusState } from '../stores/ServerStatusStore';
|
||||
import { ClientConfigStore, clientConfigState } from '../stores/ClientConfigStore';
|
||||
import { ClientConfig } from '../../models/ClientConfig';
|
||||
|
||||
const { Header, Content, Footer, Sider } = Layout;
|
||||
|
||||
function Main() {
|
||||
const serverStatus = useRecoilValue<ServerStatus>(serverStatusState);
|
||||
const clientConfig = useRecoilValue<ClientConfig>(clientConfigState);
|
||||
|
||||
const { name, version, extraPageContent } = clientConfig;
|
||||
const [chatCollapsed, setChatCollapsed] = useState(false);
|
||||
|
||||
const toggleChatCollapsed = () => {
|
||||
setChatCollapsed(!chatCollapsed);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<ServerStatusStore />
|
||||
<ClientConfigStore />
|
||||
|
||||
<Layout>
|
||||
<Sider
|
||||
collapsed={chatCollapsed}
|
||||
width={300}
|
||||
style={{
|
||||
position: 'fixed',
|
||||
right: 0,
|
||||
top: 0,
|
||||
bottom: 0,
|
||||
}}
|
||||
/>
|
||||
<Layout className="site-layout" style={{ marginRight: 200 }}>
|
||||
<Header
|
||||
className="site-layout-background"
|
||||
style={{ position: 'fixed', zIndex: 1, width: '100%' }}
|
||||
>
|
||||
{name}
|
||||
<button onClick={toggleChatCollapsed}>Toggle Chat</button>
|
||||
</Header>
|
||||
<Content style={{ margin: '80px 16px 0', overflow: 'initial' }}>
|
||||
<div>
|
||||
<Row>
|
||||
<Col span={24}>Video player goes here</Col>
|
||||
</Row>
|
||||
<Row>
|
||||
<Col span={24}>
|
||||
<Content dangerouslySetInnerHTML={{ __html: extraPageContent }} />
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
</Content>
|
||||
<Footer style={{ textAlign: 'center' }}>Footer: Owncast {version}</Footer>
|
||||
</Layout>
|
||||
</Layout>
|
||||
</>
|
||||
);
|
||||
// return (
|
||||
// <div>
|
||||
|
||||
// <Layout>
|
||||
// <Header className="header">
|
||||
// {name}
|
||||
// <button onClick={toggleChatCollapsed}>Toggle Chat</button>
|
||||
// </Header>
|
||||
// <Content>
|
||||
// <Layout>
|
||||
// <Row>
|
||||
// <Col span={24}>Video player goes here</Col>
|
||||
// </Row>
|
||||
// <Row>
|
||||
// <Col span={24}>
|
||||
// <Content dangerouslySetInnerHTML={{ __html: extraPageContent }} />
|
||||
// </Col>
|
||||
// </Row>
|
||||
|
||||
// <Sider collapsed={chatCollapsed} width={300}>
|
||||
// chat
|
||||
// </Sider>
|
||||
// </Layout>
|
||||
// </Content>
|
||||
// <Footer>Footer: Owncast {version}</Footer>
|
||||
// </Layout>
|
||||
// </div>
|
||||
// );
|
||||
}
|
||||
|
||||
export default Main;
|
||||
30
web/components/stores/ClientConfigStore.tsx
Normal file
30
web/components/stores/ClientConfigStore.tsx
Normal file
@@ -0,0 +1,30 @@
|
||||
import { useEffect } from 'react';
|
||||
import { ReactElement } from 'react-markdown/lib/react-markdown';
|
||||
import { atom, useRecoilState } from 'recoil';
|
||||
import { makeEmptyClientConfig, ClientConfig } from '../../models/ClientConfig';
|
||||
import ClientConfigService from '../../services/ClientConfigService';
|
||||
|
||||
export const clientConfigState = atom({
|
||||
key: 'clientConfigState',
|
||||
default: makeEmptyClientConfig(),
|
||||
});
|
||||
|
||||
export function ClientConfigStore(): ReactElement {
|
||||
const [, setClientConfig] = useRecoilState<ClientConfig>(clientConfigState);
|
||||
|
||||
const updateClientConfig = async () => {
|
||||
try {
|
||||
const config = await ClientConfigService.getConfig();
|
||||
console.log(`ClientConfig: ${JSON.stringify(config)}`);
|
||||
setClientConfig(config);
|
||||
} catch (error) {
|
||||
console.error(`ClientConfigService -> getConfig() ERROR: \n${error}`);
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
updateClientConfig();
|
||||
}, []);
|
||||
|
||||
return null;
|
||||
}
|
||||
34
web/components/stores/ServerStatusStore.tsx
Normal file
34
web/components/stores/ServerStatusStore.tsx
Normal file
@@ -0,0 +1,34 @@
|
||||
import { useEffect } from 'react';
|
||||
import { ReactElement } from 'react-markdown/lib/react-markdown';
|
||||
import { atom, useRecoilState } from 'recoil';
|
||||
import { ServerStatus, makeEmptyServerStatus } from '../../models/ServerStatus';
|
||||
import ServerStatusService from '../../services/StatusService';
|
||||
|
||||
export const serverStatusState = atom({
|
||||
key: 'serverStatusState',
|
||||
default: makeEmptyServerStatus(),
|
||||
});
|
||||
|
||||
export function ServerStatusStore(): ReactElement {
|
||||
const [, setServerStatus] = useRecoilState<ServerStatus>(serverStatusState);
|
||||
|
||||
const updateServerStatus = async () => {
|
||||
try {
|
||||
const status = await ServerStatusService.getStatus();
|
||||
setServerStatus(status);
|
||||
return status;
|
||||
} catch (error) {
|
||||
console.error(`serverStatusState -> getStatus() ERROR: \n${error}`);
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
setInterval(() => {
|
||||
updateServerStatus();
|
||||
}, 5000);
|
||||
updateServerStatus();
|
||||
}, []);
|
||||
|
||||
return null;
|
||||
}
|
||||
Reference in New Issue
Block a user