mirror of
https://github.com/lidarr/lidarr.git
synced 2025-08-13 02:07:12 -07:00
New: Bulk Manage Applications, Download Clients
Co-authored-by: Qstick <qstick@gmail.com>
This commit is contained in:
parent
834d334ca6
commit
77c1a42da1
109 changed files with 3588 additions and 189 deletions
|
@ -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(
|
||||
|
@ -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
|
||||
};
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
.tag {
|
||||
display: flex;
|
||||
|
||||
&.isLastTag {
|
||||
.or {
|
||||
display: none;
|
||||
|
|
|
@ -6,7 +6,7 @@ import styles from './FilterBuilderRowValueTag.css';
|
|||
|
||||
function FilterBuilderRowValueTag(props) {
|
||||
return (
|
||||
<span
|
||||
<div
|
||||
className={styles.tag}
|
||||
>
|
||||
<TagInputTag
|
||||
|
@ -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>
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -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 AlbumReleaseSelectInputConnector from './AlbumReleaseSelectInputConnector';
|
||||
import AutoCompleteInput from './AutoCompleteInput';
|
||||
|
@ -273,16 +273,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 = {
|
||||
|
|
|
@ -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}
|
||||
|
@ -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 = {
|
||||
|
|
|
@ -6,6 +6,7 @@ import { createSelector } from 'reselect';
|
|||
import { metadataProfileNames } from 'Helpers/Props';
|
||||
import createSortedSectionSelector from 'Store/Selectors/createSortedSectionSelector';
|
||||
import sortByName from 'Utilities/Array/sortByName';
|
||||
import translate from 'Utilities/String/translate';
|
||||
import SelectInput from './SelectInput';
|
||||
|
||||
function createMapStateToProps() {
|
||||
|
@ -36,7 +37,7 @@ function createMapStateToProps() {
|
|||
if (includeNoChange) {
|
||||
values.unshift({
|
||||
key: 'noChange',
|
||||
value: 'No Change',
|
||||
value: translate('NoChange'),
|
||||
disabled: true
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import PropTypes from 'prop-types';
|
||||
import React from 'react';
|
||||
import monitorOptions from 'Utilities/Artist/monitorOptions';
|
||||
import translate from 'Utilities/String/translate';
|
||||
import SelectInput from './SelectInput';
|
||||
|
||||
function MonitorAlbumsSelectInput(props) {
|
||||
|
@ -15,7 +16,7 @@ function MonitorAlbumsSelectInput(props) {
|
|||
if (includeNoChange) {
|
||||
values.unshift({
|
||||
key: 'noChange',
|
||||
value: 'No Change',
|
||||
value: translate('NoChange'),
|
||||
disabled: true
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import PropTypes from 'prop-types';
|
||||
import React from 'react';
|
||||
import monitorNewItemsOptions from 'Utilities/Artist/monitorNewItemsOptions';
|
||||
import translate from 'Utilities/String/translate';
|
||||
import SelectInput from './SelectInput';
|
||||
|
||||
function MonitorNewItemsSelectInput(props) {
|
||||
|
@ -15,7 +16,7 @@ function MonitorNewItemsSelectInput(props) {
|
|||
if (includeNoChange) {
|
||||
values.unshift({
|
||||
key: 'noChange',
|
||||
value: 'No Change',
|
||||
value: translate('NoChange'),
|
||||
disabled: true
|
||||
});
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@ function parseValue(props, value) {
|
|||
} = props;
|
||||
|
||||
if (value == null || value === '') {
|
||||
return min;
|
||||
return null;
|
||||
}
|
||||
|
||||
let newValue = isFloat ? parseFloat(value) : parseInt(value);
|
||||
|
|
|
@ -5,6 +5,7 @@ import { connect } from 'react-redux';
|
|||
import { createSelector } from 'reselect';
|
||||
import createSortedSectionSelector from 'Store/Selectors/createSortedSectionSelector';
|
||||
import sortByName from 'Utilities/Array/sortByName';
|
||||
import translate from 'Utilities/String/translate';
|
||||
import SelectInput from './SelectInput';
|
||||
|
||||
function createMapStateToProps() {
|
||||
|
@ -23,7 +24,7 @@ function createMapStateToProps() {
|
|||
if (includeNoChange) {
|
||||
values.unshift({
|
||||
key: 'noChange',
|
||||
value: 'No Change',
|
||||
value: translate('NoChange'),
|
||||
disabled: true
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import PropTypes from 'prop-types';
|
||||
import React from 'react';
|
||||
import translate from 'Utilities/String/translate';
|
||||
import SelectInput from './SelectInput';
|
||||
|
||||
const artistTypeOptions = [
|
||||
|
@ -19,7 +20,7 @@ function SeriesTypeSelectInput(props) {
|
|||
if (includeNoChange) {
|
||||
values.unshift({
|
||||
key: 'noChange',
|
||||
value: 'No Change',
|
||||
value: translate('NoChange'),
|
||||
disabled: true
|
||||
});
|
||||
}
|
||||
|
|
|
@ -75,6 +75,18 @@ class TagInput extends Component {
|
|||
//
|
||||
// Listeners
|
||||
|
||||
onTagEdit = ({ value, ...otherProps }) => {
|
||||
const currentValue = this.state.value;
|
||||
|
||||
if (currentValue && this.props.onTagReplace) {
|
||||
this.props.onTagReplace(otherProps, { name: currentValue });
|
||||
} else {
|
||||
this.props.onTagDelete(otherProps);
|
||||
}
|
||||
|
||||
this.setState({ value });
|
||||
};
|
||||
|
||||
onInputContainerPress = () => {
|
||||
this._autosuggestRef.input.focus();
|
||||
};
|
||||
|
@ -188,6 +200,7 @@ class TagInput extends Component {
|
|||
const {
|
||||
tags,
|
||||
kind,
|
||||
canEdit,
|
||||
tagComponent,
|
||||
onTagDelete
|
||||
} = this.props;
|
||||
|
@ -199,8 +212,10 @@ class TagInput extends Component {
|
|||
kind={kind}
|
||||
inputProps={inputProps}
|
||||
isFocused={this.state.isFocused}
|
||||
canEdit={canEdit}
|
||||
tagComponent={tagComponent}
|
||||
onTagDelete={onTagDelete}
|
||||
onTagEdit={this.onTagEdit}
|
||||
onInputContainerPress={this.onInputContainerPress}
|
||||
/>
|
||||
);
|
||||
|
@ -225,7 +240,7 @@ class TagInput extends Component {
|
|||
<AutoSuggestInput
|
||||
{...otherProps}
|
||||
forwardedRef={this._setAutosuggestRef}
|
||||
className={styles.internalInput}
|
||||
className={className}
|
||||
inputContainerClassName={classNames(
|
||||
inputContainerClassName,
|
||||
isFocused && styles.isFocused,
|
||||
|
@ -262,11 +277,13 @@ TagInput.propTypes = {
|
|||
placeholder: PropTypes.string.isRequired,
|
||||
delimiters: PropTypes.arrayOf(PropTypes.string).isRequired,
|
||||
minQueryLength: PropTypes.number.isRequired,
|
||||
canEdit: PropTypes.bool,
|
||||
hasError: PropTypes.bool,
|
||||
hasWarning: PropTypes.bool,
|
||||
tagComponent: PropTypes.elementType.isRequired,
|
||||
onTagAdd: PropTypes.func.isRequired,
|
||||
onTagDelete: PropTypes.func.isRequired
|
||||
onTagDelete: PropTypes.func.isRequired,
|
||||
onTagReplace: PropTypes.func
|
||||
};
|
||||
|
||||
TagInput.defaultProps = {
|
||||
|
@ -277,6 +294,7 @@ TagInput.defaultProps = {
|
|||
placeholder: '',
|
||||
delimiters: ['Tab', 'Enter', ' ', ','],
|
||||
minQueryLength: 1,
|
||||
canEdit: false,
|
||||
tagComponent: TagInputTag
|
||||
};
|
||||
|
||||
|
|
|
@ -138,6 +138,7 @@ class TagInputConnector extends Component {
|
|||
<TagInput
|
||||
onTagAdd={this.onTagAdd}
|
||||
onTagDelete={this.onTagDelete}
|
||||
onTagReplace={this.onTagReplace}
|
||||
{...this.props}
|
||||
/>
|
||||
);
|
||||
|
|
|
@ -28,8 +28,10 @@ class TagInputInput extends Component {
|
|||
tags,
|
||||
inputProps,
|
||||
kind,
|
||||
canEdit,
|
||||
tagComponent: TagComponent,
|
||||
onTagDelete
|
||||
onTagDelete,
|
||||
onTagEdit
|
||||
} = this.props;
|
||||
|
||||
return (
|
||||
|
@ -46,8 +48,10 @@ class TagInputInput extends Component {
|
|||
index={index}
|
||||
tag={tag}
|
||||
kind={kind}
|
||||
canEdit={canEdit}
|
||||
isLastTag={index === tags.length - 1}
|
||||
onDelete={onTagDelete}
|
||||
onEdit={onTagEdit}
|
||||
/>
|
||||
);
|
||||
})
|
||||
|
@ -66,8 +70,10 @@ TagInputInput.propTypes = {
|
|||
inputProps: PropTypes.object.isRequired,
|
||||
kind: PropTypes.oneOf(kinds.all).isRequired,
|
||||
isFocused: PropTypes.bool.isRequired,
|
||||
canEdit: PropTypes.bool.isRequired,
|
||||
tagComponent: PropTypes.elementType.isRequired,
|
||||
onTagDelete: PropTypes.func.isRequired,
|
||||
onTagEdit: PropTypes.func.isRequired,
|
||||
onInputContainerPress: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import MiddleTruncate from 'react-middle-truncate';
|
||||
import Label from 'Components/Label';
|
||||
import IconButton from 'Components/Link/IconButton';
|
||||
import Link from 'Components/Link/Link';
|
||||
|
@ -49,6 +48,7 @@ class TagInputTag extends Component {
|
|||
kind,
|
||||
canEdit
|
||||
} = this.props;
|
||||
|
||||
return (
|
||||
<div
|
||||
className={styles.tag}
|
||||
|
@ -63,11 +63,7 @@ class TagInputTag extends Component {
|
|||
tabIndex={-1}
|
||||
onPress={this.onDelete}
|
||||
>
|
||||
<MiddleTruncate
|
||||
text={tag.name}
|
||||
start={10}
|
||||
end={10}
|
||||
/>
|
||||
{tag.name}
|
||||
</Link>
|
||||
|
||||
{
|
||||
|
|
|
@ -31,6 +31,7 @@ function Label(props) {
|
|||
|
||||
Label.propTypes = {
|
||||
className: PropTypes.string.isRequired,
|
||||
title: PropTypes.string,
|
||||
kind: PropTypes.oneOf(kinds.all).isRequired,
|
||||
size: PropTypes.oneOf(sizes.all).isRequired,
|
||||
outline: PropTypes.bool.isRequired,
|
||||
|
|
|
@ -39,11 +39,13 @@ function IconButton(props) {
|
|||
}
|
||||
|
||||
IconButton.propTypes = {
|
||||
...Link.propTypes,
|
||||
className: PropTypes.string.isRequired,
|
||||
iconClassName: PropTypes.string,
|
||||
kind: PropTypes.string,
|
||||
name: PropTypes.object.isRequired,
|
||||
size: PropTypes.number,
|
||||
title: PropTypes.string,
|
||||
isSpinning: PropTypes.bool,
|
||||
isDisabled: PropTypes.bool
|
||||
};
|
||||
|
|
|
@ -1,110 +0,0 @@
|
|||
import classNames from 'classnames';
|
||||
import PropTypes from 'prop-types';
|
||||
import React, { Component } from 'react';
|
||||
import { Link as RouterLink } from 'react-router-dom';
|
||||
import styles from './Link.css';
|
||||
|
||||
class Link extends Component {
|
||||
|
||||
//
|
||||
// Listeners
|
||||
|
||||
onClick = (event) => {
|
||||
const {
|
||||
isDisabled,
|
||||
onPress
|
||||
} = this.props;
|
||||
|
||||
if (!isDisabled && onPress) {
|
||||
onPress(event);
|
||||
}
|
||||
};
|
||||
|
||||
//
|
||||
// Render
|
||||
|
||||
render() {
|
||||
const {
|
||||
className,
|
||||
component,
|
||||
to,
|
||||
target,
|
||||
isDisabled,
|
||||
noRouter,
|
||||
onPress,
|
||||
...otherProps
|
||||
} = this.props;
|
||||
|
||||
const linkProps = { target };
|
||||
let el = component;
|
||||
|
||||
if (to && typeof to === 'string') {
|
||||
if ((/\w+?:\/\//).test(to)) {
|
||||
el = 'a';
|
||||
linkProps.href = to;
|
||||
linkProps.target = target || '_blank';
|
||||
linkProps.rel = 'noreferrer';
|
||||
} else if (noRouter) {
|
||||
el = 'a';
|
||||
linkProps.href = to;
|
||||
linkProps.target = target || '_self';
|
||||
} else {
|
||||
el = RouterLink;
|
||||
linkProps.to = `${window.Lidarr.urlBase}/${to.replace(/^\//, '')}`;
|
||||
linkProps.target = target;
|
||||
}
|
||||
} else if (to && typeof to === 'object') {
|
||||
el = RouterLink;
|
||||
linkProps.target = target;
|
||||
if (to.pathname.startsWith(`${window.Lidarr.urlBase}/`)) {
|
||||
linkProps.to = to;
|
||||
} else {
|
||||
const pathname = `${window.Lidarr.urlBase}/${to.pathname.replace(/^\//, '')}`;
|
||||
linkProps.to = {
|
||||
...to,
|
||||
pathname
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
if (el === 'button' || el === 'input') {
|
||||
linkProps.type = otherProps.type || 'button';
|
||||
linkProps.disabled = isDisabled;
|
||||
}
|
||||
|
||||
linkProps.className = classNames(
|
||||
className,
|
||||
styles.link,
|
||||
to && styles.to,
|
||||
isDisabled && 'isDisabled'
|
||||
);
|
||||
|
||||
const props = {
|
||||
...otherProps,
|
||||
...linkProps
|
||||
};
|
||||
|
||||
props.onClick = this.onClick;
|
||||
|
||||
return (
|
||||
React.createElement(el, props)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Link.propTypes = {
|
||||
className: PropTypes.string,
|
||||
component: PropTypes.oneOfType([PropTypes.string, PropTypes.func]),
|
||||
to: PropTypes.oneOfType([PropTypes.string, PropTypes.object]),
|
||||
target: PropTypes.string,
|
||||
isDisabled: PropTypes.bool,
|
||||
noRouter: PropTypes.bool,
|
||||
onPress: PropTypes.func
|
||||
};
|
||||
|
||||
Link.defaultProps = {
|
||||
component: 'button',
|
||||
noRouter: false
|
||||
};
|
||||
|
||||
export default Link;
|
96
frontend/src/Components/Link/Link.tsx
Normal file
96
frontend/src/Components/Link/Link.tsx
Normal file
|
@ -0,0 +1,96 @@
|
|||
import classNames from 'classnames';
|
||||
import React, {
|
||||
ComponentClass,
|
||||
FunctionComponent,
|
||||
SyntheticEvent,
|
||||
useCallback,
|
||||
} from 'react';
|
||||
import { Link as RouterLink } from 'react-router-dom';
|
||||
import styles from './Link.css';
|
||||
|
||||
interface ReactRouterLinkProps {
|
||||
to?: string;
|
||||
}
|
||||
|
||||
export interface LinkProps extends React.HTMLProps<HTMLAnchorElement> {
|
||||
className?: string;
|
||||
component?:
|
||||
| string
|
||||
| FunctionComponent<LinkProps>
|
||||
| ComponentClass<LinkProps, unknown>;
|
||||
to?: string;
|
||||
target?: string;
|
||||
isDisabled?: boolean;
|
||||
noRouter?: boolean;
|
||||
onPress?(event: SyntheticEvent): void;
|
||||
}
|
||||
function Link(props: LinkProps) {
|
||||
const {
|
||||
className,
|
||||
component = 'button',
|
||||
to,
|
||||
target,
|
||||
type,
|
||||
isDisabled,
|
||||
noRouter = false,
|
||||
onPress,
|
||||
...otherProps
|
||||
} = props;
|
||||
|
||||
const onClick = useCallback(
|
||||
(event: SyntheticEvent) => {
|
||||
if (!isDisabled && onPress) {
|
||||
onPress(event);
|
||||
}
|
||||
},
|
||||
[isDisabled, onPress]
|
||||
);
|
||||
|
||||
const linkProps: React.HTMLProps<HTMLAnchorElement> & ReactRouterLinkProps = {
|
||||
target,
|
||||
};
|
||||
let el = component;
|
||||
|
||||
if (to) {
|
||||
if (/\w+?:\/\//.test(to)) {
|
||||
el = 'a';
|
||||
linkProps.href = to;
|
||||
linkProps.target = target || '_blank';
|
||||
linkProps.rel = 'noreferrer';
|
||||
} else if (noRouter) {
|
||||
el = 'a';
|
||||
linkProps.href = to;
|
||||
linkProps.target = target || '_self';
|
||||
} else {
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
el = RouterLink;
|
||||
linkProps.to = `${window.Lidarr.urlBase}/${to.replace(/^\//, '')}`;
|
||||
linkProps.target = target;
|
||||
}
|
||||
}
|
||||
|
||||
if (el === 'button' || el === 'input') {
|
||||
linkProps.type = type || 'button';
|
||||
linkProps.disabled = isDisabled;
|
||||
}
|
||||
|
||||
linkProps.className = classNames(
|
||||
className,
|
||||
styles.link,
|
||||
to && styles.to,
|
||||
isDisabled && 'isDisabled'
|
||||
);
|
||||
|
||||
const elementProps = {
|
||||
...otherProps,
|
||||
type,
|
||||
...linkProps,
|
||||
};
|
||||
|
||||
elementProps.onClick = onClick;
|
||||
|
||||
return React.createElement(el, elementProps);
|
||||
}
|
||||
|
||||
export default Link;
|
|
@ -42,6 +42,7 @@ function SpinnerButton(props) {
|
|||
}
|
||||
|
||||
SpinnerButton.propTypes = {
|
||||
...Button.Props,
|
||||
className: PropTypes.string.isRequired,
|
||||
isSpinning: PropTypes.bool.isRequired,
|
||||
isDisabled: PropTypes.bool,
|
||||
|
|
|
@ -53,10 +53,7 @@ class PageHeader extends Component {
|
|||
<div className={styles.logoContainer}>
|
||||
<Link
|
||||
className={styles.logoLink}
|
||||
to={{
|
||||
pathname: '/',
|
||||
state: { restoreScrollPosition: true }
|
||||
}}
|
||||
to={'/'}
|
||||
>
|
||||
<img
|
||||
className={styles.logo}
|
||||
|
|
12
frontend/src/Components/Table/Column.ts
Normal file
12
frontend/src/Components/Table/Column.ts
Normal file
|
@ -0,0 +1,12 @@
|
|||
import React from 'react';
|
||||
|
||||
interface Column {
|
||||
name: string;
|
||||
label: string | React.ReactNode;
|
||||
columnLabel?: string;
|
||||
isSortable?: boolean;
|
||||
isVisible: boolean;
|
||||
isModifiable?: boolean;
|
||||
}
|
||||
|
||||
export default Column;
|
|
@ -52,6 +52,7 @@ function Table(props) {
|
|||
scrollDirections.HORIZONTAL :
|
||||
scrollDirections.NONE
|
||||
}
|
||||
autoFocus={false}
|
||||
>
|
||||
<table className={className}>
|
||||
<TableHeader>
|
||||
|
@ -120,6 +121,7 @@ function Table(props) {
|
|||
}
|
||||
|
||||
Table.propTypes = {
|
||||
...TableHeaderCell.props,
|
||||
className: PropTypes.string,
|
||||
horizontalScroll: PropTypes.bool.isRequired,
|
||||
selectAll: PropTypes.bool.isRequired,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue