Commit 76e213e1 by Vladislav Lagunov

Добавлена ссылка Загрузить еще

parent 0c437340
...@@ -16,6 +16,7 @@ import memoize from '~/functions/memoize'; ...@@ -16,6 +16,7 @@ import memoize from '~/functions/memoize';
import { pick } from 'lodash'; import { pick } from 'lodash';
import classNames = require('classnames'); import classNames = require('classnames');
import { withGettext, Gettext } from '~/gettext'; import { withGettext, Gettext } from '~/gettext';
import { fade } from '@material-ui/core/styles/colorManipulator';
// Props // Props
...@@ -58,11 +59,14 @@ export default class AutoComplete<A=string> extends React.Component<Props<A> & { ...@@ -58,11 +59,14 @@ export default class AutoComplete<A=string> extends React.Component<Props<A> & {
fullWidth: true, fullWidth: true,
printItem: x => x ? String(x) : '', printItem: x => x ? String(x) : '',
} as any; } as any;
state: State<A> = { ...ST.init(), value: null }; state: State<A> = { ...ST.init(), value: null };
anchorEl: HTMLElement|null; // Ссылка на <input/> anchorEl: HTMLElement|null; // Ссылка на <input/>
rectEl: HTMLElement|null; // Ссылка на элемент для выравнивания, может быть тем же что и `inputEl` rectEl: HTMLElement|null; // Ссылка на элемент для выравнивания, может быть тем же что и `inputEl`
debounceTimer: number|null = null; debounceTimer: number|null = null;
subscription: Rx.Subscription|null = null; subscription: Rx.Subscription|null = null;
paperPrevScroll: number|null = null;
paperEl: HTMLDivElement|null = null;
// Выполнение действий из ST // Выполнение действий из ST
dispatch = (action: ST.Action<A>) => { dispatch = (action: ST.Action<A>) => {
...@@ -146,6 +150,14 @@ export default class AutoComplete<A=string> extends React.Component<Props<A> & { ...@@ -146,6 +150,14 @@ export default class AutoComplete<A=string> extends React.Component<Props<A> & {
this.anchorEl = ReactDOM.findDOMNode(this) as HTMLElement;; this.anchorEl = ReactDOM.findDOMNode(this) as HTMLElement;;
} }
componentDidUpdate() {
if (this.paperEl && this.paperPrevScroll && this.paperEl.scrollTop !== this.paperPrevScroll) {
this.paperEl.scrollTo(0, this.paperPrevScroll);
this.paperEl = null;
this.paperPrevScroll = null;
}
}
componentWillReceiveProps(nextProps: Props<A>) { componentWillReceiveProps(nextProps: Props<A>) {
if (nextProps.observable !== this.props.observable) this.listen(nextProps); if (nextProps.observable !== this.props.observable) this.listen(nextProps);
} }
...@@ -186,12 +198,25 @@ export default class AutoComplete<A=string> extends React.Component<Props<A> & { ...@@ -186,12 +198,25 @@ export default class AutoComplete<A=string> extends React.Component<Props<A> & {
}; };
}; };
handleSeeMore = (e: React.MouseEvent) => { handleSeeMore = (e: React.MouseEvent<HTMLAnchorElement>) => {
e.preventDefault(); e.preventDefault();
e.stopPropagation(); e.stopPropagation();
// const { query: { offset, limit } } = this.state; // const { query: { offset, limit } } = this.state;
this.paperEl = e.currentTarget.parentElement!.parentElement! as HTMLDivElement;
this.paperPrevScroll = this.paperEl.scrollTop;
this.dispatch({ tag: 'More' }); this.dispatch({ tag: 'More' });
}; };
renderSeeMoreLink() {
const { __, classes } = this.props;
const { total, query: { limit, offset } } = this.state;
if (total !== 0 && limit + offset >= total) return null;
return <ListItem className={classes!.seeMore}>
<a href="javascript://void 0" onMouseDown={this.handleSeeMore}>{__('See more')}</a>
</ListItem>;
}
render() { render() {
const { className, fullWidth, children, ctx, source, debounce, renderItem, printItem, openOnFocus, openOnClick, suggestionProps, keepOpenAfterSelect, textFieldProps, classes, anchorEl, observable, ...rest } = this.props; const { className, fullWidth, children, ctx, source, debounce, renderItem, printItem, openOnFocus, openOnClick, suggestionProps, keepOpenAfterSelect, textFieldProps, classes, anchorEl, observable, ...rest } = this.props;
...@@ -200,9 +225,6 @@ export default class AutoComplete<A=string> extends React.Component<Props<A> & { ...@@ -200,9 +225,6 @@ export default class AutoComplete<A=string> extends React.Component<Props<A> & {
[classes!.fullWidth!]: fullWidth [classes!.fullWidth!]: fullWidth
}); });
const seeMoreLink = <ListItem>
<a href={"#"} onMouseDown={this.handleSeeMore}>{('See more')}</a>
</ListItem>;
return <div {...rest} className={rootClass}> return <div {...rest} className={rootClass}>
{!observable && (children ? React.cloneElement(children, this.childrenProps()) : <TextField {...this.childrenProps() as any} {...textFieldProps}/>)} {!observable && (children ? React.cloneElement(children, this.childrenProps()) : <TextField {...this.childrenProps() as any} {...textFieldProps}/>)}
...@@ -216,7 +238,7 @@ export default class AutoComplete<A=string> extends React.Component<Props<A> & { ...@@ -216,7 +238,7 @@ export default class AutoComplete<A=string> extends React.Component<Props<A> & {
renderSuggestion={renderItem || printItem} renderSuggestion={renderItem || printItem}
onSelect={this.handleSuggestionSelect} onSelect={this.handleSuggestionSelect}
onVisibilityChange={this.handleVisibilityChnage} onVisibilityChange={this.handleVisibilityChnage}
after={seeMoreLink} after={this.renderSeeMoreLink()}
/> />
</div>; </div>;
} }
...@@ -283,10 +305,20 @@ export class CreateObservable extends React.Component<CreateObservableProps> { ...@@ -283,10 +305,20 @@ export class CreateObservable extends React.Component<CreateObservableProps> {
// Style // Style
export function styles(theme: Theme): StyleRules { export function styles(theme: Theme): StyleRules {
// const { unit } = theme.spacing; const { unit } = theme.spacing;
const linkStyles = {
color: theme.palette.primary.main,
textDecoration: 'none',
'&:hover': {
color: fade(theme.palette.primary.main, 0.75),
},
'&:active': {
color: theme.palette.error.main,
},
};
return { return {
root: { root: {
'& > div': { '& > div': {
position: 'relative', position: 'relative',
} }
...@@ -295,5 +327,16 @@ export function styles(theme: Theme): StyleRules { ...@@ -295,5 +327,16 @@ export function styles(theme: Theme): StyleRules {
fullWidth: { fullWidth: {
width: '100%', width: '100%',
}, },
seeMore: {
marginBottom: -unit,
'& a': {
display: 'block',
width: '100%',
height: '100%',
textAlign: 'center',
...linkStyles,
},
},
}; };
} }
...@@ -122,7 +122,7 @@ export function update<A>(ctx: Ctx<A>, action: Action<A>, state: State<A>): [Sta ...@@ -122,7 +122,7 @@ export function update<A>(ctx: Ctx<A>, action: Action<A>, state: State<A>): [Sta
suggestions.push(source[i]); suggestions.push(source[i]);
} }
} }
return [{ ...state, suggestions, query, open: true }, noop]; return [{ ...state, suggestions, query, open: true, total: source.length }, noop];
} else if ('pageCollection' in source) { } else if ('pageCollection' in source) {
if (!('auth' in ctx) || !ctx.auth) return [state, noop]; if (!('auth' in ctx) || !ctx.auth) return [state, noop];
// Запрос на поиск записей // Запрос на поиск записей
......
...@@ -13,3 +13,6 @@ msgstr "Ничего не найдено…" ...@@ -13,3 +13,6 @@ msgstr "Ничего не найдено…"
msgid "Clear" msgid "Clear"
msgstr "Очистить" msgstr "Очистить"
msgid "See more"
msgstr "Загрузить еще"
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment