Sync Packages with Radarr

This commit is contained in:
Qstick
2020-07-01 21:12:01 +01:00
committed by ta264
parent c1b9590df2
commit 6dbce8d12e
47 changed files with 2399 additions and 1886 deletions

View File

@@ -268,7 +268,7 @@
"react/jsx-curly-spacing": [2, "never"],
"react/jsx-equals-spacing": [2, "never"],
"react/jsx-indent-props": [2, 2],
"react/jsx-indent": [2, 2],
"react/jsx-indent": [2, 2, { "indentLogicalExpressions": true }],
"react/jsx-key": 2,
"react/jsx-no-bind": [2, { "allowArrowFunctions": true }],
"react/jsx-no-duplicate-props": [2, { "ignoreCase": true }],

View File

@@ -10,8 +10,7 @@ gulp.task('build',
'webpack',
'copyHtml',
'copyFonts',
'copyImages',
'copyJs'
'copyImages'
)
)
);

View File

@@ -5,17 +5,6 @@ const cache = require('gulp-cached');
const livereload = require('gulp-livereload');
const paths = require('./helpers/paths.js');
gulp.task('copyJs', () => {
return gulp.src(
[
path.join(paths.src.root, 'polyfills.js')
], { base: paths.src.root })
.pipe(cache('copyJs'))
.pipe(print())
.pipe(gulp.dest(paths.dest.root))
.pipe(livereload());
});
gulp.task('copyHtml', () => {
return gulp.src(paths.src.html, { base: paths.src.root })
.pipe(cache('copyHtml'))

View File

@@ -14,6 +14,7 @@ const frontendFolder = path.join(__dirname, '..');
const srcFolder = path.join(frontendFolder, 'src');
const isProduction = process.argv.indexOf('--production') > -1;
const isProfiling = isProduction && process.argv.indexOf('--profile') > -1;
const inlineWebWorkers = true;
const distFolder = path.resolve(frontendFolder, '..', '_output', uiFolder);
@@ -124,7 +125,9 @@ const config = {
use: {
loader: 'worker-loader',
options: {
name: '[name].js'
name: '[name].js',
inline: inlineWebWorkers,
fallback: !inlineWebWorkers
}
}
},

View File

@@ -124,16 +124,16 @@ class RemoveQueueItemsModal extends Component {
{
blacklist &&
<FormGroup>
<FormLabel>Skip Redownload</FormLabel>
<FormInputGroup
type={inputTypes.CHECK}
name="skipredownload"
value={skipredownload}
helpText="Prevents Readarr from trying download alternative releases for the removed items"
onChange={this.onSkipReDownloadChange}
/>
</FormGroup>
<FormGroup>
<FormLabel>Skip Redownload</FormLabel>
<FormInputGroup
type={inputTypes.CHECK}
name="skipredownload"
value={skipredownload}
helpText="Prevents Readarr from trying download alternative releases for the removed items"
onChange={this.onSkipReDownloadChange}
/>
</FormGroup>
}
</ModalBody>

View File

@@ -108,7 +108,7 @@ class AuthorIndexBannerOptionsModalContent extends Component {
return (
<ModalContent onModalClose={onModalClose}>
<ModalHeader>
Options
Options
</ModalHeader>
<ModalBody>

View File

@@ -128,10 +128,10 @@ class AuthorIndexOverview extends Component {
<div className={styles.posterContainer}>
{
status === 'ended' &&
<div
className={styles.ended}
title="Ended"
/>
<div
className={styles.ended}
title="Ended"
/>
}
<Link

View File

@@ -183,19 +183,19 @@ function AuthorIndexOverviewInfo(props) {
<div className={styles.infos}>
{
!!nextAiring &&
<AuthorIndexOverviewInfoRow
title={formatDateTime(nextAiring, longDateFormat, timeFormat)}
iconName={icons.SCHEDULED}
label={getRelativeDate(
nextAiring,
shortDateFormat,
showRelativeDates,
{
timeFormat,
timeForToday: true
}
)}
/>
<AuthorIndexOverviewInfoRow
title={formatDateTime(nextAiring, longDateFormat, timeFormat)}
iconName={icons.SCHEDULED}
label={getRelativeDate(
nextAiring,
shortDateFormat,
showRelativeDates,
{
timeFormat,
timeForToday: true
}
)}
/>
}
{

View File

@@ -11,7 +11,7 @@ function NoAuthor(props) {
return (
<div>
<div className={styles.message}>
All authors are hidden due to the applied filter.
All authors are hidden due to the applied filter.
</div>
</div>
);

View File

@@ -135,9 +135,9 @@ class CalendarPage extends Component {
>
{
authorError &&
<div className={styles.errorMessage}>
{getErrorMessage(authorError, 'Failed to load author from API')}
</div>
<div className={styles.errorMessage}>
{getErrorMessage(authorError, 'Failed to load author from API')}
</div>
}
{

View File

@@ -94,11 +94,11 @@ class CalendarEvent extends Component {
{
!queueItem && grabbed &&
<Icon
className={styles.statusIcon}
name={icons.DOWNLOADING}
title="Book is downloading"
/>
<Icon
className={styles.statusIcon}
name={icons.DOWNLOADING}
title="Book is downloading"
/>
}
</div>

View File

@@ -24,7 +24,7 @@ function CustomFiltersModalContent(props) {
return (
<ModalContent onModalClose={onModalClose}>
<ModalHeader>
Custom Filters
Custom Filters
</ModalHeader>
<ModalBody>
@@ -58,7 +58,7 @@ function CustomFiltersModalContent(props) {
<Button
onPress={onModalClose}
>
Close
Close
</Button>
</ModalFooter>
</ModalContent>

View File

@@ -59,7 +59,7 @@ class RootFolderSelectInputConnector extends Component {
//
// Lifecycle
componentWillMount() {
UNSAFE_componentWillMount() {
const {
value,
values,

View File

@@ -2,7 +2,7 @@ import PropTypes from 'prop-types';
import React from 'react';
import styles from './LoadingIndicator.css';
function LoadingIndicator({ className, size }) {
function LoadingIndicator({ className, rippleClassName, size }) {
const sizeInPx = `${size}px`;
const width = sizeInPx;
const height = sizeInPx;
@@ -17,17 +17,17 @@ function LoadingIndicator({ className, size }) {
style={{ width, height }}
>
<div
className={styles.ripple}
className={rippleClassName}
style={{ width, height }}
/>
<div
className={styles.ripple}
className={rippleClassName}
style={{ width, height }}
/>
<div
className={styles.ripple}
className={rippleClassName}
style={{ width, height }}
/>
</div>
@@ -37,11 +37,13 @@ function LoadingIndicator({ className, size }) {
LoadingIndicator.propTypes = {
className: PropTypes.string,
rippleClassName: PropTypes.string,
size: PropTypes.number
};
LoadingIndicator.defaultProps = {
className: styles.loading,
rippleClassName: styles.ripple,
size: 50
};

View File

@@ -61,7 +61,7 @@ class FilterMenuContent extends Component {
{
showCustomFilters &&
<MenuItem onPress={onCustomFiltersPress}>
Custom Filters
Custom Filters
</MenuItem>
}
</MenuContent>

View File

@@ -1,6 +1,7 @@
import PropTypes from 'prop-types';
import React from 'react';
import React, { useEffect } from 'react';
import { kinds, sizes } from 'Helpers/Props';
import keyboardShortcuts from 'Components/keyboardShortcuts';
import Button from 'Components/Link/Button';
import SpinnerButton from 'Components/Link/SpinnerButton';
import Modal from 'Components/Modal/Modal';
@@ -21,9 +22,19 @@ function ConfirmModal(props) {
hideCancelButton,
isSpinning,
onConfirm,
onCancel
onCancel,
bindShortcut,
unbindShortcut
} = props;
useEffect(() => {
if (isOpen) {
bindShortcut('enter', onConfirm);
} else {
unbindShortcut('enter', onConfirm);
}
}, [onConfirm]);
return (
<Modal
isOpen={isOpen}
@@ -49,7 +60,7 @@ function ConfirmModal(props) {
}
<SpinnerButton
data-autofocus={true}
autoFocus={true}
kind={kind}
isSpinning={isSpinning}
onPress={onConfirm}
@@ -74,7 +85,9 @@ ConfirmModal.propTypes = {
hideCancelButton: PropTypes.bool,
isSpinning: PropTypes.bool.isRequired,
onConfirm: PropTypes.func.isRequired,
onCancel: PropTypes.func.isRequired
onCancel: PropTypes.func.isRequired,
bindShortcut: PropTypes.func.isRequired,
unbindShortcut: PropTypes.func.isRequired
};
ConfirmModal.defaultProps = {
@@ -85,4 +98,4 @@ ConfirmModal.defaultProps = {
isSpinning: false
};
export default ConfirmModal;
export default keyboardShortcuts(ConfirmModal);

View File

@@ -1,6 +1,7 @@
import PropTypes from 'prop-types';
import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import FocusLock from 'react-focus-lock';
import classNames from 'classnames';
import elementClass from 'element-class';
import getUniqueElememtId from 'Utilities/getUniqueElementId';
@@ -181,31 +182,33 @@ class Modal extends Component {
}
return ReactDOM.createPortal(
<div
className={styles.modalContainer}
>
<FocusLock disabled={false}>
<div
ref={this._setBackgroundRef}
className={backdropClassName}
onMouseDown={this.onBackdropBeginPress}
onMouseUp={this.onBackdropEndPress}
className={styles.modalContainer}
>
<div
className={classNames(
className,
styles[size]
)}
style={style}
ref={this._setBackgroundRef}
className={backdropClassName}
onMouseDown={this.onBackdropBeginPress}
onMouseUp={this.onBackdropEndPress}
>
<ErrorBoundary
errorComponent={ModalError}
onModalClose={onModalClose}
<div
className={classNames(
className,
styles[size]
)}
style={style}
>
{children}
</ErrorBoundary>
<ErrorBoundary
errorComponent={ModalError}
onModalClose={onModalClose}
>
{children}
</ErrorBoundary>
</div>
</div>
</div>
</div>,
</FocusLock>,
this._node
);
}

View File

@@ -3,6 +3,18 @@
align-items: center;
}
.loading {
margin-top: 18px;
margin-bottom: 18px;
text-align: center;
}
.ripple {
composes: ripple from '~Components/Loading/LoadingIndicator.css';
border: 2px solid $toolbarColor;
}
.input {
margin-left: 8px;
width: 200px;

View File

@@ -74,7 +74,11 @@ class AuthorSearchInput extends Component {
if (item.type === LOADING_TYPE) {
return (
<LoadingIndicator />
<LoadingIndicator
className={styles.loading}
rippleClassName={styles.ripple}
size={30}
/>
);
}

View File

@@ -6,7 +6,6 @@ const fuseOptions = {
threshold: 0.3,
location: 0,
distance: 100,
maxPatternLength: 32,
minMatchCharLength: 1,
keys: [
'authorName',

View File

@@ -17,12 +17,18 @@ class Scroller extends Component {
componentDidMount() {
const {
scrollDirection,
autoFocus,
scrollTop
} = this.props;
if (this.props.scrollTop != null) {
this._scroller.scrollTop = scrollTop;
}
if (autoFocus && scrollDirection !== scrollDirections.NONE) {
this._scroller.focus({ preventScroll: true });
}
}
//
@@ -58,6 +64,7 @@ class Scroller extends Component {
styles[scrollDirection],
autoScroll && styles.autoScroll
)}
tabIndex={-1}
{...otherProps}
>
{children}
@@ -70,6 +77,7 @@ class Scroller extends Component {
Scroller.propTypes = {
className: PropTypes.string,
scrollDirection: PropTypes.oneOf(scrollDirections.all).isRequired,
autoFocus: PropTypes.bool.isRequired,
autoScroll: PropTypes.bool.isRequired,
scrollTop: PropTypes.number,
children: PropTypes.node,
@@ -79,6 +87,7 @@ Scroller.propTypes = {
Scroller.defaultProps = {
scrollDirection: scrollDirections.VERTICAL,
autoFocus: true,
autoScroll: true,
registerScroller: () => {}
};

View File

@@ -136,7 +136,7 @@ class TableOptionsModal extends Component {
isOpen ?
<ModalContent onModalClose={onModalClose}>
<ModalHeader>
Table Options
Table Options
</ModalHeader>
<ModalBody>
@@ -231,7 +231,7 @@ class TableOptionsModal extends Component {
<Button
onPress={onModalClose}
>
Close
Close
</Button>
</ModalFooter>
</ModalContent> :

View File

@@ -8,6 +8,16 @@ export const shortcuts = {
name: 'Open This Modal'
},
CLOSE_MODAL: {
key: 'Esc',
name: 'Close Current Modal'
},
ACCEPT_CONFIRM_MODAL: {
key: 'Enter',
name: 'Accept Confirmation Modal'
},
AUTHOR_SEARCH_INPUT: {
key: 's',
name: 'Focus Search Box'

View File

@@ -72,9 +72,9 @@ class ConfirmImportModalContent extends Component {
{
!isFetching && isPopulated &&
<ModalHeader>
Are you sure?
</ModalHeader>
<ModalHeader>
Are you sure?
</ModalHeader>
}
<ModalBody>

View File

@@ -156,7 +156,7 @@ function InteractiveSearch(props) {
{
totalReleasesCount !== items.length && !!items.length ?
<div className={styles.filteredMessage}>
Some results are hidden by the applied filter
Some results are hidden by the applied filter
</div> :
null
}

View File

@@ -126,7 +126,7 @@ class AddNewAuthorSearchResult extends Component {
{
!!disambiguation &&
<span className={styles.year}>({disambiguation})</span>
<span className={styles.year}>({disambiguation})</span>
}
{

View File

@@ -103,12 +103,12 @@ class AddNewBookSearchResult extends Component {
<div className={styles.overlay}>
{
!isSmallScreen &&
<BookCover
className={styles.poster}
images={images}
size={250}
lazy={false}
/>
<BookCover
className={styles.poster}
images={images}
size={250}
lazy={false}
/>
}
<div className={styles.content}>
@@ -117,7 +117,7 @@ class AddNewBookSearchResult extends Component {
{
!!disambiguation &&
<span className={styles.year}>({disambiguation})</span>
<span className={styles.year}>({disambiguation})</span>
}
{

View File

@@ -44,90 +44,90 @@ function ProxySettings(props) {
{
proxyEnabled.value &&
<div>
<FormGroup>
<FormLabel>Proxy Type</FormLabel>
<div>
<FormGroup>
<FormLabel>Proxy Type</FormLabel>
<FormInputGroup
type={inputTypes.SELECT}
name="proxyType"
values={proxyTypeOptions}
onChange={onInputChange}
{...proxyType}
/>
</FormGroup>
<FormInputGroup
type={inputTypes.SELECT}
name="proxyType"
values={proxyTypeOptions}
onChange={onInputChange}
{...proxyType}
/>
</FormGroup>
<FormGroup>
<FormLabel>Hostname</FormLabel>
<FormGroup>
<FormLabel>Hostname</FormLabel>
<FormInputGroup
type={inputTypes.TEXT}
name="proxyHostname"
onChange={onInputChange}
{...proxyHostname}
/>
</FormGroup>
<FormInputGroup
type={inputTypes.TEXT}
name="proxyHostname"
onChange={onInputChange}
{...proxyHostname}
/>
</FormGroup>
<FormGroup>
<FormLabel>Port</FormLabel>
<FormGroup>
<FormLabel>Port</FormLabel>
<FormInputGroup
type={inputTypes.NUMBER}
name="proxyPort"
min={1}
max={65535}
onChange={onInputChange}
{...proxyPort}
/>
</FormGroup>
<FormInputGroup
type={inputTypes.NUMBER}
name="proxyPort"
min={1}
max={65535}
onChange={onInputChange}
{...proxyPort}
/>
</FormGroup>
<FormGroup>
<FormLabel>Username</FormLabel>
<FormGroup>
<FormLabel>Username</FormLabel>
<FormInputGroup
type={inputTypes.TEXT}
name="proxyUsername"
helpText="You only need to enter a username and password if one is required. Leave them blank otherwise."
onChange={onInputChange}
{...proxyUsername}
/>
</FormGroup>
<FormInputGroup
type={inputTypes.TEXT}
name="proxyUsername"
helpText="You only need to enter a username and password if one is required. Leave them blank otherwise."
onChange={onInputChange}
{...proxyUsername}
/>
</FormGroup>
<FormGroup>
<FormLabel>Password</FormLabel>
<FormGroup>
<FormLabel>Password</FormLabel>
<FormInputGroup
type={inputTypes.PASSWORD}
name="proxyPassword"
helpText="You only need to enter a username and password if one is required. Leave them blank otherwise."
onChange={onInputChange}
{...proxyPassword}
/>
</FormGroup>
<FormInputGroup
type={inputTypes.PASSWORD}
name="proxyPassword"
helpText="You only need to enter a username and password if one is required. Leave them blank otherwise."
onChange={onInputChange}
{...proxyPassword}
/>
</FormGroup>
<FormGroup>
<FormLabel>Ignored Addresses</FormLabel>
<FormGroup>
<FormLabel>Ignored Addresses</FormLabel>
<FormInputGroup
type={inputTypes.TEXT}
name="proxyBypassFilter"
helpText="Use ',' as a separator, and '*.' as a wildcard for subdomains"
onChange={onInputChange}
{...proxyBypassFilter}
/>
</FormGroup>
<FormInputGroup
type={inputTypes.TEXT}
name="proxyBypassFilter"
helpText="Use ',' as a separator, and '*.' as a wildcard for subdomains"
onChange={onInputChange}
{...proxyBypassFilter}
/>
</FormGroup>
<FormGroup size={sizes.MEDIUM}>
<FormLabel>Bypass Proxy for Local Addresses</FormLabel>
<FormGroup size={sizes.MEDIUM}>
<FormLabel>Bypass Proxy for Local Addresses</FormLabel>
<FormInputGroup
type={inputTypes.CHECK}
name="proxyBypassLocalAddresses"
onChange={onInputChange}
{...proxyBypassLocalAddresses}
/>
</FormGroup>
</div>
<FormInputGroup
type={inputTypes.CHECK}
name="proxyBypassLocalAddresses"
onChange={onInputChange}
{...proxyBypassLocalAddresses}
/>
</FormGroup>
</div>
}
</FieldSet>
);

View File

@@ -93,32 +93,32 @@ class SecuritySettings extends Component {
{
authenticationEnabled &&
<FormGroup>
<FormLabel>Username</FormLabel>
<FormGroup>
<FormLabel>Username</FormLabel>
<FormInputGroup
type={inputTypes.TEXT}
name="username"
helpTextWarning="Requires restart to take effect"
onChange={onInputChange}
{...username}
/>
</FormGroup>
<FormInputGroup
type={inputTypes.TEXT}
name="username"
helpTextWarning="Requires restart to take effect"
onChange={onInputChange}
{...username}
/>
</FormGroup>
}
{
authenticationEnabled &&
<FormGroup>
<FormLabel>Password</FormLabel>
<FormGroup>
<FormLabel>Password</FormLabel>
<FormInputGroup
type={inputTypes.PASSWORD}
name="password"
helpTextWarning="Requires restart to take effect"
onChange={onInputChange}
{...password}
/>
</FormGroup>
<FormInputGroup
type={inputTypes.PASSWORD}
name="password"
helpTextWarning="Requires restart to take effect"
onChange={onInputChange}
{...password}
/>
</FormGroup>
}
<FormGroup>

View File

@@ -72,58 +72,58 @@ function UpdateSettings(props) {
{
!isWindows &&
<div>
<FormGroup
advancedSettings={advancedSettings}
isAdvanced={true}
size={sizes.MEDIUM}
>
<FormLabel>Automatic</FormLabel>
<div>
<FormGroup
advancedSettings={advancedSettings}
isAdvanced={true}
size={sizes.MEDIUM}
>
<FormLabel>Automatic</FormLabel>
<FormInputGroup
type={inputTypes.CHECK}
name="updateAutomatically"
helpText="Automatically download and install updates. You will still be able to install from System: Updates"
onChange={onInputChange}
{...updateAutomatically}
/>
</FormGroup>
<FormInputGroup
type={inputTypes.CHECK}
name="updateAutomatically"
helpText="Automatically download and install updates. You will still be able to install from System: Updates"
onChange={onInputChange}
{...updateAutomatically}
/>
</FormGroup>
<FormGroup
advancedSettings={advancedSettings}
isAdvanced={true}
>
<FormLabel>Mechanism</FormLabel>
<FormInputGroup
type={inputTypes.SELECT}
name="updateMechanism"
values={updateOptions}
helpText="Use Readarr's built-in updater or a script"
helpLink="https://github.com/Readarr/Readarr/wiki/Updating"
onChange={onInputChange}
{...updateMechanism}
/>
</FormGroup>
{
updateMechanism.value === 'script' &&
<FormGroup
advancedSettings={advancedSettings}
isAdvanced={true}
>
<FormLabel>Script Path</FormLabel>
<FormLabel>Mechanism</FormLabel>
<FormInputGroup
type={inputTypes.TEXT}
name="updateScriptPath"
helpText="Path to a custom script that takes an extracted update package and handle the remainder of the update process"
type={inputTypes.SELECT}
name="updateMechanism"
values={updateOptions}
helpText="Use Readarr's built-in updater or a script"
helpLink="https://github.com/Readarr/Readarr/wiki/Updating"
onChange={onInputChange}
{...updateScriptPath}
{...updateMechanism}
/>
</FormGroup>
}
</div>
{
updateMechanism.value === 'script' &&
<FormGroup
advancedSettings={advancedSettings}
isAdvanced={true}
>
<FormLabel>Script Path</FormLabel>
<FormInputGroup
type={inputTypes.TEXT}
name="updateScriptPath"
helpText="Path to a custom script that takes an extracted update package and handle the remainder of the update process"
onChange={onInputChange}
{...updateScriptPath}
/>
</FormGroup>
}
</div>
}
</FieldSet>
);

View File

@@ -199,23 +199,23 @@ function EditImportListModalContent(props) {
{
!!fields && !!fields.length &&
<div>
{
fields.map((field) => {
return (
<ProviderFieldFormGroup
key={field.name}
advancedSettings={advancedSettings}
provider="importList"
providerData={item}
section="settings.importLists"
{...field}
onChange={onFieldChange}
/>
);
})
}
</div>
<div>
{
fields.map((field) => {
return (
<ProviderFieldFormGroup
key={field.name}
advancedSettings={advancedSettings}
provider="importList"
providerData={item}
section="settings.importLists"
{...field}
onChange={onFieldChange}
/>
);
})
}
</div>
}
</Form>

View File

@@ -96,12 +96,12 @@ class Indexer extends Component {
{
!enableRss && !enableAutomaticSearch && !enableInteractiveSearch &&
<Label
kind={kinds.DISABLED}
outline={true}
>
Disabled
</Label>
<Label
kind={kinds.DISABLED}
outline={true}
>
Disabled
</Label>
}
</div>

View File

@@ -43,23 +43,23 @@ function MetadataProvider(props) {
<Form>
{
advancedSettings &&
<FieldSet legend="Metadata Provider Source">
<FormGroup
advancedSettings={advancedSettings}
isAdvanced={true}
>
<FormLabel>Metadata Source</FormLabel>
<FieldSet legend="Metadata Provider Source">
<FormGroup
advancedSettings={advancedSettings}
isAdvanced={true}
>
<FormLabel>Metadata Source</FormLabel>
<FormInputGroup
type={inputTypes.TEXT}
name="metadataSource"
helpText="Alternative Metadata Source (Leave blank for default)"
helpLink="https://github.com/Readarr/Readarr/wiki/Metadata-Source"
onChange={onInputChange}
{...settings.metadataSource}
/>
</FormGroup>
</FieldSet>
<FormInputGroup
type={inputTypes.TEXT}
name="metadataSource"
helpText="Alternative Metadata Source (Leave blank for default)"
helpLink="https://github.com/Readarr/Readarr/wiki/Metadata-Source"
onChange={onInputChange}
{...settings.metadataSource}
/>
</FormGroup>
</FieldSet>
}
<FieldSet legend="Write Metadata to Audio Files">

View File

@@ -141,12 +141,12 @@ class Notification extends Component {
{
!onGrab && !onReleaseImport && !onRename && !onTrackRetag &&
!onHealthIssue && !onDownloadFailure && !onImportFailure &&
<Label
kind={kinds.DISABLED}
outline={true}
>
Disabled
</Label>
<Label
kind={kinds.DISABLED}
outline={true}
>
Disabled
</Label>
}
<EditNotificationModalConnector

View File

@@ -1,6 +1,7 @@
import PropTypes from 'prop-types';
import React from 'react';
import React, { useEffect } from 'react';
import { kinds } from 'Helpers/Props';
import keyboardShortcuts from 'Components/keyboardShortcuts';
import Button from 'Components/Link/Button';
import Modal from 'Components/Modal/Modal';
import ModalContent from 'Components/Modal/ModalContent';
@@ -12,9 +13,14 @@ function PendingChangesModal(props) {
const {
isOpen,
onConfirm,
onCancel
onCancel,
bindShortcut
} = props;
useEffect(() => {
bindShortcut('enter', onConfirm);
}, [onConfirm]);
return (
<Modal
isOpen={isOpen}
@@ -36,6 +42,7 @@ function PendingChangesModal(props) {
</Button>
<Button
autoFocus={true}
kind={kinds.DANGER}
onPress={onConfirm}
>
@@ -52,11 +59,12 @@ PendingChangesModal.propTypes = {
isOpen: PropTypes.bool.isRequired,
kind: PropTypes.oneOf(kinds.all),
onConfirm: PropTypes.func.isRequired,
onCancel: PropTypes.func.isRequired
onCancel: PropTypes.func.isRequired,
bindShortcut: PropTypes.func.isRequired
};
PendingChangesModal.defaultProps = {
kind: kinds.PRIMARY
};
export default PendingChangesModal;
export default keyboardShortcuts(PendingChangesModal);

View File

@@ -174,7 +174,7 @@ class EditQualityProfileModalContent extends Component {
upgradeAllowed.value &&
<FormGroup size={sizes.EXTRA_SMALL}>
<FormLabel size={sizes.SMALL}>
Upgrade Until
Upgrade Until
</FormLabel>
<FormInputGroup

View File

@@ -167,7 +167,7 @@ function TagDetailsModalContent(props) {
isDisabled={isTagUsed}
onPress={onDeleteTagPress}
>
Delete
Delete
</Button>
}

View File

@@ -200,7 +200,7 @@ class RestoreBackupModalContent extends Component {
</div>
<Button onPress={onModalClose}>
Cancel
Cancel
</Button>
<SpinnerButton
@@ -209,7 +209,7 @@ class RestoreBackupModalContent extends Component {
isSpinning={isRestoring}
onPress={this.onRestorePress}
>
Restore
Restore
</SpinnerButton>
</ModalFooter>
</ModalContent>

View File

@@ -76,45 +76,45 @@ function LogsTable(props) {
<PageContentBodyConnector>
{
isFetching && !isPopulated &&
<LoadingIndicator />
<LoadingIndicator />
}
{
isPopulated && !error && !items.length &&
<div>
No logs found
</div>
<div>
No logs found
</div>
}
{
isPopulated && !error && !!items.length &&
<div>
<Table
columns={columns}
canModifyColumns={false}
{...otherProps}
>
<TableBody>
{
items.map((item) => {
return (
<LogsTableRow
key={item.id}
columns={columns}
{...item}
/>
);
})
}
</TableBody>
</Table>
<div>
<Table
columns={columns}
canModifyColumns={false}
{...otherProps}
>
<TableBody>
{
items.map((item) => {
return (
<LogsTableRow
key={item.id}
columns={columns}
{...item}
/>
);
})
}
</TableBody>
</Table>
<TablePager
totalRecords={totalRecords}
isFetching={isFetching}
{...otherProps}
/>
</div>
<TablePager
totalRecords={totalRecords}
isFetching={isFetching}
{...otherProps}
/>
</div>
}
</PageContentBodyConnector>
</PageContent>

View File

@@ -54,27 +54,27 @@ function QueuedTasks(props) {
<FieldSet legend="Queue">
{
isFetching && !isPopulated &&
<LoadingIndicator />
<LoadingIndicator />
}
{
isPopulated &&
<Table
columns={columns}
>
<TableBody>
{
items.map((item) => {
return (
<QueuedTaskRowConnector
key={item.id}
{...item}
/>
);
})
}
</TableBody>
</Table>
<Table
columns={columns}
>
<TableBody>
{
items.map((item) => {
return (
<QueuedTaskRowConnector
key={item.id}
{...item}
/>
);
})
}
</TableBody>
</Table>
}
</FieldSet>
);

View File

@@ -49,27 +49,27 @@ function ScheduledTasks(props) {
<FieldSet legend="Scheduled">
{
isFetching && !isPopulated &&
<LoadingIndicator />
<LoadingIndicator />
}
{
isPopulated &&
<Table
columns={columns}
>
<TableBody>
{
items.map((item) => {
return (
<ScheduledTaskRowConnector
key={item.id}
{...item}
/>
);
})
}
</TableBody>
</Table>
<Table
columns={columns}
>
<TableBody>
{
items.map((item) => {
return (
<ScheduledTaskRowConnector
key={item.id}
{...item}
/>
);
})
}
</TableBody>
</Table>
}
</FieldSet>
);

View File

@@ -79,6 +79,5 @@
</body>
<script src="/initialize.js" data-no-hash></script>
<script src="/polyfills.js"></script>
<!-- webpack bundles body -->
</html>

View File

@@ -1,4 +1,6 @@
import './preload.js';
import './preload';
import './polyfills';
import React from 'react';
import { render } from 'react-dom';
import { createBrowserHistory } from 'history';