mirror of
https://github.com/mgerb/classic-wow-forums
synced 2026-01-10 09:02:50 +00:00
client - forum nav should be working
This commit is contained in:
BIN
client/app/assets/forum-nav-header-bg.gif
Normal file
BIN
client/app/assets/forum-nav-header-bg.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 5.6 KiB |
BIN
client/app/assets/header-rogue.gif
Normal file
BIN
client/app/assets/header-rogue.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.7 KiB |
BIN
client/app/assets/wow-base-guild.gif
Normal file
BIN
client/app/assets/wow-base-guild.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.1 KiB |
BIN
client/app/assets/wow-base-roleplaying.gif
Normal file
BIN
client/app/assets/wow-base-roleplaying.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.0 KiB |
@@ -1,6 +1,15 @@
|
||||
.forum-nav {
|
||||
display: inline-block;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding-left: 5px;
|
||||
position: relative;
|
||||
bottom: 10;
|
||||
background-image: url('../../assets/forum-nav-header-bg.gif');
|
||||
background-repeat: no-repeat;
|
||||
height: 51px;
|
||||
width: 300px;
|
||||
overflow: hidden;
|
||||
|
||||
&__title {
|
||||
height: 27px;
|
||||
line-height: 27px;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,20 +1,125 @@
|
||||
import React from 'react';
|
||||
import { get, find, reject } from 'lodash';
|
||||
import { RouteComponentProps } from 'react-router-dom';
|
||||
import { CategoryService } from '../../services';
|
||||
import { CategoryModel } from '../../model';
|
||||
import './forum-nav.scss';
|
||||
|
||||
interface Props {}
|
||||
interface Props extends RouteComponentProps<any> {
|
||||
categoryId: number;
|
||||
}
|
||||
|
||||
interface State {}
|
||||
interface State {
|
||||
categoryList: CategoryModel[];
|
||||
selectedCategory?: CategoryModel;
|
||||
}
|
||||
|
||||
export class ForumNav extends React.Component<Props, State> {
|
||||
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
categoryList: [],
|
||||
};
|
||||
}
|
||||
|
||||
async componentDidMount() {
|
||||
const categoryList = await CategoryService.getCategories();
|
||||
this.setState({ categoryList });
|
||||
this.setSelectedCategory(categoryList, this.props.categoryId!);
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps: Props) {
|
||||
if (this.props.categoryId !== nextProps.categoryId) {
|
||||
this.setSelectedCategory(this.state.categoryList, nextProps.categoryId!);
|
||||
}
|
||||
}
|
||||
|
||||
setSelectedCategory(categoryList: CategoryModel[], categoryId: number) {
|
||||
const selectedCategory = find(categoryList, { id: categoryId });
|
||||
this.setState({ selectedCategory });
|
||||
}
|
||||
|
||||
getImageSrc(): string {
|
||||
if (this.state.selectedCategory!.category === 'realm') {
|
||||
return topicIcons['Realm Forums'];
|
||||
}
|
||||
|
||||
return topicIcons[this.state.selectedCategory!.title];
|
||||
}
|
||||
|
||||
renderDropDown() {
|
||||
let categories: any = reject(this.state.categoryList, { category: 'realm' });
|
||||
categories = [{ id: -1, title: 'Realm Forums' }, ...categories];
|
||||
return categories.map((val: any, index: number) => {
|
||||
return <option key={index} value={val.id}>{val.title}</option>;
|
||||
});
|
||||
}
|
||||
|
||||
getSelectedCategoryId(): number {
|
||||
const { selectedCategory } = this.state;
|
||||
if (!selectedCategory) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (selectedCategory.category === 'realm') {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return selectedCategory.id;
|
||||
}
|
||||
|
||||
onSelect(event: any) {
|
||||
const route = event.target.value === '-1' ? '/realms' : `/f/${event.target.value}`;
|
||||
this.props.history.push(route);
|
||||
}
|
||||
|
||||
render() {
|
||||
const { selectedCategory } = this.state;
|
||||
const imageSrc = selectedCategory ? this.getImageSrc() : undefined;
|
||||
|
||||
return (
|
||||
<div>
|
||||
<img src={require('../../assets/wow-base-general.gif')}/>
|
||||
<div className="flex">
|
||||
<img src={imageSrc} />
|
||||
<div className="forum-nav">
|
||||
<small>Forum Nav:</small><select style={{ minWidth: '194px' }}></select>
|
||||
<div className="forum-nav__title">
|
||||
<b>{get(selectedCategory, 'title')}</b>
|
||||
</div>
|
||||
<div className="flex flex--center">
|
||||
<small>Forum Nav:</small>
|
||||
<select style={{ minWidth: '194px', height: '19px' }}
|
||||
value={this.getSelectedCategoryId()}
|
||||
onChange={event => this.onSelect(event)}>
|
||||
{this.state.categoryList && this.renderDropDown()}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const topicIcons: {[key: string]: string} = {
|
||||
['Bug Report Forum']: require('../../assets/wow-base-bugs.gif'),
|
||||
['Druid']: require('../../assets/wow-base-druid.gif'),
|
||||
['Raid and Dungeon Discussion']: require('../../assets/wow-base-dungeons.gif'),
|
||||
['General Discussion']: require('../../assets/wow-base-general.gif'),
|
||||
['Hunter']: require('../../assets/wow-base-hunter.gif'),
|
||||
['Mage']: require('../../assets/wow-base-mage.gif'),
|
||||
['Off-topic']: require('../../assets/wow-base-offtopic.gif'),
|
||||
['Paladin']: require('../../assets/wow-base-paladin.gif'),
|
||||
['Priest']: require('../../assets/wow-base-priest.gif'),
|
||||
['Professions']: require('../../assets/wow-base-professions.gif'),
|
||||
['PvP Discussion']: require('../../assets/wow-base-pvp.gif'),
|
||||
['Quest Discussion']: require('../../assets/wow-base-quests.gif'),
|
||||
['Realm Forums']: require('../../assets/wow-base-realms.gif'),
|
||||
['Rogue']: require('../../assets/wow-base-rogue.gif'),
|
||||
['Shaman']: require('../../assets/wow-base-shaman.gif'),
|
||||
['Suggestions']: require('../../assets/wow-base-suggestions.gif'),
|
||||
['Site Suggestions']: require('../../assets/wow-base-support.gif'),
|
||||
['UI & Macros Forum']: require('../../assets/wow-base-uicustomizations.gif'),
|
||||
['Warlock']: require('../../assets/wow-base-warlock.gif'),
|
||||
['Warrior']: require('../../assets/wow-base-warrior.gif'),
|
||||
['Guild Recruitment']: require('../../assets/wow-base-guild.gif'),
|
||||
['Role-Playing']: require('../../assets/wow-base-roleplaying.gif'),
|
||||
};
|
||||
|
||||
@@ -35,6 +35,7 @@ export class LoginButton extends React.Component<Props, State> {
|
||||
</div>
|
||||
<div style={{ textAlign: 'center' }}>
|
||||
{!avatarSrc && <p><a onClick={() => this.props.onNavigate('/user-account')}>Account</a></p>}
|
||||
<div><b>{this.props.userStore!.user!.battletag}</b></div>
|
||||
<div><b>{this.props.userStore!.user!.character_name}</b></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -21,18 +21,25 @@ export class Forum extends React.Component<Props, State> {
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.getThreads();
|
||||
this.getThreads(this.props.match.params['id']);
|
||||
}
|
||||
|
||||
private async getThreads() {
|
||||
const threads = await ThreadService.getCategoryThreads(this.props.match.params['id']);
|
||||
// update the page if the route params change
|
||||
componentWillReceiveProps(nextProps: Props) {
|
||||
if (this.props.match.params !== nextProps.match.params) {
|
||||
this.getThreads(nextProps.match.params['id']);
|
||||
}
|
||||
}
|
||||
|
||||
private async getThreads(categoryId: string) {
|
||||
const threads = await ThreadService.getCategoryThreads(categoryId);
|
||||
this.setState({ threads });
|
||||
}
|
||||
|
||||
renderHeader() {
|
||||
return (
|
||||
<div className="forum-header">
|
||||
<ForumNav />
|
||||
<ForumNav categoryId={parseInt(this.props.match.params['id'], 10)} {...this.props}/>
|
||||
<div style={{ height: '100%' }}>
|
||||
<LoginButton onNavigate={dest => this.props.history.push(dest)}/>
|
||||
</div>
|
||||
@@ -68,11 +75,12 @@ export class Forum extends React.Component<Props, State> {
|
||||
}
|
||||
|
||||
renderThreadRows() {
|
||||
const categoryId = this.props.match.params['id'];
|
||||
return this.state.threads.map((thread, index) => {
|
||||
return (
|
||||
<div className={`forum-row ${index % 2 === 0 && 'forum-row--dark'}`} key={index}>
|
||||
{this.renderCell('flag', { maxWidth: '50px' })}
|
||||
{this.renderCell(<Link to={`/thread/${thread.id}`}>{thread.title}</Link>, { minWidth: '200px' })}
|
||||
{this.renderCell(<Link to={`/f/${categoryId}/${thread.id}`}>{thread.title}</Link>, { minWidth: '200px' })}
|
||||
{this.renderCell(<b>{thread.user.battletag}</b>, { maxWidth: '150px' })}
|
||||
{this.renderCell(<b>{thread.reply_count}</b>, { maxWidth: '150px' }, true)}
|
||||
{this.renderCell(<b>{thread.view_count}</b>, { maxWidth: '150px' }, true)}
|
||||
@@ -88,7 +96,7 @@ export class Forum extends React.Component<Props, State> {
|
||||
<div className="forum-table">
|
||||
|
||||
<div className="forum-row forum-row--header">
|
||||
<div className="forum-cell forum-cell--header flex-1">Test</div>
|
||||
<div className="forum-cell forum-cell--header flex-1">TODO:</div>
|
||||
</div>
|
||||
|
||||
<div className="forum-row forum-row--header">
|
||||
|
||||
@@ -6,7 +6,7 @@ import './home.scss';
|
||||
|
||||
import header_forms from '../../assets/header-forums.gif';
|
||||
import support from '../../assets/support.gif';
|
||||
import serverstatus from '../../assets/serverstatus.gif';
|
||||
// import serverstatus from '../../assets/serverstatus.gif';
|
||||
import uicustomizations from '../../assets/uicustomizations.gif';
|
||||
import bugs from '../../assets/bugs.gif';
|
||||
import realms from '../../assets/realms.gif';
|
||||
@@ -42,23 +42,23 @@ export class Home extends React.Component<Props, State> {
|
||||
super(props);
|
||||
}
|
||||
|
||||
private renderTopic(link: string, title: string, icon: any, text: string): any {
|
||||
private renderTopic(topicId: number | string, title: string, icon: any, text: string): any {
|
||||
return (
|
||||
<div className="topic-item">
|
||||
<img className="topic-item-icon" src={icon}/>
|
||||
<img className="topic-item-icon" src={icon} />
|
||||
<div>
|
||||
<Link to={link}>{title}</Link>
|
||||
<Link to={typeof topicId === 'number' ? `/f/${topicId}` : topicId}>{title}</Link>
|
||||
<div>{text}</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
private renderClass(title: string, url: string, icon: any): any {
|
||||
private renderClass(title: string, topicId: number, icon: any): any {
|
||||
return (
|
||||
<div className="flex flex--center" style={{ flex: 1 }}>
|
||||
<img className="topic-item-icon" src={icon}/>
|
||||
<a href={url}>{title}</a>
|
||||
<img className="topic-item-icon" src={icon} />
|
||||
<Link to={`/f/${topicId}`}>{title}</Link>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -67,19 +67,19 @@ export class Home extends React.Component<Props, State> {
|
||||
return (
|
||||
<div className="classes-container">
|
||||
<div className="item-row item-row__class">
|
||||
{this.renderClass('Druid', '#', druid)}
|
||||
{this.renderClass('Rogue', '#', rogue)}
|
||||
{this.renderClass('Priest', '#', priest)}
|
||||
{this.renderClass('Druid', 0, druid)}
|
||||
{this.renderClass('Rogue', 1, rogue)}
|
||||
{this.renderClass('Priest', 2, priest)}
|
||||
</div>
|
||||
<div className="item-row item-row__class">
|
||||
{this.renderClass('Hunter', '#', hunter)}
|
||||
{this.renderClass('Shaman', '#', shaman)}
|
||||
{this.renderClass('Warrior', '#', warrior)}
|
||||
{this.renderClass('Hunter', 3, hunter)}
|
||||
{this.renderClass('Shaman', 4, shaman)}
|
||||
{this.renderClass('Warrior', 5, warrior)}
|
||||
</div>
|
||||
<div className="item-row item-row__class">
|
||||
{this.renderClass('Mage', '#', mage)}
|
||||
{this.renderClass('Paladin', '#', paladin)}
|
||||
{this.renderClass('Warlock', '#', warlock)}
|
||||
{this.renderClass('Mage', 6, mage)}
|
||||
{this.renderClass('Paladin', 7, paladin)}
|
||||
{this.renderClass('Warlock', 8, warlock)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
@@ -101,20 +101,33 @@ export class Home extends React.Component<Props, State> {
|
||||
|
||||
<div className="topic-container">
|
||||
<div className="topic-row">
|
||||
{this.renderTopic('#', 'Technical Support', support, `If you're experiencing technical problems playing World of Warcraft, post here for assistance.`)}
|
||||
{this.renderTopic('#', 'Realm Status', serverstatus, `Collection of important messages regarding the status of the Realms.`)}
|
||||
{this.renderTopic(
|
||||
137,
|
||||
'Site Suggestions',
|
||||
support,
|
||||
`Have a suggestion for this site? Please post it here.`,
|
||||
)}
|
||||
{ /* maybe add realm status in the future */
|
||||
/* {this.renderTopic(
|
||||
'#', 'Realm Status', serverstatus,
|
||||
`Collection of important messages regarding the status of the Realms.`)} */}
|
||||
</div>
|
||||
<div className="topic-row">
|
||||
{this.renderTopic('#', 'UI & Macros Forum', uicustomizations, `Work with other players to create your own special custom interfaces and macros.`)}
|
||||
{this.renderTopic('#', 'Bug Report Forum', bugs, `Found a bug in the game? Help us squash it by reporting it here!`)}
|
||||
{this.renderTopic(
|
||||
138,
|
||||
'UI & Macros Forum',
|
||||
uicustomizations,
|
||||
`Work with other players to create your own special custom interfaces and macros.`,
|
||||
)}
|
||||
{this.renderTopic(139, 'Bug Report Forum', bugs, `Found a bug on this site? Help us squash it by reporting it here!`)}
|
||||
</div>
|
||||
|
||||
<hr/>
|
||||
<hr />
|
||||
|
||||
<div className="topic-row topic-row__classes">
|
||||
<div className="topic-item topic-item__classes">
|
||||
<div className="flex" style={{ marginBottom: '10px' }}>
|
||||
<img className="topic-item-icon" src={bullet}/>
|
||||
<img className="topic-item-icon" src={bullet} />
|
||||
<div>
|
||||
<b>Classes</b>
|
||||
<div>Discuss your favorite class:</div>
|
||||
@@ -125,50 +138,62 @@ export class Home extends React.Component<Props, State> {
|
||||
|
||||
<div className="topic-item topic-item__classes">
|
||||
<div className="item-row" style={{ minWidth: '250px' }}>
|
||||
<img className="topic-item-icon" src={professions}/>
|
||||
<img className="topic-item-icon" src={professions} />
|
||||
<div>
|
||||
<a href="#">Professions</a>
|
||||
<Link to="/f/140">Professions</Link>
|
||||
<div>Discuss professions in detail.</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="item-row">
|
||||
<img className="topic-item-icon" src={pvp}/>
|
||||
<img className="topic-item-icon" src={pvp} />
|
||||
<div>
|
||||
<a href="#">PvP Discussion</a>
|
||||
<Link to="/f/141">PvP Discussion</Link>
|
||||
<div>Discuss player versus player combat.</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="item-row">
|
||||
<img className="topic-item-icon" src={quests}/>
|
||||
<img className="topic-item-icon" src={quests} />
|
||||
<div>
|
||||
<a href="#">Quest Discussion</a>
|
||||
<Link to="/f/142">Quest Discussion</Link>
|
||||
<div>Talk about and get help with the countless quests in World of Warcraft.</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div className="topic-row">
|
||||
{this.renderTopic('/realms', 'Realm Forums', realms, `Discuss topics related to World of Warcraft with players on your specific Realm.`)}
|
||||
{this.renderTopic('#', 'Off-topic', offtopic, `Off-topic posts of interest to the World of Warcraft community.`)}
|
||||
{this.renderTopic(
|
||||
'/realms',
|
||||
'Realm Forums',
|
||||
realms,
|
||||
`Discuss topics related to World of Warcraft with players on your specific Realm.`,
|
||||
)}
|
||||
{this.renderTopic(131, 'Off-topic', offtopic, `Off-topic posts of interest to the World of Warcraft community.`)}
|
||||
</div>
|
||||
<div className="topic-row">
|
||||
{this.renderTopic('#', 'Suggestions', suggestions, `Have a suggestion for World of Warcraft? Please post it here.`)}
|
||||
{this.renderTopic('#', 'Guild Recruitment', guilds, `Searching for a guild, or do you want to advertise your guild?`)}
|
||||
{this.renderTopic(134, 'Suggestions', suggestions, `Have a suggestion for World of Warcraft? Please post it here.`)}
|
||||
{this.renderTopic(132, 'Guild Recruitment', guilds, `Searching for a guild, or do you want to advertise your guild?`)}
|
||||
</div>
|
||||
<div className="topic-row">
|
||||
{this.renderTopic('#', 'Role-Playing', roleplaying, `Pull up a chair, drink a mug of ale, meet new friends, tell stories, and role-play in this forum.`)}
|
||||
{this.renderTopic('#', 'General Discussion.', general, `Discuss World of Warcraft.`)}
|
||||
{this.renderTopic(
|
||||
135,
|
||||
'Role-Playing',
|
||||
roleplaying,
|
||||
`Pull up a chair, drink a mug of ale, meet new friends, tell stories, and role-play in this forum.`,
|
||||
)}
|
||||
{this.renderTopic(133, 'General Discussion.', general, `Discuss World of Warcraft.`)}
|
||||
</div>
|
||||
<div className="topic-row">
|
||||
{this.renderTopic('#', 'Raid and Dungeon Discussion', dungeons, `Discuss the instance dungeons and end-game raid encounters in World of Warcraft.`)}
|
||||
{this.renderTopic(
|
||||
136,
|
||||
'Raid and Dungeon Discussion',
|
||||
dungeons,
|
||||
`Discuss the instance dungeons and end-game raid encounters in World of Warcraft.`,
|
||||
)}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<hr/>
|
||||
|
||||
<hr />
|
||||
</ContentContainer>
|
||||
</ScrollToTop>
|
||||
);
|
||||
|
||||
@@ -24,7 +24,7 @@ export class Thread extends React.Component<Props, State> {
|
||||
}
|
||||
|
||||
private async getThreads() {
|
||||
const thread = await ThreadService.getThread(this.props.match.params['id']);
|
||||
const thread = await ThreadService.getThread(this.props.match.params['threadId']);
|
||||
thread.replies = [thread as any, ...thread.replies]; // add the thread topic to the front of the list
|
||||
this.setState({ thread });
|
||||
}
|
||||
@@ -71,7 +71,8 @@ export class Thread extends React.Component<Props, State> {
|
||||
<ScrollToTop {...this.props}>
|
||||
|
||||
<div style={{ padding: '16px 0 12px 0' }}>
|
||||
<ForumNav/>
|
||||
{/* todo: */}
|
||||
<ForumNav categoryId={parseInt(this.props.match.params['categoryId'], 10)} {...this.props}/>
|
||||
</div>
|
||||
|
||||
<div className="topic-bg">
|
||||
|
||||
@@ -52,7 +52,6 @@ export class UserAccount extends React.Component<Props, State> {
|
||||
this.setState({ noCharacters: true });
|
||||
return;
|
||||
}
|
||||
// remove classes that weren't in vanilla
|
||||
const characters = groupBy(res.characters, 'realm');
|
||||
this.setState({
|
||||
characters,
|
||||
|
||||
@@ -45,9 +45,9 @@ export class Routes extends React.Component<Props, State> {
|
||||
<Route exact path="/" component={Home} />
|
||||
<Route exact path="/realms" component={Realms} />
|
||||
<Route exact path="/f/:id" component={Forum} />
|
||||
<Route exact path="/f/:categoryId/:threadId" component={Thread} />
|
||||
<Route exact path="/oauth" component={Oauth} />
|
||||
<Route exact path="/user-account" component={UserAccount} />
|
||||
<Route exact path="/thread/:id" component={Thread} />
|
||||
<Route component={NotFound} />
|
||||
</Switch>
|
||||
<Footer />
|
||||
|
||||
@@ -165,12 +165,18 @@ defmodule Category do
|
||||
|
||||
defp get_other() do
|
||||
[
|
||||
%{"id" => 131, "category" => "other", "title" => "Off-Topic"},
|
||||
%{"id" => 131, "category" => "other", "title" => "Off-topic"},
|
||||
%{"id" => 132, "category" => "other", "title" => "Guild Recruitment"},
|
||||
%{"id" => 133, "category" => "other", "title" => "General Discussion"},
|
||||
%{"id" => 134, "category" => "other", "title" => "Suggestions"},
|
||||
%{"id" => 135, "category" => "other", "title" => "Role-Playing"},
|
||||
%{"id" => 136, "category" => "other", "title" => "Raid and Dungeon Discussion"},
|
||||
%{"id" => 137, "category" => "other", "title" => "Site Suggestions"},
|
||||
%{"id" => 138, "category" => "other", "title" => "UI & Macros Forum"},
|
||||
%{"id" => 139, "category" => "other", "title" => "Bug Report Forum"},
|
||||
%{"id" => 140, "category" => "other", "title" => "Professions"},
|
||||
%{"id" => 141, "category" => "other", "title" => "PvP Discussion"},
|
||||
%{"id" => 142, "category" => "other", "title" => "Quest Discussion"},
|
||||
]
|
||||
end
|
||||
|
||||
|
||||
Reference in New Issue
Block a user