Skip to content

Commit 1a53751

Browse files
committed
Implement forum
1 parent da1c914 commit 1a53751

File tree

4 files changed

+148
-1
lines changed

4 files changed

+148
-1
lines changed

views/components/Forum/Container.jsx

Lines changed: 55 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,67 @@
22

33
import React, { Component, PropTypes } from 'react';
44
import styles from '../Shared/styles/container.css';
5+
import Thread from './Thread';
6+
7+
const noDate = 0;
8+
9+
function getLatestUpdate(thread) {
10+
const myDate = new Date(thread.PostDate_js).getTime();
11+
12+
let childMaxDate = noDate;
13+
thread.Threads.forEach((childThread) => {
14+
const childDate = getLatestUpdate(childThread);
15+
if (childDate > childMaxDate) {
16+
childMaxDate = childDate;
17+
}
18+
});
19+
20+
const returnDate = (myDate > childMaxDate) ? myDate : childMaxDate;
21+
return returnDate;
22+
}
23+
24+
function sortByLatestUpdate(threadA, threadB) {
25+
const timeUpdatedA = getLatestUpdate(threadA);
26+
const timeUpdatedB = getLatestUpdate(threadB);
27+
28+
return (timeUpdatedB - timeUpdatedA);
29+
}
530

631
export default class Container extends Component {
732

33+
renderList() {
34+
const dataList = this.props.list;
35+
36+
if (dataList && dataList.length > 0) {
37+
return dataList.filter((dataItem) =>
38+
(dataItem.dataType === 'Forums')
39+
).map((dataItem) =>
40+
<li key={dataItem.ID}>
41+
<div>
42+
<h2>{dataItem.CourseCode} {dataItem.CourseName}</h2>
43+
<ul style={{ padding: '0 10px 50px 10px' }}>
44+
{
45+
dataItem.Headings.map((heading) => (
46+
[<h3>{heading.Title}</h3>,
47+
heading.Threads.sort(sortByLatestUpdate).slice(0, 5).map((thread) => (
48+
<Thread thread={thread} />
49+
))
50+
]))
51+
}
52+
</ul>
53+
</div>
54+
</li>
55+
);
56+
}
57+
return <p>Nothing to see here.</p>;
58+
}
59+
860
render() {
961
return (
1062
<div className={styles.container}>
11-
Not implemented yet
63+
<ul>
64+
{this.renderList()}
65+
</ul>
1266
</div>
1367
);
1468
}

views/components/Forum/Post.jsx

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
'use babel';
2+
3+
import React, { PropTypes } from 'react';
4+
import DOMPurify from 'dompurify';
5+
import styles from './post.css';
6+
7+
const Post = ({ post }) => (
8+
<li style={{ margin: '20px 0', listStyle: 'none' }}>
9+
<div style={{ fontSize: '0.6em' }}>{post.Poster.Name}</div>
10+
<div
11+
style={{ padding: '10px', backgroundColor: 'white', border: '2px solid rgba(0,0,0,0.2)' }}
12+
className={styles.body}
13+
dangerouslySetInnerHTML={{ __html: DOMPurify.sanitize(fixForumPost(post.PostBody)) }}
14+
/>
15+
</li>
16+
);
17+
18+
export default Post;
19+
20+
Post.propTypes = {
21+
post: PropTypes.object
22+
};
23+
24+
25+
function fixForumPost(htmlStr) {
26+
htmlStr = fixQuotedPost(htmlStr);
27+
htmlStr = fixImageUrl(htmlStr);
28+
return htmlStr;
29+
}
30+
31+
function fixQuotedPost(htmlStr) {
32+
htmlStr = htmlStr.replace(/\[quser\]/g, '<div class="quser" style="font-size: 0.6em; padding: 10px; border: 2px solid grey"><div>');
33+
htmlStr = htmlStr.replace(/\[\/quser\]/g, '</div>');
34+
htmlStr = htmlStr.replace(/\[quote[0-9]?\]/g, '<div class="qpost" style="border: 2px solid lightgrey">');
35+
htmlStr = htmlStr.replace(/\[\/quote\]/g, '</div></div>');
36+
return htmlStr;
37+
}
38+
39+
function fixImageUrl(htmlStr) {
40+
return htmlStr.replace(/src="(\/)/g, 'src="https://ivle.nus.edu.sg/');
41+
}

views/components/Forum/Thread.jsx

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
'use babel';
2+
3+
import React, { Component, PropTypes } from 'react';
4+
import Post from './Post';
5+
6+
export default class Container extends Component {
7+
8+
constructor(props) {
9+
super(props);
10+
11+
this.state = {
12+
display: 'hidden'
13+
};
14+
this.toggle = this.toggle.bind(this);
15+
}
16+
17+
getPosts(thread) {
18+
const element = [<Post key={thread.ID} post={thread} />];
19+
20+
element.push(thread.Threads.map((innerThread) =>
21+
this.getPosts(innerThread)
22+
));
23+
return element;
24+
}
25+
26+
toggle() {
27+
console.log(this.state.display);
28+
if (this.state.display === 'hidden') {
29+
this.setState({ display: '' });
30+
} else {
31+
this.setState({ display: 'hidden' });
32+
}
33+
}
34+
35+
render() {
36+
const thread = this.props.thread;
37+
return (
38+
<li style={{ margin: '20px 0', listStyle: 'none', boxShadow: '1px 1px 2px 1px rgba(0,0,0,0.3)' }}>
39+
<button onClick={this.toggle} style={{ backgroundColor: 'rgba(0,0,0,0.05)', color: 'black', padding: '10px', display: 'block' }}>{thread.PostTitle}</button>
40+
<div className={this.state.display} style={{ padding: '10px' }}>
41+
<ul style={{ padding: '0 0 20px 0' }}>
42+
{this.getPosts(thread)}
43+
</ul>
44+
</div>
45+
</li>
46+
);
47+
}
48+
}
49+
50+
Container.propTypes = {
51+
thread: PropTypes.object
52+
};

views/components/Forum/post.css

Whitespace-only changes.

0 commit comments

Comments
 (0)