commit: a541e937ca8b299092d0dc7f45d8f0b66ecc0131
parent: bc0692d75b1eeb7bc439869d892da9b835b40e0d
Author: Eugen Rochko <eugen@zeonfederated.com>
Date: Wed, 24 Aug 2016 21:08:00 +0200
More styling for statuses
Diffstat:
11 files changed, 135 insertions(+), 379 deletions(-)
diff --git a/app/assets/javascripts/components/components/avatar.jsx b/app/assets/javascripts/components/components/avatar.jsx
@@ -0,0 +1,17 @@
+const Avatar = React.createClass({
+
+ propTypes: {
+ src: React.PropTypes.string.isRequired
+ },
+
+ render () {
+ return (
+ <div style={{ width: '48px', height: '48px', flex: '0 0 auto' }}>
+ <img src={this.props.src} width={48} height={48} alt='' style={{ display: 'block', borderRadius: '4px' }} />
+ </div>
+ );
+ }
+
+});
+
+export default Avatar;
diff --git a/app/assets/javascripts/components/components/display_name.jsx b/app/assets/javascripts/components/components/display_name.jsx
@@ -0,0 +1,22 @@
+import ImmutablePropTypes from 'react-immutable-proptypes';
+
+const DisplayName = React.createClass({
+ propTypes: {
+ account: ImmutablePropTypes.map.isRequired
+ },
+
+ render () {
+ var displayName = this.props.account.get('display_name', this.props.account.get('username'));
+ var acct = this.props.account.get('acct');
+ var url = this.props.account.get('url');
+
+ return (
+ <a href={url} style={{ color: '#616b86', textDecoration: 'none' }}>
+ <strong style={{ fontWeight: 'bold', color: '#fff' }}>{displayName}</strong> <span>{acct}</span>
+ </a>
+ );
+ }
+
+});
+
+export default DisplayName;
diff --git a/app/assets/javascripts/components/components/relative_timestamp.jsx b/app/assets/javascripts/components/components/relative_timestamp.jsx
@@ -0,0 +1,55 @@
+import moment from 'moment';
+
+moment.updateLocale('en', {
+ relativeTime : {
+ future: "in %s",
+ past: "%s ago",
+ s: "s",
+ m: "a minute",
+ mm: "%dm",
+ h: "an hour",
+ hh: "%dh",
+ d: "a day",
+ dd: "%dd",
+ M: "a month",
+ MM: "%dm",
+ y: "a year",
+ yy: "%dy"
+ }
+});
+
+const RelativeTimestamp = React.createClass({
+ getInitialState () {
+ return {
+ text: ''
+ };
+ },
+
+ propTypes: {
+ timestamp: React.PropTypes.string.isRequired
+ },
+
+ componentWillMount () {
+ this._updateMomentText();
+ this.interval = setInterval(this._updateMomentText, 6000);
+ },
+
+ componentWillUnmount () {
+ clearInterval(this.interval);
+ },
+
+ _updateMomentText () {
+ this.setState({ text: moment(this.props.timestamp).fromNow() });
+ },
+
+ render () {
+ return (
+ <span style={{ color: '#616b86' }}>
+ {this.state.text}
+ </span>
+ );
+ }
+
+});
+
+export default RelativeTimestamp;
diff --git a/app/assets/javascripts/components/components/status.jsx b/app/assets/javascripts/components/components/status.jsx
@@ -1,17 +1,32 @@
import ImmutablePropTypes from 'react-immutable-proptypes';
+import Avatar from './avatar';
+import DisplayName from './display_name';
+import RelativeTimestamp from './relative_timestamp';
const Status = React.createClass({
propTypes: {
status: ImmutablePropTypes.map.isRequired
},
- render: function() {
+ render () {
var content = { __html: this.props.status.get('content') };
+ var status = this.props.status;
return (
- <div style={{ padding: '5px' }}>
- <div><strong>{this.props.status.getIn(['account', 'username'])}</strong></div>
- <div dangerouslySetInnerHTML={content} />
+ <div style={{ padding: '8px 10px', display: 'flex', flexDirection: 'row', borderBottom: '1px solid #363c4b' }}>
+ <Avatar src={status.getIn(['account', 'avatar'])} />
+
+ <div style={{ flex: '1 1 auto', marginLeft: '10px' }}>
+ <div style={{ overflow: 'hidden' }}>
+ <div style={{ float: 'right' }}>
+ <a href={status.get('url')} style={{ textDecoration: 'none' }}><RelativeTimestamp timestamp={status.get('created_at')} /></a>
+ </div>
+
+ <DisplayName account={status.get('account')} />
+ </div>
+
+ <div className='status__content' dangerouslySetInnerHTML={content} style={{ fontSize: '14px' }} />
+ </div>
</div>
);
}
diff --git a/app/assets/stylesheets/application.scss b/app/assets/stylesheets/application.scss
@@ -357,7 +357,6 @@ body {
}
}
-@import 'home';
@import 'accounts';
@import 'stream_entries';
-@import 'dashboard'
+@import 'components'
diff --git a/app/assets/stylesheets/components.scss b/app/assets/stylesheets/components.scss
@@ -0,0 +1,20 @@
+.status__content {
+ a {
+ color: #2b90d9;
+ text-decoration: none;
+
+ &:hover {
+ text-decoration: underline;
+ }
+
+ &.mention {
+ &:hover {
+ text-decoration: none;
+
+ span {
+ text-decoration: underline;
+ }
+ }
+ }
+ }
+}
diff --git a/app/assets/stylesheets/dashboard.scss b/app/assets/stylesheets/dashboard.scss
@@ -1,356 +0,0 @@
-.dashboard-wrapper {
- background: #282c37;
- border-radius: 4px;
- margin: 20px auto;
- width: 940px;
- display: flex;
- overflow: hidden;
-
- .dashboard__sidebar {
- width: 240px;
- border-radius: 4px 0 0 4px;
- flex-shrink: 0;
-
- .dashboard__top-bar {
- border-radius: 4px 0 0 0;
- }
-
- ul {
- padding: 20px 0;
-
- a {
- display: block;
- padding: 7px 20px;
- color: #d9e1e8;
- text-decoration: none;
- font-size: 14px;
- font-weight: 400;
-
- .fa {
- display: inline-block;
- width: 18px;
- text-align: center;
- margin-right: 5px;
- }
-
- &:hover {
- color: #fff;
- background: darken(#282c37, 1%);
- }
- }
-
- .active {
- a {
- background: darken(#282c37, 5%);
- border-left: 2px solid #2b90d9;
- padding-left: 18px;
- }
- }
- }
- }
-
- .dashboard__current-user {
- padding: 20px;
-
- a {
- text-decoration: none;
- color: inherit;
- outline: 0;
- }
-
- .dashboard__current-user__avatar {
- display: block;
- width: 50px;
- height: 50px;
- border-radius: 50px;
- float: left;
- margin-right: 15px;
- }
-
- .dashboard__current-user__display-name {
- font-weight: 500;
- font-size: 13px;
- color: #d9e1e8;
- display: block;
- margin-top: 5px;
- }
-
- .dashboard__current-user__username {
- font-size: 12px;
- display: block;
- color: #2b90d9;
- }
- }
-
- .dashboard__logo {
- color: #2b90d9;
-
- span {
- font-weight: 500;
- }
- }
-
- .dashboard__top-bar {
- background: #fff;
- padding: 20px;
- box-shadow: 0 0 5px rgba(0, 0, 0, 0.1);
- color: #282c37;
- font-size: 16px;
- overflow: hidden;
-
- &.alternate {
- background: lighten(#282c37, 10%);
- text-align: center;
- }
-
- ul {
- float: right;
- list-style: none;
- display: block;
-
- li {
- display: inline-block;
- margin-left: 7px;
- }
- }
-
- a {
- color: #9baec8;
- text-decoration: none;
- }
- }
-
- .dashboard__content {
- flex: 1;
- background: #d9e1e8;
- border-radius: 0 4px 4px 0;
-
- .dashboard__top-bar {
- border-radius: 0 4px 0 0;
- }
- }
-}
-
-.dashboard__content__content {
- padding: 20px;
- color: #282c37;
- line-height: 18px;
-
- h3 {
- font-size: 14px;
- font-weight: 500;
- margin-bottom: 15px;
- }
-
- p {
- margin-bottom: 15px;
- }
-
- samp {
- font-family: 'Roboto Mono', monospace;
- }
-
- ul {
- list-style: circle;
- padding-left: 15px;
- margin-bottom: 15px;
- }
-
- .table {
- width: 100%;
-
- th {
- font-weight: 500;
- text-align: left;
- border-bottom: 1px solid lighten(#282c37, 55%);
- }
-
- th, td {
- padding: 5px 0;
- line-height: 18px;
- }
- }
-
- a {
- color: #2b90d9;
- text-decoration: underline;
-
- &:hover {
- text-decoration: none;
- }
- }
-
- .btn {
- display: inline-block;
- border: 0;
- background: #2b90d9;
- border-radius: 16px;
- padding: 6px 16px;
- font-size: 12px;
- font-weight: 500;
- color: #fff;
- cursor: pointer;
- font-family: 'Roboto', sans-serif;
- text-decoration: none;
-
- &:hover {
- background: lighten(#2b90d9, 5%);
- }
-
- &.btn-iconized {
- font-size: 16px;
- font-weight: 400;
- width: 24px;
- text-align: center;
- padding: 10px 7px;
- border-radius: 100px;
- box-shadow: 0 0 15px rgba(0, 0, 0, 0.2);
- }
- }
-
- hr {
- clear: both;
- border: 0;
- padding: 0;
- width: 100%;
- height: 0;
- margin: 30px 0;
- }
-}
-
-.simple_form {
- .form-actions {
- padding-top: 20px;
- text-align: center;
- }
-
- .error_notification {
- color: #df405a;
- font-weight: 500;
- margin-bottom: 15px;
- }
-
- .input {
- margin-bottom: 15px;
-
- label {
- display: block;
- text-transform: uppercase;
- font-size: 11px;
- font-weight: 500;
- margin-bottom: 10px;
- }
-
- input[type=text], input[type=email], input[type=password], textarea {
- display: block;
- box-sizing: border-box;
- width: 100%;
- border: 0;
- background: transparent;
- border-bottom: 1px solid lighten(#282c37, 55%);
- padding: 5px 0;
- outline: 0;
- padding-bottom: 6px;
- font-size: 14px;
- font-family: 'Roboto', sans-serif;
- color: #282c37;
-
- &:focus, &:active {
- border-bottom: 2px solid #2b90d9;
- padding-bottom: 5px;
- }
- }
-
- input[type=file] {
- display: block;
- }
-
- .hint {
- display: block;
- margin-top: 5px;
- color: lighten(#282c37, 25%);
- }
-
- &.field_with_errors {
- input[type=text], input[type=email], input[type=password], textarea {
- border-bottom: 2px solid #df405a;
- padding-bottom: 5px;
-
- &:focus, &:active {
- border-bottom: 2px solid #2b90d9;
- padding-bottom: 5px;
- }
- }
-
- .error {
- display: block;
- margin-top: 5px;
- color: #df405a;
- }
- }
- }
-}
-
-.panel {
- box-sizing: border-box;
- padding: 10px 15px;
- background: lighten(#d9e1e8, 5%);
- margin-bottom: 20px;
- border-radius: 4px;
-
- .panel-heading {
- font-size: 13px;
- text-transform: uppercase;
- color: lighten(#282c37, 25%);
- margin-bottom: 10px;
- }
-
- &.panel-full {
- width: 100%;
- }
-
- .panel-row {
- display: flex;
-
- dt {
- color: #282c37;
- width: 100px;
- }
-
- dd {
- flex: 1;
- color: lighten(#282c37, 25%);
- }
-
- &.panel-row-wider {
- dt {
- width: auto;
- flex: 1;
- }
- }
- }
-}
-
-.row {
- overflow: hidden;
- clear: both;
-
- .panel {
- float: left;
- width: 320px;
- margin-right: 20px;
-
- &:last-child {
- margin-right: 0;
- }
- }
-}
-
-.page-actions {
- margin-top: 20px;
- text-align: right;
-
- .btn {
- margin-left: 5px;
- }
-}
diff --git a/app/assets/stylesheets/home.scss b/app/assets/stylesheets/home.scss
@@ -1,11 +0,0 @@
-.api-descriptions {
- .address {
- samp {
- font-weight: 400;
-
- &.method {
- font-weight: 500;
- }
- }
- }
-}
diff --git a/app/assets/stylesheets/settings.scss b/app/assets/stylesheets/settings.scss
@@ -1,3 +0,0 @@
-// Place all the styles related to the settings controller here.
-// They will automatically be included in application.css.
-// You can use Sass (SCSS) here: http://sass-lang.com/
diff --git a/app/assets/stylesheets/statuses.scss b/app/assets/stylesheets/statuses.scss
@@ -1,3 +0,0 @@
-// Place all the styles related to the statuses controller here.
-// They will automatically be included in application.css.
-// You can use Sass (SCSS) here: http://sass-lang.com/
diff --git a/package.json b/package.json
@@ -12,6 +12,7 @@
},
"dependencies": {
"immutable": "^3.8.1",
+ "moment": "^2.14.1",
"react-immutable-proptypes": "^2.1.0",
"react-redux": "^4.4.5",
"redux": "^3.5.2",