mirror of
https://github.com/owncast/owncast.git
synced 2024-10-10 19:16:02 +00:00
Add alert message for global notifications
This commit is contained in:
parent
e142fa9e7c
commit
e8c24fd2d4
@ -10,14 +10,18 @@ import '../styles/config-formfields.scss';
|
|||||||
|
|
||||||
import { AppProps } from 'next/app';
|
import { AppProps } from 'next/app';
|
||||||
import ServerStatusProvider from '../utils/server-status-context';
|
import ServerStatusProvider from '../utils/server-status-context';
|
||||||
|
import AlertMessageProvider from '../utils/alert-message-context';
|
||||||
|
|
||||||
import MainLayout from './components/main-layout';
|
import MainLayout from './components/main-layout';
|
||||||
|
|
||||||
function App({ Component, pageProps }: AppProps) {
|
function App({ Component, pageProps }: AppProps) {
|
||||||
return (
|
return (
|
||||||
<ServerStatusProvider>
|
<ServerStatusProvider>
|
||||||
<MainLayout>
|
<AlertMessageProvider>
|
||||||
<Component {...pageProps} />
|
<MainLayout>
|
||||||
</MainLayout>
|
<Component {...pageProps} />
|
||||||
|
</MainLayout>
|
||||||
|
</AlertMessageProvider>
|
||||||
</ServerStatusProvider>
|
</ServerStatusProvider>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,8 @@ import { TEXTFIELD_TYPE_NUMBER, TEXTFIELD_TYPE_PASSWORD } from './form-textfield
|
|||||||
import TextFieldWithSubmit from './form-textfield-with-submit';
|
import TextFieldWithSubmit from './form-textfield-with-submit';
|
||||||
|
|
||||||
import { ServerStatusContext } from '../../../utils/server-status-context';
|
import { ServerStatusContext } from '../../../utils/server-status-context';
|
||||||
|
import { AlertMessageContext } from '../../../utils/alert-message-context';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
TEXTFIELD_PROPS_FFMPEG,
|
TEXTFIELD_PROPS_FFMPEG,
|
||||||
TEXTFIELD_PROPS_RTMP_PORT,
|
TEXTFIELD_PROPS_RTMP_PORT,
|
||||||
@ -18,6 +20,8 @@ import { UpdateArgs } from '../../../types/config-section';
|
|||||||
export default function EditInstanceDetails() {
|
export default function EditInstanceDetails() {
|
||||||
const [formDataValues, setFormDataValues] = useState(null);
|
const [formDataValues, setFormDataValues] = useState(null);
|
||||||
const serverStatusData = useContext(ServerStatusContext);
|
const serverStatusData = useContext(ServerStatusContext);
|
||||||
|
const { setMessage } = useContext(AlertMessageContext);
|
||||||
|
|
||||||
const { serverConfig } = serverStatusData || {};
|
const { serverConfig } = serverStatusData || {};
|
||||||
|
|
||||||
const { streamKey, ffmpegPath, rtmpServerPort, webServerPort } = serverConfig;
|
const { streamKey, ffmpegPath, rtmpServerPort, webServerPort } = serverConfig;
|
||||||
@ -46,6 +50,10 @@ export default function EditInstanceDetails() {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const showConfigurationRestartMessage = () => {
|
||||||
|
setMessage('Updating server settings requires a restart of your Owncast server.')
|
||||||
|
}
|
||||||
|
|
||||||
function generateStreamKey() {
|
function generateStreamKey() {
|
||||||
let key = '';
|
let key = '';
|
||||||
for (let i = 0; i < 3; i += 1) {
|
for (let i = 0; i < 3; i += 1) {
|
||||||
@ -102,6 +110,7 @@ export default function EditInstanceDetails() {
|
|||||||
initialValue={webServerPort}
|
initialValue={webServerPort}
|
||||||
type={TEXTFIELD_TYPE_NUMBER}
|
type={TEXTFIELD_TYPE_NUMBER}
|
||||||
onChange={handleFieldChange}
|
onChange={handleFieldChange}
|
||||||
|
onSubmit={showConfigurationRestartMessage}
|
||||||
/>
|
/>
|
||||||
<TextFieldWithSubmit
|
<TextFieldWithSubmit
|
||||||
fieldName="rtmpServerPort"
|
fieldName="rtmpServerPort"
|
||||||
@ -110,6 +119,7 @@ export default function EditInstanceDetails() {
|
|||||||
initialValue={rtmpServerPort}
|
initialValue={rtmpServerPort}
|
||||||
type={TEXTFIELD_TYPE_NUMBER}
|
type={TEXTFIELD_TYPE_NUMBER}
|
||||||
onChange={handleFieldChange}
|
onChange={handleFieldChange}
|
||||||
|
onSubmit={showConfigurationRestartMessage}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -3,6 +3,8 @@ import classNames from 'classnames';
|
|||||||
import React, { useContext, useState, useEffect } from 'react';
|
import React, { useContext, useState, useEffect } from 'react';
|
||||||
import { UpdateArgs } from '../../../types/config-section';
|
import { UpdateArgs } from '../../../types/config-section';
|
||||||
import { ServerStatusContext } from '../../../utils/server-status-context';
|
import { ServerStatusContext } from '../../../utils/server-status-context';
|
||||||
|
import { AlertMessageContext } from '../../../utils/alert-message-context';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
postConfigUpdateToAPI,
|
postConfigUpdateToAPI,
|
||||||
API_S3_INFO,
|
API_S3_INFO,
|
||||||
@ -56,6 +58,8 @@ export default function EditStorage() {
|
|||||||
const serverStatusData = useContext(ServerStatusContext);
|
const serverStatusData = useContext(ServerStatusContext);
|
||||||
const { serverConfig, setFieldInConfigState } = serverStatusData || {};
|
const { serverConfig, setFieldInConfigState } = serverStatusData || {};
|
||||||
|
|
||||||
|
const {message, setMessage} = useContext(AlertMessageContext);
|
||||||
|
|
||||||
const { s3 } = serverConfig;
|
const { s3 } = serverConfig;
|
||||||
const {
|
const {
|
||||||
accessKey = '',
|
accessKey = '',
|
||||||
@ -114,6 +118,7 @@ export default function EditStorage() {
|
|||||||
setSubmitStatus(createInputStatus(STATUS_SUCCESS, 'Updated.'));
|
setSubmitStatus(createInputStatus(STATUS_SUCCESS, 'Updated.'));
|
||||||
resetTimer = setTimeout(resetStates, RESET_TIMEOUT);
|
resetTimer = setTimeout(resetStates, RESET_TIMEOUT);
|
||||||
setSaved(true);
|
setSaved(true);
|
||||||
|
setMessage('Changing your storage configuration will take place the next time you start a new stream.');
|
||||||
},
|
},
|
||||||
onError: (message: string) => {
|
onError: (message: string) => {
|
||||||
setSubmitStatus(createInputStatus(STATUS_ERROR, message));
|
setSubmitStatus(createInputStatus(STATUS_ERROR, message));
|
||||||
@ -139,14 +144,6 @@ export default function EditStorage() {
|
|||||||
enabled: shouldDisplayForm,
|
enabled: shouldDisplayForm,
|
||||||
});
|
});
|
||||||
|
|
||||||
const saveWarning = saved ? (<Alert
|
|
||||||
showIcon
|
|
||||||
message="Storage changes"
|
|
||||||
description="Your storage settings will take effect on your next stream. If you're currently streaming you'll continue to use the storage configuration previously set."
|
|
||||||
type="warning"
|
|
||||||
/>
|
|
||||||
) : null;
|
|
||||||
|
|
||||||
const isSaveable = checkSaveable(formDataValues, s3);
|
const isSaveable = checkSaveable(formDataValues, s3);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -219,8 +216,6 @@ export default function EditStorage() {
|
|||||||
</Collapse>
|
</Collapse>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{saveWarning}
|
|
||||||
|
|
||||||
<div className="button-container">
|
<div className="button-container">
|
||||||
<Button type="primary" onClick={handleSave} disabled={!isSaveable}>
|
<Button type="primary" onClick={handleSave} disabled={!isSaveable}>
|
||||||
Save
|
Save
|
||||||
|
@ -6,7 +6,9 @@ import { Typography, Table, Modal, Button } from 'antd';
|
|||||||
import { ColumnsType } from 'antd/lib/table';
|
import { ColumnsType } from 'antd/lib/table';
|
||||||
import { DeleteOutlined } from '@ant-design/icons';
|
import { DeleteOutlined } from '@ant-design/icons';
|
||||||
import { ServerStatusContext } from '../../../utils/server-status-context';
|
import { ServerStatusContext } from '../../../utils/server-status-context';
|
||||||
|
import { AlertMessageContext } from '../../../utils/alert-message-context';
|
||||||
import { UpdateArgs, VideoVariant } from '../../../types/config-section';
|
import { UpdateArgs, VideoVariant } from '../../../types/config-section';
|
||||||
|
|
||||||
import VideoVariantForm from './video-variant-form';
|
import VideoVariantForm from './video-variant-form';
|
||||||
import {
|
import {
|
||||||
API_VIDEO_VARIANTS,
|
API_VIDEO_VARIANTS,
|
||||||
@ -22,6 +24,7 @@ export default function CurrentVariantsTable() {
|
|||||||
const [displayModal, setDisplayModal] = useState(false);
|
const [displayModal, setDisplayModal] = useState(false);
|
||||||
const [modalProcessing, setModalProcessing] = useState(false);
|
const [modalProcessing, setModalProcessing] = useState(false);
|
||||||
const [editId, setEditId] = useState(0);
|
const [editId, setEditId] = useState(0);
|
||||||
|
const {setMessage} = useContext(AlertMessageContext);
|
||||||
|
|
||||||
// current data inside modal
|
// current data inside modal
|
||||||
const [modalDataState, setModalDataState] = useState(DEFAULT_VARIANT_STATE);
|
const [modalDataState, setModalDataState] = useState(DEFAULT_VARIANT_STATE);
|
||||||
@ -72,6 +75,8 @@ export default function CurrentVariantsTable() {
|
|||||||
setSubmitStatus('success');
|
setSubmitStatus('success');
|
||||||
setSubmitStatusMessage('Variants updated.');
|
setSubmitStatusMessage('Variants updated.');
|
||||||
resetTimer = setTimeout(resetStates, RESET_TIMEOUT);
|
resetTimer = setTimeout(resetStates, RESET_TIMEOUT);
|
||||||
|
|
||||||
|
setMessage('Updating your video configuration will take effect the next time you begin a new stream.');
|
||||||
},
|
},
|
||||||
onError: (message: string) => {
|
onError: (message: string) => {
|
||||||
setSubmitStatus('error');
|
setSubmitStatus('error');
|
||||||
|
@ -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, Popover } from 'antd';
|
import { Layout, Menu, Popover, Alert } from 'antd';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
SettingOutlined,
|
SettingOutlined,
|
||||||
@ -24,6 +24,8 @@ import { parseSecondsToDurationString } from '../../utils/format'
|
|||||||
|
|
||||||
import OwncastLogo from './logo';
|
import OwncastLogo from './logo';
|
||||||
import { ServerStatusContext } from '../../utils/server-status-context';
|
import { ServerStatusContext } from '../../utils/server-status-context';
|
||||||
|
import { AlertMessageContext } from '../../utils/alert-message-context';
|
||||||
|
|
||||||
import TextFieldWithSubmit from './config/form-textfield-with-submit';
|
import TextFieldWithSubmit from './config/form-textfield-with-submit';
|
||||||
import { TEXTFIELD_PROPS_STREAM_TITLE } from './config/constants';
|
import { TEXTFIELD_PROPS_STREAM_TITLE } from './config/constants';
|
||||||
|
|
||||||
@ -40,6 +42,8 @@ export default function MainLayout(props) {
|
|||||||
|
|
||||||
const [currentStreamTitle, setCurrentStreamTitle] = useState(streamTitle);
|
const [currentStreamTitle, setCurrentStreamTitle] = useState(streamTitle);
|
||||||
|
|
||||||
|
const alertMessage = useContext(AlertMessageContext);
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { route } = router || {};
|
const { route } = router || {};
|
||||||
|
|
||||||
@ -104,6 +108,17 @@ export default function MainLayout(props) {
|
|||||||
const upgradeMenuItemStyle = upgradeVersion ? 'block' : 'none';
|
const upgradeMenuItemStyle = upgradeVersion ? 'block' : 'none';
|
||||||
const upgradeVersionString = upgradeVersion || '';
|
const upgradeVersionString = upgradeVersion || '';
|
||||||
|
|
||||||
|
const clearAlertMessage = () => {
|
||||||
|
alertMessage.setMessage(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
const headerAlertMessage = alertMessage.message ? ( <Alert
|
||||||
|
message={alertMessage.message}
|
||||||
|
afterClose={clearAlertMessage}
|
||||||
|
banner
|
||||||
|
closable
|
||||||
|
/>): null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Layout className={appClass}>
|
<Layout className={appClass}>
|
||||||
<Head>
|
<Head>
|
||||||
@ -229,6 +244,9 @@ export default function MainLayout(props) {
|
|||||||
</div>
|
</div>
|
||||||
{statusIndicatorWithThumb}
|
{statusIndicatorWithThumb}
|
||||||
</Header>
|
</Header>
|
||||||
|
|
||||||
|
{headerAlertMessage}
|
||||||
|
|
||||||
<Content className={adminStyles.contentMain}>{children}</Content>
|
<Content className={adminStyles.contentMain}>{children}</Content>
|
||||||
|
|
||||||
<Footer style={{ textAlign: "center" }}>
|
<Footer style={{ textAlign: "center" }}>
|
||||||
|
27
web/utils/alert-message-context.tsx
Normal file
27
web/utils/alert-message-context.tsx
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
import React, { useState, useEffect } from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
|
export const AlertMessageContext = React.createContext({
|
||||||
|
message: null,
|
||||||
|
setMessage: (text?: string) => {
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const AlertMessageProvider = ({ children }) => {
|
||||||
|
const [message, setMessage] = useState('');
|
||||||
|
|
||||||
|
const providerValue = {
|
||||||
|
message,
|
||||||
|
setMessage
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<AlertMessageContext.Provider value={providerValue}>{children}</AlertMessageContext.Provider>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
AlertMessageProvider.propTypes = {
|
||||||
|
children: PropTypes.element.isRequired
|
||||||
|
};
|
||||||
|
|
||||||
|
export default AlertMessageProvider;
|
Loading…
x
Reference in New Issue
Block a user