From 6b6878bde06b375b1e715a3557f153acc73a8af0 Mon Sep 17 00:00:00 2001
From: eugenijm <eugenijm@protonmail.com>
Date: Mon, 18 Feb 2019 17:49:32 +0300
Subject: Added moderation menu

---
 src/components/user_card/user_card.vue | 2 ++
 1 file changed, 2 insertions(+)

(limited to 'src/components/user_card/user_card.vue')

diff --git a/src/components/user_card/user_card.vue b/src/components/user_card/user_card.vue
index 3259d1c5..b5c7fa24 100644
--- a/src/components/user_card/user_card.vue
+++ b/src/components/user_card/user_card.vue
@@ -99,6 +99,8 @@
             </button>
           </span>
         </div>
+        <ModerationTools :user='user' v-if='loggedIn.role === "admin"'>
+        </ModerationTools>
       </div>
     </div>
   </div>
-- 
cgit v1.2.3-70-g09d2


From 6aee2ed63fa479066b2243a03af05cdba68a9ba2 Mon Sep 17 00:00:00 2001
From: Brenden Bice <brenden.next@gmail.com>
Date: Thu, 11 Apr 2019 23:14:45 -0400
Subject: replace pencil with wrench icon

# Conflicts:
#	src/components/user_card/user_card.vue
---
 src/components/user_card/user_card.vue | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'src/components/user_card/user_card.vue')

diff --git a/src/components/user_card/user_card.vue b/src/components/user_card/user_card.vue
index b5c7fa24..a8055621 100644
--- a/src/components/user_card/user_card.vue
+++ b/src/components/user_card/user_card.vue
@@ -11,7 +11,7 @@
             <div :title="user.name" class='user-name' v-if="user.name_html" v-html="user.name_html"></div>
             <div :title="user.name" class='user-name' v-else>{{user.name}}</div>
             <router-link :to="{ name: 'user-settings' }" v-if="!isOtherUser">
-              <i class="button-icon icon-pencil usersettings" :title="$t('tool_tip.user_settings')"></i>
+              <i class="button-icon icon-wrench usersettings" :title="$t('tool_tip.user_settings')"></i>
             </router-link>
             <a :href="user.statusnet_profile_url" target="_blank" v-if="isOtherUser && !user.is_local">
               <i class="icon-link-ext usersettings"></i>
-- 
cgit v1.2.3-70-g09d2


From 14d506154e844cbae82489dd4edfd1d31c0559db Mon Sep 17 00:00:00 2001
From: "Haelwenn (lanodan) Monnier" <contact@hacktivis.me>
Date: Sat, 20 Apr 2019 21:06:34 +0200
Subject: user_card.vue: Fix .emoji to apply to img

---
 src/components/user_card/user_card.vue | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'src/components/user_card/user_card.vue')

diff --git a/src/components/user_card/user_card.vue b/src/components/user_card/user_card.vue
index b5c7fa24..bb95f595 100644
--- a/src/components/user_card/user_card.vue
+++ b/src/components/user_card/user_card.vue
@@ -162,7 +162,7 @@
       max-width: 100%;
       max-height: 400px;
 
-      .emoji {
+      &.emoji {
         width: 32px;
         height: 32px;
       }
-- 
cgit v1.2.3-70-g09d2


From c44c0483566efc8c48361e4143b25d852cecede4 Mon Sep 17 00:00:00 2001
From: shpuld <shp@cock.li>
Date: Wed, 1 May 2019 17:33:56 +0300
Subject: add title and alt for avatars, fix console errors in avatarlist

---
 src/components/avatar_list/avatar_list.js               |  6 +++---
 src/components/avatar_list/avatar_list.vue              |  4 ++--
 src/components/basic_user_card/basic_user_card.vue      |  6 +++++-
 src/components/notification/notification.vue            |  2 +-
 src/components/status/status.js                         |  6 +++---
 src/components/status/status.vue                        | 17 +++++++++++------
 src/components/user_avatar/user_avatar.js               |  2 +-
 src/components/user_avatar/user_avatar.vue              |  4 +++-
 src/components/user_card/user_card.vue                  |  2 +-
 .../entity_normalizer/entity_normalizer.service.js      |  3 +++
 10 files changed, 33 insertions(+), 19 deletions(-)

(limited to 'src/components/user_card/user_card.vue')

diff --git a/src/components/avatar_list/avatar_list.js b/src/components/avatar_list/avatar_list.js
index d65125c2..b9e11aaa 100644
--- a/src/components/avatar_list/avatar_list.js
+++ b/src/components/avatar_list/avatar_list.js
@@ -1,10 +1,10 @@
 import UserAvatar from '../user_avatar/user_avatar.vue'
 
 const AvatarList = {
-  props: ['avatars'],
+  props: ['users'],
   computed: {
-    slicedAvatars () {
-      return this.avatars ? this.avatars.slice(0, 15) : []
+    slicedUsers () {
+      return this.users ? this.users.slice(0, 15) : []
     }
   },
   components: {
diff --git a/src/components/avatar_list/avatar_list.vue b/src/components/avatar_list/avatar_list.vue
index b14474ba..4e0de2c9 100644
--- a/src/components/avatar_list/avatar_list.vue
+++ b/src/components/avatar_list/avatar_list.vue
@@ -1,7 +1,7 @@
 <template>
   <div class="avatars">
-      <div class="avatars-item" v-for="avatar in slicedAvatars">
-        <UserAvatar :src="avatar.profile_image_url" class="avatar-small" />
+      <div class="avatars-item" v-for="user in slicedUsers">
+        <UserAvatar :user="user" class="avatar-small" />
       </div>
   </div>
 </template>
diff --git a/src/components/basic_user_card/basic_user_card.vue b/src/components/basic_user_card/basic_user_card.vue
index 25f1fb2a..634d62b3 100644
--- a/src/components/basic_user_card/basic_user_card.vue
+++ b/src/components/basic_user_card/basic_user_card.vue
@@ -1,7 +1,11 @@
 <template>
   <div class="basic-user-card">
     <router-link :to="userProfileLink(user)">
-      <UserAvatar class="avatar" @click.prevent.native="toggleUserExpanded" :src="user.profile_image_url"/>
+      <UserAvatar
+        class="avatar"
+        :user="user"
+        @click.prevent.native="toggleUserExpanded"
+      />
     </router-link>
     <div class="basic-user-card-expanded-content" v-if="userExpanded">
       <UserCard :user="user" :rounded="true" :bordered="true"/>
diff --git a/src/components/notification/notification.vue b/src/components/notification/notification.vue
index ae11d692..3427b9c5 100644
--- a/src/components/notification/notification.vue
+++ b/src/components/notification/notification.vue
@@ -7,7 +7,7 @@
   </status>
   <div class="non-mention" :class="[userClass, { highlighted: userStyle }]" :style="[ userStyle ]" v-else>
     <a class='avatar-container' :href="notification.from_profile.statusnet_profile_url" @click.stop.prevent.capture="toggleUserExpanded">
-      <UserAvatar :compact="true" :betterShadow="betterShadow" :src="notification.from_profile.profile_image_url_original" />
+      <UserAvatar :compact="true" :betterShadow="betterShadow" :user="notification.from_profile"/>
     </a>
     <div class='notification-right'>
       <UserCard :user="getUser(notification)" :rounded="true" :bordered="true" v-if="userExpanded" />
diff --git a/src/components/status/status.js b/src/components/status/status.js
index f10eb2e4..ff8cbe18 100644
--- a/src/components/status/status.js
+++ b/src/components/status/status.js
@@ -263,13 +263,13 @@ const Status = {
       }
       return this.status.summary_html + '<br />' + this.status.statusnet_html
     },
-    combinedFavsAndRepeatsAvatars () {
+    combinedFavsAndRepeatsUsers () {
       // Use the status from the global status repository since favs and repeats are saved in it
-      const combinedAvatars = [].concat(
+      const combinedUsers = [].concat(
         this.statusFromGlobalRepository.favoritedBy,
         this.statusFromGlobalRepository.rebloggedBy
       )
-      return uniqBy(combinedAvatars, 'id')
+      return uniqBy(combinedUsers, 'id')
     }
   },
   components: {
diff --git a/src/components/status/status.vue b/src/components/status/status.vue
index a5f7429c..43c3030e 100644
--- a/src/components/status/status.vue
+++ b/src/components/status/status.vue
@@ -13,7 +13,7 @@
     </template>
     <template v-else>
       <div v-if="retweet && !noHeading && !inConversation" :class="[repeaterClass, { highlighted: repeaterStyle }]" :style="[repeaterStyle]" class="media container retweet-info">
-        <UserAvatar class="media-left" v-if="retweet" :betterShadow="betterShadow" :src="statusoid.user.profile_image_url_original"/>
+        <UserAvatar class="media-left" v-if="retweet" :betterShadow="betterShadow" :user="statusoid.user"/>
         <div class="media-body faint">
           <span class="user-name">
             <router-link v-if="retweeterHtml" :to="retweeterProfileLink" v-html="retweeterHtml"/>
@@ -27,7 +27,7 @@
       <div :class="[userClass, { highlighted: userStyle, 'is-retweet': retweet && !inConversation }]" :style="[ userStyle ]" class="media status">
         <div v-if="!noHeading" class="media-left">
           <router-link :to="userProfileLink" @click.stop.prevent.capture.native="toggleUserExpanded">
-            <UserAvatar :compact="compact" :betterShadow="betterShadow" :src="status.user.profile_image_url_original"/>
+            <UserAvatar :compact="compact" :betterShadow="betterShadow" :user="status.user"/>
           </router-link>
         </div>
         <div class="status-body">
@@ -91,8 +91,13 @@
           </div>
 
           <div v-if="showPreview" class="status-preview-container">
-            <status class="status-preview" v-if="preview" :isPreview="true" :statusoid="preview" :compact=true></status>
-            <div class="status-preview status-preview-loading" v-else>
+            <status class="status-preview"
+              v-if="preview"
+              :isPreview="true"
+              :statusoid="preview"
+              :compact=true
+            />
+            <div v-else class="status-preview status-preview-loading">
               <i class="icon-spin4 animate-spin"></i>
             </div>
           </div>
@@ -134,7 +139,7 @@
           </div>
 
           <transition name="fade">
-            <div class="favs-repeated-users" v-if="combinedFavsAndRepeatsAvatars.length > 0 && isFocused">
+            <div class="favs-repeated-users" v-if="combinedFavsAndRepeatsUsers.length > 0 && isFocused">
               <div class="stats">
                 <div class="stat-count" v-if="statusFromGlobalRepository.rebloggedBy && statusFromGlobalRepository.rebloggedBy.length > 0">
                   <a class="stat-title">{{ $t('status.repeats') }}</a>
@@ -145,7 +150,7 @@
                   <div class="stat-number">{{ statusFromGlobalRepository.favoritedBy.length }}</div>
                 </div>
                 <div class="avatar-row">
-                  <AvatarList :avatars='combinedFavsAndRepeatsAvatars'></AvatarList>
+                  <AvatarList :users="combinedFavsAndRepeatsUsers"></AvatarList>
                 </div>
               </div>
             </div>
diff --git a/src/components/user_avatar/user_avatar.js b/src/components/user_avatar/user_avatar.js
index e6fed3b5..a42b9c71 100644
--- a/src/components/user_avatar/user_avatar.js
+++ b/src/components/user_avatar/user_avatar.js
@@ -2,7 +2,7 @@ import StillImage from '../still-image/still-image.vue'
 
 const UserAvatar = {
   props: [
-    'src',
+    'user',
     'betterShadow',
     'compact'
   ],
diff --git a/src/components/user_avatar/user_avatar.vue b/src/components/user_avatar/user_avatar.vue
index 6bf7123d..e5466fdf 100644
--- a/src/components/user_avatar/user_avatar.vue
+++ b/src/components/user_avatar/user_avatar.vue
@@ -1,8 +1,10 @@
 <template>
   <StillImage
     class="avatar"
+    :alt="user.screen_name"
+    :title="user.screen_name"
+    :src="user.profile_image_url_original"
     :class="{ 'avatar-compact': compact, 'better-shadow': betterShadow }"
-    :src="imgSrc"
     :imageLoadError="imageLoadError"
   />
 </template>
diff --git a/src/components/user_card/user_card.vue b/src/components/user_card/user_card.vue
index e1d3ff57..e62b384d 100644
--- a/src/components/user_card/user_card.vue
+++ b/src/components/user_card/user_card.vue
@@ -4,7 +4,7 @@
     <div class='user-info'>
       <div class='container'>
         <router-link :to="userProfileLink(user)">
-          <UserAvatar :betterShadow="betterShadow" :src="user.profile_image_url_original"/>
+          <UserAvatar :betterShadow="betterShadow" :user="user"/>
         </router-link>
         <div class="name-and-screen-name">
           <div class="top-line">
diff --git a/src/services/entity_normalizer/entity_normalizer.service.js b/src/services/entity_normalizer/entity_normalizer.service.js
index e706e7d9..309aa1e8 100644
--- a/src/services/entity_normalizer/entity_normalizer.service.js
+++ b/src/services/entity_normalizer/entity_normalizer.service.js
@@ -275,6 +275,9 @@ export const parseStatus = (data) => {
     output.retweeted_status = parseStatus(retweetedStatus)
   }
 
+  output.favoritedBy = []
+  output.rebloggedBy = []
+
   return output
 }
 
-- 
cgit v1.2.3-70-g09d2


From 2cda9010df6192b008515b2138a2e071473bc40b Mon Sep 17 00:00:00 2001
From: taehoon <th.dev91@gmail.com>
Date: Tue, 19 Mar 2019 04:53:11 -0400
Subject: add user reporting modal

---
 src/App.js                                         |   4 +-
 src/App.vue                                        |   1 +
 src/components/checkbox/checkbox.js                |  44 ++++++++
 src/components/checkbox/checkbox.scss              |  48 +++++++++
 src/components/user_card/user_card.js              |   3 +
 src/components/user_card/user_card.vue             |  10 +-
 .../user_reporting_modal/user_reporting_modal.js   |  81 +++++++++++++++
 .../user_reporting_modal/user_reporting_modal.vue  | 111 +++++++++++++++++++++
 src/i18n/en.json                                   |   1 +
 src/main.js                                        |   4 +-
 src/modules/reports.js                             |  33 ++++++
 11 files changed, 336 insertions(+), 4 deletions(-)
 create mode 100644 src/components/checkbox/checkbox.js
 create mode 100644 src/components/checkbox/checkbox.scss
 create mode 100644 src/components/user_reporting_modal/user_reporting_modal.js
 create mode 100644 src/components/user_reporting_modal/user_reporting_modal.vue
 create mode 100644 src/modules/reports.js

(limited to 'src/components/user_card/user_card.vue')

diff --git a/src/App.js b/src/App.js
index 46145b16..e72c73e3 100644
--- a/src/App.js
+++ b/src/App.js
@@ -10,6 +10,7 @@ import MediaModal from './components/media_modal/media_modal.vue'
 import SideDrawer from './components/side_drawer/side_drawer.vue'
 import MobilePostStatusModal from './components/mobile_post_status_modal/mobile_post_status_modal.vue'
 import MobileNav from './components/mobile_nav/mobile_nav.vue'
+import UserReportingModal from './components/user_reporting_modal/user_reporting_modal.vue'
 import { windowWidth } from './services/window_utils/window_utils'
 
 export default {
@@ -26,7 +27,8 @@ export default {
     MediaModal,
     SideDrawer,
     MobilePostStatusModal,
-    MobileNav
+    MobileNav,
+    UserReportingModal
   },
   data: () => ({
     mobileActivePanel: 'timeline',
diff --git a/src/App.vue b/src/App.vue
index 3b8623ad..cb7e8d78 100644
--- a/src/App.vue
+++ b/src/App.vue
@@ -46,6 +46,7 @@
       <media-modal></media-modal>
     </div>
     <chat-panel :floating="true" v-if="currentUser && chat" class="floating-chat mobile-hidden"></chat-panel>
+    <UserReportingModal />
   </div>
 </template>
 
diff --git a/src/components/checkbox/checkbox.js b/src/components/checkbox/checkbox.js
new file mode 100644
index 00000000..324a7597
--- /dev/null
+++ b/src/components/checkbox/checkbox.js
@@ -0,0 +1,44 @@
+// TODO: Template-based functional component is supported in vue-loader 13.3.0+.
+// Also, somehow, props are not provided through 'context' even though they are defined.
+// Need to upgrade vue-loader
+
+import './checkbox.scss'
+
+export default {
+  functional: true,
+  name: 'Checkbox',
+  model: {
+    prop: 'checked',
+    event: 'change'
+  },
+  render (createElement, { data, children }) {
+    const { props = {}, attrs = {}, on = {}, ...rest } = data
+    const { name, checked, disabled, readonly, ...restAttrs } = attrs
+    const { change, ...restListeners } = on
+    const wrapperProps = {
+      attrs: restAttrs,
+      on: restListeners,
+      ...rest
+    }
+    const inputProps = {
+      attrs: {
+        name,
+        checked,
+        disabled,
+        readonly,
+        ...props
+      },
+      on: {}
+    }
+    if (change) {
+      inputProps.on.change = e => change(e.target.checked)
+    }
+    return (
+      <label class="checkbox" {...wrapperProps}>
+        <input type="checkbox" {...inputProps} />
+        <i />
+        {children && <span>{children}</span>}
+      </label>
+    )
+  }
+}
diff --git a/src/components/checkbox/checkbox.scss b/src/components/checkbox/checkbox.scss
new file mode 100644
index 00000000..07b3f39e
--- /dev/null
+++ b/src/components/checkbox/checkbox.scss
@@ -0,0 +1,48 @@
+@import '../../_variables.scss';
+
+.checkbox {
+  position: relative;
+  display: inline-block;
+  padding-left: 1.2em;
+
+  input[type=checkbox] {
+    display: none;
+
+    & + i::before {
+      position: absolute;
+      left: 0;
+      top: 0;
+      display: block;
+      content: '✔';
+      transition: color 200ms;
+      width: 1.1em;
+      height: 1.1em;
+      border-radius: $fallback--checkboxRadius;
+      border-radius: var(--checkboxRadius, $fallback--checkboxRadius);
+      box-shadow: 0px 0px 2px black inset;
+      box-shadow: var(--inputShadow);
+      background-color: $fallback--fg;
+      background-color: var(--input, $fallback--fg);
+      vertical-align: top;
+      text-align: center;
+      line-height: 1.1em;
+      font-size: 1.1em;
+      color: transparent;
+      overflow: hidden;
+      box-sizing: border-box;
+    }
+
+    &:checked + i::before {
+      color: $fallback--text;
+      color: var(--text, $fallback--text);
+    }
+
+    &:disabled + i::before {
+      opacity: .5;
+    }
+  }
+
+  & > span {
+    margin-left: .5em;
+  }
+}
\ No newline at end of file
diff --git a/src/components/user_card/user_card.js b/src/components/user_card/user_card.js
index 1a100de3..7c6ffa89 100644
--- a/src/components/user_card/user_card.js
+++ b/src/components/user_card/user_card.js
@@ -151,6 +151,9 @@ export default {
     },
     userProfileLink (user) {
       return generateProfileLink(user.id, user.screen_name, this.$store.state.instance.restrictedNicknames)
+    },
+    reportUser () {
+      this.$store.dispatch('openUserReportingModal', this.user.id)
     }
   }
 }
diff --git a/src/components/user_card/user_card.vue b/src/components/user_card/user_card.vue
index e62b384d..2d02ca03 100644
--- a/src/components/user_card/user_card.vue
+++ b/src/components/user_card/user_card.vue
@@ -99,8 +99,14 @@
             </button>
           </span>
         </div>
-        <ModerationTools :user='user' v-if='loggedIn.role === "admin"'>
-        </ModerationTools>
+        <div class='block' v-if='isOtherUser && loggedIn'>
+          <span>
+            <button @click="reportUser">
+              {{ $t('user_card.report') }}
+            </button>
+          </span>
+        </div>
+        <ModerationTools :user='user' v-if='loggedIn.role === "admin"'/>
       </div>
     </div>
   </div>
diff --git a/src/components/user_reporting_modal/user_reporting_modal.js b/src/components/user_reporting_modal/user_reporting_modal.js
new file mode 100644
index 00000000..fb9ea16d
--- /dev/null
+++ b/src/components/user_reporting_modal/user_reporting_modal.js
@@ -0,0 +1,81 @@
+
+import Status from '../status/status.vue'
+import Checkbox from '../checkbox/checkbox.js'
+
+const UserReportingModal = {
+  components: {
+    Status,
+    Checkbox
+  },
+  data () {
+    return {
+      comment: '',
+      forward: false,
+      statusIdsToReport: []
+    }
+  },
+  computed: {
+    isLoggedIn () {
+      return !!this.$store.state.users.currentUser
+    },
+    isOpen () {
+      return this.isLoggedIn && this.$store.state.reports.modalActivated
+    },
+    userId () {
+      return this.$store.state.reports.userId
+    },
+    user () {
+      return this.$store.getters.findUser(this.userId)
+    },
+    remoteInstance () {
+      return !this.user.is_local && this.user.screen_name.substr(this.user.screen_name.indexOf('@') + 1)
+    },
+    statuses () {
+      return this.$store.state.reports.statuses
+    }
+  },
+  watch: {
+    userId (value) {
+      this.statusIdsToReport = []
+    }
+  },
+  methods: {
+    closeModal () {
+      this.$store.dispatch('closeUserReportingModal')
+    },
+    reportUser () {
+      const payload = {
+        comment: this.comment,
+        forward: this.forward,
+        statusIdsToReport: this.statusIdsToReport
+      }
+      this.$store.dispatch('reportUser', payload)
+    },
+    isChecked (statusId) {
+      return this.statusIdsToReport.indexOf(statusId) !== -1
+    },
+    toggleStatus (checked, statusId) {
+      if (checked === this.isChecked(statusId)) {
+        return
+      }
+
+      if (checked) {
+        this.statusIdsToReport.push(statusId)
+      } else {
+        this.statusIdsToReport.splice(this.statusIdsToReport.indexOf(statusId), 1)
+      }
+    },
+    resize (e) {
+      const target = e.target || e
+      if (!(target instanceof window.Element)) { return }
+      // Auto is needed to make textbox shrink when removing lines
+      target.style.height = 'auto'
+      target.style.height = `${target.scrollHeight}px`
+      if (target.value === '') {
+        target.style.height = null
+      }
+    }
+  }
+}
+
+export default UserReportingModal
diff --git a/src/components/user_reporting_modal/user_reporting_modal.vue b/src/components/user_reporting_modal/user_reporting_modal.vue
new file mode 100644
index 00000000..49839da3
--- /dev/null
+++ b/src/components/user_reporting_modal/user_reporting_modal.vue
@@ -0,0 +1,111 @@
+<template>
+<div class="modal-view" @click="closeModal" v-if="isOpen">
+  <div class="user-reporting-panel panel" @click.stop="">
+    <div class="panel-heading">Reporting {{user.screen_name}}</div>
+    <div class="panel-body">
+      <div class="user-reporting-panel-left">
+        <div>
+          <p>The report will be sent to your instance moderators. You can provide an explanation of why you are reporting this account below:</p>
+          <textarea
+            v-model="comment"
+            class="form-control"
+            placeholder="Additional comments"
+            rows="1"
+            @input="resize"
+          />
+        </div>
+        <div v-if="!user.is_local">
+          <p>The account is from another server. Send an anonymized copy of the report there as well?</p>
+          <Checkbox v-model="forward">Forward to {{remoteInstance}}</Checkbox>
+        </div>
+        <div>
+          <button class="btn btn-default" @click="reportUser">Submit</button>
+        </div>
+      </div>
+      <div class="user-reporting-panel-right">
+        <div v-for="status in statuses" :key="status.id" class="status-fadein">
+          <Status :inConversation="false" :focused="false" :statusoid="status" />
+          <Checkbox :checked="isChecked(status.id)" @change="checked => toggleStatus(checked, status.id)" />
+        </div>
+      </div>
+    </div>
+  </div>
+</div>
+</template>
+
+<script src="./user_reporting_modal.js"></script>
+
+<style lang="scss">
+@import '../../_variables.scss';
+
+.user-reporting-panel {
+  width: 90vw;
+  max-width: 700px;
+
+  .panel-body {
+    display: flex;
+    border-top: 1px solid;
+    border-color: $fallback--border;
+    border-color: var(--border, $fallback--border);
+  }
+
+  &-left {
+    width: 50%;
+    padding: 1.1em;
+    border-right: 1px solid;
+    border-color: $fallback--border;
+    border-color: var(--border, $fallback--border);
+    max-width: 320px;
+    line-height: 1.4em;
+    box-sizing: border-box;
+
+    > div {
+      margin-bottom: 2em;
+
+      &:last-child {
+        margin-bottom: 0;
+      }
+    }
+
+    p {
+      margin-top: 0;
+    }
+
+    textarea.form-control {
+      line-height: 16px;
+      resize: none;
+      overflow: hidden;
+      transition: min-height 200ms 100ms;
+      min-height: 44px;
+      width: 100%;
+    }
+
+    .btn {
+      min-width: 10em;
+      padding: 0 2em;
+    }
+  }
+
+  &-right {
+    width: 50%;
+    flex: 1 1 auto;
+    min-height: 20vh;
+    max-height: 80vh;
+    overflow-y: auto;
+    overflow-x: hidden;
+
+    > div {
+      display: flex;
+      justify-content: space-between;
+      border-bottom-width: 1px;
+      border-bottom-style: solid;
+      border-color: $fallback--border;
+      border-color: var(--border, $fallback--border);
+
+      .checkbox {
+        margin: 0.75em;
+      }
+    }
+  }
+}
+</style>
diff --git a/src/i18n/en.json b/src/i18n/en.json
index b07af5e5..8292c921 100644
--- a/src/i18n/en.json
+++ b/src/i18n/en.json
@@ -420,6 +420,7 @@
     "muted": "Muted",
     "per_day": "per day",
     "remote_follow": "Remote follow",
+    "report": "Report",
     "statuses": "Statuses",
     "unblock": "Unblock",
     "unblock_progress": "Unblocking...",
diff --git a/src/main.js b/src/main.js
index 725f5806..92f843b1 100644
--- a/src/main.js
+++ b/src/main.js
@@ -12,6 +12,7 @@ import chatModule from './modules/chat.js'
 import oauthModule from './modules/oauth.js'
 import mediaViewerModule from './modules/media_viewer.js'
 import oauthTokensModule from './modules/oauth_tokens.js'
+import reportsModule from './modules/reports.js'
 
 import VueTimeago from 'vue-timeago'
 import VueI18n from 'vue-i18n'
@@ -75,7 +76,8 @@ const persistedStateOptions = {
       chat: chatModule,
       oauth: oauthModule,
       mediaViewer: mediaViewerModule,
-      oauthTokens: oauthTokensModule
+      oauthTokens: oauthTokensModule,
+      reports: reportsModule
     },
     plugins: [persistedState, pushNotifications],
     strict: false // Socket modifies itself, let's ignore this for now.
diff --git a/src/modules/reports.js b/src/modules/reports.js
new file mode 100644
index 00000000..b712cfeb
--- /dev/null
+++ b/src/modules/reports.js
@@ -0,0 +1,33 @@
+import filter from 'lodash/filter'
+
+const reports = {
+  state: {
+    userId: null,
+    statuses: [],
+    modalActivated: false
+  },
+  mutations: {
+    openUserReportingModal (state, { userId, statuses }) {
+      state.userId = userId
+      state.statuses = statuses
+      state.modalActivated = true
+    },
+    closeUserReportingModal (state) {
+      state.modalActivated = false
+    }
+  },
+  actions: {
+    openUserReportingModal ({ rootState, commit }, userId) {
+      const statuses = filter(rootState.statuses.allStatuses, status => status.user.id === userId)
+      commit('openUserReportingModal', { userId, statuses })
+    },
+    closeUserReportingModal ({ commit }) {
+      commit('closeUserReportingModal')
+    },
+    reportUser ({ commit }, payload) {
+      console.log('payload', payload)
+    }
+  }
+}
+
+export default reports
-- 
cgit v1.2.3-70-g09d2


From 9adbc2c17fced9328771a5f6e7cfefef54ebfb79 Mon Sep 17 00:00:00 2001
From: taehoon <th.dev91@gmail.com>
Date: Wed, 15 May 2019 22:01:04 -0400
Subject: make only screen name as link

---
 src/components/user_card/user_card.vue | 71 ++++++++++++++++++----------------
 1 file changed, 38 insertions(+), 33 deletions(-)

(limited to 'src/components/user_card/user_card.vue')

diff --git a/src/components/user_card/user_card.vue b/src/components/user_card/user_card.vue
index 2d02ca03..f21770ce 100644
--- a/src/components/user_card/user_card.vue
+++ b/src/components/user_card/user_card.vue
@@ -6,7 +6,7 @@
         <router-link :to="userProfileLink(user)">
           <UserAvatar :betterShadow="betterShadow" :user="user"/>
         </router-link>
-        <div class="name-and-screen-name">
+        <div class="user-summary">
           <div class="top-line">
             <div :title="user.name" class='user-name' v-if="user.name_html" v-html="user.name_html"></div>
             <div :title="user.name" class='user-name' v-else>{{user.name}}</div>
@@ -18,12 +18,14 @@
             </a>
           </div>
 
-          <router-link class='user-screen-name' :to="userProfileLink(user)">
-            <span class="handle">@{{user.screen_name}}
+          <div class="bottom-line">
+            <span class="user-screen-name-role">
+              <router-link class="user-screen-name" :to="userProfileLink(user)">@{{user.screen_name}}</router-link>
               <span class="alert staff" v-if="!hideBio && !!visibleRole">{{visibleRole}}</span>
-            </span><span v-if="user.locked"><i class="icon icon-lock"></i></span>
+            </span>
+            <span v-if="user.locked"><i class="icon icon-lock"></i></span>
             <span v-if="!hideUserStatsLocal && !hideBio" class="dailyAvg">{{dailyAvg}} {{ $t('user_card.per_day') }}</span>
-          </router-link>
+          </div>
         </div>
       </div>
       <div class="user-meta">
@@ -232,7 +234,7 @@
     opacity: .8;
   }
 
-  .name-and-screen-name {
+  .user-summary {
     display: block;
     margin-left: 0.6em;
     text-align: left;
@@ -249,6 +251,7 @@
       vertical-align: middle;
       object-fit: contain
     }
+
     .top-line {
       display: flex;
     }
@@ -269,40 +272,42 @@
     }
   }
 
-  .user-screen-name {
-    color: $fallback--lightText;
-    color: var(--lightText, $fallback--lightText);
-    display: inline-block;
+  .bottom-line {
+    display: flex;
     font-weight: light;
     font-size: 15px;
     padding-right: 0.1em;
     width: 100%;
-    display: flex;
+  }
 
-    .dailyAvg {
-      min-width: 1px;
-      flex: 0 0 auto;
-      margin-left: 1em;
-      font-size: 0.7em;
-      color: $fallback--text;
-      color: var(--text, $fallback--text);
-    }
+  .user-screen-name-role {
+    min-width: 1px;
+    flex: 0 1 auto;
+    text-overflow: ellipsis;
+    overflow: hidden;
+  }
 
-    .handle {
-      min-width: 1px;
-      flex: 0 1 auto;
-      text-overflow: ellipsis;
-      overflow: hidden;
-    }
+  .user-screen-name {
+    color: $fallback--lightText;
+    color: var(--lightText, $fallback--lightText);
+  }
 
-    // TODO use proper colors
-    .staff {
-      text-transform: capitalize;
-      color: $fallback--text;
-      color: var(--btnText, $fallback--text);
-      background-color: $fallback--fg;
-      background-color: var(--btn, $fallback--fg);
-    }
+  .dailyAvg {
+    min-width: 1px;
+    flex: 0 0 auto;
+    margin-left: 1em;
+    font-size: 0.7em;
+    color: $fallback--text;
+    color: var(--text, $fallback--text);
+  }
+
+  // TODO use proper colors
+  .staff {
+    text-transform: capitalize;
+    color: $fallback--text;
+    color: var(--btnText, $fallback--text);
+    background-color: $fallback--fg;
+    background-color: var(--btn, $fallback--fg);
   }
 
   .user-meta {
-- 
cgit v1.2.3-70-g09d2


From 34ffcb028a9cf195f430a33d8c029ac4cc8b191d Mon Sep 17 00:00:00 2001
From: taehoon <th.dev91@gmail.com>
Date: Wed, 15 May 2019 22:01:31 -0400
Subject: refactor css

---
 src/components/user_card/user_card.vue | 54 ++++++++++++++++------------------
 1 file changed, 26 insertions(+), 28 deletions(-)

(limited to 'src/components/user_card/user_card.vue')

diff --git a/src/components/user_card/user_card.vue b/src/components/user_card/user_card.vue
index f21770ce..530f56e0 100644
--- a/src/components/user_card/user_card.vue
+++ b/src/components/user_card/user_card.vue
@@ -276,38 +276,36 @@
     display: flex;
     font-weight: light;
     font-size: 15px;
-    padding-right: 0.1em;
-    width: 100%;
-  }
 
-  .user-screen-name-role {
-    min-width: 1px;
-    flex: 0 1 auto;
-    text-overflow: ellipsis;
-    overflow: hidden;
-  }
+    .user-screen-name-role {
+      min-width: 1px;
+      flex: 0 1 auto;
+      text-overflow: ellipsis;
+      overflow: hidden;
+    }
 
-  .user-screen-name {
-    color: $fallback--lightText;
-    color: var(--lightText, $fallback--lightText);
-  }
+    .user-screen-name {
+      color: $fallback--lightText;
+      color: var(--lightText, $fallback--lightText);
+    }
 
-  .dailyAvg {
-    min-width: 1px;
-    flex: 0 0 auto;
-    margin-left: 1em;
-    font-size: 0.7em;
-    color: $fallback--text;
-    color: var(--text, $fallback--text);
-  }
+    .dailyAvg {
+      min-width: 1px;
+      flex: 0 0 auto;
+      margin-left: 1em;
+      font-size: 0.7em;
+      color: $fallback--text;
+      color: var(--text, $fallback--text);
+    }
 
-  // TODO use proper colors
-  .staff {
-    text-transform: capitalize;
-    color: $fallback--text;
-    color: var(--btnText, $fallback--text);
-    background-color: $fallback--fg;
-    background-color: var(--btn, $fallback--fg);
+    // TODO use proper colors
+    .staff {
+      text-transform: capitalize;
+      color: $fallback--text;
+      color: var(--btnText, $fallback--text);
+      background-color: $fallback--fg;
+      background-color: var(--btn, $fallback--fg);
+    }
   }
 
   .user-meta {
-- 
cgit v1.2.3-70-g09d2


From 205a9821e630fae9864a518824e52dea4fd0de28 Mon Sep 17 00:00:00 2001
From: taehoon <th.dev91@gmail.com>
Date: Sun, 19 May 2019 14:25:02 -0400
Subject: make staff label visible

---
 src/components/user_card/user_card.vue | 12 ++++--------
 1 file changed, 4 insertions(+), 8 deletions(-)

(limited to 'src/components/user_card/user_card.vue')

diff --git a/src/components/user_card/user_card.vue b/src/components/user_card/user_card.vue
index 530f56e0..b4495673 100644
--- a/src/components/user_card/user_card.vue
+++ b/src/components/user_card/user_card.vue
@@ -19,10 +19,8 @@
           </div>
 
           <div class="bottom-line">
-            <span class="user-screen-name-role">
-              <router-link class="user-screen-name" :to="userProfileLink(user)">@{{user.screen_name}}</router-link>
-              <span class="alert staff" v-if="!hideBio && !!visibleRole">{{visibleRole}}</span>
-            </span>
+            <router-link class="user-screen-name" :to="userProfileLink(user)">@{{user.screen_name}}</router-link>
+            <span class="alert staff" v-if="!hideBio && !!visibleRole">{{visibleRole}}</span>
             <span v-if="user.locked"><i class="icon icon-lock"></i></span>
             <span v-if="!hideUserStatsLocal && !hideBio" class="dailyAvg">{{dailyAvg}} {{ $t('user_card.per_day') }}</span>
           </div>
@@ -277,14 +275,11 @@
     font-weight: light;
     font-size: 15px;
 
-    .user-screen-name-role {
+    .user-screen-name {
       min-width: 1px;
       flex: 0 1 auto;
       text-overflow: ellipsis;
       overflow: hidden;
-    }
-
-    .user-screen-name {
       color: $fallback--lightText;
       color: var(--lightText, $fallback--lightText);
     }
@@ -300,6 +295,7 @@
 
     // TODO use proper colors
     .staff {
+      flex: none;
       text-transform: capitalize;
       color: $fallback--text;
       color: var(--btnText, $fallback--text);
-- 
cgit v1.2.3-70-g09d2

