From f98991a614591d327eb603e8ad28fc91b8552d1e Mon Sep 17 00:00:00 2001 From: Max Maximov Date: Tue, 17 Oct 2017 06:31:12 +0300 Subject: [PATCH 1/4] data-list: a little refactoring --- components/data-list/data-list.examples.js | 55 +++++++------- components/data-list/data-list.examples2.js | 8 +-- components/data-list/data-list.js | 50 ++++++------- components/data-list/data-list.mock.js | 1 + components/data-list/item.js | 79 ++++++++++----------- components/data-list/types.js | 22 ++++-- 6 files changed, 108 insertions(+), 107 deletions(-) diff --git a/components/data-list/data-list.examples.js b/components/data-list/data-list.examples.js index bbbbc87b5bd..7b9d7d4b3a1 100644 --- a/components/data-list/data-list.examples.js +++ b/components/data-list/data-list.examples.js @@ -8,41 +8,35 @@ import DataList from './data-list'; import Selection from './selection'; import mock, {moreItems} from './data-list.mock'; -import {moreLessButtonStates} from './item'; +import {moreLessStates} from './types'; class DataListDemo extends PureComponent { expandedItems = new Set(); + moreExpandedItems = new Set(); + isItemCollapsible = item => item.collapsible && item.items && item.id > 10; isItemCollapsed = item => !this.expandedItems.has(item.id); + getKey = item => item.id; + getChildren = item => { const collapsible = this.isItemCollapsible(item); const collapsed = this.isItemCollapsed(item); return ((collapsible && collapsed) || !item.items) ? [] : item.items; }; + isItemSelectable = item => item.selectable; + state = { data: mock, selection: new Selection({ data: mock, - isItemSelectable: item => item.selectable, - getChildren: this.getChildren + getKey: this.getKey, + getChildren: this.getChildren, + isItemSelectable: this.isItemSelectable }) }; - moreExpandebleItems = new Set([mock[0].id]); - moreExpandedItems = new Set(); - - itemMoreLessState = item => { - if (this.moreExpandebleItems.has(item.id)) { - return this.moreExpandedItems.has(item.id) - ? moreLessButtonStates.LESS - : moreLessButtonStates.MORE; - } else { - return moreLessButtonStates.UNUSED; - } - }; - onItemMoreLess = (item, more) => { if (more) { this.moreExpandedItems.add(item.id); @@ -60,10 +54,6 @@ class DataListDemo extends PureComponent { }; itemFormatter = item => { - const items = this.getChildren(item); - const collapsible = this.isItemCollapsible(item); - const collapsed = this.isItemCollapsed(item); - const onCollapse = () => { this.expandedItems.delete(item.id); this.setState({data: [...this.state.data]}); @@ -74,11 +64,23 @@ class DataListDemo extends PureComponent { this.setState({data: [...this.state.data]}); }; + let moreLessState = moreLessStates.UNUSED; + if (item.moreLess) { + if (this.moreExpandedItems.has(item.id)) { + moreLessState = moreLessStates.LESS; + } else { + moreLessState = moreLessStates.MORE; + } + } + return { - ...item, - items, - collapsible, - collapsed, + key: this.getKey(item), + title: item.title, + children: this.getChildren(item), + selectable: this.isItemSelectable(item), + collapsible: this.isItemCollapsible(item), + collapsed: this.isItemCollapsed(item), + moreLessState, onCollapse, onExpand }; @@ -88,13 +90,10 @@ class DataListDemo extends PureComponent { return ( ); } diff --git a/components/data-list/data-list.examples2.js b/components/data-list/data-list.examples2.js index 40c17fce19d..6c86913acef 100644 --- a/components/data-list/data-list.examples2.js +++ b/components/data-list/data-list.examples2.js @@ -6,7 +6,7 @@ import DataList from './data-list'; import Selection from './selection'; import mock, {moreItems} from './data-list.mock'; -import {moreLessButtonStates} from './item'; +import {moreLessStates} from './types'; class DataListDemo extends PureComponent { state = { @@ -35,10 +35,10 @@ class DataListDemo extends PureComponent { itemMoreLessState = item => { if (this.moreExpandebleItems.has(item.id)) { return this.moreExpandedItems.has(item.id) - ? moreLessButtonStates.LESS - : moreLessButtonStates.MORE; + ? moreLessStates.LESS + : moreLessStates.MORE; } else { - return moreLessButtonStates.UNUSED; + return moreLessStates.UNUSED; } }; diff --git a/components/data-list/data-list.js b/components/data-list/data-list.js index a568f8728f6..1451743c95d 100644 --- a/components/data-list/data-list.js +++ b/components/data-list/data-list.js @@ -20,22 +20,16 @@ import Shortcuts from '../shortcuts/shortcuts'; import Loader from '../loader/loader'; import Selection from './selection'; -import Item, {moreLessButtonStates} from './item'; +import Item from './item'; import type {ItemType} from './types'; import styles from './data-list.css'; -import type {MoreLessButtonState} from './item'; - type Props = { className?: string, data: any[], - loading: boolean, - itemFormatter: (item: any) => ItemType, - + loading: boolean, onItemMoreLess: (item?: ItemType, more?: boolean) => void, - itemMoreLessState: (item?: ItemType) => MoreLessButtonState, - remoteSelection: boolean, // selectionShortcutsHOC @@ -54,22 +48,15 @@ type Props = { class DataList extends PureComponent { static propTypes = { data: PropTypes.array.isRequired, - loading: PropTypes.bool, - itemFormatter: PropTypes.func.isRequired, - + loading: PropTypes.bool, onItemMoreLess: PropTypes.func, - itemMoreLessState: PropTypes.func, - remoteSelection: PropTypes.bool }; static defaultProps = { loading: false, - onItemMoreLess: () => {}, - itemMoreLessState: () => moreLessButtonStates.UNUSED, - remoteSelection: false }; @@ -119,8 +106,10 @@ class DataList extends PureComponent { const item = itemFormatter(selection.getFocused()); if (item.collapsed) { - item.onExpand(); - } else { + if (item.onExpand) { + item.onExpand(); + } + } else if (item.onCollapse) { item.onCollapse(); } } @@ -156,34 +145,37 @@ class DataList extends PureComponent { diff --git a/components/data-list/types.js b/components/data-list/types.js index c7187926400..b122327eb95 100644 --- a/components/data-list/types.js +++ b/components/data-list/types.js @@ -1,11 +1,25 @@ /* @flow */ +export const moreLessStates = { + UNUSED: 0, + MORE: 1, + MORE_LOADING: 2, + LESS: 3 +}; + +export type MoreLessState = + typeof moreLessStates.UNUSED | + typeof moreLessStates.MORE | + typeof moreLessStates.MORE_LOADING | + typeof moreLessStates.LESS; + export type ItemType = { - id: number, + key: number|string, title: any, + children?: ItemType[], selectable?: boolean, collapsible?: boolean, collapsed?: boolean, - items?: ItemType[], - onCollapse: () => void, - onExpand: () => void + moreLessState?: MoreLessState, + onCollapse?: () => void, + onExpand?: () => void }; From 44ae16917ab6434e713625a1dbd09bf01d829f35 Mon Sep 17 00:00:00 2001 From: Max Maximov Date: Tue, 17 Oct 2017 18:45:40 +0300 Subject: [PATCH 2/4] data-list: using context for common props --- components/data-list/data-list.js | 25 ++++++++++++---- components/data-list/item.js | 47 +++++++++++++------------------ 2 files changed, 38 insertions(+), 34 deletions(-) diff --git a/components/data-list/data-list.js b/components/data-list/data-list.js index 1451743c95d..ea80ed93768 100644 --- a/components/data-list/data-list.js +++ b/components/data-list/data-list.js @@ -54,6 +54,14 @@ class DataList extends PureComponent { remoteSelection: PropTypes.bool }; + static childContextTypes = { + itemFormatter: PropTypes.func.isRequired, + selection: PropTypes.instanceOf(Selection).isRequired, + onSelect: PropTypes.func, + onFocus: PropTypes.func, + onItemMoreLess: PropTypes.func + }; + static defaultProps = { loading: false, onItemMoreLess: () => {}, @@ -65,6 +73,17 @@ class DataList extends PureComponent { shortcutsScope: getUID('ring-data-list-') }; + getChildContext() { + const { + itemFormatter, selection, onSelect, onItemMoreLess + } = this.props; + + return { + itemFormatter, selection, onSelect, onItemMoreLess, + onFocus: this.onItemFocus + }; + } + componentWillReceiveProps(nextProps) { const {data, selection, onSelect, selectable} = this.props; @@ -159,8 +178,6 @@ class DataList extends PureComponent { title={title} items={children} - itemFormatter={itemFormatter} - collapsible={collapsible} collapsed={collapsed} onCollapse={onCollapse} @@ -168,15 +185,11 @@ class DataList extends PureComponent { focused={selection.isFocused(model)} showFocus={selection.isFocused(model)} - onFocus={this.onItemFocus} - selection={selection} selectable={selectable} selected={selection.isSelected(model)} - onSelect={this.onItemSelect} moreLessState={moreLessState} - onItemMoreLess={this.props.onItemMoreLess} /> ); })} diff --git a/components/data-list/item.js b/components/data-list/item.js index b6bb79a37e4..deb008c16ad 100644 --- a/components/data-list/item.js +++ b/components/data-list/item.js @@ -1,6 +1,7 @@ /* @flow */ /* eslint-disable react/jsx-no-literals */ import React, {PureComponent, Element} from 'react'; +import PropTypes from 'prop-types'; import classNames from 'classnames'; import Link from '../link/link'; @@ -15,7 +16,7 @@ import { import Selection from './selection'; import Title from './title'; import {moreLessStates} from './types'; -import type {MoreLessState, ItemType} from './types'; +import type {MoreLessState} from './types'; import styles from './data-list.css'; const ITEM_LEFT_OFFSET = 30; @@ -28,23 +29,17 @@ type Props = { level: number, parentShift?: number, - itemFormatter: (item: any) => ItemType, - collapsible: boolean, collapsed: boolean, onCollapse: () => void, onExpand: () => void, showFocus: boolean, - onFocus: (item: ItemType) => void, - selection: Selection, selectable: boolean, selected: boolean, - onSelect: (item: ItemType, selected: boolean) => void, - moreLessState: MoreLessState, - onItemMoreLess: (item?: ItemType, more?: boolean) => void + moreLessState: MoreLessState }; export default class Item extends PureComponent { @@ -52,38 +47,38 @@ export default class Item extends PureComponent { items: [], level: 0, parentShift: 0, - moreLessState: moreLessStates.UNUSED, - onItemMoreLess: () => {} + moreLessState: moreLessStates.UNUSED + }; + + static contextTypes = { + itemFormatter: PropTypes.func.isRequired, + selection: PropTypes.instanceOf(Selection).isRequired, + onSelect: PropTypes.func, + onFocus: PropTypes.func, + onItemMoreLess: PropTypes.func }; props: Props; onShowMore = (): void => { - const {onItemMoreLess, model} = this.props; - onItemMoreLess(model, true); + this.context.onItemMoreLess(this.props.model, true); }; onShowLess = (): void => { - const {onItemMoreLess, model} = this.props; - onItemMoreLess(model, false); + this.context.onItemMoreLess(this.props.model, false); }; onFocus = (): void => { - const {onFocus, model} = this.props; - onFocus(model); + this.context.onFocus(this.props.model); }; onSelect = (selected: boolean): void => { - const {onSelect, model} = this.props; - onSelect(model, selected); + this.context.onSelect(this.props.model, selected); }; renderItem = (model: any, parentShift: number): Element => { - const { - onFocus, onSelect, selection, level, - itemFormatter - } = this.props; - + const {level} = this.props; + const {itemFormatter, selection} = this.context; const item = itemFormatter(model); const { @@ -97,11 +92,10 @@ export default class Item extends PureComponent { model={model} title={title} items={children} + level={level + 1} parentShift={parentShift} - itemFormatter={itemFormatter} - collapsible={collapsible} collapsed={collapsed} onCollapse={onCollapse} @@ -109,12 +103,9 @@ export default class Item extends PureComponent { focused={selection.isFocused(model)} showFocus={selection.isFocused(model)} - onFocus={onFocus} - selection={selection} selectable={selectable} selected={selection.isSelected(model)} - onSelect={onSelect} /> ); }; From d677ced05ae52c807ff879d5e910b9c6e549e412 Mon Sep 17 00:00:00 2001 From: Max Maximov Date: Thu, 19 Oct 2017 02:18:31 +0100 Subject: [PATCH 3/4] fixup! data-list: using context for common props --- components/data-list/data-list.js | 6 +++--- components/data-list/item.js | 7 ++++--- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/components/data-list/data-list.js b/components/data-list/data-list.js index ea80ed93768..45cece2d592 100644 --- a/components/data-list/data-list.js +++ b/components/data-list/data-list.js @@ -56,7 +56,6 @@ class DataList extends PureComponent { static childContextTypes = { itemFormatter: PropTypes.func.isRequired, - selection: PropTypes.instanceOf(Selection).isRequired, onSelect: PropTypes.func, onFocus: PropTypes.func, onItemMoreLess: PropTypes.func @@ -75,11 +74,11 @@ class DataList extends PureComponent { getChildContext() { const { - itemFormatter, selection, onSelect, onItemMoreLess + itemFormatter, onSelect, onItemMoreLess } = this.props; return { - itemFormatter, selection, onSelect, onItemMoreLess, + itemFormatter, onSelect, onItemMoreLess, onFocus: this.onItemFocus }; } @@ -186,6 +185,7 @@ class DataList extends PureComponent { focused={selection.isFocused(model)} showFocus={selection.isFocused(model)} + selection={selection} selectable={selectable} selected={selection.isSelected(model)} diff --git a/components/data-list/item.js b/components/data-list/item.js index deb008c16ad..49b4ac78a19 100644 --- a/components/data-list/item.js +++ b/components/data-list/item.js @@ -36,6 +36,7 @@ type Props = { showFocus: boolean, + selection: Selection, selectable: boolean, selected: boolean, @@ -52,7 +53,6 @@ export default class Item extends PureComponent { static contextTypes = { itemFormatter: PropTypes.func.isRequired, - selection: PropTypes.instanceOf(Selection).isRequired, onSelect: PropTypes.func, onFocus: PropTypes.func, onItemMoreLess: PropTypes.func @@ -77,8 +77,8 @@ export default class Item extends PureComponent { }; renderItem = (model: any, parentShift: number): Element => { - const {level} = this.props; - const {itemFormatter, selection} = this.context; + const {level, selection} = this.props; + const {itemFormatter} = this.context; const item = itemFormatter(model); const { @@ -104,6 +104,7 @@ export default class Item extends PureComponent { focused={selection.isFocused(model)} showFocus={selection.isFocused(model)} + selection={selection} selectable={selectable} selected={selection.isSelected(model)} /> From 363ce35adca72ee52aea76b307f00a0f72f05060 Mon Sep 17 00:00:00 2001 From: Max Maximov Date: Thu, 19 Oct 2017 02:20:04 +0100 Subject: [PATCH 4/4] data-list: examples --- components/data-list-ng/data-list-ng.examples.html | 13 ++++++------- components/data-list/data-list.examples.js | 8 ++++---- components/data-list/data-list.mock.js | 14 +++++++------- 3 files changed, 17 insertions(+), 18 deletions(-) diff --git a/components/data-list-ng/data-list-ng.examples.html b/components/data-list-ng/data-list-ng.examples.html index 3345b2c5072..94f5e2ab7a2 100644 --- a/components/data-list-ng/data-list-ng.examples.html +++ b/components/data-list-ng/data-list-ng.examples.html @@ -3,9 +3,9 @@
@@ -17,16 +17,15 @@ import data from '@jetbrains/ring-ui/components/data-list/data-list.mock.js'; function itemFormatter(item) { - return { - ...item, - collapsible: false - }; + const {id: key, title, children, selectable} = item; + return {key, title, children, selectable}; } const selection = new Selection({ data, - isItemSelectable: item => item.selectable, - getChildren: item => item.items || [] + getKey: item => item.id, + getChildren: item => item.children || [], + isItemSelectable: item => item.selectable }); const exampleModule = angular.module('Example.data-list', [RingDataList]); diff --git a/components/data-list/data-list.examples.js b/components/data-list/data-list.examples.js index 7b9d7d4b3a1..b113921d811 100644 --- a/components/data-list/data-list.examples.js +++ b/components/data-list/data-list.examples.js @@ -14,7 +14,7 @@ class DataListDemo extends PureComponent { expandedItems = new Set(); moreExpandedItems = new Set(); - isItemCollapsible = item => item.collapsible && item.items && item.id > 10; + isItemCollapsible = item => item.collapsible && item.children && item.id > 10; isItemCollapsed = item => !this.expandedItems.has(item.id); getKey = item => item.id; @@ -22,7 +22,7 @@ class DataListDemo extends PureComponent { getChildren = item => { const collapsible = this.isItemCollapsible(item); const collapsed = this.isItemCollapsed(item); - return ((collapsible && collapsed) || !item.items) ? [] : item.items; + return ((collapsible && collapsed) || !item.children) ? [] : item.children; }; isItemSelectable = item => item.selectable; @@ -40,10 +40,10 @@ class DataListDemo extends PureComponent { onItemMoreLess = (item, more) => { if (more) { this.moreExpandedItems.add(item.id); - item.items = item.items.concat([...moreItems]); + item.children = item.children.concat([...moreItems]); } else { this.moreExpandedItems.delete(item.id); - item.items = item.items.slice(0, item.items.length - moreItems.length); + item.children = item.children.slice(0, item.children.length - moreItems.length); } this.setState({data: [...this.state.data]}); diff --git a/components/data-list/data-list.mock.js b/components/data-list/data-list.mock.js index 6dad7fb4c85..91e6d8d308f 100644 --- a/components/data-list/data-list.mock.js +++ b/components/data-list/data-list.mock.js @@ -13,13 +13,13 @@ export default [ collapsible: true, selectable: true, moreLess: true, - items: [ + children: [ { id: 11, title: '6 projects: as a member of jetbrains-team', collapsible: true, selectable: true, - items: [ + children: [ { id: 111, selectable: true, @@ -59,7 +59,7 @@ export default [ title: Code Reviewer in 5 projects, selectable: true, collapsible: true, - items: [ + children: [ { id: 21, selectable: true, @@ -76,7 +76,7 @@ export default [ id: 22, title: '6 projects: as a member of jetbrains-team', collapsible: true, - items: [ + children: [ { id: 221, collapsible: true, @@ -127,7 +127,7 @@ export default [ title: Code Viewer in 5 projects, selectable: true, collapsible: true, - items: [ + children: [ { id: 31, collapsible: true, @@ -156,7 +156,7 @@ export default [ id: 4, title: Commenter in 12 projects, collapsible: true, - items: [ + children: [ { id: 41, collapsible: true, @@ -191,7 +191,7 @@ export default [ team role ), - items: [ + children: [ { id: 51, selectable: true,