diff options
Diffstat (limited to 'src/components')
23 files changed, 323 insertions, 384 deletions
diff --git a/src/components/basic_user_card/basic_user_card.vue b/src/components/basic_user_card/basic_user_card.vue index 4ede15e9..77fb0aa0 100644 --- a/src/components/basic_user_card/basic_user_card.vue +++ b/src/components/basic_user_card/basic_user_card.vue @@ -1,26 +1,22 @@ <template> <div class="user-card"> <router-link :to="userProfileLink(user)"> - <UserAvatar class="avatar" :compact="true" @click.prevent.native="toggleUserExpanded" :src="user.profile_image_url"/> + <UserAvatar class="avatar" @click.prevent.native="toggleUserExpanded" :src="user.profile_image_url"/> </router-link> <div class="user-card-expanded-content" v-if="userExpanded"> <user-card-content :user="user" :switcher="false"></user-card-content> </div> <div class="user-card-collapsed-content" v-else> - <div class="user-card-primary-area"> - <div :title="user.name" class="user-name"> - <span v-if="user.name_html" v-html="user.name_html"></span> - <span v-else>{{ user.name }}</span> - </div> - <div> - <router-link class='user-screen-name' :to="userProfileLink(user)"> - @{{user.screen_name}} - </router-link> - </div> + <div :title="user.name" class="user-card-user-name"> + <span v-if="user.name_html" v-html="user.name_html"></span> + <span v-else>{{ user.name }}</span> </div> - <div class="user-card-secondary-area"> - <slot name="secondary-area"></slot> + <div> + <router-link class="user-card-screen-name" :to="userProfileLink(user)"> + @{{user.screen_name}} + </router-link> </div> + <slot></slot> </div> </div> </template> @@ -46,30 +42,21 @@ margin-left: 0.7em; text-align: left; flex: 1; - display: flex; - align-items: flex-start; - justify-content: space-between; + min-width: 0; } - &-primary-area { - flex: 1; - .user-name { - img { - object-fit: contain; - height: 16px; - width: 16px; - vertical-align: middle; - } + &-user-name { + img { + object-fit: contain; + height: 16px; + width: 16px; + vertical-align: middle; } } - &-secondary-area { - flex: none; - } - &-expanded-content { flex: 1; - margin: 0.2em 0 0 0.7em; + margin-left: 0.7em; border-radius: $fallback--panelRadius; border-radius: var(--panelRadius, $fallback--panelRadius); border-style: solid; diff --git a/src/components/block_card/block_card.vue b/src/components/block_card/block_card.vue index ed7fe30b..8eb56e25 100644 --- a/src/components/block_card/block_card.vue +++ b/src/components/block_card/block_card.vue @@ -1,6 +1,6 @@ <template> <basic-user-card :user="user"> - <template slot="secondary-area"> + <div class="block-card-content-container"> <button class="btn btn-default" @click="unblockUser" :disabled="progress" v-if="blocked"> <template v-if="progress"> {{ $t('user_card.unblock_progress') }} @@ -17,8 +17,18 @@ {{ $t('user_card.block') }} </template> </button> - </template> + </div> </basic-user-card> </template> -<script src="./block_card.js"></script>
\ No newline at end of file +<script src="./block_card.js"></script> + +<style lang="scss"> +.block-card-content-container { + margin-top: 0.5em; + text-align: right; + button { + width: 10em; + } +} +</style> diff --git a/src/components/follow_card/follow_card.js b/src/components/follow_card/follow_card.js new file mode 100644 index 00000000..425c9c3e --- /dev/null +++ b/src/components/follow_card/follow_card.js @@ -0,0 +1,45 @@ +import BasicUserCard from '../basic_user_card/basic_user_card.vue' +import { requestFollow, requestUnfollow } from '../../services/follow_manipulate/follow_manipulate' + +const FollowCard = { + props: [ + 'user', + 'noFollowsYou' + ], + data () { + return { + inProgress: false, + requestSent: false, + updated: false + } + }, + components: { + BasicUserCard + }, + computed: { + isMe () { return this.$store.state.users.currentUser.id === this.user.id }, + following () { return this.updated ? this.updated.following : this.user.following }, + showFollow () { + return !this.following || this.updated && !this.updated.following + } + }, + methods: { + followUser () { + this.inProgress = true + requestFollow(this.user, this.$store).then(({ sent, updated }) => { + this.inProgress = false + this.requestSent = sent + this.updated = updated + }) + }, + unfollowUser () { + this.inProgress = true + requestUnfollow(this.user, this.$store).then(({ updated }) => { + this.inProgress = false + this.updated = updated + }) + } + } +} + +export default FollowCard diff --git a/src/components/follow_card/follow_card.vue b/src/components/follow_card/follow_card.vue new file mode 100644 index 00000000..6cb064eb --- /dev/null +++ b/src/components/follow_card/follow_card.vue @@ -0,0 +1,53 @@ +<template> + <basic-user-card :user="user"> + <div class="follow-card-content-container"> + <span class="faint" v-if="!noFollowsYou && user.follows_you"> + {{ isMe ? $t('user_card.its_you') : $t('user_card.follows_you') }} + </span> + <button + v-if="showFollow" + class="btn btn-default" + @click="followUser" + :disabled="inProgress" + :title="requestSent ? $t('user_card.follow_again') : ''" + > + <template v-if="inProgress"> + {{ $t('user_card.follow_progress') }} + </template> + <template v-else-if="requestSent"> + {{ $t('user_card.follow_sent') }} + </template> + <template v-else> + {{ $t('user_card.follow') }} + </template> + </button> + <button v-if="following" class="btn btn-default pressed" @click="unfollowUser" :disabled="inProgress"> + <template v-if="inProgress"> + {{ $t('user_card.follow_progress') }} + </template> + <template v-else> + {{ $t('user_card.follow_unfollow') }} + </template> + </button> + </div> + </basic-user-card> +</template> + +<script src="./follow_card.js"></script> + +<style lang="scss"> +.follow-card-content-container { + flex-shrink: 0; + display: flex; + flex-direction: row; + justify-content: space-between; + flex-wrap: wrap; + line-height: 1.5em; + + .btn { + margin-top: 0.5em; + margin-left: auto; + width: 10em; + } +} +</style> diff --git a/src/components/follow_list/follow_list.js b/src/components/follow_list/follow_list.js deleted file mode 100644 index 9777c87e..00000000 --- a/src/components/follow_list/follow_list.js +++ /dev/null @@ -1,68 +0,0 @@ -import UserCard from '../user_card/user_card.vue' - -const FollowList = { - data () { - return { - loading: false, - bottomedOut: false, - error: false - } - }, - props: ['userId', 'showFollowers'], - created () { - window.addEventListener('scroll', this.scrollLoad) - if (this.entries.length === 0) { - this.fetchEntries() - } - }, - destroyed () { - window.removeEventListener('scroll', this.scrollLoad) - this.$store.dispatch('clearFriendsAndFollowers', this.userId) - }, - computed: { - user () { - return this.$store.getters.userById(this.userId) - }, - entries () { - return this.showFollowers ? this.user.followers : this.user.friends - }, - showFollowsYou () { - return !this.showFollowers || (this.showFollowers && this.userId !== this.$store.state.users.currentUser.id) - } - }, - methods: { - fetchEntries () { - if (!this.loading) { - const command = this.showFollowers ? 'addFollowers' : 'addFriends' - this.loading = true - this.$store.dispatch(command, this.userId).then(entries => { - this.error = false - this.loading = false - this.bottomedOut = entries.length === 0 - }).catch(() => { - this.error = true - this.loading = false - }) - } - }, - scrollLoad (e) { - const bodyBRect = document.body.getBoundingClientRect() - const height = Math.max(bodyBRect.height, -(bodyBRect.y)) - if (this.loading === false && - this.bottomedOut === false && - this.$el.offsetHeight > 0 && - (window.innerHeight + window.pageYOffset) >= (height - 750) - ) { - this.fetchEntries() - } - } - }, - watch: { - 'user': 'fetchEntries' - }, - components: { - UserCard - } -} - -export default FollowList diff --git a/src/components/follow_list/follow_list.vue b/src/components/follow_list/follow_list.vue deleted file mode 100644 index 27102edf..00000000 --- a/src/components/follow_list/follow_list.vue +++ /dev/null @@ -1,33 +0,0 @@ -<template> - <div class="follow-list"> - <user-card - v-for="entry in entries" - :key="entry.id" :user="entry" - :noFollowsYou="!showFollowsYou" - /> - <div class="text-center panel-footer"> - <a v-if="error" @click="fetchEntries" class="alert error"> - {{$t('general.generic_error')}} - </a> - <i v-else-if="loading" class="icon-spin3 animate-spin"/> - <span v-else-if="bottomedOut"></span> - <a v-else @click="fetchEntries">{{$t('general.more')}}</a> - </div> - </div> -</template> - -<script src="./follow_list.js"></script> - -<style lang="scss"> - -.follow-list { - .panel-footer { - padding: 10px; - } - - .error { - font-size: 14px; - } -} - -</style> diff --git a/src/components/follow_request_card/follow_request_card.js b/src/components/follow_request_card/follow_request_card.js new file mode 100644 index 00000000..1a00a1c1 --- /dev/null +++ b/src/components/follow_request_card/follow_request_card.js @@ -0,0 +1,20 @@ +import BasicUserCard from '../basic_user_card/basic_user_card.vue' + +const FollowRequestCard = { + props: ['user'], + components: { + BasicUserCard + }, + methods: { + approveUser () { + this.$store.state.api.backendInteractor.approveUser(this.user.id) + this.$store.dispatch('removeFollowRequest', this.user) + }, + denyUser () { + this.$store.state.api.backendInteractor.denyUser(this.user.id) + this.$store.dispatch('removeFollowRequest', this.user) + } + } +} + +export default FollowRequestCard diff --git a/src/components/follow_request_card/follow_request_card.vue b/src/components/follow_request_card/follow_request_card.vue new file mode 100644 index 00000000..4a3bbba4 --- /dev/null +++ b/src/components/follow_request_card/follow_request_card.vue @@ -0,0 +1,29 @@ +<template> + <basic-user-card :user="user"> + <div class="follow-request-card-content-container"> + <button class="btn btn-default" @click="approveUser">{{ $t('user_card.approve') }}</button> + <button class="btn btn-default" @click="denyUser">{{ $t('user_card.deny') }}</button> + </div> + </basic-user-card> +</template> + +<script src="./follow_request_card.js"></script> + +<style lang="scss"> +.follow-request-card-content-container { + display: flex; + flex-direction: row; + flex-wrap: wrap; + button { + margin-top: 0.5em; + margin-right: 0.5em; + flex: 1 1; + max-width: 12em; + min-width: 8em; + + &:last-child { + margin-right: 0; + } + } +} +</style> diff --git a/src/components/follow_requests/follow_requests.js b/src/components/follow_requests/follow_requests.js index bf890530..704a76c6 100644 --- a/src/components/follow_requests/follow_requests.js +++ b/src/components/follow_requests/follow_requests.js @@ -1,8 +1,8 @@ -import UserCard from '../user_card/user_card.vue' +import FollowRequestCard from '../follow_request_card/follow_request_card.vue' const FollowRequests = { components: { - UserCard + FollowRequestCard }, computed: { requests () { diff --git a/src/components/follow_requests/follow_requests.vue b/src/components/follow_requests/follow_requests.vue index 87dc4194..b83c2d68 100644 --- a/src/components/follow_requests/follow_requests.vue +++ b/src/components/follow_requests/follow_requests.vue @@ -4,7 +4,7 @@ {{$t('nav.friend_requests')}} </div> <div class="panel-body"> - <user-card v-for="request in requests" :key="request.id" :user="request" :showFollows="false" :showApproval="true"></user-card> + <FollowRequestCard v-for="request in requests" :key="request.id" :user="request"/> </div> </div> </template> diff --git a/src/components/settings/settings.vue b/src/components/settings/settings.vue index 16814f65..5041b3a3 100644 --- a/src/components/settings/settings.vue +++ b/src/components/settings/settings.vue @@ -150,7 +150,7 @@ <label for="preloadImage">{{$t('settings.preload_images')}}</label> </li> <li> - <input type="checkbox" id="useOneClickNsfw" v-model="useOneClickNsfw"> + <input :disabled="!hideNsfwLocal" type="checkbox" id="useOneClickNsfw" v-model="useOneClickNsfw"> <label for="useOneClickNsfw">{{$t('settings.use_one_click_nsfw')}}</label> </li> </ul> diff --git a/src/components/timeline/timeline.js b/src/components/timeline/timeline.js index 25c553cb..d986663e 100644 --- a/src/components/timeline/timeline.js +++ b/src/components/timeline/timeline.js @@ -1,7 +1,6 @@ import Status from '../status/status.vue' import timelineFetcher from '../../services/timeline_fetcher/timeline_fetcher.service.js' import StatusOrConversation from '../status_or_conversation/status_or_conversation.vue' -import UserCard from '../user_card/user_card.vue' import { throttle } from 'lodash' const Timeline = { @@ -44,8 +43,7 @@ const Timeline = { }, components: { Status, - StatusOrConversation, - UserCard + StatusOrConversation }, created () { const store = this.$store @@ -70,14 +68,21 @@ const Timeline = { document.addEventListener('visibilitychange', this.handleVisibilityChange, false) this.unfocused = document.hidden } + window.addEventListener('keydown', this.handleShortKey) }, destroyed () { window.removeEventListener('scroll', this.scrollLoad) + window.removeEventListener('keydown', this.handleShortKey) if (typeof document.hidden !== 'undefined') document.removeEventListener('visibilitychange', this.handleVisibilityChange, false) this.$store.commit('setLoading', { timeline: this.timelineName, value: false }) }, methods: { + handleShortKey (e) { + if (e.key === '.') this.showNewStatuses() + }, showNewStatuses () { + if (this.newStatusCount === 0) return + if (this.timeline.flushMarker !== 0) { this.$store.commit('clearTimeline', { timeline: this.timelineName }) this.$store.commit('queueFlush', { timeline: this.timelineName, id: 0 }) diff --git a/src/components/user_card/user_card.js b/src/components/user_card/user_card.js deleted file mode 100644 index 28e22f09..00000000 --- a/src/components/user_card/user_card.js +++ /dev/null @@ -1,64 +0,0 @@ -import UserCardContent from '../user_card_content/user_card_content.vue' -import UserAvatar from '../user_avatar/user_avatar.vue' -import generateProfileLink from 'src/services/user_profile_link_generator/user_profile_link_generator' -import { requestFollow, requestUnfollow } from '../../services/follow_manipulate/follow_manipulate' - -const UserCard = { - props: [ - 'user', - 'noFollowsYou', - 'showApproval' - ], - data () { - return { - userExpanded: false, - followRequestInProgress: false, - followRequestSent: false, - updated: false - } - }, - components: { - UserCardContent, - UserAvatar - }, - computed: { - currentUser () { return this.$store.state.users.currentUser }, - following () { return this.updated ? this.updated.following : this.user.following }, - showFollow () { - return !this.showApproval && (!this.following || this.updated && !this.updated.following) - } - }, - methods: { - toggleUserExpanded () { - this.userExpanded = !this.userExpanded - }, - approveUser () { - this.$store.state.api.backendInteractor.approveUser(this.user.id) - this.$store.dispatch('removeFollowRequest', this.user) - }, - denyUser () { - this.$store.state.api.backendInteractor.denyUser(this.user.id) - this.$store.dispatch('removeFollowRequest', this.user) - }, - userProfileLink (user) { - return generateProfileLink(user.id, user.screen_name, this.$store.state.instance.restrictedNicknames) - }, - followUser () { - this.followRequestInProgress = true - requestFollow(this.user, this.$store).then(({ sent, updated }) => { - this.followRequestInProgress = false - this.followRequestSent = sent - this.updated = updated - }) - }, - unfollowUser () { - this.followRequestInProgress = true - requestUnfollow(this.user, this.$store).then(({ updated }) => { - this.followRequestInProgress = false - this.updated = updated - }) - } - } -} - -export default UserCard diff --git a/src/components/user_card/user_card.vue b/src/components/user_card/user_card.vue deleted file mode 100644 index ce4edb3c..00000000 --- a/src/components/user_card/user_card.vue +++ /dev/null @@ -1,159 +0,0 @@ -<template> - <div class="card"> - <router-link :to="userProfileLink(user)"> - <UserAvatar class="avatar" @click.prevent.native="toggleUserExpanded" :src="user.profile_image_url"/> - </router-link> - <div class="user-card-main-content"> - <div class="usercard" v-if="userExpanded"> - <user-card-content :user="user" :switcher="false"></user-card-content> - </div> - <div class="name-and-screen-name" v-if="!userExpanded"> - <div :title="user.name" class="user-name"> - <span v-if="user.name_html" v-html="user.name_html"></span> - <span v-else>{{ user.name }}</span> - </div> - <div class="user-link-action"> - <router-link class='user-screen-name' :to="userProfileLink(user)"> - @{{user.screen_name}} - </router-link> - </div> - </div> - <div class="follow-box" v-if="!userExpanded"> - <span class="faint" v-if="!noFollowsYou && user.follows_you"> - {{ currentUser.id == user.id ? $t('user_card.its_you') : $t('user_card.follows_you') }} - </span> - <button - v-if="showFollow" - class="btn btn-default" - @click="followUser" - :disabled="followRequestInProgress" - :title="followRequestSent ? $t('user_card.follow_again') : ''" - > - <template v-if="followRequestInProgress"> - {{ $t('user_card.follow_progress') }} - </template> - <template v-else-if="followRequestSent"> - {{ $t('user_card.follow_sent') }} - </template> - <template v-else> - {{ $t('user_card.follow') }} - </template> - </button> - <button v-if="following" class="btn btn-default pressed" @click="unfollowUser" :disabled="followRequestInProgress"> - <template v-if="followRequestInProgress"> - {{ $t('user_card.follow_progress') }} - </template> - <template v-else> - {{ $t('user_card.follow_unfollow') }} - </template> - </button> - </div> - <div class="approval" v-if="showApproval"> - <button class="btn btn-default" @click="approveUser">{{ $t('user_card.approve') }}</button> - <button class="btn btn-default" @click="denyUser">{{ $t('user_card.deny') }}</button> - </div> - </div> - </div> -</template> - -<script src="./user_card.js"></script> - -<style lang="scss"> -@import '../../_variables.scss'; - -.user-card-main-content { - display: flex; - flex-direction: column; - flex: 1 1 100%; - margin-left: 0.7em; - min-width: 0; -} - -.name-and-screen-name { - text-align: left; - width: 100%; - - .user-name { - img { - object-fit: contain; - height: 16px; - width: 16px; - vertical-align: middle; - } - } - - .user-link-action { - display: flex; - align-items: flex-start; - justify-content: space-between; - } -} - - -.card { - display: flex; - flex: 1 0; - padding-top: 0.6em; - padding-right: 1em; - padding-bottom: 0.6em; - padding-left: 1em; - border-bottom: 1px solid; - margin: 0; - border-bottom-color: $fallback--border; - border-bottom-color: var(--border, $fallback--border); - - .avatar { - padding: 0; - } - - .follow-box { - text-align: center; - flex-shrink: 0; - display: flex; - flex-direction: row; - justify-content: space-between; - flex-wrap: wrap; - line-height: 1.5em; - - .btn { - margin-top: 0.5em; - margin-left: auto; - width: 10em; - } - } -} - -.usercard { - width: fill-available; - border-radius: $fallback--panelRadius; - border-radius: var(--panelRadius, $fallback--panelRadius); - border-style: solid; - border-color: $fallback--border; - border-color: var(--border, $fallback--border); - border-width: 1px; - overflow: hidden; - - .panel-heading { - background: transparent; - flex-direction: column; - align-items: stretch; - } - - p { - margin-bottom: 0; - } -} - -.approval { - display: flex; - flex-direction: row; - flex-wrap: wrap; - button { - margin-top: 0.5em; - margin-right: 0.5em; - flex: 1 1; - max-width: 12em; - min-width: 8em; - } -} -</style> diff --git a/src/components/user_card_content/user_card_content.vue b/src/components/user_card_content/user_card_content.vue index a3d24eb1..689b9ec6 100644 --- a/src/components/user_card_content/user_card_content.vue +++ b/src/components/user_card_content/user_card_content.vue @@ -222,6 +222,13 @@ overflow: hidden; flex: 1 1 auto; margin-right: 1em; + + img { + object-fit: contain; + height: 16px; + width: 16px; + vertical-align: middle; + } } .user-screen-name { @@ -386,4 +393,24 @@ } } +.usercard { + width: fill-available; + border-radius: $fallback--panelRadius; + border-radius: var(--panelRadius, $fallback--panelRadius); + border-style: solid; + border-color: $fallback--border; + border-color: var(--border, $fallback--border); + border-width: 1px; + overflow: hidden; + + .panel-heading { + background: transparent; + flex-direction: column; + align-items: stretch; + } + + p { + margin-bottom: 0; + } +} </style> diff --git a/src/components/user_profile/user_profile.js b/src/components/user_profile/user_profile.js index 37179ce1..7708141c 100644 --- a/src/components/user_profile/user_profile.js +++ b/src/components/user_profile/user_profile.js @@ -1,9 +1,39 @@ +import { compose } from 'vue-compose' +import get from 'lodash/get' import UserCardContent from '../user_card_content/user_card_content.vue' -import UserCard from '../user_card/user_card.vue' +import FollowCard from '../follow_card/follow_card.vue' import Timeline from '../timeline/timeline.vue' -import FollowList from '../follow_list/follow_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('addFollowers', props.userId), + select: (props, $store) => get($store.getters.userById(props.userId), 'followers', []), + destory: (props, $store) => $store.dispatch('clearFollowers', props.userId), + childPropName: 'entries', + additionalPropNames: ['userId'] + }), + withList({ getEntryProps: user => ({ user }) }) +)(FollowCard) + +const FriendList = compose( + withLoadMore({ + fetch: (props, $store) => $store.dispatch('addFriends', props.userId), + select: (props, $store) => get($store.getters.userById(props.userId), 'friends', []), + destory: (props, $store) => $store.dispatch('clearFriends', props.userId), + childPropName: 'entries', + additionalPropNames: ['userId'] + }), + withList({ getEntryProps: user => ({ user }) }) +)(FollowCard) const UserProfile = { + data () { + return { + error: false + } + }, created () { this.$store.commit('clearTimeline', { timeline: 'user' }) this.$store.commit('clearTimeline', { timeline: 'favorites' }) @@ -13,6 +43,16 @@ const UserProfile = { this.startFetchFavorites() if (!this.user.id) { this.$store.dispatch('fetchUser', this.fetchBy) + .catch((reason) => { + const errorMessage = get(reason, 'error.error') + if (errorMessage === 'No user with such user_id') { // Known error + this.error = this.$t('user_profile.profile_does_not_exist') + } else if (errorMessage) { + this.error = errorMessage + } else { + this.error = this.$t('user_profile.profile_loading_error') + } + }) } }, destroyed () { @@ -105,9 +145,9 @@ const UserProfile = { }, components: { UserCardContent, - UserCard, Timeline, - FollowList + FollowerList, + FriendList } } diff --git a/src/components/user_profile/user_profile.vue b/src/components/user_profile/user_profile.vue index 09fb93de..a3d2825f 100644 --- a/src/components/user_profile/user_profile.vue +++ b/src/components/user_profile/user_profile.vue @@ -18,16 +18,10 @@ :user-id="fetchBy" /> <div :label="$t('user_card.followees')" v-if="followsTabVisible" :disabled="!user.friends_count"> - <FollowList v-if="user.friends_count > 0" :userId="userId" :showFollowers="false" /> - <div class="userlist-placeholder" v-else> - <i class="icon-spin3 animate-spin"></i> - </div> + <FriendList :userId="userId" /> </div> <div :label="$t('user_card.followers')" v-if="followersTabVisible" :disabled="!user.followers_count"> - <FollowList v-if="user.followers_count > 0" :userId="userId" :showFollowers="true" /> - <div class="userlist-placeholder" v-else> - <i class="icon-spin3 animate-spin"></i> - </div> + <FollowerList :userId="userId" :entryProps="{noFollowsYou: isUs}" /> </div> <Timeline :label="$t('user_card.media')" @@ -55,7 +49,8 @@ </div> </div> <div class="panel-body"> - <i class="icon-spin3 animate-spin"></i> + <span v-if="error">{{ error }}</span> + <i class="icon-spin3 animate-spin" v-else></i> </div> </div> </div> diff --git a/src/components/user_search/user_search.js b/src/components/user_search/user_search.js index fe67b2ad..55040826 100644 --- a/src/components/user_search/user_search.js +++ b/src/components/user_search/user_search.js @@ -1,8 +1,8 @@ -import UserCard from '../user_card/user_card.vue' +import FollowCard from '../follow_card/follow_card.vue' import userSearchApi from '../../services/new_api/user_search.js' const userSearch = { components: { - UserCard + FollowCard }, props: [ 'query' diff --git a/src/components/user_search/user_search.vue b/src/components/user_search/user_search.vue index b39e10f4..1269eea6 100644 --- a/src/components/user_search/user_search.vue +++ b/src/components/user_search/user_search.vue @@ -13,7 +13,7 @@ <i class="icon-spin3 animate-spin"/> </div> <div v-else class="panel-body"> - <user-card v-for="user in users" :key="user.id" :user="user" :showFollows="true"></user-card> + <FollowCard v-for="user in users" :key="user.id" :user="user"/> </div> </div> </template> diff --git a/src/components/user_settings/user_settings.js b/src/components/user_settings/user_settings.js index 06e72112..d6972737 100644 --- a/src/components/user_settings/user_settings.js +++ b/src/components/user_settings/user_settings.js @@ -1,7 +1,6 @@ import { compose } from 'vue-compose' import unescape from 'lodash/unescape' import get from 'lodash/get' - import TabSwitcher from '../tab_switcher/tab_switcher.js' import ImageCropper from '../image_cropper/image_cropper.vue' import StyleSwitcher from '../style_switcher/style_switcher.vue' @@ -62,6 +61,9 @@ const UserSettings = { activeTab: 'profile' } }, + created () { + this.$store.dispatch('fetchTokens') + }, components: { StyleSwitcher, TabSwitcher, @@ -89,6 +91,15 @@ const UserSettings = { }, currentSaveStateNotice () { return this.$store.state.interface.settings.currentSaveStateNotice + }, + oauthTokens () { + return this.$store.state.oauthTokens.tokens.map(oauthToken => { + return { + id: oauthToken.id, + appName: oauthToken.app_name, + validUntil: new Date(oauthToken.valid_until).toLocaleDateString() + } + }) } }, methods: { @@ -308,6 +319,11 @@ const UserSettings = { logout () { this.$store.dispatch('logout') this.$router.replace('/') + }, + revokeToken (id) { + if (window.confirm(`${this.$i18n.t('settings.revoke_token')}?`)) { + this.$store.dispatch('revokeToken', id) + } } } } diff --git a/src/components/user_settings/user_settings.vue b/src/components/user_settings/user_settings.vue index 983cbda0..a1123638 100644 --- a/src/components/user_settings/user_settings.vue +++ b/src/components/user_settings/user_settings.vue @@ -122,6 +122,30 @@ </div> <div class="setting-item"> + <h2>{{$t('settings.oauth_tokens')}}</h2> + <table class="oauth-tokens"> + <thead> + <tr> + <th>{{$t('settings.app_name')}}</th> + <th>{{$t('settings.valid_until')}}</th> + <th></th> + </tr> + </thead> + <tbody> + <tr v-for="oauthToken in oauthTokens" :key="oauthToken.id"> + <td>{{oauthToken.appName}}</td> + <td>{{oauthToken.validUntil}}</td> + <td class="actions"> + <button class="btn btn-default" @click="revokeToken(oauthToken.id)"> + {{$t('settings.revoke_token')}} + </button> + </td> + </tr> + </tbody> + </table> + </div> + + <div class="setting-item"> <h2>{{$t('settings.delete_account')}}</h2> <p v-if="!deletingAccount">{{$t('settings.delete_account_description')}}</p> <div v-if="deletingAccount"> @@ -213,5 +237,17 @@ border-radius: $fallback--avatarRadius; border-radius: var(--avatarRadius, $fallback--avatarRadius); } + + .oauth-tokens { + width: 100%; + + th { + text-align: left; + } + + .actions { + text-align: right; + } + } } </style> diff --git a/src/components/who_to_follow/who_to_follow.js b/src/components/who_to_follow/who_to_follow.js index 82098fc2..be0b8827 100644 --- a/src/components/who_to_follow/who_to_follow.js +++ b/src/components/who_to_follow/who_to_follow.js @@ -1,9 +1,9 @@ import apiService from '../../services/api/api.service.js' -import UserCard from '../user_card/user_card.vue' +import FollowCard from '../follow_card/follow_card.vue' const WhoToFollow = { components: { - UserCard + FollowCard }, data () { return { diff --git a/src/components/who_to_follow/who_to_follow.vue b/src/components/who_to_follow/who_to_follow.vue index df2e03c8..1630f5ac 100644 --- a/src/components/who_to_follow/who_to_follow.vue +++ b/src/components/who_to_follow/who_to_follow.vue @@ -4,7 +4,7 @@ {{$t('who_to_follow.who_to_follow')}} </div> <div class="panel-body"> - <user-card v-for="user in users" :key="user.id" :user="user" :showFollows="true"></user-card> + <FollowCard v-for="user in users" :key="user.id" :user="user"/> </div> </div> </template> |
