reafctor: normalize component formatting (#2082)
* refactor: move/rename BanUserButton file * refactor: move/rename Chart file * refactor: update generic component filenames to PascalCase * refactor: update config component filenames to PascalCase * refactor: update AdminLayout component filename to PascalCase * refactor: update/move VideoJS component * chore(eslint): disable bad react/require-default-props rule * refactor: normalize ActionButton component * refactor: normalize ActionButtonRow component * refactor: normalize FollowButton component * refactor: normalize NotifyButton component * refactor: normalize ChatActionMessage component * refactor: normalize ChatContainer component * refactor: normalize ChatJoinMessage component * refactor: normalize ChatModerationActionMenu component * refactor: normalize ChatModerationDetailsModal component * refactor: normalize ChatModeratorNotification component * refactor: normalize ChatSocialMessage component * refactor: normalize ChatSystemMessage component * refactor: normalize ChatTextField component * refactor: normalize ChatUserBadge component * refactor: normalize ChatUserMessage component * refactor: normalize ContentHeader component * refactor: normalize OwncastLogo component * refactor: normalize UserDropdown component * chore(eslint): modify react/function-component-definition rule * refactor: normalize CodecSelector component * refactor: update a bunch of functional components using eslint * refactor: update a bunch of functional components using eslint, pt2 * refactor: update a bunch of functional components using eslint, pt3 * refactor: replace all component->component default imports with named imports * refactor: replace all component-stories->component default imports with named imports * refactor: remove default exports from most components * chore(eslint): add eslint config files for the components and pages dirs * fix: use-before-define error in ChatContainer * Fix ChatContainer import * Only process .tsx files in Next builds Co-authored-by: Gabe Kangas <gabek@real-ity.com>
This commit is contained in:
@@ -62,7 +62,7 @@ interface Props {
|
||||
onOk: any; // todo: make better type
|
||||
visible: boolean;
|
||||
}
|
||||
function NewTokenModal(props: Props) {
|
||||
const NewTokenModal = (props: Props) => {
|
||||
const { onOk, onCancel, visible } = props;
|
||||
const [selectedScopes, setSelectedScopes] = useState([]);
|
||||
const [name, setName] = useState('');
|
||||
@@ -131,9 +131,9 @@ function NewTokenModal(props: Props) {
|
||||
</p>
|
||||
</Modal>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export default function AccessTokens() {
|
||||
const AccessTokens = () => {
|
||||
const [tokens, setTokens] = useState([]);
|
||||
const [isTokenModalVisible, setIsTokenModalVisible] = useState(false);
|
||||
|
||||
@@ -264,4 +264,5 @@ export default function AccessTokens() {
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
};
|
||||
export default AccessTokens;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { DeleteOutlined } from '@ant-design/icons';
|
||||
import { Button, Checkbox, Input, Modal, Space, Table, Typography } from 'antd';
|
||||
import React, { useContext, useEffect, useState } from 'react';
|
||||
import FormStatusIndicator from '../../components/config/form-status-indicator';
|
||||
import { FormStatusIndicator } from '../../components/config/FormStatusIndicator';
|
||||
import {
|
||||
API_EXTERNAL_ACTIONS,
|
||||
postConfigUpdateToAPI,
|
||||
@@ -20,7 +20,7 @@ interface Props {
|
||||
visible: boolean;
|
||||
}
|
||||
|
||||
function NewActionModal(props: Props) {
|
||||
const NewActionModal = (props: Props) => {
|
||||
const { onOk, onCancel, visible } = props;
|
||||
|
||||
const [actionUrl, setActionUrl] = useState('');
|
||||
@@ -131,9 +131,9 @@ function NewActionModal(props: Props) {
|
||||
</div>
|
||||
</Modal>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export default function Actions() {
|
||||
const Actions = () => {
|
||||
const serverStatusData = useContext(ServerStatusContext);
|
||||
const { serverConfig, setFieldInConfigState } = serverStatusData || {};
|
||||
const { externalActions } = serverConfig;
|
||||
@@ -310,4 +310,5 @@ export default function Actions() {
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
};
|
||||
export default Actions;
|
||||
|
||||
@@ -13,8 +13,8 @@ import {
|
||||
UPDATE_CHAT_MESSGAE_VIZ,
|
||||
} from '../../../utils/apis';
|
||||
import { isEmptyObject } from '../../../utils/format';
|
||||
import MessageVisiblityToggle from '../../../components/message-visiblity-toggle';
|
||||
import UserPopover from '../../../components/user-popover';
|
||||
import { MessageVisiblityToggle } from '../../../components/MessageVisiblityToggle';
|
||||
import { UserPopover } from '../../../components/UserPopover';
|
||||
|
||||
const { Title } = Typography;
|
||||
|
||||
|
||||
@@ -8,9 +8,9 @@ import {
|
||||
MODERATORS,
|
||||
BANNED_IPS,
|
||||
} from '../../../utils/apis';
|
||||
import UserTable from '../../../components/user-table';
|
||||
import ClientTable from '../../../components/client-table';
|
||||
import BannedIPsTable from '../../../components/banned-ips-table';
|
||||
import { UserTable } from '../../../components/UserTable';
|
||||
import { ClientTable } from '../../../components/ClientTable';
|
||||
import { BannedIPsTable } from '../../../components/BannedIPsTable';
|
||||
|
||||
const { TabPane } = Tabs;
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { Typography } from 'antd';
|
||||
import React, { useContext, useEffect, useState } from 'react';
|
||||
import { TEXTFIELD_TYPE_TEXTAREA } from '../../components/config/form-textfield';
|
||||
import TextFieldWithSubmit from '../../components/config/form-textfield-with-submit';
|
||||
import ToggleSwitch from '../../components/config/form-toggleswitch';
|
||||
import EditValueArray from '../../components/config/edit-string-array';
|
||||
import { TEXTFIELD_TYPE_TEXTAREA } from '../../components/config/TextField';
|
||||
import { TextFieldWithSubmit } from '../../components/config/TextFieldWithSubmit';
|
||||
import { ToggleSwitch } from '../../components/config/ToggleSwitch';
|
||||
import { EditValueArray } from '../../components/config/EditValueArray';
|
||||
import {
|
||||
createInputStatus,
|
||||
StatusState,
|
||||
|
||||
@@ -6,10 +6,10 @@ import {
|
||||
TEXTFIELD_TYPE_TEXT,
|
||||
TEXTFIELD_TYPE_TEXTAREA,
|
||||
TEXTFIELD_TYPE_URL,
|
||||
} from '../../components/config/form-textfield';
|
||||
import TextFieldWithSubmit from '../../components/config/form-textfield-with-submit';
|
||||
import ToggleSwitch from '../../components/config/form-toggleswitch';
|
||||
import EditValueArray from '../../components/config/edit-string-array';
|
||||
} from '../../components/config/TextField';
|
||||
import { TextFieldWithSubmit } from '../../components/config/TextFieldWithSubmit';
|
||||
import { ToggleSwitch } from '../../components/config/ToggleSwitch';
|
||||
import { EditValueArray } from '../../components/config/EditValueArray';
|
||||
import { UpdateArgs } from '../../types/config-section';
|
||||
import {
|
||||
FIELD_PROPS_ENABLE_FEDERATION,
|
||||
@@ -27,72 +27,70 @@ import {
|
||||
import { ServerStatusContext } from '../../utils/server-status-context';
|
||||
import { createInputStatus, STATUS_ERROR, STATUS_SUCCESS } from '../../utils/input-statuses';
|
||||
|
||||
function FederationInfoModal({ cancelPressed, okPressed }) {
|
||||
return (
|
||||
<Modal
|
||||
width="70%"
|
||||
title="Enable Social Features"
|
||||
visible
|
||||
onCancel={cancelPressed}
|
||||
footer={
|
||||
<div>
|
||||
<Button onClick={cancelPressed}>Do not enable</Button>
|
||||
<Button type="primary" onClick={okPressed}>
|
||||
Enable Social Features
|
||||
</Button>
|
||||
</div>
|
||||
}
|
||||
>
|
||||
<Typography.Title level={3}>How do Owncast's social features work?</Typography.Title>
|
||||
<Typography.Paragraph>
|
||||
Owncast's social features are accomplished by having your server join The{' '}
|
||||
<a href="https://en.wikipedia.org/wiki/Fediverse" rel="noopener noreferrer" target="_blank">
|
||||
Fediverse
|
||||
</a>
|
||||
, a decentralized, open, collection of independent servers, like yours.
|
||||
</Typography.Paragraph>
|
||||
Please{' '}
|
||||
const FederationInfoModal = ({ cancelPressed, okPressed }) => (
|
||||
<Modal
|
||||
width="70%"
|
||||
title="Enable Social Features"
|
||||
visible
|
||||
onCancel={cancelPressed}
|
||||
footer={
|
||||
<div>
|
||||
<Button onClick={cancelPressed}>Do not enable</Button>
|
||||
<Button type="primary" onClick={okPressed}>
|
||||
Enable Social Features
|
||||
</Button>
|
||||
</div>
|
||||
}
|
||||
>
|
||||
<Typography.Title level={3}>How do Owncast's social features work?</Typography.Title>
|
||||
<Typography.Paragraph>
|
||||
Owncast's social features are accomplished by having your server join The{' '}
|
||||
<a href="https://en.wikipedia.org/wiki/Fediverse" rel="noopener noreferrer" target="_blank">
|
||||
Fediverse
|
||||
</a>
|
||||
, a decentralized, open, collection of independent servers, like yours.
|
||||
</Typography.Paragraph>
|
||||
Please{' '}
|
||||
<a href="https://owncast.online/docs/social" rel="noopener noreferrer" target="_blank">
|
||||
read more
|
||||
</a>{' '}
|
||||
about these features, the details behind them, and how they work.
|
||||
<Typography.Paragraph />
|
||||
<Typography.Title level={3}>What do you need to know?</Typography.Title>
|
||||
<ul>
|
||||
<li>
|
||||
These features are brand new. Given the variability of interfacing with the rest of the
|
||||
world, bugs are possible. Please report anything that you think isn't working quite right.
|
||||
</li>
|
||||
<li>You must always host your Owncast server with SSL using a https url.</li>
|
||||
<li>
|
||||
You should not change your server name URL or social username once people begin following
|
||||
you, as your server will be seen as a completely different user on the Fediverse, and the
|
||||
old user will disappear.
|
||||
</li>
|
||||
<li>
|
||||
Turning on <i>Private mode</i> will allow you to manually approve each follower and limit
|
||||
the visibility of your posts to followers only.
|
||||
</li>
|
||||
</ul>
|
||||
<Typography.Title level={3}>Learn more about The Fediverse</Typography.Title>
|
||||
<Typography.Paragraph>
|
||||
If these concepts are new you should discover more about what this functionality has to offer.
|
||||
Visit{' '}
|
||||
<a href="https://owncast.online/docs/social" rel="noopener noreferrer" target="_blank">
|
||||
read more
|
||||
our documentation
|
||||
</a>{' '}
|
||||
about these features, the details behind them, and how they work.
|
||||
<Typography.Paragraph />
|
||||
<Typography.Title level={3}>What do you need to know?</Typography.Title>
|
||||
<ul>
|
||||
<li>
|
||||
These features are brand new. Given the variability of interfacing with the rest of the
|
||||
world, bugs are possible. Please report anything that you think isn't working quite right.
|
||||
</li>
|
||||
<li>You must always host your Owncast server with SSL using a https url.</li>
|
||||
<li>
|
||||
You should not change your server name URL or social username once people begin following
|
||||
you, as your server will be seen as a completely different user on the Fediverse, and the
|
||||
old user will disappear.
|
||||
</li>
|
||||
<li>
|
||||
Turning on <i>Private mode</i> will allow you to manually approve each follower and limit
|
||||
the visibility of your posts to followers only.
|
||||
</li>
|
||||
</ul>
|
||||
<Typography.Title level={3}>Learn more about The Fediverse</Typography.Title>
|
||||
<Typography.Paragraph>
|
||||
If these concepts are new you should discover more about what this functionality has to
|
||||
offer. Visit{' '}
|
||||
<a href="https://owncast.online/docs/social" rel="noopener noreferrer" target="_blank">
|
||||
our documentation
|
||||
</a>{' '}
|
||||
to be pointed at some resources that will help get you started on The Fediverse.
|
||||
</Typography.Paragraph>
|
||||
</Modal>
|
||||
);
|
||||
}
|
||||
to be pointed at some resources that will help get you started on The Fediverse.
|
||||
</Typography.Paragraph>
|
||||
</Modal>
|
||||
);
|
||||
|
||||
FederationInfoModal.propTypes = {
|
||||
cancelPressed: PropTypes.func.isRequired,
|
||||
okPressed: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
export default function ConfigFederation() {
|
||||
const ConfigFederation = () => {
|
||||
const { Title } = Typography;
|
||||
const [formDataValues, setFormDataValues] = useState(null);
|
||||
const [isInfoModalOpen, setIsInfoModalOpen] = useState(false);
|
||||
@@ -331,4 +329,5 @@ export default function ConfigFederation() {
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
};
|
||||
export default ConfigFederation;
|
||||
|
||||
@@ -6,9 +6,10 @@ import Discord from '../../components/config/notification/discord';
|
||||
import Browser from '../../components/config/notification/browser';
|
||||
import Twitter from '../../components/config/notification/twitter';
|
||||
import Federation from '../../components/config/notification/federation';
|
||||
import TextFieldWithSubmit, {
|
||||
import {
|
||||
TextFieldWithSubmit,
|
||||
TEXTFIELD_TYPE_URL,
|
||||
} from '../../components/config/form-textfield-with-submit';
|
||||
} from '../../components/config/TextFieldWithSubmit';
|
||||
import { TEXTFIELD_PROPS_FEDERATION_INSTANCE_URL } from '../../utils/config-constants';
|
||||
import { ServerStatusContext } from '../../utils/server-status-context';
|
||||
import { UpdateArgs } from '../../types/config-section';
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import React from 'react';
|
||||
import { Typography } from 'antd';
|
||||
|
||||
import EditInstanceDetails from '../../components/config/edit-instance-details';
|
||||
import EditInstanceTags from '../../components/config/edit-tags';
|
||||
import EditSocialLinks from '../../components/config/edit-social-links';
|
||||
import EditPageContent from '../../components/config/edit-page-content';
|
||||
import EditCustomStyles from '../../components/config/edit-custom-css';
|
||||
import { EditInstanceDetails } from '../../components/config/EditInstanceDetails';
|
||||
import { EditInstanceTags } from '../../components/config/EditInstanceTags';
|
||||
import { EditSocialLinks } from '../../components/config/EditSocialLinks';
|
||||
import { EditPageContent } from '../../components/config/EditPageContent';
|
||||
import { EditCustomStyles } from '../../components/config/EditCustomStyles';
|
||||
|
||||
const { Title } = Typography;
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React from 'react';
|
||||
import { Typography } from 'antd';
|
||||
import EditServerDetails from '../../components/config/edit-server-details';
|
||||
import { EditInstanceDetails } from '../../components/config/EditInstanceDetails2';
|
||||
|
||||
const { Title } = Typography;
|
||||
|
||||
@@ -13,7 +13,7 @@ export default function ConfigServerDetails() {
|
||||
it's likely the other settings will not need to be changed.
|
||||
</p>
|
||||
<div className="form-module config-server-details-container">
|
||||
<EditServerDetails />
|
||||
<EditInstanceDetails />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React from 'react';
|
||||
import { Typography } from 'antd';
|
||||
import EditSocialLinks from '../../components/config/edit-social-links';
|
||||
import { EditSocialLinks } from '../../components/config/EditSocialLinks';
|
||||
|
||||
const { Title } = Typography;
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Typography } from 'antd';
|
||||
import React from 'react';
|
||||
import EditStorage from '../../components/config/edit-storage';
|
||||
import { EditStorage } from '../../components/config/EditStorage';
|
||||
|
||||
const { Title } = Typography;
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { Col, Collapse, Row, Typography } from 'antd';
|
||||
import React from 'react';
|
||||
import VideoCodecSelector from '../../components/config/video-codec-selector';
|
||||
import VideoLatency from '../../components/config/video-latency';
|
||||
import VideoVariantsTable from '../../components/config/video-variants-table';
|
||||
import { CodecSelector as VideoCodecSelector } from '../../components/config/CodecSelector';
|
||||
import { VideoLatency } from '../../components/config/VideoLatency';
|
||||
import { CurrentVariantsTable } from '../../components/config/CurrentVariantsTable';
|
||||
|
||||
const { Panel } = Collapse;
|
||||
const { Title } = Typography;
|
||||
@@ -28,7 +28,7 @@ export default function ConfigVideoSettings() {
|
||||
<Row gutter={[16, 16]}>
|
||||
<Col md={24} lg={12}>
|
||||
<div className="form-module variants-table-module">
|
||||
<VideoVariantsTable />
|
||||
<CurrentVariantsTable />
|
||||
</div>
|
||||
</Col>
|
||||
<Col md={24} lg={12}>
|
||||
|
||||
@@ -2,8 +2,8 @@ import { BulbOutlined, LaptopOutlined, SaveOutlined } from '@ant-design/icons';
|
||||
import { Row, Col, Typography } from 'antd';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { fetchData, FETCH_INTERVAL, HARDWARE_STATS } from '../../utils/apis';
|
||||
import Chart from '../../components/chart';
|
||||
import StatisticItem from '../../components/statistic';
|
||||
import { Chart } from '../../components/Chart';
|
||||
import { StatisticItem } from '../../components/StatisticItem';
|
||||
|
||||
// TODO: FIX TS WARNING FROM THIS.
|
||||
// interface TimedValue {
|
||||
|
||||
@@ -3,13 +3,13 @@ import { Skeleton, Card, Statistic, Row, Col } from 'antd';
|
||||
import { UserOutlined, ClockCircleOutlined } from '@ant-design/icons';
|
||||
import { formatDistanceToNow, formatRelative } from 'date-fns';
|
||||
import { ServerStatusContext } from '../../utils/server-status-context';
|
||||
import LogTable from '../../components/log-table';
|
||||
import Offline from '../../components/offline-notice';
|
||||
import StreamHealthOverview from '../../components/stream-health-overview';
|
||||
import { LogTable } from '../../components/LogTable';
|
||||
import { Offline } from '../../components/Offline';
|
||||
import { StreamHealthOverview } from '../../components/StreamHealthOverview';
|
||||
|
||||
import { LOGS_WARN, fetchData, FETCH_INTERVAL } from '../../utils/apis';
|
||||
import { formatIPAddress, isEmptyObject } from '../../utils/format';
|
||||
import NewsFeed from '../../components/news-feed';
|
||||
import { NewsFeed } from '../../components/NewsFeed';
|
||||
|
||||
function streamDetailsFormatter(streamDetails) {
|
||||
return (
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import LogTable from '../../components/log-table';
|
||||
import { LogTable } from '../../components/LogTable';
|
||||
|
||||
import { LOGS_ALL, fetchData } from '../../utils/apis';
|
||||
|
||||
|
||||
@@ -4,8 +4,8 @@ import { Row, Col, Typography, Space, Statistic, Card, Alert, Spin } from 'antd'
|
||||
import React, { ReactNode, useEffect, useState } from 'react';
|
||||
import { ClockCircleOutlined, WarningOutlined, WifiOutlined } from '@ant-design/icons';
|
||||
import { fetchData, FETCH_INTERVAL, API_STREAM_HEALTH_METRICS } from '../../utils/apis';
|
||||
import Chart from '../../components/chart';
|
||||
import StreamHealthOverview from '../../components/stream-health-overview';
|
||||
import { Chart } from '../../components/Chart';
|
||||
import { StreamHealthOverview } from '../../components/StreamHealthOverview';
|
||||
|
||||
interface TimedValue {
|
||||
time: Date;
|
||||
@@ -17,16 +17,14 @@ interface DescriptionBoxProps {
|
||||
description: ReactNode;
|
||||
}
|
||||
|
||||
function DescriptionBox({ title, description }: DescriptionBoxProps) {
|
||||
return (
|
||||
<div className="description-box">
|
||||
<Typography.Title>{title}</Typography.Title>
|
||||
<Typography.Paragraph>{description}</Typography.Paragraph>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
const DescriptionBox = ({ title, description }: DescriptionBoxProps) => (
|
||||
<div className="description-box">
|
||||
<Typography.Title>{title}</Typography.Title>
|
||||
<Typography.Paragraph>{description}</Typography.Paragraph>
|
||||
</div>
|
||||
);
|
||||
|
||||
export default function StreamHealth() {
|
||||
const StreamHealth = () => {
|
||||
const [errors, setErrors] = useState<TimedValue[]>([]);
|
||||
const [qualityVariantChanges, setQualityVariantChanges] = useState<TimedValue[]>([]);
|
||||
|
||||
@@ -409,4 +407,5 @@ export default function StreamHealth() {
|
||||
</Space>
|
||||
</>
|
||||
);
|
||||
}
|
||||
};
|
||||
export default StreamHealth;
|
||||
|
||||
@@ -5,7 +5,7 @@ import { getGithubRelease } from '../../utils/apis';
|
||||
|
||||
const { Title } = Typography;
|
||||
|
||||
function AssetTable(assets) {
|
||||
const AssetTable = assets => {
|
||||
const data = Object.values(assets) as object[];
|
||||
|
||||
const columns = [
|
||||
@@ -32,9 +32,9 @@ function AssetTable(assets) {
|
||||
pagination={false}
|
||||
/>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export default function Logs() {
|
||||
const Logs = () => {
|
||||
const [release, setRelease] = useState({
|
||||
html_url: '',
|
||||
name: '',
|
||||
@@ -71,4 +71,5 @@ export default function Logs() {
|
||||
<AssetTable {...release.assets} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
};
|
||||
export default Logs;
|
||||
|
||||
@@ -2,9 +2,9 @@ import React, { useState, useEffect, useContext } from 'react';
|
||||
import { Row, Col, Typography, Menu, Dropdown, Spin, Alert } from 'antd';
|
||||
import { DownOutlined, UserOutlined } from '@ant-design/icons';
|
||||
import { getUnixTime, sub } from 'date-fns';
|
||||
import Chart from '../../components/chart';
|
||||
import StatisticItem from '../../components/statistic';
|
||||
import ViewerTable from '../../components/viewer-table';
|
||||
import { Chart } from '../../components/Chart';
|
||||
import { StatisticItem } from '../../components/StatisticItem';
|
||||
import { ViewerTable } from '../../components/ViewerTable';
|
||||
|
||||
import { ServerStatusContext } from '../../utils/server-status-context';
|
||||
|
||||
|
||||
@@ -55,7 +55,7 @@ interface Props {
|
||||
visible: boolean;
|
||||
}
|
||||
|
||||
function NewWebhookModal(props: Props) {
|
||||
const NewWebhookModal = (props: Props) => {
|
||||
const { onOk, onCancel, visible } = props;
|
||||
|
||||
const [selectedEvents, setSelectedEvents] = useState([]);
|
||||
@@ -121,9 +121,9 @@ function NewWebhookModal(props: Props) {
|
||||
</p>
|
||||
</Modal>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export default function Webhooks() {
|
||||
const Webhooks = () => {
|
||||
const [webhooks, setWebhooks] = useState([]);
|
||||
const [isModalVisible, setIsModalVisible] = useState(false);
|
||||
|
||||
@@ -247,4 +247,5 @@ export default function Webhooks() {
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
};
|
||||
export default Webhooks;
|
||||
|
||||
Reference in New Issue
Block a user