mirror of
https://github.com/owncast/owncast.git
synced 2024-10-10 19:16:02 +00:00
Fix some React lifecycle and rendering errors that exist in build
This commit is contained in:
parent
e9d43492d0
commit
d8a5380b7f
@ -6,7 +6,7 @@ describe('Lighthouse Metrics', () => {
|
|||||||
it('Capture Metrics', () => {
|
it('Capture Metrics', () => {
|
||||||
cy.lighthouse({
|
cy.lighthouse({
|
||||||
accessibility: 97,
|
accessibility: 97,
|
||||||
'best-practices': 97,
|
'best-practices': 90,
|
||||||
seo: 90,
|
seo: 90,
|
||||||
performance: 60, // Once the performance issues are fixed revert this 90,
|
performance: 60, // Once the performance issues are fixed revert this 90,
|
||||||
});
|
});
|
||||||
|
|||||||
@ -1,7 +1,6 @@
|
|||||||
import React, { useState, useContext, useEffect } from 'react';
|
import React, { useState, useContext, useEffect } from 'react';
|
||||||
import { Button, Collapse, Typography } from 'antd';
|
import { Button, Collapse, Typography, Tooltip } from 'antd';
|
||||||
import { CopyOutlined, RedoOutlined } from '@ant-design/icons';
|
import { CopyOutlined, RedoOutlined } from '@ant-design/icons';
|
||||||
import dynamic from 'next/dynamic';
|
|
||||||
import { TEXTFIELD_TYPE_NUMBER, TEXTFIELD_TYPE_PASSWORD, TEXTFIELD_TYPE_URL } from './TextField';
|
import { TEXTFIELD_TYPE_NUMBER, TEXTFIELD_TYPE_PASSWORD, TEXTFIELD_TYPE_URL } from './TextField';
|
||||||
import { TextFieldWithSubmit } from './TextFieldWithSubmit';
|
import { TextFieldWithSubmit } from './TextFieldWithSubmit';
|
||||||
import { ServerStatusContext } from '../../utils/server-status-context';
|
import { ServerStatusContext } from '../../utils/server-status-context';
|
||||||
@ -18,10 +17,6 @@ import { ResetYP } from './ResetYP';
|
|||||||
|
|
||||||
// Lazy loaded components
|
// Lazy loaded components
|
||||||
|
|
||||||
const Tooltip = dynamic(() => import('antd').then(mod => mod.Tooltip), {
|
|
||||||
ssr: false,
|
|
||||||
});
|
|
||||||
|
|
||||||
const { Panel } = Collapse;
|
const { Panel } = Collapse;
|
||||||
|
|
||||||
// eslint-disable-next-line react/function-component-definition
|
// eslint-disable-next-line react/function-component-definition
|
||||||
|
|||||||
@ -4,7 +4,7 @@ import Link from 'next/link';
|
|||||||
import Head from 'next/head';
|
import Head from 'next/head';
|
||||||
import { differenceInSeconds } from 'date-fns';
|
import { differenceInSeconds } from 'date-fns';
|
||||||
import { useRouter } from 'next/router';
|
import { useRouter } from 'next/router';
|
||||||
import { Layout, Menu, Alert, Button, Space } from 'antd';
|
import { Layout, Menu, Alert, Button, Space, Tooltip } from 'antd';
|
||||||
import {
|
import {
|
||||||
SettingOutlined,
|
SettingOutlined,
|
||||||
HomeOutlined,
|
HomeOutlined,
|
||||||
@ -19,7 +19,6 @@ import {
|
|||||||
} from '@ant-design/icons';
|
} from '@ant-design/icons';
|
||||||
|
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import dynamic from 'next/dynamic';
|
|
||||||
import { upgradeVersionAvailable } from '../../utils/apis';
|
import { upgradeVersionAvailable } from '../../utils/apis';
|
||||||
import { parseSecondsToDurationString } from '../../utils/format';
|
import { parseSecondsToDurationString } from '../../utils/format';
|
||||||
|
|
||||||
@ -34,12 +33,6 @@ import { UpdateArgs } from '../../types/config-section';
|
|||||||
|
|
||||||
import FediverseIcon from '../../assets/images/fediverse-black.png';
|
import FediverseIcon from '../../assets/images/fediverse-black.png';
|
||||||
|
|
||||||
// Lazy loaded components
|
|
||||||
|
|
||||||
const Tooltip = dynamic(() => import('antd').then(mod => mod.Tooltip), {
|
|
||||||
ssr: false,
|
|
||||||
});
|
|
||||||
|
|
||||||
export type MainLayoutProps = {
|
export type MainLayoutProps = {
|
||||||
children: ReactNode;
|
children: ReactNode;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,23 +1,16 @@
|
|||||||
// Custom component for AntDesign Button that makes an api call, then displays a confirmation icon upon
|
// Custom component for AntDesign Button that makes an api call, then displays a confirmation icon upon
|
||||||
import React, { useState, useEffect, FC } from 'react';
|
import React, { useState, useEffect, FC } from 'react';
|
||||||
import { Button } from 'antd';
|
import { Button, Tooltip } from 'antd';
|
||||||
import {
|
import {
|
||||||
EyeOutlined,
|
EyeOutlined,
|
||||||
EyeInvisibleOutlined,
|
EyeInvisibleOutlined,
|
||||||
CheckCircleFilled,
|
CheckCircleFilled,
|
||||||
ExclamationCircleFilled,
|
ExclamationCircleFilled,
|
||||||
} from '@ant-design/icons';
|
} from '@ant-design/icons';
|
||||||
import dynamic from 'next/dynamic';
|
|
||||||
import { fetchData, UPDATE_CHAT_MESSGAE_VIZ } from '../../utils/apis';
|
import { fetchData, UPDATE_CHAT_MESSGAE_VIZ } from '../../utils/apis';
|
||||||
import { MessageType } from '../../types/chat';
|
import { MessageType } from '../../types/chat';
|
||||||
import { isEmptyObject } from '../../utils/format';
|
import { isEmptyObject } from '../../utils/format';
|
||||||
|
|
||||||
// Lazy loaded components
|
|
||||||
|
|
||||||
const Tooltip = dynamic(() => import('antd').then(mod => mod.Tooltip), {
|
|
||||||
ssr: false,
|
|
||||||
});
|
|
||||||
|
|
||||||
export type MessageToggleProps = {
|
export type MessageToggleProps = {
|
||||||
isVisible: boolean;
|
isVisible: boolean;
|
||||||
message: MessageType;
|
message: MessageType;
|
||||||
|
|||||||
@ -1,12 +1,11 @@
|
|||||||
// This displays a clickable user name (or whatever children element you provide), and displays a simple tooltip of created time. OnClick a modal with more information about the user is displayed.
|
// This displays a clickable user name (or whatever children element you provide), and displays a simple tooltip of created time. OnClick a modal with more information about the user is displayed.
|
||||||
|
|
||||||
import { useState, ReactNode, FC } from 'react';
|
import { useState, ReactNode, FC } from 'react';
|
||||||
import { Divider, Modal, Typography, Row, Col, Space } from 'antd';
|
import { Divider, Modal, Typography, Row, Col, Space, Tooltip } from 'antd';
|
||||||
import formatDistanceToNow from 'date-fns/formatDistanceToNow';
|
import formatDistanceToNow from 'date-fns/formatDistanceToNow';
|
||||||
import format from 'date-fns/format';
|
import format from 'date-fns/format';
|
||||||
import { uniq } from 'lodash';
|
import { uniq } from 'lodash';
|
||||||
|
|
||||||
import dynamic from 'next/dynamic';
|
|
||||||
import { BanUserButton } from './BanUserButton';
|
import { BanUserButton } from './BanUserButton';
|
||||||
import { ModeratorUserButton } from './ModeratorUserButton';
|
import { ModeratorUserButton } from './ModeratorUserButton';
|
||||||
|
|
||||||
@ -14,12 +13,6 @@ import { User, UserConnectionInfo } from '../../types/chat';
|
|||||||
import { formatDisplayDate } from './UserTable';
|
import { formatDisplayDate } from './UserTable';
|
||||||
import { formatUAstring } from '../../utils/format';
|
import { formatUAstring } from '../../utils/format';
|
||||||
|
|
||||||
// Lazy loaded components
|
|
||||||
|
|
||||||
const Tooltip = dynamic(() => import('antd').then(mod => mod.Tooltip), {
|
|
||||||
ssr: false,
|
|
||||||
});
|
|
||||||
|
|
||||||
export type UserPopoverProps = {
|
export type UserPopoverProps = {
|
||||||
user: User;
|
user: User;
|
||||||
connectionInfo?: UserConnectionInfo | null;
|
connectionInfo?: UserConnectionInfo | null;
|
||||||
|
|||||||
@ -5,9 +5,15 @@ import cn from 'classnames';
|
|||||||
import { ChatSocialMessage as ChatMessage } from '../../../interfaces/chat-social-message.model';
|
import { ChatSocialMessage as ChatMessage } from '../../../interfaces/chat-social-message.model';
|
||||||
import styles from './ChatSocialMessage.module.scss';
|
import styles from './ChatSocialMessage.module.scss';
|
||||||
|
|
||||||
const FollowIcon = dynamic(() => import('./follow.svg'));
|
const FollowIcon = dynamic(() => import('./follow.svg'), {
|
||||||
const LikeIcon = dynamic(() => import('./like.svg'));
|
ssr: false,
|
||||||
const RepostIcon = dynamic(() => import('./repost.svg'));
|
});
|
||||||
|
const LikeIcon = dynamic(() => import('./like.svg'), {
|
||||||
|
ssr: false,
|
||||||
|
});
|
||||||
|
const RepostIcon = dynamic(() => import('./repost.svg'), {
|
||||||
|
ssr: false,
|
||||||
|
});
|
||||||
|
|
||||||
export interface ChatSocialMessageProps {
|
export interface ChatSocialMessageProps {
|
||||||
message: ChatMessage;
|
message: ChatMessage;
|
||||||
|
|||||||
@ -13,7 +13,9 @@ import styles from './ChatTextField.module.scss';
|
|||||||
|
|
||||||
// Lazy loaded components
|
// Lazy loaded components
|
||||||
|
|
||||||
const EmojiPicker = dynamic(() => import('./EmojiPicker').then(mod => mod.EmojiPicker));
|
const EmojiPicker = dynamic(() => import('./EmojiPicker').then(mod => mod.EmojiPicker), {
|
||||||
|
ssr: false,
|
||||||
|
});
|
||||||
|
|
||||||
type CustomElement = { type: 'paragraph' | 'span'; children: CustomText[] } | ImageNode;
|
type CustomElement = { type: 'paragraph' | 'span'; children: CustomText[] } | ImageNode;
|
||||||
type CustomText = { text: string };
|
type CustomText = { text: string };
|
||||||
|
|||||||
@ -2,6 +2,7 @@
|
|||||||
import { FC, ReactNode, useEffect, useState } from 'react';
|
import { FC, ReactNode, useEffect, useState } from 'react';
|
||||||
import cn from 'classnames';
|
import cn from 'classnames';
|
||||||
import { LinkOutlined } from '@ant-design/icons';
|
import { LinkOutlined } from '@ant-design/icons';
|
||||||
|
import { Tooltip } from 'antd';
|
||||||
import { useRecoilValue } from 'recoil';
|
import { useRecoilValue } from 'recoil';
|
||||||
import dynamic from 'next/dynamic';
|
import dynamic from 'next/dynamic';
|
||||||
import { decodeHTML } from 'entities';
|
import { decodeHTML } from 'entities';
|
||||||
@ -14,17 +15,19 @@ import { User } from '../../../interfaces/user.model';
|
|||||||
|
|
||||||
// Lazy loaded components
|
// Lazy loaded components
|
||||||
|
|
||||||
const Tooltip = dynamic(() => import('antd').then(mod => mod.Tooltip), {
|
const ChatModerationActionMenu = dynamic(
|
||||||
ssr: false,
|
() =>
|
||||||
});
|
import('../ChatModerationActionMenu/ChatModerationActionMenu').then(
|
||||||
|
mod => mod.ChatModerationActionMenu,
|
||||||
const ChatModerationActionMenu = dynamic(() =>
|
),
|
||||||
import('../ChatModerationActionMenu/ChatModerationActionMenu').then(
|
{
|
||||||
mod => mod.ChatModerationActionMenu,
|
ssr: false,
|
||||||
),
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
const Highlight = dynamic(() => import('react-highlighter-ts').then(mod => mod.Highlight));
|
const Highlight = dynamic(() => import('react-highlighter-ts').then(mod => mod.Highlight), {
|
||||||
|
ssr: false,
|
||||||
|
});
|
||||||
|
|
||||||
export type ChatUserMessageProps = {
|
export type ChatUserMessageProps = {
|
||||||
message: ChatMessage;
|
message: ChatMessage;
|
||||||
|
|||||||
@ -19,14 +19,22 @@ import styles from './UserDropdown.module.scss';
|
|||||||
import { AppStateOptions } from '../../stores/application-state';
|
import { AppStateOptions } from '../../stores/application-state';
|
||||||
|
|
||||||
// Lazy loaded components
|
// Lazy loaded components
|
||||||
const Modal = dynamic(() => import('../../ui/Modal/Modal').then(mod => mod.Modal));
|
const Modal = dynamic(() => import('../../ui/Modal/Modal').then(mod => mod.Modal), {
|
||||||
|
ssr: false,
|
||||||
|
});
|
||||||
|
|
||||||
const NameChangeModal = dynamic(() =>
|
const NameChangeModal = dynamic(
|
||||||
import('../../modals/NameChangeModal/NameChangeModal').then(mod => mod.NameChangeModal),
|
() => import('../../modals/NameChangeModal/NameChangeModal').then(mod => mod.NameChangeModal),
|
||||||
|
{
|
||||||
|
ssr: false,
|
||||||
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
const AuthModal = dynamic(() =>
|
const AuthModal = dynamic(
|
||||||
import('../../modals/AuthModal/AuthModal').then(mod => mod.AuthModal),
|
() => import('../../modals/AuthModal/AuthModal').then(mod => mod.AuthModal),
|
||||||
|
{
|
||||||
|
ssr: false,
|
||||||
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
export type UserDropdownProps = {
|
export type UserDropdownProps = {
|
||||||
@ -58,9 +66,6 @@ export const UserDropdown: FC<UserDropdownProps> = ({ username: defaultUsername
|
|||||||
);
|
);
|
||||||
|
|
||||||
const currentUser = useRecoilValue(currentUserAtom);
|
const currentUser = useRecoilValue(currentUserAtom);
|
||||||
if (!currentUser) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
const { displayName } = currentUser;
|
const { displayName } = currentUser;
|
||||||
const username = defaultUsername || displayName;
|
const username = defaultUsername || displayName;
|
||||||
|
|||||||
@ -17,28 +17,12 @@ import { DisplayableError } from '../../types/displayable-error';
|
|||||||
import setupNoLinkReferrer from '../../utils/no-link-referrer';
|
import setupNoLinkReferrer from '../../utils/no-link-referrer';
|
||||||
import { ServerRenderedHydration } from '../ServerRendered/ServerRenderedHydration';
|
import { ServerRenderedHydration } from '../ServerRendered/ServerRenderedHydration';
|
||||||
import { Content } from '../ui/Content/Content';
|
import { Content } from '../ui/Content/Content';
|
||||||
|
import { TitleNotifier } from '../TitleNotifier/TitleNotifier';
|
||||||
|
import { PushNotificationServiceWorker } from '../workers/PushNotificationServiceWorker/PushNotificationServiceWorker';
|
||||||
import { Theme } from '../theme/Theme';
|
import { Theme } from '../theme/Theme';
|
||||||
|
|
||||||
// Lazy loaded components
|
// Lazy loaded components
|
||||||
|
|
||||||
const TitleNotifier = dynamic(
|
|
||||||
() => import('../TitleNotifier/TitleNotifier').then(mod => mod.TitleNotifier),
|
|
||||||
{
|
|
||||||
ssr: false,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
const PushNotificationServiceWorker = dynamic(
|
|
||||||
() =>
|
|
||||||
import('../workers/PushNotificationServiceWorker/PushNotificationServiceWorker').then(
|
|
||||||
mod => mod.PushNotificationServiceWorker,
|
|
||||||
),
|
|
||||||
{
|
|
||||||
ssr: false,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
const FatalErrorStateModal = dynamic(
|
const FatalErrorStateModal = dynamic(
|
||||||
() =>
|
() =>
|
||||||
import('../modals/FatalErrorStateModal/FatalErrorStateModal').then(
|
import('../modals/FatalErrorStateModal/FatalErrorStateModal').then(
|
||||||
|
|||||||
@ -388,11 +388,9 @@ export const ClientConfigStore: FC = () => {
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!accessToken) {
|
if (accessToken) {
|
||||||
return;
|
getChatHistory();
|
||||||
}
|
}
|
||||||
|
|
||||||
getChatHistory();
|
|
||||||
}, [accessToken]);
|
}, [accessToken]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|||||||
@ -149,7 +149,7 @@ const MobileContent = ({
|
|||||||
supportsBrowserNotifications,
|
supportsBrowserNotifications,
|
||||||
}) => {
|
}) => {
|
||||||
if (!currentUser) {
|
if (!currentUser) {
|
||||||
return null;
|
return <Skeleton loading active paragraph={{ rows: 7 }} />;
|
||||||
}
|
}
|
||||||
const { id, displayName } = currentUser;
|
const { id, displayName } = currentUser;
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import { Tag } from 'antd';
|
import { Tag, Tooltip } from 'antd';
|
||||||
import { FC } from 'react';
|
import { FC } from 'react';
|
||||||
import cn from 'classnames';
|
import cn from 'classnames';
|
||||||
import dynamic from 'next/dynamic';
|
import dynamic from 'next/dynamic';
|
||||||
@ -7,14 +7,13 @@ import styles from './Header.module.scss';
|
|||||||
|
|
||||||
// Lazy loaded components
|
// Lazy loaded components
|
||||||
|
|
||||||
const UserDropdown = dynamic(() =>
|
const UserDropdown = dynamic(
|
||||||
import('../../common/UserDropdown/UserDropdown').then(mod => mod.UserDropdown),
|
() => import('../../common/UserDropdown/UserDropdown').then(mod => mod.UserDropdown),
|
||||||
|
{
|
||||||
|
ssr: false,
|
||||||
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
const Tooltip = dynamic(() => import('antd').then(mod => mod.Tooltip), {
|
|
||||||
ssr: false,
|
|
||||||
});
|
|
||||||
|
|
||||||
export type HeaderComponentProps = {
|
export type HeaderComponentProps = {
|
||||||
name: string;
|
name: string;
|
||||||
chatAvailable: boolean;
|
chatAvailable: boolean;
|
||||||
|
|||||||
@ -8,16 +8,18 @@ import styles from './Sidebar.module.scss';
|
|||||||
import { currentUserAtom, visibleChatMessagesSelector } from '../../stores/ClientConfigStore';
|
import { currentUserAtom, visibleChatMessagesSelector } from '../../stores/ClientConfigStore';
|
||||||
|
|
||||||
// Lazy loaded components
|
// Lazy loaded components
|
||||||
const ChatContainer = dynamic(() =>
|
const ChatContainer = dynamic(
|
||||||
import('../../chat/ChatContainer/ChatContainer').then(mod => mod.ChatContainer),
|
() => import('../../chat/ChatContainer/ChatContainer').then(mod => mod.ChatContainer),
|
||||||
|
{
|
||||||
|
ssr: false,
|
||||||
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
export const Sidebar: FC = () => {
|
export const Sidebar: FC = () => {
|
||||||
const currentUser = useRecoilValue(currentUserAtom);
|
const currentUser = useRecoilValue(currentUserAtom);
|
||||||
const messages = useRecoilValue<ChatMessage[]>(visibleChatMessagesSelector);
|
const messages = useRecoilValue<ChatMessage[]>(visibleChatMessagesSelector);
|
||||||
|
|
||||||
if (!currentUser) {
|
if (!currentUser) {
|
||||||
return null;
|
return <Sider className={styles.root} collapsedWidth={0} width={320} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
const { id, isModerator, displayName } = currentUser;
|
const { id, isModerator, displayName } = currentUser;
|
||||||
|
|||||||
@ -1,10 +1,21 @@
|
|||||||
import React, { useState, useEffect } from 'react';
|
import React, { useState, useEffect } from 'react';
|
||||||
import { Table, Tag, Space, Button, Modal, Checkbox, Input, Typography, Row, Col } from 'antd';
|
import {
|
||||||
|
Table,
|
||||||
|
Tag,
|
||||||
|
Space,
|
||||||
|
Button,
|
||||||
|
Modal,
|
||||||
|
Checkbox,
|
||||||
|
Input,
|
||||||
|
Typography,
|
||||||
|
Row,
|
||||||
|
Col,
|
||||||
|
Tooltip,
|
||||||
|
} from 'antd';
|
||||||
import { DeleteOutlined } from '@ant-design/icons';
|
import { DeleteOutlined } from '@ant-design/icons';
|
||||||
|
|
||||||
import format from 'date-fns/format';
|
import format from 'date-fns/format';
|
||||||
|
|
||||||
import dynamic from 'next/dynamic';
|
|
||||||
import {
|
import {
|
||||||
fetchData,
|
fetchData,
|
||||||
ACCESS_TOKENS,
|
ACCESS_TOKENS,
|
||||||
@ -14,12 +25,6 @@ import {
|
|||||||
|
|
||||||
const { Title, Paragraph } = Typography;
|
const { Title, Paragraph } = Typography;
|
||||||
|
|
||||||
// Lazy loaded components
|
|
||||||
|
|
||||||
const Tooltip = dynamic(() => import('antd').then(mod => mod.Tooltip), {
|
|
||||||
ssr: false,
|
|
||||||
});
|
|
||||||
|
|
||||||
const availableScopes = {
|
const availableScopes = {
|
||||||
CAN_SEND_SYSTEM_MESSAGES: {
|
CAN_SEND_SYSTEM_MESSAGES: {
|
||||||
name: 'System messages',
|
name: 'System messages',
|
||||||
|
|||||||
@ -1,17 +1,22 @@
|
|||||||
/* eslint-disable react/destructuring-assignment */
|
/* eslint-disable react/destructuring-assignment */
|
||||||
import { DeleteOutlined } from '@ant-design/icons';
|
import { DeleteOutlined } from '@ant-design/icons';
|
||||||
import { Button, Checkbox, Col, Input, Modal, Row, Space, Table, Tag, Typography } from 'antd';
|
import {
|
||||||
import dynamic from 'next/dynamic';
|
Button,
|
||||||
|
Checkbox,
|
||||||
|
Col,
|
||||||
|
Input,
|
||||||
|
Modal,
|
||||||
|
Row,
|
||||||
|
Space,
|
||||||
|
Table,
|
||||||
|
Tag,
|
||||||
|
Typography,
|
||||||
|
Tooltip,
|
||||||
|
} from 'antd';
|
||||||
import React, { useEffect, useState } from 'react';
|
import React, { useEffect, useState } from 'react';
|
||||||
import { CREATE_WEBHOOK, DELETE_WEBHOOK, fetchData, WEBHOOKS } from '../../utils/apis';
|
import { CREATE_WEBHOOK, DELETE_WEBHOOK, fetchData, WEBHOOKS } from '../../utils/apis';
|
||||||
import { isValidUrl, DEFAULT_TEXTFIELD_URL_PATTERN } from '../../utils/urls';
|
import { isValidUrl, DEFAULT_TEXTFIELD_URL_PATTERN } from '../../utils/urls';
|
||||||
|
|
||||||
// Lazy loaded components
|
|
||||||
|
|
||||||
const Tooltip = dynamic(() => import('antd').then(mod => mod.Tooltip), {
|
|
||||||
ssr: false,
|
|
||||||
});
|
|
||||||
|
|
||||||
const { Title, Paragraph } = Typography;
|
const { Title, Paragraph } = Typography;
|
||||||
|
|
||||||
const availableEvents = {
|
const availableEvents = {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user