0

Add alert message for global notifications

This commit is contained in:
Gabe Kangas 2021-02-03 23:24:12 -08:00
parent e142fa9e7c
commit e8c24fd2d4
6 changed files with 73 additions and 14 deletions

View File

@ -10,14 +10,18 @@ import '../styles/config-formfields.scss';
import { AppProps } from 'next/app';
import ServerStatusProvider from '../utils/server-status-context';
import AlertMessageProvider from '../utils/alert-message-context';
import MainLayout from './components/main-layout';
function App({ Component, pageProps }: AppProps) {
return (
<ServerStatusProvider>
<MainLayout>
<Component {...pageProps} />
</MainLayout>
<AlertMessageProvider>
<MainLayout>
<Component {...pageProps} />
</MainLayout>
</AlertMessageProvider>
</ServerStatusProvider>
);
}

View File

@ -6,6 +6,8 @@ import { TEXTFIELD_TYPE_NUMBER, TEXTFIELD_TYPE_PASSWORD } from './form-textfield
import TextFieldWithSubmit from './form-textfield-with-submit';
import { ServerStatusContext } from '../../../utils/server-status-context';
import { AlertMessageContext } from '../../../utils/alert-message-context';
import {
TEXTFIELD_PROPS_FFMPEG,
TEXTFIELD_PROPS_RTMP_PORT,
@ -18,6 +20,8 @@ import { UpdateArgs } from '../../../types/config-section';
export default function EditInstanceDetails() {
const [formDataValues, setFormDataValues] = useState(null);
const serverStatusData = useContext(ServerStatusContext);
const { setMessage } = useContext(AlertMessageContext);
const { serverConfig } = serverStatusData || {};
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() {
let key = '';
for (let i = 0; i < 3; i += 1) {
@ -102,6 +110,7 @@ export default function EditInstanceDetails() {
initialValue={webServerPort}
type={TEXTFIELD_TYPE_NUMBER}
onChange={handleFieldChange}
onSubmit={showConfigurationRestartMessage}
/>
<TextFieldWithSubmit
fieldName="rtmpServerPort"
@ -110,6 +119,7 @@ export default function EditInstanceDetails() {
initialValue={rtmpServerPort}
type={TEXTFIELD_TYPE_NUMBER}
onChange={handleFieldChange}
onSubmit={showConfigurationRestartMessage}
/>
</div>
);

View File

@ -3,6 +3,8 @@ import classNames from 'classnames';
import React, { useContext, useState, useEffect } from 'react';
import { UpdateArgs } from '../../../types/config-section';
import { ServerStatusContext } from '../../../utils/server-status-context';
import { AlertMessageContext } from '../../../utils/alert-message-context';
import {
postConfigUpdateToAPI,
API_S3_INFO,
@ -56,6 +58,8 @@ export default function EditStorage() {
const serverStatusData = useContext(ServerStatusContext);
const { serverConfig, setFieldInConfigState } = serverStatusData || {};
const {message, setMessage} = useContext(AlertMessageContext);
const { s3 } = serverConfig;
const {
accessKey = '',
@ -114,6 +118,7 @@ export default function EditStorage() {
setSubmitStatus(createInputStatus(STATUS_SUCCESS, 'Updated.'));
resetTimer = setTimeout(resetStates, RESET_TIMEOUT);
setSaved(true);
setMessage('Changing your storage configuration will take place the next time you start a new stream.');
},
onError: (message: string) => {
setSubmitStatus(createInputStatus(STATUS_ERROR, message));
@ -139,14 +144,6 @@ export default function EditStorage() {
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);
return (
@ -219,8 +216,6 @@ export default function EditStorage() {
</Collapse>
</div>
{saveWarning}
<div className="button-container">
<Button type="primary" onClick={handleSave} disabled={!isSaveable}>
Save

View File

@ -6,7 +6,9 @@ import { Typography, Table, Modal, Button } from 'antd';
import { ColumnsType } from 'antd/lib/table';
import { DeleteOutlined } from '@ant-design/icons';
import { ServerStatusContext } from '../../../utils/server-status-context';
import { AlertMessageContext } from '../../../utils/alert-message-context';
import { UpdateArgs, VideoVariant } from '../../../types/config-section';
import VideoVariantForm from './video-variant-form';
import {
API_VIDEO_VARIANTS,
@ -22,6 +24,7 @@ export default function CurrentVariantsTable() {
const [displayModal, setDisplayModal] = useState(false);
const [modalProcessing, setModalProcessing] = useState(false);
const [editId, setEditId] = useState(0);
const {setMessage} = useContext(AlertMessageContext);
// current data inside modal
const [modalDataState, setModalDataState] = useState(DEFAULT_VARIANT_STATE);
@ -72,6 +75,8 @@ export default function CurrentVariantsTable() {
setSubmitStatus('success');
setSubmitStatusMessage('Variants updated.');
resetTimer = setTimeout(resetStates, RESET_TIMEOUT);
setMessage('Updating your video configuration will take effect the next time you begin a new stream.');
},
onError: (message: string) => {
setSubmitStatus('error');

View File

@ -4,7 +4,7 @@ import Link from 'next/link';
import Head from 'next/head'
import { differenceInSeconds } from "date-fns";
import { useRouter } from 'next/router';
import { Layout, Menu, Popover } from 'antd';
import { Layout, Menu, Popover, Alert } from 'antd';
import {
SettingOutlined,
@ -24,6 +24,8 @@ import { parseSecondsToDurationString } from '../../utils/format'
import OwncastLogo from './logo';
import { ServerStatusContext } from '../../utils/server-status-context';
import { AlertMessageContext } from '../../utils/alert-message-context';
import TextFieldWithSubmit from './config/form-textfield-with-submit';
import { TEXTFIELD_PROPS_STREAM_TITLE } from './config/constants';
@ -40,6 +42,8 @@ export default function MainLayout(props) {
const [currentStreamTitle, setCurrentStreamTitle] = useState(streamTitle);
const alertMessage = useContext(AlertMessageContext);
const router = useRouter();
const { route } = router || {};
@ -104,6 +108,17 @@ export default function MainLayout(props) {
const upgradeMenuItemStyle = upgradeVersion ? 'block' : 'none';
const upgradeVersionString = upgradeVersion || '';
const clearAlertMessage = () => {
alertMessage.setMessage(null);
}
const headerAlertMessage = alertMessage.message ? ( <Alert
message={alertMessage.message}
afterClose={clearAlertMessage}
banner
closable
/>): null;
return (
<Layout className={appClass}>
<Head>
@ -229,6 +244,9 @@ export default function MainLayout(props) {
</div>
{statusIndicatorWithThumb}
</Header>
{headerAlertMessage}
<Content className={adminStyles.contentMain}>{children}</Content>
<Footer style={{ textAlign: "center" }}>

View 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;