From f79727a8632490f11c1423773fdd6adfb6337a7b Mon Sep 17 00:00:00 2001 From: muhamedsalih-tw <104364298+muhamedsalih-tw@users.noreply.github.com> Date: Tue, 25 Oct 2022 12:51:28 +0530 Subject: Transform 'AuthLayoutContainer' component hierarchy to tsx (#699) Co-authored-by: Muhamed <> Co-authored-by: Vijay A --- .eslintrc.js | 6 +- src/components/AppUpdateInfoBar.tsx | 14 +- src/components/auth/AuthLayout.jsx | 127 ---------------- src/components/auth/AuthLayout.tsx | 128 ++++++++++++++++ src/components/ui/AppLoader/index.tsx | 68 +++++---- src/components/ui/AppLoader/styles.ts | 9 +- src/components/ui/InfoBar.js | 105 ------------- src/components/ui/InfoBar.tsx | 89 +++++++++++ src/components/ui/Modal/index.tsx | 36 ++--- src/components/ui/headline/index.tsx | 15 +- src/components/ui/icon/index.tsx | 10 +- src/components/ui/input/index.tsx | 59 +++----- src/containers/auth/AuthLayoutContainer.tsx | 10 +- src/features/publishDebugInfo/Component.js | 219 ---------------------------- src/features/publishDebugInfo/Component.tsx | 208 ++++++++++++++++++++++++++ src/features/publishDebugInfo/index.ts | 14 +- src/routes.tsx | 30 ++-- 17 files changed, 547 insertions(+), 600 deletions(-) delete mode 100644 src/components/auth/AuthLayout.jsx create mode 100644 src/components/auth/AuthLayout.tsx delete mode 100644 src/components/ui/InfoBar.js create mode 100644 src/components/ui/InfoBar.tsx delete mode 100644 src/features/publishDebugInfo/Component.js create mode 100644 src/features/publishDebugInfo/Component.tsx diff --git a/.eslintrc.js b/.eslintrc.js index bbf0e6022..fd4ff7516 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -70,14 +70,16 @@ module.exports = { 'import/no-unresolved': 0, 'import/prefer-default-export': 0, // eslint-plugin-react - 'react/default-props-match-prop-types': 1, + // TODO - [TS DEBT] should remove below config once application converted to TS + 'react/default-props-match-prop-types': 0, + 'react/require-default-props': 0, + // eslint-plugin-react 'react/destructuring-assignment': 0, 'react/button-has-type': 0, 'react/forbid-prop-types': 0, 'react/jsx-curly-newline': 0, 'react/no-unused-prop-types': 1, 'react/react-in-jsx-scope': 0, - 'react/require-default-props': 1, 'react/jsx-no-bind': 0, 'react/jsx-no-target-blank': 0, 'react/jsx-props-no-spreading': 0, diff --git a/src/components/AppUpdateInfoBar.tsx b/src/components/AppUpdateInfoBar.tsx index 3ff488b74..ff4a9b9ad 100644 --- a/src/components/AppUpdateInfoBar.tsx +++ b/src/components/AppUpdateInfoBar.tsx @@ -1,6 +1,7 @@ import { defineMessages, useIntl } from 'react-intl'; import { mdiInformation } from '@mdi/js'; +import { MouseEventHandler } from 'react'; import InfoBar from './ui/InfoBar'; import Icon from './ui/icon'; @@ -21,17 +22,14 @@ const messages = defineMessages({ }, }); -type Props = { - onInstallUpdate: () => void; +export interface IProps { + onInstallUpdate: MouseEventHandler; onHide: () => void; updateVersionParsed: string; -}; +} -const AppUpdateInfoBar = ({ - onInstallUpdate, - updateVersionParsed, - onHide, -}: Props) => { +const AppUpdateInfoBar = (props: IProps) => { + const { onInstallUpdate, updateVersionParsed, onHide } = props; const intl = useIntl(); return ( diff --git a/src/components/auth/AuthLayout.jsx b/src/components/auth/AuthLayout.jsx deleted file mode 100644 index 5c87c3080..000000000 --- a/src/components/auth/AuthLayout.jsx +++ /dev/null @@ -1,127 +0,0 @@ -import { cloneElement, Component } from 'react'; -import PropTypes from 'prop-types'; -import { observer } from 'mobx-react'; -import { TitleBar } from 'electron-react-titlebar/renderer'; - -import { injectIntl } from 'react-intl'; -import { mdiFlash } from '@mdi/js'; -import Link from '../ui/Link'; -import InfoBar from '../ui/InfoBar'; - -import { Component as PublishDebugInfo } from '../../features/publishDebugInfo'; - -import { - oneOrManyChildElements, - globalError as globalErrorPropType, -} from '../../prop-types'; -import { updateVersionParse } from '../../helpers/update-helpers'; -import globalMessages from '../../i18n/globalMessages'; - -import { isWindows } from '../../environment'; -import AppUpdateInfoBar from '../AppUpdateInfoBar'; -import { GITHUB_FERDIUM_URL } from '../../config'; -import Icon from '../ui/icon'; - -import { serverName } from '../../api/apiBase'; - -class AuthLayout extends Component { - static propTypes = { - children: oneOrManyChildElements.isRequired, - error: globalErrorPropType.isRequired, - isOnline: PropTypes.bool.isRequired, - isAPIHealthy: PropTypes.bool.isRequired, - retryHealthCheck: PropTypes.func.isRequired, - isHealthCheckLoading: PropTypes.bool.isRequired, - isFullScreen: PropTypes.bool.isRequired, - installAppUpdate: PropTypes.func.isRequired, - appUpdateIsDownloaded: PropTypes.bool.isRequired, - updateVersion: PropTypes.string.isRequired, - }; - - constructor() { - super(); - - this.state = { - shouldShowAppUpdateInfoBar: true, - }; - } - - render() { - const { - children, - error, - isOnline, - isAPIHealthy, - retryHealthCheck, - isHealthCheckLoading, - isFullScreen, - installAppUpdate, - appUpdateIsDownloaded, - updateVersion, - } = this.props; - - const { intl } = this.props; - let serverNameParse = serverName(); - serverNameParse = - serverNameParse === 'Custom' ? 'your Custom Server' : serverNameParse; - - return ( - <> - {isWindows && !isFullScreen && ( - - )} -
- {!isOnline && ( - - - {intl.formatMessage(globalMessages.notConnectedToTheInternet)} - - )} - {appUpdateIsDownloaded && this.state.shouldShowAppUpdateInfoBar && ( - { - this.setState({ shouldShowAppUpdateInfoBar: false }); - }} - /> - )} - {isOnline && !isAPIHealthy && ( - - - {intl.formatMessage(globalMessages.APIUnhealthy, { - serverNameParse, - })} - - )} -
- {/* Inject globalError into children */} - {cloneElement(children, { - error, - })} -
- {/*
*/} - - - - - - - ); - } -} - -export default injectIntl(observer(AuthLayout)); diff --git a/src/components/auth/AuthLayout.tsx b/src/components/auth/AuthLayout.tsx new file mode 100644 index 000000000..527c2bb74 --- /dev/null +++ b/src/components/auth/AuthLayout.tsx @@ -0,0 +1,128 @@ +import { + cloneElement, + Component, + MouseEventHandler, + ReactElement, +} from 'react'; +import { observer } from 'mobx-react'; +import { TitleBar } from 'electron-react-titlebar/renderer'; +import { injectIntl, WrappedComponentProps } from 'react-intl'; +import { mdiFlash } from '@mdi/js'; +import { GlobalError } from '../../@types/ferdium-components.types'; +import Link from '../ui/Link'; +import InfoBar from '../ui/InfoBar'; +import { Component as PublishDebugInfo } from '../../features/publishDebugInfo'; +import { updateVersionParse } from '../../helpers/update-helpers'; +import globalMessages from '../../i18n/globalMessages'; +import { isWindows } from '../../environment'; +import AppUpdateInfoBar from '../AppUpdateInfoBar'; +import { GITHUB_FERDIUM_URL } from '../../config'; +import Icon from '../ui/icon'; +import { serverName } from '../../api/apiBase'; + +export interface IProps extends WrappedComponentProps { + children: ReactElement; + error: GlobalError; + isOnline: boolean; + isAPIHealthy: boolean; + retryHealthCheck: MouseEventHandler; + isHealthCheckLoading: boolean; + isFullScreen: boolean; + installAppUpdate: MouseEventHandler; + appUpdateIsDownloaded: boolean; + updateVersion: string; +} + +interface IState { + shouldShowAppUpdateInfoBar: boolean; +} + +@observer +class AuthLayout extends Component { + constructor(props: IProps) { + super(props); + + this.state = { + shouldShowAppUpdateInfoBar: true, + }; + } + + render(): ReactElement { + const { + children, + error, + isOnline, + isAPIHealthy, + retryHealthCheck, + isHealthCheckLoading, + isFullScreen, + installAppUpdate, + appUpdateIsDownloaded, + updateVersion, + intl, + } = this.props; + + let serverNameParse = serverName(); + serverNameParse = + serverNameParse === 'Custom' ? 'your Custom Server' : serverNameParse; + + return ( + <> + {isWindows && !isFullScreen && ( + + )} +
+ {!isOnline && ( + + + {intl.formatMessage(globalMessages.notConnectedToTheInternet)} + + )} + {appUpdateIsDownloaded && this.state.shouldShowAppUpdateInfoBar && ( + { + this.setState({ shouldShowAppUpdateInfoBar: false }); + }} + /> + )} + {isOnline && !isAPIHealthy && ( + + + {intl.formatMessage(globalMessages.APIUnhealthy, { + serverNameParse, + })} + + )} +
+ {/* Inject globalError into children */} + {cloneElement(children, { + error, + })} +
+ {/*
*/} + + + + + + + ); + } +} + +export default injectIntl(AuthLayout); diff --git a/src/components/ui/AppLoader/index.tsx b/src/components/ui/AppLoader/index.tsx index caa7e381d..f4d9b8e73 100644 --- a/src/components/ui/AppLoader/index.tsx +++ b/src/components/ui/AppLoader/index.tsx @@ -1,7 +1,7 @@ -import { Component } from 'react'; +import { Component, ReactElement } from 'react'; import classnames from 'classnames'; - -import injectStyle from 'react-jss'; +import withStyles, { WithStylesProps } from 'react-jss'; +import { Theme } from '../../../themes'; import FullscreenLoader from '../FullscreenLoader'; import shuffleArray from '../../../helpers/array-helpers'; @@ -18,24 +18,27 @@ const textList = shuffleArray([ 'Fixing bugs', ]); -type Props = { - classes: typeof styles; - theme: any; - texts: string[]; -}; - -class AppLoader extends Component { - static defaultProps = { - texts: textList, - }; +interface IProps extends WithStylesProps { + theme: Theme; + texts?: string[]; +} - state = { - step: 0, - }; +interface IState { + step: number; +} +class AppLoader extends Component { interval: NodeJS.Timeout | null = null; - componentDidMount() { + constructor(props: IProps) { + super(props); + + this.state = { + step: 0, + }; + } + + componentDidMount(): void { this.interval = setInterval(() => { this.setState((prevState: { step: number }) => ({ step: prevState.step === textList.length - 1 ? 0 : prevState.step + 1, @@ -43,14 +46,14 @@ class AppLoader extends Component { }, 2500); } - componentWillUnmount() { + componentWillUnmount(): void { if (this.interval) { clearInterval(this.interval); } } - render() { - const { classes, theme, texts } = this.props; + render(): ReactElement { + const { classes, theme, texts = textList } = this.props; const { step } = this.state; return ( @@ -58,20 +61,21 @@ class AppLoader extends Component { className={classes.component} spinnerColor={theme.colorAppLoaderSpinner} > - {texts.map((text, i) => ( - - {text} - - ))} + {texts && + texts.map((text, i) => ( + + {text} + + ))} ); } } -export default injectStyle(styles, { injectTheme: true })(AppLoader); +export default withStyles(styles, { injectTheme: true })(AppLoader); diff --git a/src/components/ui/AppLoader/styles.ts b/src/components/ui/AppLoader/styles.ts index 9891e0387..6bf3b4f3c 100644 --- a/src/components/ui/AppLoader/styles.ts +++ b/src/components/ui/AppLoader/styles.ts @@ -1,8 +1,7 @@ -let sloganTransition = 'none'; - -if (window && window.matchMedia('(prefers-reduced-motion: no-preference)')) { - sloganTransition = 'opacity 1s ease'; -} +const sloganTransition = + window && window.matchMedia('(prefers-reduced-motion: no-preference)') + ? 'opacity 1s ease' + : 'none'; export default { component: { diff --git a/src/components/ui/InfoBar.js b/src/components/ui/InfoBar.js deleted file mode 100644 index d73491da0..000000000 --- a/src/components/ui/InfoBar.js +++ /dev/null @@ -1,105 +0,0 @@ -import { Component } from 'react'; -import PropTypes from 'prop-types'; -import { observer } from 'mobx-react'; -import classnames from 'classnames'; -import Loader from 'react-loader'; -import { defineMessages, injectIntl } from 'react-intl'; - -import { mdiClose } from '@mdi/js'; -import Appear from './effects/Appear'; -import Icon from './icon'; - -const messages = defineMessages({ - hide: { - id: 'infobar.hide', - defaultMessage: 'Hide', - }, -}); - -// Should this file be converted into the coding style similar to './toggle/index.tsx'? -class InfoBar extends Component { - static propTypes = { - // eslint-disable-next-line react/forbid-prop-types - children: PropTypes.any.isRequired, - onClick: PropTypes.func, - type: PropTypes.string, - className: PropTypes.string, - ctaLabel: PropTypes.string, - ctaLoading: PropTypes.bool, - position: PropTypes.string, - sticky: PropTypes.bool, - onHide: PropTypes.func, - }; - - static defaultProps = { - onClick: () => null, - type: 'primary', - className: '', - ctaLabel: '', - ctaLoading: false, - position: 'bottom', - sticky: false, - onHide: () => null, - }; - - render() { - const { - children, - type, - className, - ctaLabel, - ctaLoading, - onClick, - position, - sticky, - onHide, - } = this.props; - - const { intl } = this.props; - - let transitionName = 'slideUp'; - if (position === 'top') { - transitionName = 'slideDown'; - } - - return ( - -
- {children} - {ctaLabel && ( - - )} -
- {!sticky && ( - - )} -
- ); - } -} - -export default injectIntl(observer(InfoBar)); diff --git a/src/components/ui/InfoBar.tsx b/src/components/ui/InfoBar.tsx new file mode 100644 index 000000000..ef8f6ad6f --- /dev/null +++ b/src/components/ui/InfoBar.tsx @@ -0,0 +1,89 @@ +import { Component, MouseEventHandler, ReactNode } from 'react'; +import { observer } from 'mobx-react'; +import classnames from 'classnames'; +import Loader from 'react-loader'; +import { defineMessages, injectIntl, WrappedComponentProps } from 'react-intl'; + +import { mdiClose } from '@mdi/js'; +import { noop } from 'lodash'; +import Appear from './effects/Appear'; +import Icon from './icon'; + +const messages = defineMessages({ + hide: { + id: 'infobar.hide', + defaultMessage: 'Hide', + }, +}); + +interface IProps extends WrappedComponentProps { + children: ReactNode; + onClick?: MouseEventHandler; + type?: string; + className?: string; + ctaLabel?: string; + ctaLoading?: boolean; + position?: string; + sticky?: boolean; + onHide?: () => void; +} + +@observer +class InfoBar extends Component { + render() { + const { + children, + type = 'primary', + onClick = noop, + className = '', + ctaLabel = '', + ctaLoading = false, + position = 'bottom', + sticky = false, + onHide = noop, + intl, + } = this.props; + + const transitionName = position === 'top' ? 'slideDown' : 'slideUp'; + + return ( + +
+ {children} + {ctaLabel && ( + + )} +
+ {!sticky && ( + + )} +
+ ); + } +} + +export default injectIntl(InfoBar); diff --git a/src/components/ui/Modal/index.tsx b/src/components/ui/Modal/index.tsx index 7407a686d..154beef0c 100644 --- a/src/components/ui/Modal/index.tsx +++ b/src/components/ui/Modal/index.tsx @@ -1,41 +1,33 @@ -import { Component, ReactChildren } from 'react'; +import { Component, ReactNode } from 'react'; import ReactModal from 'react-modal'; import classnames from 'classnames'; -import injectCSS from 'react-jss'; +import injectCSS, { WithStylesProps } from 'react-jss'; import { mdiClose } from '@mdi/js'; import Icon from '../icon'; import styles from './styles'; -type Props = { - children: ReactChildren; - className: string; - classes: any; +interface IProps extends WithStylesProps { + children: ReactNode; isOpen: boolean; - portal: string; close: () => void; - shouldCloseOnOverlayClick: boolean; - showClose: boolean; -}; - -class Modal extends Component { - static defaultProps = { - className: null, - portal: 'modal-portal', - shouldCloseOnOverlayClick: false, - showClose: true, - }; + className?: string | null; + portal?: string; + shouldCloseOnOverlayClick?: boolean; + showClose?: boolean; +} +class Modal extends Component { render() { const { children, - className, classes, isOpen, - portal, close, - shouldCloseOnOverlayClick, - showClose, + className = null, + portal = 'modal-portal', + shouldCloseOnOverlayClick = false, + showClose = true, } = this.props; return ( diff --git a/src/components/ui/headline/index.tsx b/src/components/ui/headline/index.tsx index b5a5f695f..bebd8adcf 100644 --- a/src/components/ui/headline/index.tsx +++ b/src/components/ui/headline/index.tsx @@ -1,16 +1,22 @@ import classnames from 'classnames'; -import { Component, createElement, ReactNode } from 'react'; +import { + Component, + createElement, + MouseEventHandler, + ReactElement, + ReactNode, +} from 'react'; import injectStyle, { WithStylesProps } from 'react-jss'; import { Theme } from '../../../themes'; import { Omit } from '../typings/generic'; interface IProps extends WithStylesProps { + children: ReactNode; level?: number; className?: string; - children: string | ReactNode; id?: string; - onClick?: () => void; + onClick?: MouseEventHandler; } const styles = (theme: Theme) => ({ @@ -40,7 +46,7 @@ const styles = (theme: Theme) => ({ }); class HeadlineComponent extends Component { - render() { + render(): ReactElement { const { classes, level, className, children, id, onClick } = this.props; return createElement( @@ -61,7 +67,6 @@ class HeadlineComponent extends Component { } const Headline = injectStyle(styles, { injectTheme: true })(HeadlineComponent); - const createH = (level: number) => (props: Omit) => ( diff --git a/src/components/ui/icon/index.tsx b/src/components/ui/icon/index.tsx index 7e13b98c7..5b432a194 100644 --- a/src/components/ui/icon/index.tsx +++ b/src/components/ui/icon/index.tsx @@ -1,6 +1,6 @@ import MdiIcon from '@mdi/react'; import classnames from 'classnames'; -import { Component } from 'react'; +import { Component, ReactElement } from 'react'; import injectStyle, { WithStylesProps } from 'react-jss'; import { Theme } from '../../../themes'; @@ -18,12 +18,8 @@ const styles = (theme: Theme) => ({ }); class IconComponent extends Component { - public static defaultProps = { - size: 1, - }; - - render() { - const { classes, icon, size, className } = this.props; + render(): ReactElement { + const { classes, icon, size = 1, className } = this.props; if (!icon) { console.warn('No Icon specified'); diff --git a/src/components/ui/input/index.tsx b/src/components/ui/input/index.tsx index aa282cce0..b19bb4bc9 100644 --- a/src/components/ui/input/index.tsx +++ b/src/components/ui/input/index.tsx @@ -3,14 +3,12 @@ import Icon from '@mdi/react'; import classnames from 'classnames'; import { Component, createRef, InputHTMLAttributes } from 'react'; import injectSheet, { WithStylesProps } from 'react-jss'; - +import { noop } from 'lodash'; import { IFormField } from '../typings/generic'; - import Error from '../error'; import Label from '../label'; import Wrapper from '../wrapper'; import { scorePasswordFunc } from './scorePassword'; - import styles from './styles'; interface IData { @@ -26,7 +24,7 @@ interface IProps suffix?: string; scorePassword?: boolean; showPasswordToggle?: boolean; - data: IData; + data?: IData; inputClassName?: string; onEnterKey?: Function; } @@ -37,42 +35,31 @@ interface IState { } class InputComponent extends Component { - static defaultProps = { - focus: false, - onChange: () => {}, - onBlur: () => {}, - onFocus: () => {}, - scorePassword: false, - showLabel: true, - showPasswordToggle: false, - type: 'text', - disabled: false, - }; - - state = { - passwordScore: 0, - showPassword: false, - }; - private inputRef = createRef(); - componentDidMount() { - const { focus, data } = this.props; + constructor(props: IProps) { + super(props); + + this.state = { + passwordScore: 0, + showPassword: false, + }; + } + + componentDidMount(): void { + const { focus, data = {} } = this.props; if (this.inputRef && this.inputRef.current) { if (focus) { this.inputRef.current.focus(); } - if (data) { - Object.keys(data).map( - key => (this.inputRef.current!.dataset[key] = data[key]), - ); - } + for (const key of Object.keys(data)) + this.inputRef.current!.dataset[key] = data[key]; } } - onChange(e: React.ChangeEvent) { + onChange(e: React.ChangeEvent): void { const { scorePassword, onChange } = this.props; if (onChange) { @@ -97,28 +84,28 @@ class InputComponent extends Component { const { classes, className, - disabled, error, id, inputClassName, label, prefix, - scorePassword, suffix, - showLabel, - showPasswordToggle, - type, value, name, placeholder, spellCheck, - onBlur, - onFocus, min, max, step, required, noMargin, + onBlur = noop, + onFocus = noop, + scorePassword = false, + showLabel = true, + showPasswordToggle = false, + type = 'text', + disabled = false, } = this.props; const { showPassword, passwordScore } = this.state; diff --git a/src/containers/auth/AuthLayoutContainer.tsx b/src/containers/auth/AuthLayoutContainer.tsx index 6fc6713f1..6a1fed0d7 100644 --- a/src/containers/auth/AuthLayoutContainer.tsx +++ b/src/containers/auth/AuthLayoutContainer.tsx @@ -2,14 +2,15 @@ import { Component, ReactElement } from 'react'; import { inject, observer } from 'mobx-react'; import { ThemeProvider } from 'react-jss'; import { Outlet } from 'react-router-dom'; - import { StoresProps } from '../../@types/ferdium-components.types'; import AuthLayout from '../../components/auth/AuthLayout'; import AppLoader from '../../components/ui/AppLoader'; -interface AuthLayoutContainerProps extends StoresProps {} +interface IProps extends StoresProps {} -class AuthLayoutContainer extends Component { +@inject('stores', 'actions') +@observer +class AuthLayoutContainer extends Component { render(): ReactElement { const { stores, actions } = this.props; const { app, features, globalError, user } = stores; @@ -39,7 +40,6 @@ class AuthLayoutContainer extends Component { { } } -export default inject('stores', 'actions')(observer(AuthLayoutContainer)); +export default AuthLayoutContainer; diff --git a/src/features/publishDebugInfo/Component.js b/src/features/publishDebugInfo/Component.js deleted file mode 100644 index 27661d917..000000000 --- a/src/features/publishDebugInfo/Component.js +++ /dev/null @@ -1,219 +0,0 @@ -import { inject, observer } from 'mobx-react'; -import PropTypes from 'prop-types'; -import { Component } from 'react'; -import { defineMessages, injectIntl } from 'react-intl'; -import injectSheet from 'react-jss'; -import { state as ModalState } from './store'; - -import { H1 } from '../../components/ui/headline'; -import { sendAuthRequest } from '../../api/utils/auth'; -import Button from '../../components/ui/button'; -import Input from '../../components/ui/input/index'; -import Modal from '../../components/ui/Modal'; -import { DEBUG_API } from '../../config'; -import AppStore from '../../stores/AppStore'; -import ServicesStore from '../../stores/ServicesStore'; - -const debug = require('../../preload-safe-debug')( - 'Ferdium:feature:publishDebugInfo', -); - -const messages = defineMessages({ - title: { - id: 'feature.publishDebugInfo.title', - defaultMessage: 'Publish debug information', - }, - info: { - id: 'feature.publishDebugInfo.info', - defaultMessage: - "Publishing your debug information helps us find issues and errors in Ferdium. By publishing your debug information you accept Ferdium Debugger's privacy policy and terms of service", - }, - error: { - id: 'feature.publishDebugInfo.error', - defaultMessage: - 'There was an error while trying to publish the debug information. Please try again later or view the console for more information.', - }, - privacy: { - id: 'feature.publishDebugInfo.privacy', - defaultMessage: 'Privacy policy', - }, - terms: { - id: 'feature.publishDebugInfo.terms', - defaultMessage: 'Terms of service', - }, - publish: { - id: 'feature.publishDebugInfo.publish', - defaultMessage: 'Accept and publish', - }, - published: { - id: 'feature.publishDebugInfo.published', - defaultMessage: 'Your debug log was published and is now availible at', - }, -}); - -const styles = theme => ({ - modal: { - width: '80%', - maxWidth: 600, - background: theme.styleTypes.primary.contrast, - paddingTop: 30, - }, - headline: { - fontSize: 20, - marginBottom: 20, - marginTop: -27, - }, - info: { - paddingBottom: 20, - }, - link: { - color: `${theme.styleTypes.primary.accent} !important`, - padding: 10, - cursor: 'pointer', - }, - button: { - width: '100%', - marginTop: 10, - cursor: 'pointer', - }, -}); - -class PublishDebugLogModal extends Component { - state = { - log: null, - error: false, - isSendingLog: false, - }; - - // Close this modal - close() { - ModalState.isModalVisible = false; - this.setState({ - log: null, - error: false, - isSendingLog: false, - }); - } - - async publishDebugInfo() { - debug('debugInfo: starting publish'); - this.setState({ - isSendingLog: true, - }); - - const debugInfo = JSON.stringify(this.props.stores.app.debugInfo); - - const request = await sendAuthRequest( - `${DEBUG_API}/create`, - { - method: 'POST', - body: JSON.stringify({ - log: debugInfo, - }), - }, - false, - ); - - debug(`debugInfo: publishing status: ${request.status}`); - if (request.status === 200) { - const response = await request.json(); - if (response.id) { - this.setState({ - log: response.id, - }); - } else { - this.setState({ - error: true, - }); - } - } else { - this.setState({ - error: true, - }); - } - - debug('debugInfo: finished publishing'); - } - - render() { - const { isModalVisible } = ModalState; - - const { classes } = this.props; - - const { log, error, isSendingLog } = this.state; - - const { intl } = this.props; - - return ( - this.close()} - > -

- {intl.formatMessage(messages.title)} -

- {log && ( - <> -

- {intl.formatMessage(messages.published)} -

- - - )} - - {error && ( -

{intl.formatMessage(messages.error)}

- )} - - {!log && !error && ( - <> -

{intl.formatMessage(messages.info)}

- - - {intl.formatMessage(messages.privacy)} - - - {intl.formatMessage(messages.terms)} - - -