aboutsummaryrefslogtreecommitdiff
path: root/vnext/src
diff options
context:
space:
mode:
Diffstat (limited to 'vnext/src')
-rw-r--r--vnext/src/App.js60
-rw-r--r--vnext/src/api/index.js2
-rw-r--r--vnext/src/components/Avatar.js21
-rw-r--r--vnext/src/components/Feeds.js11
-rw-r--r--vnext/src/components/Message.js24
-rw-r--r--vnext/src/components/Thread.js49
-rw-r--r--vnext/src/components/UserInfo.js85
-rw-r--r--vnext/src/index.js4
-rw-r--r--vnext/src/style/main.css80
-rw-r--r--vnext/src/views/index.html12
10 files changed, 154 insertions, 194 deletions
diff --git a/vnext/src/App.js b/vnext/src/App.js
index 955c1200..71dc3926 100644
--- a/vnext/src/App.js
+++ b/vnext/src/App.js
@@ -166,66 +166,6 @@ export default class App extends React.Component {
<Route exact path="/:user/:mid" render={(props) => <Thread ref={this.thread} visitor={user} {...props} />} />
</Switch>
</section>
- <aside id="column">
- {
- user.uid > 0 &&
- <>
- <ul>
- <li>
- <Link to="/home">
- <Icon name="ei-clock" size="s" />My feed
- </Link>
- </li>
- <li>
- <Link to="/pm">
- <Icon name="ei-envelope" size="s" />PM
- </Link>
- </li>
- <li>
- <Link to={`/${user.uname}/?show=recomm`} rel="nofollow">
- <Icon name="ei-heart" size="s" />Recommendations
- </Link>
- </li>
- <li>
- <Link to={`/${user.uname}/?media=1`} rel="nofollow">
- <Icon name="ei-camera" size="s" />Photos
- </Link>
- </li>
- <li>
- <Link to="/settings" rel="nofollow">
- <Icon name="ei-gear" size="s" />Settings
- </Link>
- </li>
- </ul>
- <hr />
- <SearchBox pathname={`/${user.uname}/`} onSearch={this.search} {...this.props} />
- <hr />
- <div id="ustats">
- <ul>
- {
- user.read &&
- <li><Link to={`/${user.uname}/friends`}>I read: { user.read.length }</Link></li>
- }
- <li><Link to={`/${user.uname}/readers`}>My readers: {user.readers? user.readers.length : 0}</Link></li>
- {
- user.statsMyBL &&
- <li><Link to={`/${user.uname}/bl`}>My blacklist: {user.statsMyBL}</Link></li>
- }
- <li>Messages: {user.statsMessages}</li>
- <li>Comments: {user.statsReplies}</li>
- </ul>
- {
- user.read &&
- <div className="iread">
- {
- user.read.map(u => <Avatar user={u} key={u.uid} />)
- }
- </div>
- }
- </div>
- </>
- }
- </aside>
</div>
</>
</Router>
diff --git a/vnext/src/api/index.js b/vnext/src/api/index.js
index 90c8b15e..ab26a359 100644
--- a/vnext/src/api/index.js
+++ b/vnext/src/api/index.js
@@ -32,7 +32,7 @@ export function me(username = '', password = '') {
}
export function info(username) {
- return client.get(`/info/${username}`);
+ return client.get(`/users?uname=${username}`);
}
export function getChats() {
diff --git a/vnext/src/components/Avatar.js b/vnext/src/components/Avatar.js
index 0df0dbd7..f79d7b09 100644
--- a/vnext/src/components/Avatar.js
+++ b/vnext/src/components/Avatar.js
@@ -6,15 +6,26 @@ import { UserType } from './Types';
export default function Avatar(props) {
return (
- <div className="msg-avatar">
- <Link to={{ pathname: props.link || `/${props.user.uname}/`}}>
- <img src={`//i.juick.com/a/${props.user.uid}.png`} alt={`${props.user.uname}`} />
- </Link>
+ <div style={{ display: 'flex' }}>
+ <div className="msg-avatar">
+ <Link to={{ pathname: props.link || `/${props.user.uname}/` }}>
+ <img src={`//i.juick.com/a/${props.user.uid}.png`} alt={`${props.user.uname}`} />
+ </Link>
+ </div>
+ <div style={{ display: 'flex', flexDirection: 'column' }}>
+ <span itemProp="author" itemScope="" itemType="http://schema.org/Person">
+ <Link to={{ pathname: `/${props.user.uname}/` }} itemProp="url" rel="author">
+ <span itemProp="name">{props.user.uname}</span>
+ </Link>
+ </span>
+ {props.children}
+ </div>
</div>
);
}
Avatar.propTypes = {
user: UserType,
- link: PropTypes.string
+ link: PropTypes.string,
+ children: PropTypes.node
};
diff --git a/vnext/src/components/Feeds.js b/vnext/src/components/Feeds.js
index 194af71c..a7833f67 100644
--- a/vnext/src/components/Feeds.js
+++ b/vnext/src/components/Feeds.js
@@ -8,6 +8,8 @@ import moment from 'moment';
import Message from './Message';
import Spinner from './Spinner';
+import UserInfo from './UserInfo';
+
import { getMessages } from '../api';
import { UserType } from './Types';
@@ -38,7 +40,12 @@ export function Blog(props) {
search: search,
pageParam: search.search ? 'page' : 'before_mid'
};
- return (<Feed authRequired={false} query={query} {...props} />);
+ return (
+ <>
+ <UserInfo user={user} />
+ <Feed authRequired={false} query={query} {...props} />
+ </>
+ );
}
export function Tag(props) {
@@ -75,7 +82,7 @@ class Feed extends React.Component {
shouldComponentUpdate(nextProps, nextState) {
return this.props.visitor.uid !== nextProps.visitor.uid
- || this.state !== nextState || this.props.location !== nextProps.location;
+ || this.state !== nextState || this.props.location !== nextProps.location;
}
getSnapshotBeforeUpdate(prevProps) {
diff --git a/vnext/src/components/Message.js b/vnext/src/components/Message.js
index f091296b..b36936ba 100644
--- a/vnext/src/components/Message.js
+++ b/vnext/src/components/Message.js
@@ -13,20 +13,16 @@ export default function Message({ data, visitor, children, ...rest }) {
return (
<div className="msg-cont" itemProp="blogPost" itemScope="" itemType="http://schema.org/BlogPosting" itemRef="org">
<header className="h">
- <span itemProp="author" itemScope="" itemType="http://schema.org/Person">
- <Link to={{ pathname: `/${data.user.uname}/` }} itemProp="url" rel="author">
- <span itemProp="name">{data.user.uname}</span>
- </Link>
- </span>
- <Avatar user={data.user} />
- <div className="msg-ts">
- <Link to={{ pathname: `/${data.user.uname}/${data.mid}`, state: { msg: data } }}>
- <time itemProp="datePublished dateModified" itemType="http://schema.org/Date" dateTime={data.timestamp}
- title={moment.utc(data.timestamp).local().format('lll')}>
- {moment.utc(data.timestamp).fromNow()}
- </time>
- </Link>
- </div>
+ <Avatar user={data.user}>
+ <div className="msg-ts">
+ <Link to={{ pathname: `/${data.user.uname}/${data.mid}`, state: { msg: data } }}>
+ <time itemProp="datePublished dateModified" itemType="http://schema.org/Date" dateTime={data.timestamp}
+ title={moment.utc(data.timestamp).local().format('lll')}>
+ {moment.utc(data.timestamp).fromNow()}
+ </time>
+ </Link>
+ </div>
+ </Avatar>
<Tags user={data.user} data={data.tags || []} />
</header>
<div className="msg-txt">
diff --git a/vnext/src/components/Thread.js b/vnext/src/components/Thread.js
index b0e73b40..2097a315 100644
--- a/vnext/src/components/Thread.js
+++ b/vnext/src/components/Thread.js
@@ -45,7 +45,7 @@ export default class Thread extends React.Component {
.then(response => {
let msg = response.data.shift();
this.setState({
- msg: {...msg},
+ msg: { ...msg },
replies: response.data,
loading: false,
active: 0
@@ -100,29 +100,20 @@ export default class Thread extends React.Component {
<li id={msg.rid} key={msg.rid} className="msg">
<div className="msg-cont">
<div className="msg-header">
- {!msg.user.banned ? (
- <>
- <span itemProp="author" itemScope="" itemType="http://schema.org/Person">
- <Link to={`/${msg.user.uname}/`} itemProp="url" rel="author"><span itemProp="name">{msg.user.uname}</span></Link>
- </span><Avatar user={msg.user} />
- </>) : (
- <>
- <span>[удалено]:</span><Avatar user={{ uid: 0 }} />
- </>
- )
- }
- <div className="msg-ts">
- <a href={`/${msg.user.uname}/${msg.mid}`}>
- <time itemProp="datePublished dateModified" itemType="http://schema.org/Date" dateTime={msg.timestamp}
- title={moment.utc(msg.timestamp).local().format('lll')}>
- {moment.utc(msg.timestamp).fromNow()}
- </time>
- </a>
- {msg.replyto > 0 &&
- (
- <a href={`#${msg.replyto}`}> in reply to {msg.to.uname}&nbsp;</a>
- )}
- </div>
+ <Avatar user={msg.user}>
+ <div className="msg-ts">
+ <a href={`/${msg.user.uname}/${msg.mid}`}>
+ <time itemProp="datePublished dateModified" itemType="http://schema.org/Date" dateTime={msg.timestamp}
+ title={moment.utc(msg.timestamp).local().format('lll')}>
+ {moment.utc(msg.timestamp).fromNow()}
+ </time>
+ </a>
+ {msg.replyto > 0 &&
+ (
+ <a href={`#${msg.replyto}`}> in reply to {msg.to.uname}&nbsp;</a>
+ )}
+ </div>
+ </Avatar>
</div>
<div className="msg-txt"><p dangerouslySetInnerHTML={{ __html: format(msg.body, msg.mid, (msg.tags || []).indexOf('code') >= 0) }}></p></div>
{
@@ -149,10 +140,10 @@ export default class Thread extends React.Component {
</li>
)) : (
<>
- {Array(loaders).fill().map((it, i) => <Spinner key={i} />)}
- </>
- )
- }
+ {Array(loaders).fill().map((it, i) => <Spinner key={i} />)}
+ </>
+ )
+ }
</ul>
</>
);
@@ -170,7 +161,7 @@ Thread.propTypes = {
visitor: UserType.isRequired
};
-function Recommendations({forMessage, ...rest}) {
+function Recommendations({ forMessage, ...rest }) {
const { likes, recommendations } = forMessage;
return recommendations && recommendations.length > 0 && (
<div className="msg-recomms">{'Recommended by '}
diff --git a/vnext/src/components/UserInfo.js b/vnext/src/components/UserInfo.js
new file mode 100644
index 00000000..147bb6f8
--- /dev/null
+++ b/vnext/src/components/UserInfo.js
@@ -0,0 +1,85 @@
+import React from 'react';
+
+import { Link } from 'react-router-dom';
+
+import { info } from '../api';
+
+import Avatar from './Avatar';
+import Icon from './Icon';
+import SearchBox from './SearchBox';
+
+export default class UserInfo extends React.Component {
+ constructor(props) {
+ super(props);
+ this.state = {
+ user: { uname: props.user, uid: 0 }
+ };
+ }
+ componentDidMount() {
+ info(this.state.user.uname).then(response => {
+ this.setState({
+ user: response.data[0]
+ });
+ });
+ }
+ render() {
+ const { user } = this.state;
+ return (
+ <div style={{ padding: '14px' }}>
+ <Avatar user={user}>
+ <div className="msg-ts">Was online recently</div>
+ </Avatar>
+ <div>
+ {
+ user.uid > 0 &&
+ <>
+ <ul>
+ <li>
+ <Link to="/pm">
+ <Icon name="ei-envelope" size="s" />PM
+ </Link>
+ </li>
+ <li>
+ <Link to={`/${user.uname}/?show=recomm`} rel="nofollow">
+ <Icon name="ei-heart" size="s" />Recommendations
+ </Link>
+ </li>
+ <li>
+ <Link to={`/${user.uname}/?media=1`} rel="nofollow">
+ <Icon name="ei-camera" size="s" />Photos
+ </Link>
+ </li>
+ </ul>
+ <hr />
+ <SearchBox pathname={`/${user.uname}/`} onSearch={this.search} {...this.props} />
+ <hr />
+ <div id="ustats">
+ <ul>
+ {
+ user.read &&
+ <li><Link to={`/${user.uname}/friends`}>I read: {user.read.length}</Link></li>
+ }
+ <li><Link to={`/${user.uname}/readers`}>My readers: {user.readers ? user.readers.length : 0}</Link></li>
+ {
+ user.statsMyBL &&
+ <li><Link to={`/${user.uname}/bl`}>My blacklist: {user.statsMyBL}</Link></li>
+ }
+ <li>Messages: {user.statsMessages}</li>
+ <li>Comments: {user.statsReplies}</li>
+ </ul>
+ {
+ user.read &&
+ <div className="iread">
+ {
+ user.read.map(u => <Avatar user={u} key={u.uid} />)
+ }
+ </div>
+ }
+ </div>
+ </>
+ }
+ </div>
+ </div>
+ );
+ }
+} \ No newline at end of file
diff --git a/vnext/src/index.js b/vnext/src/index.js
index b9fc5f54..24fe9352 100644
--- a/vnext/src/index.js
+++ b/vnext/src/index.js
@@ -5,7 +5,7 @@ import App from './App';
let container = document.createElement('div');
ReactDOM.render(<App />, container);
-let body = document.getElementById('wrapper').parentNode;
+let body = document.getElementById('content').parentNode;
body.replaceChild(container.getElementsByTagName('header')[0], body.querySelector('#header'));
-body.replaceChild(container.querySelector('#wrapper'), body.querySelector('#wrapper'));
+body.replaceChild(container.querySelector('#content'), body.querySelector('#content'));
diff --git a/vnext/src/style/main.css b/vnext/src/style/main.css
index a5e0326d..913572dc 100644
--- a/vnext/src/style/main.css
+++ b/vnext/src/style/main.css
@@ -70,27 +70,10 @@ html {
background: #f8f8f8;
color: #222;
}
-#wrapper {
- margin: 0 auto;
- width: 1000px;
- margin-top: 52px;
-}
-#column {
- float: left;
- margin-left: 10px;
- overflow: hidden;
- padding-top: 10px;
- width: 240px;
-}
#content {
- float: right;
- margin: 12px 0 0 0;
- width: 728px;
-}
-#minimal_content {
margin: 0 auto;
- min-width: 310px;
- width: auto;
+ width: 728px;
+ margin-top: 62px;
}
noscript article {
background-image: url("matrix.jpg");
@@ -135,7 +118,6 @@ body > header {
transform: translateY(-100%);
}
#footer {
- clear: both;
color: #999;
font-size: 10pt;
margin: 40px;
@@ -147,7 +129,6 @@ body > header {
text-size-adjust: 100%;
}
body,
- #wrapper,
#topwrapper,
#content,
#footer {
@@ -156,18 +137,9 @@ body > header {
min-width: 310px;
width: auto;
}
- #wrapper {
- margin-top: 50px;
- }
body > header {
margin-bottom: 15px;
}
- #column {
- float: none;
- margin: 0 10px;
- padding-top: 0;
- width: auto;
- }
}
/* #endregion */
@@ -229,46 +201,6 @@ body > header {
border-top: 1px solid #CCC;
}
-#column ul,
-#column p,
-#column hr {
- margin: 10px 0;
-}
-#column li > a {
- display: block;
- height: 100%;
- padding: 6px;
-}
-#column li > a:hover {
- background-color: #fff;
- box-shadow: 0 0 3px rgba(0, 0, 0, 0.16);
- transition: background-color 0.2s ease-in;
-}
-#column .margtop {
- margin-top: 15px;
-}
-
-#column .tags {
- background: #fff;
- box-shadow: 0 0 3px rgba(0, 0, 0, 0.16);
- line-height: 140%;
- padding: 6px;
- text-align: justify;
-}
-#column .inp {
- background: #fff;
- border: 1px solid #ddddd5;
- outline: none !important;
- padding: 4px;
- width: 222px;
-}
-#column .tags h4 {
- background: #eee;
- border: 1px solid #eee;
- color: #888;
- display: block;
- text-align: center;
-}
#ctitle {
font-size: 14pt;
}
@@ -403,10 +335,9 @@ article .tags > a,
margin-bottom: 0;
}
.msg-avatar {
- float: left;
- height: 48px;
+ min-height: 48px;
margin-right: 10px;
- width: 48px;
+ min-width: 48px;
}
.msg-avatar img {
height: 48px;
@@ -419,7 +350,6 @@ article .tags > a,
line-height: 140%;
margin-bottom: 12px;
padding: 20px;
- width: 640px;
}
.reply-new .msg-cont {
border-right: 5px solid #0C0;
@@ -542,7 +472,7 @@ article .tags > a,
}
@media screen and (max-width: 480px) {
- #wrapper {
+ #content {
margin-top: 104px;
}
#search {
diff --git a/vnext/src/views/index.html b/vnext/src/views/index.html
index 35a876ea..e5862bc1 100644
--- a/vnext/src/views/index.html
+++ b/vnext/src/views/index.html
@@ -44,15 +44,15 @@
<body id="body">
<div id="header">
- <div id="header_wrapper">
- <div id="logo"><a href="/">Juick</a></div>
- </div>
+ <div id="header_wrapper">
+ <div id="logo"><a href="/">Juick</a></div>
+ </div>
</div>
- <div id="wrapper">
+ <div id="content">
<noscript>
<article>
- Javascript is required to use Juick from browser.<br />
- Alternatively we have <a href="mailto:juick@juick.com">maillist-like</a> and <a href="xmpp:juick@juick.com">chat</a> interfaces.
+ Javascript is required to use Juick from browser.<br /> Alternatively we have <a href="mailto:juick@juick.com">maillist-like</a>
+ and <a href="xmpp:juick@juick.com">chat</a> interfaces.
</article>
</noscript>
</div>