More fixes/patches

This commit is contained in:
Ryan McGrath 2018-04-11 23:16:10 -04:00
parent 1f90ca2575
commit c02ad19f2b
No known key found for this signature in database
GPG key ID: 811674B62B666830
18 changed files with 582 additions and 239 deletions

View file

@ -0,0 +1,34 @@
/**
* AttendeesListViewController
*
* Yeah, I do it iOS style. Handles fetching and displaying upcoming tournaments.
*
* @copyright Ryan McGrath 2018.
*/
import moment from 'moment';
import React from 'react';
import {FlatList, View, ActivityIndicator} from 'react-native';
import {inject, observer} from 'mobx-react/native';
import {SearchBar} from 'react-native-elements';
import styles from '../styles';
import Constants from '../utils/Constants';
import MemeleeViewController from './MemeleeViewController';
import TournamentRow from './components/TournamentRow';
const keyExtractor = (item, index) => item.id;
export default class AttendeesListViewController extends MemeleeViewController {
renderItem = ({item}) => (<View />)
render() {
const props = {
data: this.props.data,
keyExtractor: keyExtractor,
renderItem: this.renderItem
};
return <FlatList {...props} renderItem={this.renderItem} />
}
}

View file

@ -9,9 +9,8 @@
import moment from 'moment';
import React from 'react';
import {ScrollView, Text, View} from 'react-native';
import {v4} from 'uuid';
import {inject, observer} from 'mobx-react/native';
//import SmashGG from '../store';
import MemeleeViewController from './MemeleeViewController';
const Match = ({set, ...rest}) => (
@ -22,32 +21,17 @@ const Match = ({set, ...rest}) => (
</View>
);
@inject('Events') @observer
export default class BracketViewController extends MemeleeViewController {
state = {
brackets: {
winners: [],
losers: [],
grandFinals: []
}
};
componentWillMount() {
const evtSlugs = this.props.evt.slug.split('/');
const evtSlug = evtSlugs.length > 0 ? evtSlugs[evtSlugs.length - 1] : null;
const tournamentSlug = this.props.tournament.slugs[0].replace('tournament/', '');
SmashGG.fetchBracketData(tournamentSlug, evtSlug, this.props.bracket.id).then(this.updateBracketsData).catch(console.error);
this.props.Events.fetchBracketData(this.props.bracket.id);
}
updateBracketsData = (brackets) => {
this.setState({brackets: brackets});
}
render() {
return (<ScrollView style={{flex: 1, backgroundColor: '#21212d'}} contentContainerStyle={{width: 10001}}>
{['winners', 'losers'].map(key => (
<View key={key} style={{backgroundColor: '#21212d', flexDirection: 'row', paddingTop: 20, paddingBottom: 20, paddingLeft: 20}}>
{this.state.brackets[key].map(bracket => (
{this.props.Events.bracketData[key].map(bracket => (
<View key={bracket.key} style={{backgroundColor: '#21212d', marginRight: 20, width: 200, flexDirection: 'column'}}>
<Text>{bracket.title}</Text>
{bracket.sets.map(set => <Match key={set.id} set={set} />)}

View file

@ -0,0 +1,34 @@
/**
* AttendeesListViewController
*
* Yeah, I do it iOS style. Handles fetching and displaying upcoming tournaments.
*
* @copyright Ryan McGrath 2018.
*/
import moment from 'moment';
import React from 'react';
import {FlatList, View, ActivityIndicator} from 'react-native';
import {inject, observer} from 'mobx-react/native';
import {SearchBar} from 'react-native-elements';
import styles from '../styles';
import Constants from '../utils/Constants';
import MemeleeViewController from './MemeleeViewController';
import TournamentRow from './components/TournamentRow';
const keyExtractor = (item, index) => item.id;
export default class AttendeesListViewController extends MemeleeViewController {
renderItem = ({item}) => (<View />)
render() {
const props = {
data: this.props.data,
keyExtractor: keyExtractor,
renderItem: this.renderItem
};
return <FlatList {...props} renderItem={this.renderItem} />
}
}

View file

@ -8,40 +8,61 @@
import moment from 'moment';
import React from 'react';
import {ScrollView, Image, Text, View, TouchableOpacity} from 'react-native';
import {ScrollView, StyleSheet, ActivityIndicator, Image, Text, View, TouchableOpacity} from 'react-native';
import {inject, observer} from 'mobx-react/native';
import Markdown from 'react-native-simple-markdown'
//import SmashGG from '../store';
import SegmentedControlTab from 'react-native-segmented-control-tab';
import SettingsList, {Header, Item} from 'react-native-settings-list';
import styles from '../styles';
import Constants from '../utils/Constants';
import MemeleeViewController from './MemeleeViewController';
const Loading = (props) => (
<View style={{paddingTop: 20}}>
<ActivityIndicator animating size="large" />
</View>
);
const Standings = (props) => (
props.error ? <View style={{padding: 20}}>
<Text style={styles.eventsErrorTextHeader}>No Standings Found</Text>
<Text style={styles.eventsErrorText}>Matches may not have been played yet.</Text>
</View> : <View>
<View style={{flexDirection: 'row', backgroundColor: '#010101'}}>
<Text style={{backgroundColor: '#010101', color: '#f9f9f9', padding: 8, paddingLeft: 58, width: 230}}>Players</Text>
<Text style={{backgroundColor: '#010101', color: '#f9f9f9', padding: 8}}>Losses</Text>
</View>
<ScrollView>
{props.standings.map(standing => (
<View key={standing.id} style={{flexDirection: 'row', borderBottomWidth: 1, borderBottomColor: 'gray'}}>
<Text key={standing.id} style={{padding: 8, width: 50, textAlign: 'center', backgroundColor: 'gray'}}>
{standing.standing}
</Text>
<Text style={{padding: 8, width: 180}}>{standing.name}</Text>
<View style={{padding: 8, flex: 1}}>{standing.losses.map(loss => <Text key={standing.id + loss} style={{flexShrink: 1}}>{loss}</Text>)}</View>
</View>
))}
</ScrollView>
</View>
);
const s = StyleSheet.flatten(styles.tournamentDetailsEventWrapper);
const Brackets = (props) => (
<SettingsList style={styles.tournamentEventsWrapper} borderWidth={s.borderBottomWidth} borderColor={s.borderBottomColor}>
{props.brackets.map(bracket => (
<Item key={bracket.name} itemWidth={50} title={bracket.name} backgroundColor={s.backgroundColor} style={styles.tournamentDetailsEventWrapper} titleStyle={styles.tournamentDetailsEventItem} onPress={() => props.onPress(bracket)} />
))}
</SettingsList>
);
@inject('Events') @observer
export default class EventInfoViewController extends MemeleeViewController {
state = {
standings: [],
brackets: []
};
componentWillMount() {
const evtSlugs = this.props.evt.slug.split('/');
const evtSlug = evtSlugs.length > 0 ? evtSlugs[evtSlugs.length - 1] : null;
const tournamentSlug = this.props.tournament.slugs[0].replace('tournament/', '');
if((evtSlug && evtSlug !== '') && (tournamentSlug && tournamentSlug != '')) {
SmashGG.fetchEventExpanded(tournamentSlug, evtSlug).then(this.updateBracketsData).catch(console.error);
SmashGG.fetchEventStandings(tournamentSlug, evtSlug).then(this.updateStandingsData).catch(console.error);
}
}
updateBracketsData = (data) => {
this.setState({brackets: data});
}
updateStandingsData = (data) => {
this.setState({standings: data});
}
state = {selectedIndex: 0};
onBracketPress = (bracket) => {
this.props.navigator.push({
screen: 'memelee.bracket',
screen: Constants.Screens.Bracket,
title: bracket.name,
backButtonTitle: 'Back',
passProps: {
@ -53,29 +74,25 @@ export default class EventInfoViewController extends MemeleeViewController {
});
}
render() {
return (<ScrollView>
<Text style={{padding: 8, backgroundColor: '#003366', fontSize: 16}}>Brackets</Text>
{this.state.brackets.map(bracket => (
<TouchableOpacity key={bracket.id} onPress={() => this.onBracketPress(bracket)}>
<Text style={{padding: 8, backgroundColor: 'gray'}}>{bracket.name}</Text>
</TouchableOpacity>
))}
swapIndex = (index) => {
this.setState({selectedIndex: index});
}
<Text style={{padding: 8, marginTop: 20, backgroundColor: '#003366', fontSize: 16}}>Standings</Text>
<View style={{flexDirection: 'row', backgroundColor: '#010101'}}>
<Text style={{backgroundColor: '#010101', color: '#f9f9f9', padding: 8, paddingLeft: 58, width: 230}}>Players</Text>
<Text style={{backgroundColor: '#010101', color: '#f9f9f9', padding: 8}}>Losses</Text>
</View>
{this.state.standings.map(standing => (
<View key={standing.id} style={{flexDirection: 'row', borderBottomWidth: 1, borderBottomColor: 'gray'}}>
<Text key={standing.id} style={{padding: 8, width: 50, textAlign: 'center', backgroundColor: 'gray'}}>
{standing.finalPlacement}
</Text>
<Text style={{padding: 8, width: 180}}>{standing.name}</Text>
<View style={{padding: 8, flex: 1}}>{standing.losses.map(loss => <Text key={standing.id + loss} style={{flexShrink: 1}}>{loss}</Text>)}</View>
</View>
))}
</ScrollView>);
render() {
return (<View>
<SegmentedControlTab values={['Standings', 'Brackets']} borderRadius={0} activeTabStyle={styles.tournamentInfoActiveTableStyle} tabStyle={styles.tournamentInfoTabsStyle} tabTextStyle={styles.tournamentInfoTabTextStyle} selectedIndex={this.state.selectedIndex} onTabPress={this.swapIndex} />
{this.state.selectedIndex === 0 ?
this.props.Events.fetchingStandingData ?
<Loading /> : <Standings standings={this.props.Events.standings} error={this.props.Events.standingsError} />
: null
}
{this.state.selectedIndex === 1 ?
this.props.Events.fetchingBracketData ?
<Loading /> : <Brackets error={this.props.Events.standingsError} brackets={this.props.Events.phases} onPress={this.onBracketPress} />
: null
}
</View>);
}
}

View file

@ -0,0 +1,28 @@
/**
* AttendeesListViewController
*
* Yeah, I do it iOS style. Handles fetching and displaying upcoming tournaments.
*
* @copyright Ryan McGrath 2018.
*/
import React from 'react';
import {ScrollView, View} from 'react-native';
import Markdown from 'react-native-markdown-renderer';
import Hyperlink from 'react-native-hyperlink';
import styles from '../styles';
import Constants from '../utils/Constants';
import MemeleeViewController from './MemeleeViewController';
export default class GenericInfoViewController extends MemeleeViewController {
render = () => (<ScrollView>
<View style={styles.tournamentDetailsTextWrapper}>
<Hyperlink>
<Markdown style={styles.tournamentDetailsText}>
{this.props.info && this.props.info !== '' ? this.props.info : ''}
</Markdown>
</Hyperlink>
</View>
</ScrollView>);
}

View file

@ -0,0 +1,34 @@
/**
* AttendeesListViewController
*
* Yeah, I do it iOS style. Handles fetching and displaying upcoming tournaments.
*
* @copyright Ryan McGrath 2018.
*/
import moment from 'moment';
import React from 'react';
import {FlatList, View, ActivityIndicator} from 'react-native';
import {inject, observer} from 'mobx-react/native';
import {SearchBar} from 'react-native-elements';
import styles from '../styles';
import Constants from '../utils/Constants';
import MemeleeViewController from './MemeleeViewController';
import TournamentRow from './components/TournamentRow';
const keyExtractor = (item, index) => item.id;
export default class AttendeesListViewController extends MemeleeViewController {
renderItem = ({item}) => (<View />)
render() {
const props = {
data: this.props.data,
keyExtractor: keyExtractor,
renderItem: this.renderItem
};
return <FlatList {...props} renderItem={this.renderItem} />
}
}

View file

@ -9,12 +9,15 @@
import moment from 'moment';
import React from 'react';
import {ScrollView, StyleSheet, Image, Text, View, TouchableOpacity, Dimensions} from 'react-native';
//import Markdown from 'react-native-simple-markdown'
import Markdown from 'react-native-markdown-renderer';
import Markdown, {PluginContainer} from 'react-native-markdown-renderer';
import SegmentedControlTab from 'react-native-segmented-control-tab';
import SettingsList, {Header, Item} from 'react-native-settings-list';
import linkify from 'linkify-it';
import styles from '../styles';
import Constants from '../utils/Constants';
import {openURL, parseSlugs} from '../utils';
import EventsStore from '../stores/TournamentEventStore';
import MemeleeViewController from './MemeleeViewController';
const w = Dimensions.get('screen').width;
@ -31,41 +34,126 @@ const w = Dimensions.get('screen').width;
export default class TournamentInfoViewController extends MemeleeViewController {
state = {
selectedIndex: 0
selectedIndex: 0,
tabs: []
};
componentWillMount = () => {
const tabs = [
{slug: 'attendees', name: 'Attendees', screen: Constants.Screens.Attendees, adminOnly: false},
{slug: 'location', name: 'Location', screen: Constants.Screens.Location, adminOnly: false},
{slug: 'contact', name: 'Contact', screen: Constants.Screens.Contact, adminOnly: false}
];
if(this.props.tournament.rules && this.props.tournament.rules !== '') {
if(this.props.tournament.rules.startsWith('http://') || this.props.tournament.rules.startsWith('https://')) {
tabs.push({slug: 'rules', name: 'Rules', url: this.props.tournament.rules, adminOnly: false});
} else {
tabs.push({slug: 'rules', name: 'Rules', info: this.props.tournament.rules, adminOnly: false});
}
}
if(this.props.tournament.prizes && this.props.tournament.prizes !== '') {
if(this.props.tournament.prizes.startsWith('http://') || this.props.tournament.prizes.startsWith('https://')) {
tabs.push({slug: 'prizes', name: 'Prizes', url: this.props.tournament.prizes, adminOnly: false});
} else {
tabs.push({slug: 'prizes', name: 'Prizes', info: this.props.tournament.prizes, adminOnly: false});
}
}
if(this.props.tournament.publishing && this.props.tournament.publishing.fantasy)
tabs.push({
slug: 'fantasy',
name: 'Fantasy',
url: 'https://smash.gg/tournament/' + parseSlugs(this.props.tournament, null).tournament + '/fantasy/',
adminOnly: false
});
const generatedTabs = this.props.tournament.generatedTabs;
if(generatedTabs) {
const objs = Object.keys(generatedTabs).map(key => generatedTabs[key]);
objs.forEach(tab => {
Object.keys(tab).map(key => ({
slug: key,
name: tab[key].name,
adminOnly: tab[key].adminOnly
})).filter(tab => !tab.adminOnly || tab.adminOnly === false).forEach(tab => tabs.push(tab));
});
}
this.setState({tabs: tabs});
}
onEventTapped = (evt) => {
EventsStore.loadEventData(this.props.tournament, evt);
this.props.navigator.push({
screen: 'memelee.tournamentEventInfoScreen',
screen: Constants.Screens.TournamentEventInfoScreen,
title: evt.name,
passProps: {tournament: this.props.tournament, evt: evt},
navigatorStyle: {tabBarHidden: true}
});
}
handleTab = (tab) => {
if(tab.screen)
return this.props.navigator.push({
screen: tab.screen,
title: tab.name,
passProps: {data: []},
navigatorStyle: {tabBarHidden: true}
});
if(tab.url)
return openURL(tab.url);
if(tab.info)
return this.props.navigator.push({
screen: Constants.Screens.Info,
title: tab.name,
passProps: {info: tab.info},
navigatorStyle: {tabBarHidden: true}
});
}
swapIndex = (index) => {
this.setState({
selectedIndex: index
});
}
plugins = []
render() {
const s = StyleSheet.flatten(styles.tournamentDetailsEventWrapper);
const ss = {
itemWidth: 50,
backgroundColor: s.backgroundColor,
style: styles.tournamentDetailsEventWrapper,
titleStyle: styles.tournamentDetailsEventItem
};
return (<ScrollView>
<Image style={[styles.tournamentInfoHeader, {width: w}]} source={this.props.tournament.memeleePromoImage.msrc} />
<SegmentedControlTab values={['Overview', 'Events']} borderRadius={0} activeTabStyle={styles.tournamentInfoActiveTableStyle} tabStyle={styles.tournamentInfoTabsStyle} tabTextStyle={styles.tournamentInfoTabTextStyle} selectedIndex={this.state.selectedIndex} onTabPress={this.swapIndex} />
{this.state.selectedIndex === 0 ? (<View style={styles.tournamentDetailsTextWrapper}>
<Markdown style={styles.tournamentDetailsText}>
{this.props.tournament.details && this.props.tournament.details !== '' ? this.props.tournament.details : ''}
</Markdown>
</View>) : null}
{this.state.selectedIndex === 0 ? (<View>
<View style={styles.tournamentDetailsTextWrapper}>
<Markdown style={styles.tournamentDetailsText} plugins={this.plugins}>
{this.props.tournament.details && this.props.tournament.details !== '' ? this.props.tournament.details : ''}
</Markdown>
</View>
<SettingsList style={styles.tournamentEventsWrapper} borderWidth={s.borderBottomWidth} borderColor={s.borderBottomColor}>
{this.state.tabs.map(tab => <Item key={tab.slug} {...ss} title={tab.name} onPress={() => this.handleTab(tab)} />)}
</SettingsList>
</View>
) : null}
{this.state.selectedIndex === 1 ? (<SettingsList style={styles.tournamentEventsWrapper} borderWidth={s.borderBottomWidth} borderColor={s.borderBottomColor}>
{this.props.tournament.memeleeEvents.map(evt => (
<Item key={evt.id} itemWidth={50} title={evt.name} backgroundColor={s.backgroundColor} style={styles.tournamentDetailsEventWrapper} titleStyle={styles.tournamentDetailsEventItem} />
<Item key={evt.id} itemWidth={50} title={evt.name} backgroundColor={s.backgroundColor} style={styles.tournamentDetailsEventWrapper} titleStyle={styles.tournamentDetailsEventItem} onPress={() => this.onEventTapped(evt)} />
))}
</SettingsList>) : null}
</ScrollView>);

View file

@ -13,6 +13,7 @@ import {inject, observer} from 'mobx-react/native';
import {SearchBar} from 'react-native-elements';
import styles from '../styles';
import Constants from '../utils/Constants';
import MemeleeViewController from './MemeleeViewController';
import TournamentRow from './components/TournamentRow';
@ -26,7 +27,7 @@ export default class UpcomingTournamentsViewController extends MemeleeViewContro
onTap = (tournament) => {
this.props.navigator.push({
screen: 'memelee.tournamentInfoScreen',
screen: Constants.Screens.TournamentInfoScreen,
title: tournament.name,
passProps: {tournament: tournament},
navigatorStyle: {tabBarHidden: true}

View file

@ -37,8 +37,7 @@ export default class TournamentRow extends React.Component {
<Icon name="map-marker" size={16} color={styles.tournamentPromoIconColors.mapMarker} /> {this.props.tournament.hasOnlineEvents && (!this.props.tournament.city || this.props.tournament.city === '') ? 'Online' : (this.props.tournament.city ? this.props.tournament.city + ', ' : '') + this.props.tournament.addrState}</Text>
<View style={{flexDirection: 'row'}}>
<Text style={styles.tournamentRowEventsCount}>
<Icon name="trophy-variant" size={16} color={styles.tournamentPromoIconColors.eventsCount} />
{this.props.tournament.memeleeEventsCount} Events
<Icon name="trophy-variant" size={16} color={styles.tournamentPromoIconColors.eventsCount} /> {this.props.tournament.memeleeEventsCount} Events
</Text>
<Text style={[styles.tournamentRowEventsCount, {marginLeft: 10}]}>
<Icon name="human-greeting" size={16} color={styles.tournamentPromoIconColors.attendeesCount} /> {this.props.tournament.attendeeCount} Attendees