abstract dynamic video tile load within new dynamicloader class to allow to load other elements dynamically.
This commit is contained in:
parent
dfd92b1730
commit
57a7a9a827
@ -1,4 +1,4 @@
|
||||
.maincontent {
|
||||
float: left;
|
||||
width: 70%;
|
||||
}
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
import {shallow} from 'enzyme';
|
||||
import React from 'react';
|
||||
import DynamicContentContainer from './DynamicContentContainer';
|
||||
|
||||
describe('<DynamicContentContainer/>', function () {
|
||||
it('renders without crashing ', function () {
|
||||
const wrapper = shallow(<DynamicContentContainer data={[]} renderElement={(el) => (<></>)}/>);
|
||||
wrapper.unmount();
|
||||
});
|
||||
|
||||
it('inserts tiles correctly if enough available', () => {
|
||||
const wrapper = shallow(<DynamicContentContainer data={[
|
||||
{}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}
|
||||
]} renderElement={(el) => (<a/>)}/>);
|
||||
expect(wrapper.find('a')).toHaveLength(16);
|
||||
});
|
||||
|
||||
it('inserts tiles correctly if not enough available', () => {
|
||||
const wrapper = shallow(<DynamicContentContainer data={[
|
||||
{}, {}, {}, {}
|
||||
]} renderElement={(el) => (<a/>)}/>);
|
||||
expect(wrapper.find('a')).toHaveLength(4);
|
||||
});
|
||||
|
||||
it('no items available', () => {
|
||||
const wrapper = shallow(<DynamicContentContainer data={[]} renderElement={(el) => (<a/>)}/>);
|
||||
expect(wrapper.find('a')).toHaveLength(0);
|
||||
expect(wrapper.find('.maincontent').text()).toBe('no items to show!');
|
||||
});
|
||||
});
|
@ -0,0 +1,87 @@
|
||||
import React from 'react';
|
||||
import style from './DynamicContentContainer.module.css';
|
||||
|
||||
interface Props<T> {
|
||||
renderElement: (elem: T) => JSX.Element;
|
||||
data: T[];
|
||||
initialLoadNr?: number;
|
||||
}
|
||||
|
||||
interface state<T> {
|
||||
loadeditems: T[];
|
||||
selectionnr: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* A videocontainer storing lots of Preview elements
|
||||
* includes scroll handling and loading of preview infos
|
||||
*/
|
||||
class DynamicContentContainer<T> extends React.Component<Props<T>, state<T>> {
|
||||
// stores current index of loaded elements
|
||||
loadindex: number = 0;
|
||||
|
||||
constructor(props: Props<T>) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
loadeditems: [],
|
||||
selectionnr: 0
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount(): void {
|
||||
document.addEventListener('scroll', this.trackScrolling);
|
||||
|
||||
this.loadPreviewBlock(this.props.initialLoadNr ? this.props.initialLoadNr : 16);
|
||||
}
|
||||
|
||||
render(): JSX.Element {
|
||||
return (
|
||||
<div className={style.maincontent}>
|
||||
{this.state.loadeditems.map((elem) => {
|
||||
return this.props.renderElement(elem);
|
||||
})}
|
||||
{/*todo css for no items to show*/}
|
||||
{this.state.loadeditems.length === 0 ? 'no items to show!' : null}
|
||||
{this.props.children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
componentWillUnmount(): void {
|
||||
// unbind scroll listener when unmounting component
|
||||
document.removeEventListener('scroll', this.trackScrolling);
|
||||
}
|
||||
|
||||
/**
|
||||
* load previews to the container
|
||||
* @param nr number of previews to load
|
||||
*/
|
||||
loadPreviewBlock(nr: number): void {
|
||||
let ret = [];
|
||||
for (let i = 0; i < nr; i++) {
|
||||
// only add if not end
|
||||
if (this.props.data.length > this.loadindex + i) {
|
||||
ret.push(this.props.data[this.loadindex + i]);
|
||||
}
|
||||
}
|
||||
|
||||
this.setState({
|
||||
loadeditems: [...this.state.loadeditems, ...ret]
|
||||
});
|
||||
|
||||
this.loadindex += nr;
|
||||
}
|
||||
|
||||
/**
|
||||
* scroll event handler -> load new previews if on bottom
|
||||
*/
|
||||
trackScrolling = (): void => {
|
||||
// comparison if current scroll position is on bottom --> 200 is bottom offset to trigger load
|
||||
if (window.innerHeight + document.documentElement.scrollTop + 200 >= document.documentElement.offsetHeight) {
|
||||
this.loadPreviewBlock(8);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
export default DynamicContentContainer;
|
@ -7,24 +7,4 @@ describe('<VideoContainer/>', function () {
|
||||
const wrapper = shallow(<VideoContainer data={[]}/>);
|
||||
wrapper.unmount();
|
||||
});
|
||||
|
||||
it('inserts tiles correctly if enough available', () => {
|
||||
const wrapper = shallow(<VideoContainer data={[
|
||||
{}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}
|
||||
]}/>);
|
||||
expect(wrapper.find('Preview')).toHaveLength(16);
|
||||
});
|
||||
|
||||
it('inserts tiles correctly if not enough available', () => {
|
||||
const wrapper = shallow(<VideoContainer data={[
|
||||
{}, {}, {}, {}
|
||||
]}/>);
|
||||
expect(wrapper.find('Preview')).toHaveLength(4);
|
||||
});
|
||||
|
||||
it('no items available', () => {
|
||||
const wrapper = shallow(<VideoContainer data={[]}/>);
|
||||
expect(wrapper.find('Preview')).toHaveLength(0);
|
||||
expect(wrapper.find('.maincontent').text()).toBe('no items to show!');
|
||||
});
|
||||
});
|
||||
|
@ -1,89 +1,21 @@
|
||||
import React from 'react';
|
||||
import Preview from '../Preview/Preview';
|
||||
import style from './VideoContainer.module.css';
|
||||
import {VideoTypes} from '../../types/ApiTypes';
|
||||
import DynamicContentContainer from '../DynamicContentContainer/DynamicContentContainer';
|
||||
|
||||
interface Props {
|
||||
data: VideoTypes.VideoUnloadedType[];
|
||||
children?: JSX.Element;
|
||||
}
|
||||
|
||||
interface state {
|
||||
loadeditems: VideoTypes.VideoUnloadedType[];
|
||||
selectionnr: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* A videocontainer storing lots of Preview elements
|
||||
* includes scroll handling and loading of preview infos
|
||||
*/
|
||||
class VideoContainer extends React.Component<Props, state> {
|
||||
// stores current index of loaded elements
|
||||
loadindex: number = 0;
|
||||
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
loadeditems: [],
|
||||
selectionnr: 0
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount(): void {
|
||||
document.addEventListener('scroll', this.trackScrolling);
|
||||
|
||||
this.loadPreviewBlock(16);
|
||||
}
|
||||
|
||||
render(): JSX.Element {
|
||||
return (
|
||||
<div className={style.maincontent}>
|
||||
{this.state.loadeditems.map((elem) => (
|
||||
<Preview key={elem.MovieId} name={elem.MovieName} movieId={elem.MovieId} />
|
||||
))}
|
||||
{/*todo css for no items to show*/}
|
||||
{this.state.loadeditems.length === 0 ? 'no items to show!' : null}
|
||||
{this.props.children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
componentWillUnmount(): void {
|
||||
this.setState({});
|
||||
// unbind scroll listener when unmounting component
|
||||
document.removeEventListener('scroll', this.trackScrolling);
|
||||
}
|
||||
|
||||
/**
|
||||
* load previews to the container
|
||||
* @param nr number of previews to load
|
||||
*/
|
||||
loadPreviewBlock(nr: number): void {
|
||||
console.log('loadpreviewblock called ...');
|
||||
let ret = [];
|
||||
for (let i = 0; i < nr; i++) {
|
||||
// only add if not end
|
||||
if (this.props.data.length > this.loadindex + i) {
|
||||
ret.push(this.props.data[this.loadindex + i]);
|
||||
}
|
||||
}
|
||||
|
||||
this.setState({
|
||||
loadeditems: [...this.state.loadeditems, ...ret]
|
||||
});
|
||||
|
||||
this.loadindex += nr;
|
||||
}
|
||||
|
||||
/**
|
||||
* scroll event handler -> load new previews if on bottom
|
||||
*/
|
||||
trackScrolling = (): void => {
|
||||
// comparison if current scroll position is on bottom --> 200 is bottom offset to trigger load
|
||||
if (window.innerHeight + document.documentElement.scrollTop + 200 >= document.documentElement.offsetHeight) {
|
||||
this.loadPreviewBlock(8);
|
||||
}
|
||||
};
|
||||
}
|
||||
const VideoContainer = (props: Props): JSX.Element => {
|
||||
return (
|
||||
<DynamicContentContainer
|
||||
renderElement={(el): JSX.Element => <Preview key={el.MovieId} name={el.MovieName} movieId={el.MovieId} />}
|
||||
data={props.data}>
|
||||
{props.children}
|
||||
</DynamicContentContainer>
|
||||
);
|
||||
};
|
||||
|
||||
export default VideoContainer;
|
||||
|
@ -1,6 +1,5 @@
|
||||
import {TagType} from '../../types/VideoTypes';
|
||||
import React from 'react';
|
||||
import videocontainerstyle from '../../elements/VideoContainer/VideoContainer.module.css';
|
||||
import {Link} from 'react-router-dom';
|
||||
import {TagPreview} from '../../elements/Preview/Preview';
|
||||
import {APINode, callAPI} from '../../utils/Api';
|
||||
@ -9,6 +8,7 @@ import SideBar, {SideBarTitle} from '../../elements/SideBar/SideBar';
|
||||
import Tag from '../../elements/Tag/Tag';
|
||||
import {DefaultTags} from '../../types/GeneralTypes';
|
||||
import NewTagPopup from '../../elements/Popups/NewTagPopup/NewTagPopup';
|
||||
import DynamicContentContainer from '../../elements/DynamicContentContainer/DynamicContentContainer';
|
||||
|
||||
interface TagViewState {
|
||||
loadedtags: TagType[];
|
||||
@ -53,15 +53,19 @@ class TagView extends React.Component<Props, TagViewState> {
|
||||
Add a new Tag!
|
||||
</button>
|
||||
</SideBar>
|
||||
<div className={videocontainerstyle.maincontent}>
|
||||
{this.state.loadedtags
|
||||
? this.state.loadedtags.map((m) => (
|
||||
<Link to={'/categories/' + m.TagId} key={m.TagId}>
|
||||
<TagPreview name={m.TagName} />
|
||||
</Link>
|
||||
))
|
||||
: 'loading'}
|
||||
</div>
|
||||
{this.state.loadedtags.length !== 0 ? (
|
||||
<DynamicContentContainer
|
||||
data={this.state.loadedtags}
|
||||
renderElement={(m): JSX.Element => (
|
||||
<Link to={'/categories/' + m.TagId} key={m.TagId}>
|
||||
<TagPreview name={m.TagName} />
|
||||
</Link>
|
||||
)}
|
||||
initialLoadNr={20}
|
||||
/>
|
||||
) : (
|
||||
'loading'
|
||||
)}
|
||||
{this.handlePopups()}
|
||||
</>
|
||||
);
|
||||
|
@ -2,7 +2,7 @@ import React from 'react';
|
||||
|
||||
class TVShowPage extends React.Component {
|
||||
render(): JSX.Element {
|
||||
return <></>;
|
||||
return <>TvShowPage</>;
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user