Skip to content

Commit

Permalink
New: Bulk Manage Applications, Download Clients
Browse files Browse the repository at this point in the history
Co-authored-by: Qstick <qstick@gmail.com>
  • Loading branch information
mynameisbogdan and Qstick committed Jul 17, 2023
1 parent f7c135f commit f436d73
Show file tree
Hide file tree
Showing 123 changed files with 4,076 additions and 223 deletions.
5 changes: 5 additions & 0 deletions frontend/src/App/ModelBase.ts
@@ -0,0 +1,5 @@
interface ModelBase {
id: number;
}

export default ModelBase;
48 changes: 48 additions & 0 deletions frontend/src/App/State/AppSectionState.ts
@@ -0,0 +1,48 @@
import SortDirection from 'Helpers/Props/SortDirection';

export interface Error {
responseJSON: {
message: string;
};
}

export interface AppSectionDeleteState {
isDeleting: boolean;
deleteError: Error;
}

export interface AppSectionSaveState {
isSaving: boolean;
saveError: Error;
}

export interface PagedAppSectionState {
pageSize: number;
}

export interface AppSectionSchemaState<T> {
isSchemaFetching: boolean;
isSchemaPopulated: boolean;
schemaError: Error;
schema: {
items: T[];
};
}

export interface AppSectionItemState<T> {
isFetching: boolean;
isPopulated: boolean;
error: Error;
item: T;
}

interface AppSectionState<T> {
isFetching: boolean;
isPopulated: boolean;
error: Error;
items: T[];
sortKey: string;
sortDirection: SortDirection;
}

export default AppSectionState;
41 changes: 41 additions & 0 deletions frontend/src/App/State/AppState.ts
@@ -0,0 +1,41 @@
import SettingsAppState from './SettingsAppState';
import TagsAppState from './TagsAppState';

interface FilterBuilderPropOption {
id: string;
name: string;
}

export interface FilterBuilderProp<T> {
name: string;
label: string;
type: string;
valueType?: string;
optionsSelector?: (items: T[]) => FilterBuilderPropOption[];
}

export interface PropertyFilter {
key: string;
value: boolean | string | number | string[] | number[];
type: string;
}

export interface Filter {
key: string;
label: string;
filers: PropertyFilter[];
}

export interface CustomFilter {
id: number;
type: string;
label: string;
filers: PropertyFilter[];
}

interface AppState {
settings: SettingsAppState;
tags: TagsAppState;
}

export default AppState;
40 changes: 40 additions & 0 deletions frontend/src/App/State/SettingsAppState.ts
@@ -0,0 +1,40 @@
import AppSectionState, {
AppSectionDeleteState,
AppSectionSaveState,
} from 'App/State/AppSectionState';
import DownloadClient from 'typings/DownloadClient';
import ImportList from 'typings/ImportList';
import Indexer from 'typings/Indexer';
import Notification from 'typings/Notification';
import { UiSettings } from 'typings/UiSettings';

export interface DownloadClientAppState
extends AppSectionState<DownloadClient>,
AppSectionDeleteState,
AppSectionSaveState {}

export interface ImportListAppState
extends AppSectionState<ImportList>,
AppSectionDeleteState,
AppSectionSaveState {}

export interface IndexerAppState
extends AppSectionState<Indexer>,
AppSectionDeleteState,
AppSectionSaveState {}

export interface NotificationAppState
extends AppSectionState<Notification>,
AppSectionDeleteState {}

export type UiSettingsAppState = AppSectionState<UiSettings>;

interface SettingsAppState {
downloadClients: DownloadClientAppState;
importLists: ImportListAppState;
indexers: IndexerAppState;
notifications: NotificationAppState;
uiSettings: UiSettingsAppState;
}

export default SettingsAppState;
12 changes: 12 additions & 0 deletions frontend/src/App/State/TagsAppState.ts
@@ -0,0 +1,12 @@
import ModelBase from 'App/ModelBase';
import AppSectionState, {
AppSectionDeleteState,
} from 'App/State/AppSectionState';

export interface Tag extends ModelBase {
label: string;
}

interface TagsAppState extends AppSectionState<Tag>, AppSectionDeleteState {}

export default TagsAppState;
5 changes: 1 addition & 4 deletions frontend/src/Author/Details/AuthorDetails.js
Expand Up @@ -392,10 +392,7 @@ class AuthorDetails extends Component {
name={icons.ARROW_UP}
size={30}
title={translate('GoToAuthorListing')}
to={{
pathname: '/',
state: { restoreScrollPosition: true }
}}
to={'/'}
/>

<IconButton
Expand Down
6 changes: 3 additions & 3 deletions frontend/src/Author/Editor/AuthorEditorFooter.js
Expand Up @@ -160,9 +160,9 @@ class AuthorEditorFooter extends Component {
} = this.state;

const monitoredOptions = [
{ key: NO_CHANGE, value: 'No Change', disabled: true },
{ key: 'monitored', value: 'Monitored' },
{ key: 'unmonitored', value: 'Unmonitored' }
{ key: NO_CHANGE, value: translate('NoChange'), disabled: true },
{ key: 'monitored', value: translate('Monitored') },
{ key: 'unmonitored', value: translate('Unmonitored') }
];

return (
Expand Down
6 changes: 3 additions & 3 deletions frontend/src/Book/Editor/BookEditorFooter.js
Expand Up @@ -89,9 +89,9 @@ class BookEditorFooter extends Component {
} = this.state;

const monitoredOptions = [
{ key: NO_CHANGE, value: 'No Change', disabled: true },
{ key: 'monitored', value: 'Monitored' },
{ key: 'unmonitored', value: 'Unmonitored' }
{ key: NO_CHANGE, value: translate('NoChange'), disabled: true },
{ key: 'monitored', value: translate('Monitored') },
{ key: 'unmonitored', value: translate('Unmonitored') }
];

return (
Expand Down
6 changes: 3 additions & 3 deletions frontend/src/Bookshelf/BookshelfFooter.js
Expand Up @@ -88,9 +88,9 @@ class BookshelfFooter extends Component {
} = this.state;

const monitoredOptions = [
{ key: NO_CHANGE, value: 'No Change', disabled: true },
{ key: 'monitored', value: 'Monitored' },
{ key: 'unmonitored', value: 'Unmonitored' }
{ key: NO_CHANGE, value: translate('NoChange'), disabled: true },
{ key: 'monitored', value: translate('Monitored') },
{ key: 'unmonitored', value: translate('Unmonitored') }
];

const noChanges = monitored === NO_CHANGE &&
Expand Down
8 changes: 5 additions & 3 deletions frontend/src/Components/Alert.js
Expand Up @@ -4,7 +4,9 @@ import React from 'react';
import { kinds } from 'Helpers/Props';
import styles from './Alert.css';

function Alert({ className, kind, children, ...otherProps }) {
function Alert(props) {
const { className, kind, children, ...otherProps } = props;

return (
<div
className={classNames(
Expand All @@ -19,8 +21,8 @@ function Alert({ className, kind, children, ...otherProps }) {
}

Alert.propTypes = {
className: PropTypes.string.isRequired,
kind: PropTypes.oneOf(kinds.all).isRequired,
className: PropTypes.string,
kind: PropTypes.oneOf(kinds.all),
children: PropTypes.node.isRequired
};

Expand Down
2 changes: 1 addition & 1 deletion frontend/src/Components/Filter/Builder/FilterBuilderRow.js
Expand Up @@ -210,7 +210,7 @@ class FilterBuilderRow extends Component {
key: availablePropFilter.name,
value: availablePropFilter.label
};
});
}).sort((a, b) => a.value.localeCompare(b.value));

const ValueComponent = getRowValueConnector(selectedFilterBuilderProp);

Expand Down
@@ -1,4 +1,6 @@
.tag {
display: flex;

&.isLastTag {
.or {
display: none;
Expand Down
Expand Up @@ -6,7 +6,7 @@ import styles from './FilterBuilderRowValueTag.css';

function FilterBuilderRowValueTag(props) {
return (
<span
<div
className={styles.tag}
>
<TagInputTag
Expand All @@ -15,12 +15,13 @@ function FilterBuilderRowValueTag(props) {
/>

{
!props.isLastTag &&
<span className={styles.or}>
props.isLastTag ?
null :
<div className={styles.or}>
or
</span>
</div>
}
</span>
</div>
);
}

Expand Down
1 change: 1 addition & 0 deletions frontend/src/Components/Form/EnhancedSelectInput.css
Expand Up @@ -59,6 +59,7 @@
display: flex;
justify-content: center;
max-width: 90%;
max-height: 100%;
width: 350px !important;
height: auto !important;
}
Expand Down
15 changes: 13 additions & 2 deletions frontend/src/Components/Form/FormInputGroup.js
@@ -1,7 +1,7 @@
import PropTypes from 'prop-types';
import React from 'react';
import Link from 'Components/Link/Link';
import { inputTypes } from 'Helpers/Props';
import { inputTypes, kinds } from 'Helpers/Props';
import translate from 'Utilities/String/translate';
// import translate from 'Utilities/String/translate';
import AutoCompleteInput from './AutoCompleteInput';
Expand Down Expand Up @@ -270,16 +270,27 @@ FormInputGroup.propTypes = {
className: PropTypes.string.isRequired,
containerClassName: PropTypes.string.isRequired,
inputClassName: PropTypes.string,
name: PropTypes.string.isRequired,
value: PropTypes.any,
values: PropTypes.arrayOf(PropTypes.any),
type: PropTypes.string.isRequired,
kind: PropTypes.oneOf(kinds.all),
min: PropTypes.number,
max: PropTypes.number,
unit: PropTypes.string,
buttons: PropTypes.oneOfType([PropTypes.node, PropTypes.arrayOf(PropTypes.node)]),
helpText: PropTypes.string,
helpTexts: PropTypes.arrayOf(PropTypes.string),
helpTextWarning: PropTypes.string,
helpLink: PropTypes.string,
autoFocus: PropTypes.bool,
includeNoChange: PropTypes.bool,
includeNoChangeDisabled: PropTypes.bool,
selectedValueOptions: PropTypes.object,
pending: PropTypes.bool,
errors: PropTypes.arrayOf(PropTypes.object),
warnings: PropTypes.arrayOf(PropTypes.object)
warnings: PropTypes.arrayOf(PropTypes.object),
onChange: PropTypes.func.isRequired
};

FormInputGroup.defaultProps = {
Expand Down
26 changes: 14 additions & 12 deletions frontend/src/Components/Form/FormLabel.js
Expand Up @@ -4,16 +4,18 @@ import React from 'react';
import { sizes } from 'Helpers/Props';
import styles from './FormLabel.css';

function FormLabel({
children,
className,
errorClassName,
size,
name,
hasError,
isAdvanced,
...otherProps
}) {
function FormLabel(props) {
const {
children,
className,
errorClassName,
size,
name,
hasError,
isAdvanced,
...otherProps
} = props;

return (
<label
{...otherProps}
Expand All @@ -31,13 +33,13 @@ function FormLabel({
}

FormLabel.propTypes = {
children: PropTypes.node.isRequired,
children: PropTypes.oneOfType([PropTypes.node, PropTypes.string]).isRequired,
className: PropTypes.string,
errorClassName: PropTypes.string,
size: PropTypes.oneOf(sizes.all),
name: PropTypes.string,
hasError: PropTypes.bool,
isAdvanced: PropTypes.bool.isRequired
isAdvanced: PropTypes.bool
};

FormLabel.defaultProps = {
Expand Down

0 comments on commit f436d73

Please sign in to comment.