Skip to content
This repository has been archived by the owner on Feb 6, 2019. It is now read-only.

Commit

Permalink
Merge ab4fb09 into 558a966
Browse files Browse the repository at this point in the history
  • Loading branch information
ezmiller committed Aug 28, 2016
2 parents 558a966 + ab4fb09 commit 0bbb544
Show file tree
Hide file tree
Showing 10 changed files with 143 additions and 34 deletions.
15 changes: 14 additions & 1 deletion beavy/common/morphing_schema.py
@@ -1,4 +1,4 @@
from marshmallow import pre_dump
from marshmallow import pre_dump, fields


class MorphingSchema():
Expand All @@ -16,3 +16,16 @@ def _obj_to_name(self, obj):
def _get_serializer(self, obj):
name = self._obj_to_name(obj)
return self.registry.get(name, self.FALLBACK)()


class MorphingNested(fields.Nested, MorphingSchema):

def _get_serializer(self, obj):
name = self._obj_to_name(obj)
rv = self.nested.registry.get(name, self.nested.FALLBACK)()
return rv

def _serialize(self, nested_obj, attr, obj):
rv = [self._get_serializer(obj).dump(obj).data
for obj in nested_obj]
return rv
7 changes: 4 additions & 3 deletions beavy/common/paging_schema.py
@@ -1,4 +1,5 @@
from marshmallow import Schema, fields, post_dump
from beavy.common.morphing_schema import MorphingNested


class BasePaging(Schema):
Expand All @@ -17,11 +18,11 @@ def move_to_meta(self, data):
# FIXME: add support for paging links
return {
"meta": data,
"data": items.get("data", []),
"links": items.get("links", [])
"data": [item.get("data") for item in items],
"links": []
}


def makePaginationSchema(itemsCls, field_cls=fields.Nested):
def makePaginationSchema(itemsCls, field_cls=MorphingNested):
return type("{}Paging".format(itemsCls.__class__.__name__),
(BasePaging, ), dict(items=field_cls(itemsCls, many=True)))
23 changes: 23 additions & 0 deletions beavy/jsbeavy/actions/latest.jsx
@@ -0,0 +1,23 @@
import { CALL_API } from 'middleware/api'
import { LATEST } from 'reducers/latest'

export const LATEST_REQUEST = 'LATEST_REQUEST'
export const LATEST_SUCCESS = 'LATEST_SUCCESS'
export const LATEST_FAILURE = 'LATEST_FAILURE'

const fetchLatest = (page = 1) => {
return {
[CALL_API]: {
types: [LATEST_REQUEST, LATEST_SUCCESS, LATEST_FAILURE],
endpoint: '/latest?page=' + page,
key: LATEST
}
}
}

export function loadLatest (page = 1) {
return (dispatch, getState) => {
return dispatch(fetchLatest(page = page))
}
}

43 changes: 17 additions & 26 deletions beavy/jsbeavy/components/InfiniteList.jsx
@@ -1,22 +1,21 @@
/*eslint-disable react/no-multi-comp*/
import React, { Component, PropTypes} from 'react'
import ReactDOM from 'react-dom'
import { FormattedMessage } from 'react-intl'
import Infinite from 'react-infinite'
import map from 'lodash/collection/map'
import fill from 'lodash/array/fill'
import { fill, isEqual } from 'lodash'

class SizeReportWrapper extends Component {
propTypes: {
reportHeight: PropTypes.func.isRequired,
element: PropTypes.Component.isRequired,
}
componentDidMount () {
console.log('mounted')
var el = React.findDOMNode(this.refs.child)
var el = ReactDOM.findDOMNode(this.refs.child)
this.props.reportHeight(el.offsetHeight)
}
render () {
console.log('rendering')
return React.cloneElement(this.props.element, {ref: 'child'})
}
}
Expand Down Expand Up @@ -45,63 +44,55 @@ export default class InfiniteList extends Component {
}

shouldComponentUpdate (nextProps, nextState) {
var propsChanged = this.props !== nextProps
var propsChanged = !isEqual(this.props, nextProps)
var stateChanged = this.state !== nextState
return propsChanged || stateChanged
}

render () {
console.log(this.state)
console.log(map(this.props.children, (c, i) => <SizeReportWrapper element={c} reportHeight={(height) => this.reportHeight(i, height)} />))
// Note that the slightly confusing way of disabling infinite loading
// on the Infinite component, is to set the infiniteLoadBeginEdgeOffset
// prop to undefined, or not to set it all. We are setting it ot undefined
// when has_next == false.
return <Infinite elementHeight={this.state.elementHeights}
containerHeight={this.state.containerHeight}
infiniteLoadBeginBottomOffset={this.props.meta.has_next && 400}
infiniteLoadBeginEdgeOffset={!this.props.meta.has_next ? undefined : 200}
onInfiniteLoad={::this.handleInfiniteLoad}
loadingSpinnerDelegate={this.elementInfiniteLoad()}
isInfiniteLoading={this.props.isFetching}
preloadBatchSize={20}
className='infinite-list'
scrollNumberCallback={this.scrollCallback}
selectedItem={this.props.selectedItem}
>
{map(this.props.children, (c, i) => <SizeReportWrapper element={c} reportHeight={(height) => this.reportHeight(i, height)} />
{map(this.props.children, (c, i) =>
<SizeReportWrapper
key={i}
element={c}
reportHeight={(height) => this.reportHeight(i, height)} />
)}
</Infinite>
}

reportHeight (i, height) {
console.log(i, height)
let curHeights = this.state.elementHeights
curHeights[i] = height
this.setState({elementHeights: curHeights})
}

handleResize (e) {
this.setState({containerHeight: window.innerHeight - 60})
}

componentDidMount () {
window.addEventListener('resize', this.handleResize)
}

componentDidUnmount () {
window.removeEventListener('resize', this.handleResize)
}

componentWillReceiveProps (newProps) {
let newState = {elements: newProps.children}
if (this.props.children.length < newProps.children.length) {
const minimalItemHeight = newProps.minimalItemHeight || this.props.minimalItemHeight || 100
newState.elementHeights = this.state.elementHeights.concat(
fill(Array(newProps.children.length - this.props.children.length), minimalItemHeight))
}
console.log(newState)
this.setState(newState)
}

handleInfiniteLoad () {
console.log('LOAD MOA!')
this.props.loader(this.props.meta.page + 1)
if (this.props.meta.has_next && !this.props.isFetching) {
this.props.loader(this.props.meta.page + 1)
}
}

elementInfiniteLoad () {
Expand Down
11 changes: 11 additions & 0 deletions beavy/jsbeavy/reducers/latest.jsx
@@ -0,0 +1,11 @@
import { addNamedExtension } from 'config/extensions'
import paginate from 'reducers/paginate'
import { LATEST_SUCCESS, LATEST_FAILURE, LATEST_REQUEST } from 'actions/latest'

export const LATEST = 'latest'

addNamedExtension('reducers', LATEST, paginate({
mapActionToKey: x => LATEST,
types: [LATEST_REQUEST, LATEST_SUCCESS, LATEST_FAILURE]
}))

64 changes: 64 additions & 0 deletions beavy/jsbeavy/views/LatestView.jsx
@@ -0,0 +1,64 @@
/* eslint-disable react/no-multi-comp */
import React, { Component } from 'react'
import { connect } from 'react-redux'
import { getStoreEntity } from 'utils'
import { LATEST } from 'reducers/latest'
import { loadLatest } from 'actions/latest'
import InfiniteList from 'components/InfiniteList'

// This should be a stateless component but if it's to be
// consumed by the InfiniteList later, we'll need to add
// a ref and you can't do that on stateless components.
class Link extends Component {
render () {
const props = this.props
return (
<li key={props.key} style={{height: 20}}>
<a target='_blank' href={props.url}>{props.title}</a>
</li>
)
}
}

const LinksList = ({
meta,
links,
isFetching,
loadMore
}) => (
<InfiniteList
meta={meta}
loader={loadMore}
minimalItemHeight={24}
isFetching={isFetching}
>
{links.map(l =>
<Link key={l.id} {...l} />
)}
</InfiniteList>
)

const mapStateToProps = (state) => {
return {
meta: state[LATEST].meta,
links: state[LATEST].data.map((item) => {
return getStoreEntity(state, item)
}),
isFetching: state[LATEST].isFetching
}
}

const mapDispatchToProps = (dispatch, props) => {
return {
loadMore: (page) => {
console.log('loadMore', {page: page})
dispatch(loadLatest(page))
}
}
}

export default connect(
mapStateToProps,
mapDispatchToProps
)(LinksList)
/* eslint-enable react/no-multi-comp */
4 changes: 4 additions & 0 deletions beavy/jsbeavy/views/index.jsx
Expand Up @@ -5,6 +5,7 @@ import { make_url } from 'utils'

import UserView from 'views/UserView'
import HomeView from 'views/HomeView'
import LatestView from 'views/LatestView'

export default function setupViews (Application) {
addExtension('routes',
Expand All @@ -19,4 +20,7 @@ export default function setupViews (Application) {
<Route key='account' name='account' path={make_url.account('')}>
{getExtensions('accountRoutes')}
</Route>)

addExtension('routes',
<Route key='latest' name='latest' path='/latest' component={LatestView} />)
}
2 changes: 1 addition & 1 deletion beavy/models/object.py
Expand Up @@ -14,7 +14,7 @@

class ObjectQuery(AccessQuery):

def by_capability(self, aborting=True, abort_code=404, *caps):
def by_capability(self, *caps, aborting=True, abort_code=404):
caps = set(chain.from_iterable(map(lambda c:
getattr(Object.TypesForCapability,
getattr(c, 'value', c), []),
Expand Down
6 changes: 4 additions & 2 deletions beavy/views/lists/latest.py
Expand Up @@ -8,9 +8,11 @@

@lists_bp.route("latest/")
@rate_limit("2/second; 100/minute; 1000/hour; 1000/day")
@fallbackRender('home.html')
@fallbackRender('home.html', 'latest')
def latest():
query = Object.query.by_capability('listed', aborting=False # noqa
).with_my_activities(
).order_by(desc('objects.created_at'))
return objects_paged.dump(as_page(query, error_out=False)).data
rv = objects_paged.dump(as_page(query, per_page=5, error_out=False)).data
print("DEBUG: latest() rv: ", rv)
return rv
2 changes: 1 addition & 1 deletion package.json
Expand Up @@ -47,7 +47,7 @@
"po2json": "^0.4.1",
"react": "^0.14.3",
"react-dom": "^0.14.3",
"react-infinite": "^0.7.1",
"react-infinite": "^0.9.2",
"react-prosemirror": "^0.1.4",
"react-intl": "^2.0.0-beta-2",
"react-proxy-loader": "^0.3.4",
Expand Down

0 comments on commit 0bbb544

Please sign in to comment.