mirror of
https://github.com/pybricks/pybricks-code.git
synced 2026-09-14 10:35:11 +00:00
add basic about dialog
This commit is contained in:
@@ -0,0 +1,63 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// Copyright (c) 2021 The Pybricks Authors
|
||||
|
||||
// The about dialog
|
||||
|
||||
import { AnchorButton, Classes, Dialog } from '@blueprintjs/core';
|
||||
import { WithI18nProps, withI18n } from '@shopify/react-i18n';
|
||||
import React from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { Action, Dispatch } from '../actions';
|
||||
import { closeAboutDialog } from '../actions/app';
|
||||
import { RootState } from '../reducers';
|
||||
import {
|
||||
appName,
|
||||
legoDisclaimer,
|
||||
pybricksCopyright,
|
||||
pybricksWebsiteUrl,
|
||||
} from '../settings/ui';
|
||||
import { AboutStringId } from './about-i18n';
|
||||
import en from './about-i18n.en.json';
|
||||
|
||||
type StateProps = { showAboutDialog: boolean };
|
||||
|
||||
type DispatchProps = { onClose: () => void };
|
||||
|
||||
type AboutDialogProps = StateProps & DispatchProps & WithI18nProps;
|
||||
|
||||
class AboutDialog extends React.Component<AboutDialogProps> {
|
||||
render(): JSX.Element {
|
||||
const { i18n, showAboutDialog, onClose } = this.props;
|
||||
return (
|
||||
<Dialog title={appName} isOpen={showAboutDialog} onClose={() => onClose()}>
|
||||
<div className={Classes.DIALOG_BODY}>
|
||||
<p>
|
||||
<strong>{i18n.translate(AboutStringId.Description)}</strong>
|
||||
</p>
|
||||
<p>{pybricksCopyright}</p>
|
||||
</div>
|
||||
<div className={Classes.DIALOG_FOOTER}>
|
||||
<p>{legoDisclaimer}</p>
|
||||
<div className={Classes.DIALOG_FOOTER_ACTIONS}>
|
||||
<AnchorButton href={pybricksWebsiteUrl} target="blank_">
|
||||
{i18n.translate(AboutStringId.WebsiteButtonLabel)}
|
||||
</AnchorButton>
|
||||
</div>
|
||||
</div>
|
||||
</Dialog>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const mapStateToProps = (state: RootState): StateProps => ({
|
||||
showAboutDialog: state.app.showAboutDialog,
|
||||
});
|
||||
|
||||
const mapDispatchToProps = (dispatch: Dispatch): DispatchProps => ({
|
||||
onClose: (): Action => dispatch(closeAboutDialog()),
|
||||
});
|
||||
|
||||
export default connect(
|
||||
mapStateToProps,
|
||||
mapDispatchToProps,
|
||||
)(withI18n({ id: 'about', fallback: en, translations: { en } })(AboutDialog));
|
||||
@@ -5,6 +5,7 @@ import React, { useState } from 'react';
|
||||
import { useSelector } from 'react-redux';
|
||||
import SplitterLayout from 'react-splitter-layout';
|
||||
import { RootState } from '../reducers';
|
||||
import AboutDialog from './AboutDialog';
|
||||
import Editor from './Editor';
|
||||
import SettingsDrawer from './SettingsDrawer';
|
||||
import StatusBar from './StatusBar';
|
||||
@@ -64,6 +65,7 @@ function App(): JSX.Element {
|
||||
</SplitterLayout>
|
||||
<StatusBar />
|
||||
<SettingsDrawer />
|
||||
<AboutDialog key="about" />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ import { WithI18nProps, withI18n } from '@shopify/react-i18n';
|
||||
import React from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { Action, Dispatch } from '../actions';
|
||||
import { closeSettings } from '../actions/app';
|
||||
import { closeSettings, openAboutDialog } from '../actions/app';
|
||||
import { setBoolean } from '../actions/settings';
|
||||
import { RootState } from '../reducers';
|
||||
import { tooltipDelay } from '../settings/ui';
|
||||
@@ -29,6 +29,7 @@ type DispatchProps = {
|
||||
onShowDocsChanged: (checked: boolean) => void;
|
||||
onDarkModeChanged: (checked: boolean) => void;
|
||||
onFlashCurrentProgramChanged: (checked: boolean) => void;
|
||||
onAbout: () => void;
|
||||
};
|
||||
|
||||
type SettingsProps = StateProps & DispatchProps & WithI18nProps;
|
||||
@@ -45,6 +46,7 @@ class SettingsDrawer extends React.PureComponent<SettingsProps> {
|
||||
onDarkModeChanged,
|
||||
flashCurrentProgram,
|
||||
onFlashCurrentProgramChanged,
|
||||
onAbout,
|
||||
} = this.props;
|
||||
return (
|
||||
<Drawer
|
||||
@@ -131,6 +133,16 @@ class SettingsDrawer extends React.PureComponent<SettingsProps> {
|
||||
/>
|
||||
</Tooltip>
|
||||
</FormGroup>
|
||||
<FormGroup label={i18n.translate(SettingsStringId.HelpTitle)}>
|
||||
<a
|
||||
onClick={() => {
|
||||
onAbout();
|
||||
return true;
|
||||
}}
|
||||
>
|
||||
{i18n.translate(SettingsStringId.HelpAboutLabel)}
|
||||
</a>
|
||||
</FormGroup>
|
||||
</div>
|
||||
</Drawer>
|
||||
);
|
||||
@@ -152,6 +164,7 @@ const mapDispatchToProps = (dispatch: Dispatch): DispatchProps => ({
|
||||
dispatch(setBoolean(SettingId.DarkMode, checked)),
|
||||
onFlashCurrentProgramChanged: (checked): Action =>
|
||||
dispatch(setBoolean(SettingId.FlashCurrentProgram, checked)),
|
||||
onAbout: (): Action => dispatch(openAboutDialog()),
|
||||
});
|
||||
|
||||
export default connect(
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"about": {
|
||||
"description": "A simple web app for programming LEGO® Powered Up smart hubs using Pybricks MicroPython.",
|
||||
"websiteButton": { "label": "Pybricks Website" }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// Copyright (c) 2021 The Pybricks Authors
|
||||
|
||||
import { lookup } from '../../test';
|
||||
import { AboutStringId } from './about-i18n';
|
||||
import en from './about-i18n.en.json';
|
||||
|
||||
describe('Ensure .json file has matches for AboutStringId', () => {
|
||||
test.each(Object.values(AboutStringId))('%s', (id) => {
|
||||
expect(lookup(en, id)).toBeDefined();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,9 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// Copyright (c) 2021 The Pybricks Authors
|
||||
|
||||
// About dialog translation keys.
|
||||
|
||||
export enum AboutStringId {
|
||||
Description = 'about.description',
|
||||
WebsiteButtonLabel = 'about.websiteButton.label',
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"settings": {
|
||||
"title": "Settings",
|
||||
"title": "Settings & Help",
|
||||
"appearance": {
|
||||
"title": "Appearance",
|
||||
"documentation": {
|
||||
@@ -21,6 +21,12 @@
|
||||
"label": "Include current program",
|
||||
"tooltip": "Select to include your program when installing the firmware."
|
||||
}
|
||||
},
|
||||
"help": {
|
||||
"title": "Help",
|
||||
"about": {
|
||||
"label": "About"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,4 +14,6 @@ export enum SettingsStringId {
|
||||
FirmwareTitle = 'settings.firmware.title',
|
||||
FirmwareCurrentProgramLabel = 'settings.firmware.flash-current-program.label',
|
||||
FirmwareCurrentProgramTooltip = 'settings.firmware.flash-current-program.tooltip',
|
||||
HelpTitle = 'settings.help.title',
|
||||
HelpAboutLabel = 'settings.help.about.label',
|
||||
}
|
||||
|
||||
@@ -15,3 +15,7 @@
|
||||
.pb-settings .bp3-form-helper-text {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.pb-settings a {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user