add dynamic scrolling to bucket list in browser (#8336)

Fixes #8181
master
Kanagaraj M 5 years ago committed by Harshavardhana
parent 5c2af3f792
commit 65ac7c5671
  1. 47
      browser/app/js/buckets/BucketList.js
  2. 6
      browser/app/js/buckets/__tests__/BucketList.test.js
  3. 8
      browser/app/js/buckets/__tests__/selectors.test.js
  4. 2
      browser/app/js/buckets/selectors.js
  5. 71
      browser/ui-assets.go

@ -17,14 +17,29 @@
import React from "react" import React from "react"
import { connect } from "react-redux" import { connect } from "react-redux"
import { Scrollbars } from "react-custom-scrollbars" import { Scrollbars } from "react-custom-scrollbars"
import InfiniteScroll from "react-infinite-scroller"
import * as actionsBuckets from "./actions" import * as actionsBuckets from "./actions"
import { getVisibleBuckets } from "./selectors" import { getFilteredBuckets } from "./selectors"
import BucketContainer from "./BucketContainer" import BucketContainer from "./BucketContainer"
import web from "../web" import web from "../web"
import history from "../history" import history from "../history"
import { pathSlice } from "../utils" import { pathSlice } from "../utils"
export class BucketList extends React.Component { export class BucketList extends React.Component {
constructor(props) {
super(props)
this.state = {
page: 1
}
this.loadNextPage = this.loadNextPage.bind(this)
}
componentDidUpdate(prevProps) {
if (this.props.filter !== prevProps.filter) {
this.setState({
page: 1
})
}
}
componentWillMount() { componentWillMount() {
const { fetchBuckets, setBucketList, selectBucket } = this.props const { fetchBuckets, setBucketList, selectBucket } = this.props
if (web.LoggedIn()) { if (web.LoggedIn()) {
@ -39,18 +54,33 @@ export class BucketList extends React.Component {
} }
} }
} }
loadNextPage() {
this.setState({
page: this.state.page + 1
})
}
render() { render() {
const { visibleBuckets } = this.props const { filteredBuckets } = this.props
const visibleBuckets = filteredBuckets.slice(0, this.state.page * 100)
return ( return (
<div className="fesl-inner"> <div className="fesl-inner">
<Scrollbars <Scrollbars
renderTrackVertical={props => <div className="scrollbar-vertical" />} renderTrackVertical={props => <div className="scrollbar-vertical" />}
> >
<ul> <InfiniteScroll
{visibleBuckets.map(bucket => ( pageStart={0}
<BucketContainer key={bucket} bucket={bucket} /> loadMore={this.loadNextPage}
))} hasMore={filteredBuckets.length > visibleBuckets.length}
</ul> useWindow={false}
element="div"
initialLoad={false}
>
<ul>
{visibleBuckets.map(bucket => (
<BucketContainer key={bucket} bucket={bucket} />
))}
</ul>
</InfiniteScroll>
</Scrollbars> </Scrollbars>
</div> </div>
) )
@ -59,7 +89,8 @@ export class BucketList extends React.Component {
const mapStateToProps = state => { const mapStateToProps = state => {
return { return {
visibleBuckets: getVisibleBuckets(state) filteredBuckets: getFilteredBuckets(state),
filter: state.buckets.filter
} }
} }

@ -29,13 +29,13 @@ jest.mock("../../web", () => ({
describe("BucketList", () => { describe("BucketList", () => {
it("should render without crashing", () => { it("should render without crashing", () => {
const fetchBuckets = jest.fn() const fetchBuckets = jest.fn()
shallow(<BucketList visibleBuckets={[]} fetchBuckets={fetchBuckets} />) shallow(<BucketList filteredBuckets={[]} fetchBuckets={fetchBuckets} />)
}) })
it("should call fetchBuckets before component is mounted", () => { it("should call fetchBuckets before component is mounted", () => {
const fetchBuckets = jest.fn() const fetchBuckets = jest.fn()
const wrapper = shallow( const wrapper = shallow(
<BucketList visibleBuckets={[]} fetchBuckets={fetchBuckets} /> <BucketList filteredBuckets={[]} fetchBuckets={fetchBuckets} />
) )
expect(fetchBuckets).toHaveBeenCalled() expect(fetchBuckets).toHaveBeenCalled()
}) })
@ -46,7 +46,7 @@ describe("BucketList", () => {
history.push("/bk1/pre1") history.push("/bk1/pre1")
const wrapper = shallow( const wrapper = shallow(
<BucketList <BucketList
visibleBuckets={[]} filteredBuckets={[]}
setBucketList={setBucketList} setBucketList={setBucketList}
selectBucket={selectBucket} selectBucket={selectBucket}
/> />

@ -14,9 +14,9 @@
* limitations under the License. * limitations under the License.
*/ */
import { getVisibleBuckets, getCurrentBucket } from "../selectors" import { getFilteredBuckets, getCurrentBucket } from "../selectors"
describe("getVisibleBuckets", () => { describe("getFilteredBuckets", () => {
let state let state
beforeEach(() => { beforeEach(() => {
state = { state = {
@ -28,11 +28,11 @@ describe("getVisibleBuckets", () => {
it("should return all buckets if no filter specified", () => { it("should return all buckets if no filter specified", () => {
state.buckets.filter = "" state.buckets.filter = ""
expect(getVisibleBuckets(state)).toEqual(["test1", "test11", "test2"]) expect(getFilteredBuckets(state)).toEqual(["test1", "test11", "test2"])
}) })
it("should return all matching buckets if filter is specified", () => { it("should return all matching buckets if filter is specified", () => {
state.buckets.filter = "test1" state.buckets.filter = "test1"
expect(getVisibleBuckets(state)).toEqual(["test1", "test11"]) expect(getFilteredBuckets(state)).toEqual(["test1", "test11"])
}) })
}) })

@ -19,7 +19,7 @@ import { createSelector } from "reselect"
const bucketsSelector = state => state.buckets.list const bucketsSelector = state => state.buckets.list
const bucketsFilterSelector = state => state.buckets.filter const bucketsFilterSelector = state => state.buckets.filter
export const getVisibleBuckets = createSelector( export const getFilteredBuckets = createSelector(
bucketsSelector, bucketsSelector,
bucketsFilterSelector, bucketsFilterSelector,
(buckets, filter) => buckets.filter(bucket => bucket.indexOf(filter) > -1) (buckets, filter) => buckets.filter(bucket => bucket.indexOf(filter) > -1)

File diff suppressed because one or more lines are too long
Loading…
Cancel
Save