1
0
mirror of https://github.com/mgerb/classic-wow-forums synced 2026-01-09 16:42:49 +00:00

client - thread page work

This commit is contained in:
2018-01-10 23:45:02 -06:00
parent 8eb31b984e
commit 991e1bfe5a
45 changed files with 367 additions and 120 deletions

BIN
client/app/assets/Tyren.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

BIN
client/app/assets/blizz.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 314 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 371 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 464 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 313 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 401 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 373 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 749 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 687 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

View File

@@ -0,0 +1,6 @@
.forum-nav {
display: inline-block;
padding-left: 5px;
position: relative;
bottom: 10;
}

View File

@@ -0,0 +1,20 @@
import React from 'react';
import './forum-nav.scss';
interface Props {}
interface State {}
export class ForumNav extends React.Component<Props, State> {
render() {
return (
<div>
<img src={require('../../assets/wow-base-general.gif')}/>
<div className="forum-nav">
<small>Forum Nav:</small><select style={{ minWidth: '194px' }}></select>
</div>
</div>
);
}
}

View File

@@ -1,4 +1,7 @@
export * from './content-container/content-container';
export * from './footer/footer';
export * from './forum-nav/forum-nav';
export * from './header/header';
export * from './login-button/login-button';
export * from './portrait/portrait';
export * from './scroll-to-top/scroll-to-top';

View File

@@ -0,0 +1,9 @@
.portrait {
position: relative;
&__level-circle {
position: absolute;
top: 8px;
left: 8px;
}
}

View File

@@ -0,0 +1,29 @@
import React from 'react';
import './portrait.scss';
interface Props {
imageSrc: any;
}
interface State {
}
export class Portrait extends React.Component<Props, State> {
componentDidMount() {}
render() {
return (
<div className="portrait">
<img src={require('../../assets/portrait-top.gif')}/>
<div>
<img src={require('../../assets/level-circle.gif')} className="portrait__level-circle"/>
<img src={require('../../assets/portrait-left.gif')}/>
<img src={this.props.imageSrc}/>
<img src={require('../../assets/portrait-right.gif')}/>
</div>
<img src={require('../../assets/portrait-bot.gif')}/>
</div>
);
}
}

View File

@@ -0,0 +1,15 @@
import React from 'react';
export class ScrollToTop extends React.Component<any, any> {
constructor(props: any) {
super(props);
}
componentDidMount() {
window.scrollTo(0, 0);
}
render() {
return this.props.children;
}
}

View File

@@ -8,13 +8,6 @@ $grey2: #161616;
justify-content: space-between;
}
.forum-nav {
display: inline-block;
padding-left: 5px;
position: relative;
bottom: 10;
}
.forum-body {
min-height: 500px;
margin-bottom: 100px;

View File

@@ -2,7 +2,7 @@ import React from 'react';
import { Link, RouteComponentProps } from 'react-router-dom';
import { get } from 'lodash';
import { ThreadService } from '../../services';
import { LoginButton } from '../../components';
import { ForumNav, LoginButton, ScrollToTop } from '../../components';
import { ThreadModel } from '../../model';
import './forum.scss';
@@ -32,12 +32,7 @@ export class Forum extends React.Component<Props, State> {
renderHeader() {
return (
<div className="forum-header">
<div>
<img src={require('../../assets/wow-base-general.gif')}/>
<div className="forum-nav">
<small>Forum Nav:</small><select style={{ minWidth: '194px' }}></select>
</div>
</div>
<ForumNav />
<div style={{ height: '100%' }}>
<LoginButton/>
</div>
@@ -115,10 +110,10 @@ export class Forum extends React.Component<Props, State> {
render() {
return (
<div>
<ScrollToTop>
{this.renderHeader()}
{this.renderBody()}
</div>
</ScrollToTop>
);
}

View File

@@ -1,6 +1,6 @@
import React from 'react';
import { Link, RouteComponentProps } from 'react-router-dom';
import { ContentContainer } from '../../components';
import { ContentContainer, ScrollToTop } from '../../components';
import './home.scss';
@@ -87,88 +87,90 @@ export class Home extends React.Component<Props, State> {
render() {
return (
<ContentContainer>
<img src={header_forms} />
<div>
<b>Welcome to the World of Warcraft community forums!</b>
</div>
<p>
Blizzard provides the World of Warcraft community forums for its player to chat, exchange ideas, and submit feedback. Posting on
the World of Warcraft community forums requires a World of Warcraft account. Only customers are allowed to post on these forums,
but anyone can read them. Please note that you must adhere to the Forum Guidelines if you wish to post on the forums.
</p>
<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.`)}
<ScrollToTop>
<ContentContainer>
<img src={header_forms} />
<div>
<b>Welcome to the World of Warcraft community forums!</b>
</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!`)}
<p>
Blizzard provides the World of Warcraft community forums for its player to chat, exchange ideas, and submit feedback. Posting on
the World of Warcraft community forums requires a World of Warcraft account. Only customers are allowed to post on these forums,
but anyone can read them. Please note that you must adhere to the Forum Guidelines if you wish to post on the forums.
</p>
<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.`)}
</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!`)}
</div>
<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}/>
<div>
<b>Classes</b>
<div>Discuss your favorite class:</div>
</div>
</div>
{this.renderClasses()}
</div>
<div className="topic-item topic-item__classes">
<div className="item-row" style={{ minWidth: '250px' }}>
<img className="topic-item-icon" src={professions}/>
<div>
<a href="#">Professions</a>
<div>Discuss professions in detail.</div>
</div>
</div>
<div className="item-row">
<img className="topic-item-icon" src={pvp}/>
<div>
<a href="#">PvP Discussion</a>
<div>Discuss player versus player combat.</div>
</div>
</div>
<div className="item-row">
<img className="topic-item-icon" src={quests}/>
<div>
<a href="#">Quest Discussion</a>
<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.`)}
</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?`)}
</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.`)}
</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.`)}
</div>
</div>
<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}/>
<div>
<b>Classes</b>
<div>Discuss your favorite class:</div>
</div>
</div>
{this.renderClasses()}
</div>
<div className="topic-item topic-item__classes">
<div className="item-row" style={{ minWidth: '250px' }}>
<img className="topic-item-icon" src={professions}/>
<div>
<a href="#">Professions</a>
<div>Discuss professions in detail.</div>
</div>
</div>
<div className="item-row">
<img className="topic-item-icon" src={pvp}/>
<div>
<a href="#">PvP Discussion</a>
<div>Discuss player versus player combat.</div>
</div>
</div>
<div className="item-row">
<img className="topic-item-icon" src={quests}/>
<div>
<a href="#">Quest Discussion</a>
<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.`)}
</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?`)}
</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.`)}
</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.`)}
</div>
</div>
<hr/>
</ContentContainer>
</ContentContainer>
</ScrollToTop>
);
}
}

View File

@@ -3,7 +3,7 @@ import { chain } from 'lodash';
import { Link, RouteComponentProps } from 'react-router-dom';
import { CategoryService } from '../../services';
import { CategoryModel } from '../../model';
import { ContentContainer } from '../../components';
import { ContentContainer, ScrollToTop } from '../../components';
import './realms.scss';
import header_realmforums from '../../assets/header-realmforums.gif';
import realms_large from '../../assets/realms-large.gif';
@@ -49,6 +49,10 @@ export class Realms extends React.Component<Props, State> {
render() {
const { realms } = this.state;
if (realms.length === 0) {
return <div></div>;
}
// copy list so we don't modify state
const realmsCopy = realms.slice();
// split realms into 3 lists
@@ -56,32 +60,34 @@ export class Realms extends React.Component<Props, State> {
const list2 = realmsCopy.splice(0, realmsCopy.length / 2);
const list3 = realmsCopy;
return realms.length === 0 ? <div></div> : (
<ContentContainer>
<div className="flex flex--center">
<img src={realms_large}/>
<img src={header_realmforums}/>
</div>
return (
<ScrollToTop>
<ContentContainer>
<div className="flex flex--center">
<img src={realms_large}/>
<img src={header_realmforums}/>
</div>
<div style={{ margin: '15px 0' }}>
<div><b>Welcome to the World of Warcraft Realm Forums!</b></div>
<div>Use these forums to discuss topics related to World of Warcraft with player on your own Realm.</div>
</div>
<div style={{ margin: '15px 0' }}>
<div><b>Welcome to the World of Warcraft Realm Forums!</b></div>
<div>Use these forums to discuss topics related to World of Warcraft with player on your own Realm.</div>
</div>
<div className="flex flex--wrap">
<ul className="realm-column">
{this.renderRealms(list1)}
</ul>
<div className="flex flex--wrap">
<ul className="realm-column">
{this.renderRealms(list1)}
</ul>
<ul className="realm-column">
{this.renderRealms(list2)}
</ul>
<ul className="realm-column">
{this.renderRealms(list2)}
</ul>
<ul className="realm-column">
{this.renderRealms(list3)}
</ul>
</div>
</ContentContainer>
<ul className="realm-column">
{this.renderRealms(list3)}
</ul>
</div>
</ContentContainer>
</ScrollToTop>
);
}
}

View File

@@ -0,0 +1,88 @@
.topic-bg {
background-image: url('../../assets/topic-bg.gif');
background-repeat: repeat-x;
height: 41px;
display: flex;
justify-content: space-between;
align-items: center;
}
.threadTopic-container {
background-color: #0C0C0C;
border-style: solid;
border-width: 1px;
border-color: #8C8E89 #8C8E89 #0C0C0C #0C0C0C;
padding: 2px 10px 0 5px;
margin-top: 8px;
}
.threadTopic {
display: flex;
align-items: center;
}
.paging-bg {
background-image: url('../../assets/paging-bg.gif');
background-repeat: repeat-x;
height: 25px;
margin-bottom: 4px;
}
.reply-body {
background-color: #000000;
padding: 0 6px 4px 6px;
}
.reply-container {
background-color: #000000;
padding: 2px;
border: 1px solid #343434;
& + & {
margin-top: 3px;
}
}
.reply {
display: flex;
background-color: rgb(22, 22, 22);
// border: 1px solid #343434;
&__user-container {
display: flex;
align-items: center;
flex-direction: column;
padding: 4px;
width: 150px;
border-right: 1px solid #000000;
}
&__title {
display: flex;
align-items: center;
justify-content: space-between;
height: 26px;
border-bottom: 1px solid #000000;
padding: 0 6px;
color: white;
&__button {
cursor: pointer;
& + & {
margin-left: 3px;
}
}
}
&__content {
padding: 20px;
}
}
.forumliner-bot-bg {
background-image: url('../../assets/forumliner-bot-bg.gif');
background-repeat: repeat-x;
width: 100%;
height: 15px;
}

View File

@@ -1,25 +1,106 @@
import React from 'react';
import { RouteComponentProps } from 'react-router-dom';
import { get } from 'lodash';
import { ThreadService } from '../../services';
import { ForumNav, Portrait, ScrollToTop } from '../../components';
import { ThreadModel } from '../../model';
import './thread.scss';
interface Props extends RouteComponentProps<any> {}
interface State {}
interface State {
thread?: ThreadModel;
}
export class Thread extends React.Component<Props, State> {
constructor(props: Props) {
super(props);
this.state = {};
}
componentDidMount() {
this.getThreads();
}
private async getThreads() {
const thread = await ThreadService.getThread(this.props.match.params['id']);
console.log(thread);
thread.replies = [thread as any, ...thread.replies]; // add the thread topic to the front of the list
this.setState({ thread });
}
renderReplies(): any {
return this.state.thread!.replies.map((reply, index) => {
return (
<div className="reply-container" key={index}>
<div className="reply">
<div className="reply__user-container">
<Portrait imageSrc={require('../../assets/Tyren.gif')}/>
<div>Tyren</div>
<div>Blizzard Poster</div>
</div>
<div className="flex-1">
<div className="reply__title">
<div>
<b>{`${index + 1}. `}{this.state.thread!.title}</b>
<small style={{ paddingLeft: '5px' }}>| {reply.inserted_at}</small>
</div>
<div>
<img src={require('../../assets/quote-button.gif')} className="reply__title__button"/>
<img src={require('../../assets/reply-button.gif')} className="reply__title__button"/>
</div>
</div>
{/* TODO: xss sanitization */}
<div className="reply__content">{reply.content}</div>
</div>
</div>
</div>
);
});
}
private navigateForumIndex() {
this.props.history.push(`/f/${this.state.thread!.category_id}`);
}
render() {
const replies = get(this.state, 'thread.replies');
return (
<div></div>
<ScrollToTop {...this.props}>
<div style={{ padding: '16px 0 12px 0' }}>
<ForumNav/>
</div>
<div className="topic-bg">
<div className="threadTopic-container">
<div className="threadTopic">
<img src={require('../../assets/sticky.gif')} style={{ marginRight: '5px' }}/>
<b>Topic: </b><small style={{ paddingLeft: '15px', color: 'white' }}>| 12/20/2005 1:11:44 AM PST</small>
</div>
</div>
<img src={require('../../assets/forum-index.gif')}
onClick={() => this.navigateForumIndex()}
style={{ cursor: 'pointer' }}
/>
</div>
<div className="paging-bg"/>
<div className="reply-body">
{replies && this.renderReplies()}
</div>
<div className="paging-bg"/>
<div className="forumliner-bot-bg"/>
<img src={require('../../assets/forum-index-bot.gif')}
onClick={() => this.navigateForumIndex()}
style={{ cursor: 'pointer', float: 'right' }}
/>
<div style={{ height: '200px' }}/>
</ScrollToTop>
);
}
}