about summary refs log tree commit diff
path: root/app
diff options
context:
space:
mode:
Diffstat (limited to 'app')
-rw-r--r--app/assets/javascripts/components/components/avatar.jsx17
-rw-r--r--app/assets/javascripts/components/components/display_name.jsx22
-rw-r--r--app/assets/javascripts/components/components/relative_timestamp.jsx55
-rw-r--r--app/assets/javascripts/components/components/status.jsx23
-rw-r--r--app/assets/stylesheets/application.scss3
-rw-r--r--app/assets/stylesheets/components.scss20
-rw-r--r--app/assets/stylesheets/dashboard.scss356
-rw-r--r--app/assets/stylesheets/home.scss11
-rw-r--r--app/assets/stylesheets/settings.scss3
-rw-r--r--app/assets/stylesheets/statuses.scss3
10 files changed, 134 insertions, 379 deletions
diff --git a/app/assets/javascripts/components/components/avatar.jsx b/app/assets/javascripts/components/components/avatar.jsx
new file mode 100644
index 000000000..7db3eeff7
--- /dev/null
+++ 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
new file mode 100644
index 000000000..97db31707
--- /dev/null
+++ 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
new file mode 100644
index 000000000..3216d0a0d
--- /dev/null
+++ 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
index 68c1efaad..e54bc8c04 100644
--- 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
index 668b6f90d..a444a2ff2 100644
--- 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
new file mode 100644
index 000000000..0bec9ba80
--- /dev/null
+++ 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
deleted file mode 100644
index 983172bd0..000000000
--- a/app/assets/stylesheets/dashboard.scss
+++ /dev/null
@@ -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
deleted file mode 100644
index c9f2740ad..000000000
--- a/app/assets/stylesheets/home.scss
+++ /dev/null
@@ -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
deleted file mode 100644
index fbe669080..000000000
--- a/app/assets/stylesheets/settings.scss
+++ /dev/null
@@ -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
deleted file mode 100644
index bb9365adc..000000000
--- a/app/assets/stylesheets/statuses.scss
+++ /dev/null
@@ -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/