More blank components and stories to be filled in

This commit is contained in:
Gabe Kangas 2022-04-28 14:36:05 -07:00
parent e0c073171d
commit e5d3b0e4ee
No known key found for this signature in database
GPG key ID: 9A56337728BC81EA
16 changed files with 194 additions and 36 deletions

View file

@ -18,6 +18,15 @@ Make sure you're running an instance of Owncast on localhost:8080, as your copy
```npm run dev```
### Components and Styles
You can start the [Storybook](https://storybook.js.org/) UI for exploring, testing, and developing components by running:
```npm run storybook```
This allows for components to be made available without the need of the server to be running and changes to be made in
isolation.
### Update the project
You can add or edit a pages by modifying `pages/something.js`. The page auto-updates as you edit the file.

View file

@ -4,5 +4,5 @@ interface Props {
export default function CustomPageContent(props: Props) {
const { content } = props;
return <div>{content}</div>;
return <div dangerouslySetInnerHTML={{ __html: content }} />;
}

View file

@ -0,0 +1,9 @@
import { Follower } from '../interfaces/follower';
interface Props {
follower: Follower;
}
export default function FollowerCollection(props: Props) {
return <div>This is a single follower</div>;
}

View file

@ -0,0 +1,9 @@
import { Follower } from '../interfaces/follower';
interface Props {
followers: Follower[];
}
export default function FollowerCollection(props: Props) {
return <div>List of followers go here</div>;
}

View file

@ -5,5 +5,5 @@ interface Props {
}
export default function ChatContainer(props: Props) {
return <div>Component goes here</div>;
return <div>Chat container goes here</div>;
}

View file

@ -3,6 +3,7 @@ import { ReactElement } from 'react-markdown/lib/react-markdown';
import { atom, useRecoilState } from 'recoil';
import { makeEmptyClientConfig, ClientConfig } from '../../interfaces/client-config.model';
import ClientConfigService from '../../services/client-config-service';
import { ChatMessage } from '../../interfaces/chat-message.model';
// The config that comes from the API.
export const clientConfigState = atom({
@ -15,11 +16,16 @@ export const chatCurrentlyVisible = atom({
default: false,
});
export const chatDislayName = atom({
export const chatDisplayName = atom({
key: 'chatDisplayName',
default: '',
});
export const chatMessages = atom({
key: 'chatMessages',
default: [] as ChatMessage[],
});
export function ClientConfigStore(): ReactElement {
const [, setClientConfig] = useRecoilState<ClientConfig>(clientConfigState);

View file

@ -1,7 +1,12 @@
import { useRecoilValue } from 'recoil';
import { Layout, Row, Col, Tabs } from 'antd';
import { clientConfigState } from '../../stores/ClientConfigStore';
import { ClientConfig } from '../../../interfaces/client-config.model';
import { Layout, Row, Col } from 'antd';
import CustomPageContent from '../../CustomPageContent';
import OwncastPlayer from '../../video/OwncastPlayer';
import FollowerCollection from '../../FollowersCollection';
const { TabPane } = Tabs;
const { Content } = Layout;
@ -13,11 +18,20 @@ export default function FooterComponent() {
<Content style={{ margin: '80px 16px 0', overflow: 'initial' }}>
<div>
<Row>
<Col span={24}>Video player goes here</Col>
<Col span={24}>
<OwncastPlayer source="https://watch.owncast.online" />
</Col>
</Row>
<Row>
<Col span={24}>
<Content dangerouslySetInnerHTML={{ __html: extraPageContent }} />
<Tabs defaultActiveKey="1" type="card">
<TabPane tab="About" key="1">
<CustomPageContent content={extraPageContent} />
</TabPane>
<TabPane tab="Followers" key="2">
<FollowerCollection />
</TabPane>
</Tabs>
</Col>
</Row>
</div>

View file

@ -1,13 +1,9 @@
import { useRecoilValue } from 'recoil';
import { clientConfigState } from '../../stores/ClientConfigStore';
import { ClientConfig } from '../../../interfaces/client-config.model';
import { Layout } from 'antd';
const { Footer } = Layout;
export default function FooterComponent() {
const clientConfig = useRecoilValue<ClientConfig>(clientConfigState);
const { version } = clientConfig;
export default function FooterComponent(props) {
const { version } = props;
return <Footer style={{ textAlign: 'center' }}>Footer: Owncast {version}</Footer>;
}

View file

@ -1,31 +1,17 @@
import s from './Header.module.scss';
import { Layout } from 'antd';
import { ServerStatusStore, serverStatusState } from '../../stores/ServerStatusStore';
import {
ClientConfigStore,
clientConfigState,
chatCurrentlyVisible,
} from '../../stores/ClientConfigStore';
import { ClientConfig } from '../../../interfaces/client-config.model';
import { useRecoilState, useRecoilValue } from 'recoil';
import { useEffect } from 'react';
import UserDropdown from '../../UserDropdownMenu';
import s from './Header.module.scss';
const { Header } = Layout;
export default function HeaderComponent() {
const clientConfig = useRecoilValue<ClientConfig>(clientConfigState);
const [chatOpen, setChatOpen] = useRecoilState(chatCurrentlyVisible);
const { name } = clientConfig;
useEffect(() => {
console.log({ chatOpen });
}, [chatOpen]);
export default function HeaderComponent(props) {
const { name } = props;
return (
<Header className={`${s.header}`}>
Logo goes here
{name}
<button onClick={() => setChatOpen(!chatOpen)}>Toggle Chat</button>
<UserDropdown />
</Header>
);
}

View file

@ -1,12 +1,15 @@
import Sider from 'antd/lib/layout/Sider';
import { useRecoilValue } from 'recoil';
import { chatCurrentlyVisible } from '../../stores/ClientConfigStore';
import { ChatMessage } from '../../../interfaces/chat-message.model';
import ChatContainer from '../../chat/ChatContainer';
import { chatMessages } from '../../stores/ClientConfigStore';
export default function Sidebar() {
let chatOpen = useRecoilValue(chatCurrentlyVisible);
const messages = useRecoilValue<ChatMessage[]>(chatMessages);
return (
<Sider
collapsed={!chatOpen}
collapsed={false}
width={300}
style={{
position: 'fixed',
@ -14,6 +17,8 @@ export default function Sidebar() {
top: 0,
bottom: 0,
}}
/>
>
<ChatContainer messages={messages} />
</Sider>
);
}

View file

@ -0,0 +1,7 @@
export interface Follower {
name: string;
description?: string;
username?: string;
image?: string;
link: string;
}

View file

@ -0,0 +1,22 @@
import React from 'react';
import { ComponentStory, ComponentMeta } from '@storybook/react';
import * as FollowerComponent from '../components/Follower';
export default {
title: 'owncast/Follower',
component: FollowerComponent,
parameters: {},
} as ComponentMeta<typeof FollowerComponent>;
const Template: ComponentStory<typeof FollowerComponent> = args => <FollowerComponent {...args} />;
export const Example = Template.bind({});
Example.args = {
follower: {
name: 'John Doe',
description: 'User',
username: '@account@domain.tld',
image: 'https://avatars0.githubusercontent.com/u/1234?s=460&v=4',
link: 'https://yahoo.com',
},
};

View file

@ -0,0 +1,61 @@
import React from 'react';
import { ComponentStory, ComponentMeta } from '@storybook/react';
import FollowerCollection from '../components/FollowersCollection';
export default {
title: 'owncast/Follower collection',
component: FollowerCollection,
parameters: {},
} as ComponentMeta<typeof FollowerCollection>;
const Template: ComponentStory<typeof FollowerCollection> = args => (
<FollowerCollection {...args} />
);
export const Example = Template.bind({});
Example.args = {
followers: [
{
name: 'John Doe',
description: 'User',
username: '@account@domain.tld',
image: 'https://avatars0.githubusercontent.com/u/1234?s=460&v=4',
link: 'https://yahoo.com',
},
{
name: 'John Doe',
description: 'User',
username: '@account@domain.tld',
image: 'https://avatars0.githubusercontent.com/u/1234?s=460&v=4',
link: 'https://yahoo.com',
},
{
name: 'John Doe',
description: 'User',
username: '@account@domain.tld',
image: 'https://avatars0.githubusercontent.com/u/1234?s=460&v=4',
link: 'https://yahoo.com',
},
{
name: 'John Doe',
description: 'User',
username: '@account@domain.tld',
image: 'https://avatars0.githubusercontent.com/u/1234?s=460&v=4',
link: 'https://yahoo.com',
},
{
name: 'John Doe',
description: 'User',
username: '@account@domain.tld',
image: 'https://avatars0.githubusercontent.com/u/1234?s=460&v=4',
link: 'https://yahoo.com',
},
{
name: 'John Doe',
description: 'User',
username: '@account@domain.tld',
image: 'https://avatars0.githubusercontent.com/u/1234?s=460&v=4',
link: 'https://yahoo.com',
},
],
};

View file

@ -0,0 +1,18 @@
import React from 'react';
import { ComponentStory, ComponentMeta } from '@storybook/react';
import Footer from '../components/ui/Footer/Footer';
export default {
title: 'owncast/Footer',
component: Footer,
parameters: {},
} as ComponentMeta<typeof Footer>;
// eslint-disable-next-line @typescript-eslint/no-unused-Footer
const Template: ComponentStory<typeof Footer> = args => <Footer {...args} />;
// eslint-disable-next-line @typescript-eslint/no-unused-vars
export const Example = Template.bind({});
Example.args = {
version: 'v1.2.3',
};

View file

@ -0,0 +1,16 @@
import React from 'react';
import { ComponentStory, ComponentMeta } from '@storybook/react';
import Header from '../components/ui/Header/Header';
export default {
title: 'owncast/Header',
component: Header,
parameters: {},
} as ComponentMeta<typeof Header>;
const Template: ComponentStory<typeof Header> = args => <Header {...args} />;
export const Example = Template.bind({});
Example.args = {
name: 'Example Stream Name',
};