commit: e1d61746892e5bdd8c0dd92a4704336b3efdb7e4
parent: 9681bb7bfd6b861fe2bfaa4532a4c36d476ae5cf
Author: Roger Braun <roger@rogerbraun.net>
Date: Wed, 30 Nov 2016 13:39:17 +0100
Add basic username completion.
We need to get users into the store, though.
Diffstat:
5 files changed, 93 insertions(+), 2 deletions(-)
diff --git a/build/webpack.base.conf.js b/build/webpack.base.conf.js
@@ -56,7 +56,7 @@ module.exports = {
test: /\.js$/,
loader: 'babel',
include: projectRoot,
- exclude: /node_modules/
+ exclude: /node_modules\/(?!tributejs)/
},
{
test: /\.json$/,
diff --git a/package.json b/package.json
@@ -13,11 +13,13 @@
"lint": "eslint --ext .js,.vue src test/unit/specs test/e2e/specs"
},
"dependencies": {
+ "babel-plugin-add-module-exports": "^0.2.1",
"diff": "^3.0.1",
"karma-mocha-reporter": "^2.2.1",
"node-sass": "^3.10.1",
"sanitize-html": "^1.13.0",
"sass-loader": "^4.0.2",
+ "tributejs": "^2.1.0",
"vue": "^2.0.1",
"vue-router": "^2.0.1",
"vue-timeago": "^3.1.2",
diff --git a/src/components/post_status_form/post_status_form.js b/src/components/post_status_form/post_status_form.js
@@ -1,8 +1,10 @@
import statusPoster from '../../services/status_poster/status_poster.service.js'
import MediaUpload from '../media_upload/media_upload.vue'
import fileTypeService from '../../services/file_type/file_type.service.js'
+import Tribute from '../../../node_modules/tributejs/src/Tribute.js'
+require('../../../node_modules/tributejs/scss/tribute.scss')
-import { reject, map, uniqBy } from 'lodash'
+import { merge, reject, map, uniqBy } from 'lodash'
const buildMentionsString = ({user, attentions}, currentUser) => {
let allAttentions = [...attentions]
@@ -19,6 +21,51 @@ const buildMentionsString = ({user, attentions}, currentUser) => {
return mentions.join(' ') + ' '
}
+const defaultCollection = {
+ // symbol that starts the lookup
+ trigger: '@',
+
+ // element to target for @mentions
+ iframe: null,
+
+ // class added in the flyout menu for active item
+ selectClass: 'highlight',
+
+ // function called on select that returns the content to insert
+ selectTemplate: function (item) {
+ return '@' + item.original.screen_name
+ },
+
+ // template for displaying item in menu
+ menuItemTemplate: function (item) {
+ return `<img src="${item.original.profile_image_url}"></img> <div class='name'>${item.string}</div>`
+ },
+
+ // template for when no match is found (optional),
+ // If no template is provided, menu is hidden.
+ noMatchTemplate: null,
+
+ // specify an alternative parent container for the menu
+ menuContainer: document.body,
+
+ // column to search against in the object (accepts function or string)
+ lookup: 'name',
+
+ // column that contains the content to insert by default
+ fillAttr: 'screen_name',
+
+ // REQUIRED: array of objects to match
+ values: [],
+
+ // specify whether a space is required before the trigger character
+ requireLeadingSpace: true,
+
+ // specify whether a space is allowed in the middle of mentions
+ allowSpaces: false
+}
+
+const tribute = new Tribute({ collection: [] })
+
const PostStatusForm = {
props: [
'replyTo',
@@ -44,6 +91,24 @@ const PostStatusForm = {
}
}
},
+ computed: {
+ completions () {
+ let users = map(this.$store.state.statuses.allStatuses, 'user')
+ users = uniqBy(users, 'id')
+ users = merge({values: users}, defaultCollection)
+ return [users]
+ }
+ },
+ watch: {
+ completions () {
+ tribute.collection = this.completions
+ }
+ },
+ mounted () {
+ const textarea = this.$el.querySelector('textarea')
+ tribute.collection = this.completions
+ tribute.attach(textarea)
+ },
methods: {
postStatus (newStatus) {
statusPoster.postStatus({
diff --git a/src/components/post_status_form/post_status_form.vue b/src/components/post_status_form/post_status_form.vue
@@ -24,6 +24,22 @@
<script src="./post_status_form.js"></script>
<style lang="scss">
+ .tribute-container {
+ ul {
+ padding: 0px;
+ li {
+ display: flex;
+ align-items: center;
+ }
+ }
+ img {
+ padding: 3px;
+ width: 16px;
+ height: 16px;
+ border-radius: 50%;
+ }
+ }
+
.post-status-form, .login {
.form-bottom {
display: flex;
diff --git a/yarn.lock b/yarn.lock
@@ -451,6 +451,10 @@ babel-messages@^6.8.0:
dependencies:
babel-runtime "^6.0.0"
+babel-plugin-add-module-exports:
+ version "0.2.1"
+ resolved "https://registry.yarnpkg.com/babel-plugin-add-module-exports/-/babel-plugin-add-module-exports-0.2.1.tgz#9ae9a1f4a8dc67f0cdec4f4aeda1e43a5ff65e25"
+
babel-plugin-check-es2015-constants@^6.3.13:
version "6.8.0"
resolved "https://registry.yarnpkg.com/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.8.0.tgz#dbf024c32ed37bfda8dee1e76da02386a8d26fe7"
@@ -5482,6 +5486,10 @@ tough-cookie@~2.3.0:
dependencies:
punycode "^1.4.1"
+tributejs:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/tributejs/-/tributejs-2.1.0.tgz#2015cf2cd5fe0b7cb35f203bf67c5880bb9255d7"
+
trim-newlines@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-1.0.0.tgz#5887966bb582a4503a41eb524f7d35011815a613"