From a50999093716d8ce6db47a47b9290395456985de Mon Sep 17 00:00:00 2001 From: taehoon Date: Wed, 3 Apr 2019 21:13:25 -0400 Subject: [PATCH 01/46] add checkbox component --- src/components/checkbox/checkbox.js | 44 ++++++++++++++++++++++++ src/components/checkbox/checkbox.scss | 48 +++++++++++++++++++++++++++ 2 files changed, 92 insertions(+) create mode 100644 src/components/checkbox/checkbox.js create mode 100644 src/components/checkbox/checkbox.scss diff --git a/src/components/checkbox/checkbox.js b/src/components/checkbox/checkbox.js new file mode 100644 index 00000000..76e7e4f4 --- /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 ( + + ) + } +} diff --git a/src/components/checkbox/checkbox.scss b/src/components/checkbox/checkbox.scss new file mode 100644 index 00000000..4dfcfe34 --- /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; + + &-indicator::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; + } + + input[type=checkbox] { + display: none; + + &:checked + .checkbox-indicator::before { + color: $fallback--text; + color: var(--text, $fallback--text); + } + + &:disabled + .checkbox-indicator::before { + opacity: .5; + } + } + + & > span { + margin-left: .5em; + } +} From 4b292564d8add9973116b785132648ddc2be3e1a Mon Sep 17 00:00:00 2001 From: taehoon Date: Wed, 3 Apr 2019 21:43:24 -0400 Subject: [PATCH 02/46] add SelectableRow component --- src/components/selectable_row/selectable_row.js | 16 ++++++++++++++++ src/components/selectable_row/selectable_row.vue | 10 ++++++++++ 2 files changed, 26 insertions(+) create mode 100644 src/components/selectable_row/selectable_row.js create mode 100644 src/components/selectable_row/selectable_row.vue diff --git a/src/components/selectable_row/selectable_row.js b/src/components/selectable_row/selectable_row.js new file mode 100644 index 00000000..9a2d57cd --- /dev/null +++ b/src/components/selectable_row/selectable_row.js @@ -0,0 +1,16 @@ +import Checkbox from '../checkbox/checkbox.js' + +const SelectableRow = { + components: { + Checkbox + }, + props: ['checked'], + data () { + }, + computed: { + }, + methods: { + } +} + +export default SelectableRow diff --git a/src/components/selectable_row/selectable_row.vue b/src/components/selectable_row/selectable_row.vue new file mode 100644 index 00000000..11853672 --- /dev/null +++ b/src/components/selectable_row/selectable_row.vue @@ -0,0 +1,10 @@ + + + + + From 1cec2b696952ef2c472219329961bc102ed315df Mon Sep 17 00:00:00 2001 From: taehoon Date: Wed, 3 Apr 2019 22:17:42 -0400 Subject: [PATCH 03/46] use reusable List vue component instead of withList hoc Using slot is the preferred way in vue --- src/components/list/list.vue | 28 +++++++++++++++++++ src/components/user_settings/user_settings.js | 27 ++++++++---------- .../user_settings/user_settings.vue | 14 +++++++--- 3 files changed, 49 insertions(+), 20 deletions(-) create mode 100644 src/components/list/list.vue diff --git a/src/components/list/list.vue b/src/components/list/list.vue new file mode 100644 index 00000000..f361e3b1 --- /dev/null +++ b/src/components/list/list.vue @@ -0,0 +1,28 @@ + + + + + diff --git a/src/components/user_settings/user_settings.js b/src/components/user_settings/user_settings.js index dd931e67..057d1cec 100644 --- a/src/components/user_settings/user_settings.js +++ b/src/components/user_settings/user_settings.js @@ -10,29 +10,24 @@ import ScopeSelector from '../scope_selector/scope_selector.vue' import fileSizeFormatService from '../../services/file_size_format/file_size_format.js' import BlockCard from '../block_card/block_card.vue' import MuteCard from '../mute_card/mute_card.vue' +import List from '../list/list.vue' import EmojiInput from '../emoji-input/emoji-input.vue' import Autosuggest from '../autosuggest/autosuggest.vue' import withSubscription from '../../hocs/with_subscription/with_subscription' import withList from '../../hocs/with_list/with_list' import userSearchApi from '../../services/new_api/user_search.js' -const BlockList = compose( - withSubscription({ - fetch: (props, $store) => $store.dispatch('fetchBlocks'), - select: (props, $store) => get($store.state.users.currentUser, 'blockIds', []), - childPropName: 'entries' - }), - withList({ getEntryProps: userId => ({ userId }) }) -)(BlockCard) +const BlockList = withSubscription({ + fetch: (props, $store) => $store.dispatch('fetchBlocks'), + select: (props, $store) => get($store.state.users.currentUser, 'blockIds', []), + childPropName: 'items' +})(List) -const MuteList = compose( - withSubscription({ - fetch: (props, $store) => $store.dispatch('fetchMutes'), - select: (props, $store) => get($store.state.users.currentUser, 'muteIds', []), - childPropName: 'entries' - }), - withList({ getEntryProps: userId => ({ userId }) }) -)(MuteCard) +const MuteList = withSubscription({ + fetch: (props, $store) => $store.dispatch('fetchMutes'), + select: (props, $store) => get($store.state.users.currentUser, 'muteIds', []), + childPropName: 'items' +})(List) const UserSettings = { data () { diff --git a/src/components/user_settings/user_settings.vue b/src/components/user_settings/user_settings.vue index 9d37ffc4..741fbe3f 100644 --- a/src/components/user_settings/user_settings.vue +++ b/src/components/user_settings/user_settings.vue @@ -200,9 +200,12 @@ - + + - +
@@ -211,9 +214,12 @@
- + + - + From 738a3dc02da7a3633137e8f0831ec8404e1ba85b Mon Sep 17 00:00:00 2001 From: taehoon Date: Wed, 3 Apr 2019 22:28:08 -0400 Subject: [PATCH 04/46] refactor using List component --- src/components/user_profile/user_profile.js | 38 +++++++++----------- src/components/user_profile/user_profile.vue | 12 +++++-- 2 files changed, 27 insertions(+), 23 deletions(-) diff --git a/src/components/user_profile/user_profile.js b/src/components/user_profile/user_profile.js index cb465d66..8dbf8dac 100644 --- a/src/components/user_profile/user_profile.js +++ b/src/components/user_profile/user_profile.js @@ -4,30 +4,25 @@ import UserCard from '../user_card/user_card.vue' import FollowCard from '../follow_card/follow_card.vue' import Timeline from '../timeline/timeline.vue' import ModerationTools from '../moderation_tools/moderation_tools.vue' +import List from '../list/list.vue' import withLoadMore from '../../hocs/with_load_more/with_load_more' import withList from '../../hocs/with_list/with_list' -const FollowerList = compose( - withLoadMore({ - fetch: (props, $store) => $store.dispatch('fetchFollowers', props.userId), - select: (props, $store) => get($store.getters.findUser(props.userId), 'followerIds', []).map(id => $store.getters.findUser(id)), - destory: (props, $store) => $store.dispatch('clearFollowers', props.userId), - childPropName: 'entries', - additionalPropNames: ['userId'] - }), - withList({ getEntryProps: user => ({ user }) }) -)(FollowCard) +const FollowerList = withLoadMore({ + fetch: (props, $store) => $store.dispatch('fetchFollowers', props.userId), + select: (props, $store) => get($store.getters.findUser(props.userId), 'followerIds', []).map(id => $store.getters.findUser(id)), + destory: (props, $store) => $store.dispatch('clearFollowers', props.userId), + childPropName: 'items', + additionalPropNames: ['userId'] +})(List) -const FriendList = compose( - withLoadMore({ - fetch: (props, $store) => $store.dispatch('fetchFriends', props.userId), - select: (props, $store) => get($store.getters.findUser(props.userId), 'friendIds', []).map(id => $store.getters.findUser(id)), - destory: (props, $store) => $store.dispatch('clearFriends', props.userId), - childPropName: 'entries', - additionalPropNames: ['userId'] - }), - withList({ getEntryProps: user => ({ user }) }) -)(FollowCard) +const FriendList = withLoadMore({ + fetch: (props, $store) => $store.dispatch('fetchFriends', props.userId), + select: (props, $store) => get($store.getters.findUser(props.userId), 'friendIds', []).map(id => $store.getters.findUser(id)), + destory: (props, $store) => $store.dispatch('clearFriends', props.userId), + childPropName: 'items', + additionalPropNames: ['userId'] +})(List) const UserProfile = { data () { @@ -134,7 +129,8 @@ const UserProfile = { Timeline, FollowerList, FriendList, - ModerationTools + ModerationTools, + FollowCard } } diff --git a/src/components/user_profile/user_profile.vue b/src/components/user_profile/user_profile.vue index 89900f60..39f3c381 100644 --- a/src/components/user_profile/user_profile.vue +++ b/src/components/user_profile/user_profile.vue @@ -14,10 +14,18 @@ :user-id="userId" />
- + + +
- + + +
Date: Wed, 3 Apr 2019 22:31:17 -0400 Subject: [PATCH 05/46] remove withList hoc --- src/components/user_profile/user_profile.js | 2 - src/components/user_settings/user_settings.js | 2 - src/hocs/with_list/with_list.js | 40 ------------------- src/hocs/with_list/with_list.scss | 6 --- 4 files changed, 50 deletions(-) delete mode 100644 src/hocs/with_list/with_list.js delete mode 100644 src/hocs/with_list/with_list.scss diff --git a/src/components/user_profile/user_profile.js b/src/components/user_profile/user_profile.js index 8dbf8dac..1ef247cd 100644 --- a/src/components/user_profile/user_profile.js +++ b/src/components/user_profile/user_profile.js @@ -1,4 +1,3 @@ -import { compose } from 'vue-compose' import get from 'lodash/get' import UserCard from '../user_card/user_card.vue' import FollowCard from '../follow_card/follow_card.vue' @@ -6,7 +5,6 @@ import Timeline from '../timeline/timeline.vue' import ModerationTools from '../moderation_tools/moderation_tools.vue' import List from '../list/list.vue' import withLoadMore from '../../hocs/with_load_more/with_load_more' -import withList from '../../hocs/with_list/with_list' const FollowerList = withLoadMore({ fetch: (props, $store) => $store.dispatch('fetchFollowers', props.userId), diff --git a/src/components/user_settings/user_settings.js b/src/components/user_settings/user_settings.js index 057d1cec..2bbb01db 100644 --- a/src/components/user_settings/user_settings.js +++ b/src/components/user_settings/user_settings.js @@ -1,4 +1,3 @@ -import { compose } from 'vue-compose' import unescape from 'lodash/unescape' import get from 'lodash/get' import map from 'lodash/map' @@ -14,7 +13,6 @@ import List from '../list/list.vue' import EmojiInput from '../emoji-input/emoji-input.vue' import Autosuggest from '../autosuggest/autosuggest.vue' import withSubscription from '../../hocs/with_subscription/with_subscription' -import withList from '../../hocs/with_list/with_list' import userSearchApi from '../../services/new_api/user_search.js' const BlockList = withSubscription({ diff --git a/src/hocs/with_list/with_list.js b/src/hocs/with_list/with_list.js deleted file mode 100644 index 896f8fc8..00000000 --- a/src/hocs/with_list/with_list.js +++ /dev/null @@ -1,40 +0,0 @@ -import Vue from 'vue' -import map from 'lodash/map' -import isEmpty from 'lodash/isEmpty' -import './with_list.scss' - -const defaultEntryPropsGetter = entry => ({ entry }) -const defaultKeyGetter = entry => entry.id - -const withList = ({ - getEntryProps = defaultEntryPropsGetter, // function to accept entry and index values and return props to be passed into the item component - getKey = defaultKeyGetter // funciton to accept entry and index values and return key prop value -}) => (ItemComponent) => ( - Vue.component('withList', { - props: [ - 'entries', // array of entry - 'entryProps', // additional props to be passed into each entry - 'entryListeners' // additional event listeners to be passed into each entry - ], - render (createElement) { - return ( -
- {map(this.entries, (entry, index) => { - const props = { - key: getKey(entry, index), - props: { - ...this.$props.entryProps, - ...getEntryProps(entry, index) - }, - on: this.$props.entryListeners - } - return - })} - {isEmpty(this.entries) && this.$slots.empty &&
{this.$slots.empty}
} -
- ) - } - }) -) - -export default withList diff --git a/src/hocs/with_list/with_list.scss b/src/hocs/with_list/with_list.scss deleted file mode 100644 index c6e13d5b..00000000 --- a/src/hocs/with_list/with_list.scss +++ /dev/null @@ -1,6 +0,0 @@ -.with-list { - &-empty-content { - text-align: center; - padding: 10px; - } -} \ No newline at end of file From 39efe9c522bd91f541cbbb2ff08c7c538cca4a9e Mon Sep 17 00:00:00 2001 From: taehoon Date: Wed, 3 Apr 2019 22:35:10 -0400 Subject: [PATCH 06/46] remove unused yarn package --- package.json | 1 - yarn.lock | 10 ---------- 2 files changed, 11 deletions(-) diff --git a/package.json b/package.json index 14937673..fcdea2c1 100644 --- a/package.json +++ b/package.json @@ -30,7 +30,6 @@ "v-click-outside": "^2.1.1", "vue": "^2.5.13", "vue-chat-scroll": "^1.2.1", - "vue-compose": "^0.7.1", "vue-i18n": "^7.3.2", "vue-popperjs": "^2.0.3", "vue-router": "^3.0.1", diff --git a/yarn.lock b/yarn.lock index e463c0d5..69951563 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6430,16 +6430,6 @@ vue-chat-scroll@^1.2.1: version "1.3.5" resolved "https://registry.yarnpkg.com/vue-chat-scroll/-/vue-chat-scroll-1.3.5.tgz#a5ee5bae5058f614818a96eac5ee3be4394a2f68" -vue-compose@^0.7.1: - version "0.7.1" - resolved "https://registry.yarnpkg.com/vue-compose/-/vue-compose-0.7.1.tgz#1c11c4cd5e2c8f2743b03fce8ab43d78aabc20b3" - dependencies: - vue-hoc "0.x.x" - -vue-hoc@0.x.x: - version "0.4.7" - resolved "https://registry.yarnpkg.com/vue-hoc/-/vue-hoc-0.4.7.tgz#4d3322ba89b8b0e42b19045ef536c21d948a4fac" - vue-hot-reload-api@^2.0.11: version "2.3.1" resolved "https://registry.yarnpkg.com/vue-hot-reload-api/-/vue-hot-reload-api-2.3.1.tgz#b2d3d95402a811602380783ea4f566eb875569a2" From 23b9d1eaa31efc83705288409e5993279ae969e6 Mon Sep 17 00:00:00 2001 From: taehoon Date: Wed, 3 Apr 2019 22:38:48 -0400 Subject: [PATCH 07/46] rename selectable_row to selectable_list --- .../selectable_row.js => selectable_list/selectable_list.js} | 4 ++-- .../selectable_list.vue} | 0 2 files changed, 2 insertions(+), 2 deletions(-) rename src/components/{selectable_row/selectable_row.js => selectable_list/selectable_list.js} (74%) rename src/components/{selectable_row/selectable_row.vue => selectable_list/selectable_list.vue} (100%) diff --git a/src/components/selectable_row/selectable_row.js b/src/components/selectable_list/selectable_list.js similarity index 74% rename from src/components/selectable_row/selectable_row.js rename to src/components/selectable_list/selectable_list.js index 9a2d57cd..cd431eeb 100644 --- a/src/components/selectable_row/selectable_row.js +++ b/src/components/selectable_list/selectable_list.js @@ -1,6 +1,6 @@ import Checkbox from '../checkbox/checkbox.js' -const SelectableRow = { +const SelectableList = { components: { Checkbox }, @@ -13,4 +13,4 @@ const SelectableRow = { } } -export default SelectableRow +export default SelectableList diff --git a/src/components/selectable_row/selectable_row.vue b/src/components/selectable_list/selectable_list.vue similarity index 100% rename from src/components/selectable_row/selectable_row.vue rename to src/components/selectable_list/selectable_list.vue From d9b3f5be4733f0eef4d3c8dff982224cd1a5303e Mon Sep 17 00:00:00 2001 From: taehoon Date: Wed, 3 Apr 2019 22:48:00 -0400 Subject: [PATCH 08/46] use SelectableList for blocks/mutes list --- .../selectable_list/selectable_list.js | 11 +++++------ .../selectable_list/selectable_list.vue | 18 +++++++++++++++--- src/components/user_settings/user_settings.js | 6 +++--- 3 files changed, 23 insertions(+), 12 deletions(-) diff --git a/src/components/selectable_list/selectable_list.js b/src/components/selectable_list/selectable_list.js index cd431eeb..138e63ab 100644 --- a/src/components/selectable_list/selectable_list.js +++ b/src/components/selectable_list/selectable_list.js @@ -4,12 +4,11 @@ const SelectableList = { components: { Checkbox }, - props: ['checked'], - data () { - }, - computed: { - }, - methods: { + props: { + items: { + type: Array, + default: () => [] + } } } diff --git a/src/components/selectable_list/selectable_list.vue b/src/components/selectable_list/selectable_list.vue index 11853672..2e0671ef 100644 --- a/src/components/selectable_list/selectable_list.vue +++ b/src/components/selectable_list/selectable_list.vue @@ -1,10 +1,22 @@ - + diff --git a/src/components/user_settings/user_settings.js b/src/components/user_settings/user_settings.js index 2bbb01db..f8742cd4 100644 --- a/src/components/user_settings/user_settings.js +++ b/src/components/user_settings/user_settings.js @@ -9,7 +9,7 @@ import ScopeSelector from '../scope_selector/scope_selector.vue' import fileSizeFormatService from '../../services/file_size_format/file_size_format.js' import BlockCard from '../block_card/block_card.vue' import MuteCard from '../mute_card/mute_card.vue' -import List from '../list/list.vue' +import SelectableList from '../selectable_list/selectable_list.vue' import EmojiInput from '../emoji-input/emoji-input.vue' import Autosuggest from '../autosuggest/autosuggest.vue' import withSubscription from '../../hocs/with_subscription/with_subscription' @@ -19,13 +19,13 @@ const BlockList = withSubscription({ fetch: (props, $store) => $store.dispatch('fetchBlocks'), select: (props, $store) => get($store.state.users.currentUser, 'blockIds', []), childPropName: 'items' -})(List) +})(SelectableList) const MuteList = withSubscription({ fetch: (props, $store) => $store.dispatch('fetchMutes'), select: (props, $store) => get($store.state.users.currentUser, 'muteIds', []), childPropName: 'items' -})(List) +})(SelectableList) const UserSettings = { data () { From e0b246375009a4c533d90def0842bd8cf59f78cc Mon Sep 17 00:00:00 2001 From: taehoon Date: Wed, 3 Apr 2019 23:26:13 -0400 Subject: [PATCH 09/46] save selected items to the state --- .../selectable_list/selectable_list.js | 25 +++++++++++++++++++ .../selectable_list/selectable_list.vue | 2 +- 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/src/components/selectable_list/selectable_list.js b/src/components/selectable_list/selectable_list.js index 138e63ab..5c01bbab 100644 --- a/src/components/selectable_list/selectable_list.js +++ b/src/components/selectable_list/selectable_list.js @@ -8,6 +8,31 @@ const SelectableList = { items: { type: Array, default: () => [] + }, + getKey: { + type: Function, + default: item => item + } + }, + data () { + return { + selected: [] + } + }, + methods: { + toggle (checked, item) { + const oldChecked = this.isChecked(item) + if (checked !== oldChecked) { + const key = this.getKey(item) + if (checked) { + this.selected.push(key) + } else { + this.selected.splice(this.selected.indexOf(key), 1) + } + } + }, + isChecked (item) { + return this.selected.indexOf(this.getKey(item)) !== -1 } } } diff --git a/src/components/selectable_list/selectable_list.vue b/src/components/selectable_list/selectable_list.vue index 2e0671ef..d7b166bc 100644 --- a/src/components/selectable_list/selectable_list.vue +++ b/src/components/selectable_list/selectable_list.vue @@ -1,7 +1,7 @@