diff options
Diffstat (limited to 'src/components')
| -rw-r--r-- | src/components/attachment/attachment.vue | 2 | ||||
| -rw-r--r-- | src/components/moderation_tools/moderation_tools.vue | 6 | ||||
| -rw-r--r-- | src/components/progress_button/progress_button.vue | 2 | ||||
| -rw-r--r-- | src/components/search/search.js | 98 | ||||
| -rw-r--r-- | src/components/search/search.vue | 211 | ||||
| -rw-r--r-- | src/components/search_bar/search_bar.js | 27 | ||||
| -rw-r--r-- | src/components/search_bar/search_bar.vue (renamed from src/components/user_finder/user_finder.vue) | 38 | ||||
| -rw-r--r-- | src/components/side_drawer/side_drawer.vue | 4 | ||||
| -rw-r--r-- | src/components/tab_switcher/tab_switcher.js | 12 | ||||
| -rw-r--r-- | src/components/user_card/user_card.js | 10 | ||||
| -rw-r--r-- | src/components/user_card/user_card.vue | 213 | ||||
| -rw-r--r-- | src/components/user_finder/user_finder.js | 20 | ||||
| -rw-r--r-- | src/components/user_profile/user_profile.js | 2 | ||||
| -rw-r--r-- | src/components/user_search/user_search.js | 49 | ||||
| -rw-r--r-- | src/components/user_search/user_search.vue | 57 |
15 files changed, 490 insertions, 261 deletions
diff --git a/src/components/attachment/attachment.vue b/src/components/attachment/attachment.vue index 108dc36e..ec326c45 100644 --- a/src/components/attachment/attachment.vue +++ b/src/components/attachment/attachment.vue @@ -100,7 +100,7 @@ <!-- eslint-disable vue/no-v-html --> <h1><a :href="attachment.url">{{ attachment.oembed.title }}</a></h1> <div v-html="attachment.oembed.oembedHTML" /> - <!-- eslint-enabled vue/no-v-html --> + <!-- eslint-enable vue/no-v-html --> </div> </div> </div> diff --git a/src/components/moderation_tools/moderation_tools.vue b/src/components/moderation_tools/moderation_tools.vue index c6f8354b..f1ab67a6 100644 --- a/src/components/moderation_tools/moderation_tools.vue +++ b/src/components/moderation_tools/moderation_tools.vue @@ -1,8 +1,5 @@ <template> - <div - class="block" - style="position: relative" - > + <div> <Popper trigger="click" append-to-body @@ -131,6 +128,7 @@ </div> <button slot="reference" + class="btn btn-default btn-block" :class="{ pressed: showDropDown }" @click="toggleMenu" > diff --git a/src/components/progress_button/progress_button.vue b/src/components/progress_button/progress_button.vue index d19aa97d..283a51af 100644 --- a/src/components/progress_button/progress_button.vue +++ b/src/components/progress_button/progress_button.vue @@ -3,7 +3,7 @@ :disabled="progress || disabled" @click="onClick" > - <template v-if="progress"> + <template v-if="progress && $slots.progress"> <slot name="progress" /> </template> <template v-else> diff --git a/src/components/search/search.js b/src/components/search/search.js new file mode 100644 index 00000000..b434e127 --- /dev/null +++ b/src/components/search/search.js @@ -0,0 +1,98 @@ +import FollowCard from '../follow_card/follow_card.vue' +import Conversation from '../conversation/conversation.vue' +import Status from '../status/status.vue' +import map from 'lodash/map' + +const Search = { + components: { + FollowCard, + Conversation, + Status + }, + props: [ + 'query' + ], + data () { + return { + loaded: false, + loading: false, + searchTerm: this.query || '', + userIds: [], + statuses: [], + hashtags: [], + currenResultTab: 'statuses' + } + }, + computed: { + users () { + return this.userIds.map(userId => this.$store.getters.findUser(userId)) + }, + visibleStatuses () { + const allStatusesObject = this.$store.state.statuses.allStatusesObject + + return this.statuses.filter(status => + allStatusesObject[status.id] && !allStatusesObject[status.id].deleted + ) + } + }, + mounted () { + this.search(this.query) + }, + watch: { + query (newValue) { + this.searchTerm = newValue + this.search(newValue) + } + }, + methods: { + newQuery (query) { + this.$router.push({ name: 'search', query: { query } }) + this.$refs.searchInput.focus() + }, + search (query) { + if (!query) { + this.loading = false + return + } + + this.loading = true + this.userIds = [] + this.statuses = [] + this.hashtags = [] + this.$refs.searchInput.blur() + + this.$store.dispatch('search', { q: query, resolve: true }) + .then(data => { + this.loading = false + this.userIds = map(data.accounts, 'id') + this.statuses = data.statuses + this.hashtags = data.hashtags + this.currenResultTab = this.getActiveTab() + this.loaded = true + }) + }, + resultCount (tabName) { + const length = this[tabName].length + return length === 0 ? '' : ` (${length})` + }, + onResultTabSwitch (_index, dataset) { + this.currenResultTab = dataset.filter + }, + getActiveTab () { + if (this.visibleStatuses.length > 0) { + return 'statuses' + } else if (this.users.length > 0) { + return 'people' + } else if (this.hashtags.length > 0) { + return 'hashtags' + } + + return 'statuses' + }, + lastHistoryRecord (hashtag) { + return hashtag.history && hashtag.history[0] + } + } +} + +export default Search diff --git a/src/components/search/search.vue b/src/components/search/search.vue new file mode 100644 index 00000000..4350e672 --- /dev/null +++ b/src/components/search/search.vue @@ -0,0 +1,211 @@ +<template> + <div class="panel panel-default"> + <div class="panel-heading"> + <div class="title"> + {{ $t('nav.search') }} + </div> + </div> + <div class="search-input-container"> + <input + ref="searchInput" + v-model="searchTerm" + class="search-input" + :placeholder="$t('nav.search')" + @keyup.enter="newQuery(searchTerm)" + > + <button + class="btn search-button" + @click="newQuery(searchTerm)" + > + <i class="icon-search" /> + </button> + </div> + <div + v-if="loading" + class="text-center loading-icon" + > + <i class="icon-spin3 animate-spin" /> + </div> + <div v-else-if="loaded"> + <div class="search-nav-heading"> + <tab-switcher + ref="tabSwitcher" + :on-switch="onResultTabSwitch" + :custom-active="currenResultTab" + > + <span + data-tab-dummy + data-filter="statuses" + :label="$t('user_card.statuses') + resultCount('visibleStatuses')" + /> + <span + data-tab-dummy + data-filter="people" + :label="$t('search.people') + resultCount('users')" + /> + <span + data-tab-dummy + data-filter="hashtags" + :label="$t('search.hashtags') + resultCount('hashtags')" + /> + </tab-switcher> + </div> + </div> + <div class="panel-body"> + <div v-if="currenResultTab === 'statuses'"> + <div + v-if="visibleStatuses.length === 0 && !loading && loaded" + class="search-result-heading" + > + <h4>{{ $t('search.no_results') }}</h4> + </div> + <Status + v-for="status in visibleStatuses" + :key="status.id" + :collapsable="false" + :expandable="false" + :compact="false" + class="search-result" + :statusoid="status" + :no-heading="false" + /> + </div> + <div v-else-if="currenResultTab === 'people'"> + <div + v-if="users.length === 0 && !loading && loaded" + class="search-result-heading" + > + <h4>{{ $t('search.no_results') }}</h4> + </div> + <FollowCard + v-for="user in users" + :key="user.id" + :user="user" + class="list-item search-result" + /> + </div> + <div v-else-if="currenResultTab === 'hashtags'"> + <div + v-if="hashtags.length === 0 && !loading && loaded" + class="search-result-heading" + > + <h4>{{ $t('search.no_results') }}</h4> + </div> + <div + v-for="hashtag in hashtags" + :key="hashtag.url" + class="status trend search-result" + > + <div class="hashtag"> + <router-link :to="{ name: 'tag-timeline', params: { tag: hashtag.name } }"> + #{{ hashtag.name }} + </router-link> + <div v-if="lastHistoryRecord(hashtag)"> + <span v-if="lastHistoryRecord(hashtag).accounts == 1"> + {{ $t('search.person_talking', { count: lastHistoryRecord(hashtag).accounts }) }} + </span> + <span v-else> + {{ $t('search.people_talking', { count: lastHistoryRecord(hashtag).accounts }) }} + </span> + </div> + </div> + <div + v-if="lastHistoryRecord(hashtag)" + class="count" + > + {{ lastHistoryRecord(hashtag).uses }} + </div> + </div> + </div> + </div> + <div class="search-result-footer text-center panel-footer faint" /> + </div> +</template> + +<script src="./search.js"></script> + +<style lang="scss"> +@import '../../_variables.scss'; + +.search-result-heading { + color: $fallback--faint; + color: var(--faint, $fallback--faint); + padding: 0.75rem; + text-align: center; +} + +@media all and (max-width: 800px) { + .search-nav-heading { + .tab-switcher .tabs .tab-wrapper { + display: block; + justify-content: center; + flex: 1 1 auto; + text-align: center; + } + } +} + +.search-result { + box-sizing: border-box; + border-bottom: 1px solid; + border-color: $fallback--border; + border-color: var(--border, $fallback--border); +} + +.search-result-footer { + border-width: 1px 0 0 0; + border-style: solid; + border-color: var(--border, $fallback--border); + padding: 10px; + background-color: $fallback--fg; + background-color: var(--panel, $fallback--fg); +} + +.search-input-container { + padding: 0.8rem; + display: flex; + justify-content: center; + + .search-input { + width: 100%; + line-height: 1.125rem; + font-size: 1rem; + padding: 0.5rem; + box-sizing: border-box; + } + + .search-button { + margin-left: 0.5em; + } +} + +.loading-icon { + padding: 1em; +} + +.trend { + display: flex; + align-items: center; + + .hashtag { + flex: 1 1 auto; + color: $fallback--text; + color: var(--text, $fallback--text); + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } + + .count { + flex: 0 0 auto; + width: 2rem; + font-size: 1.5rem; + line-height: 2.25rem; + font-weight: 500; + text-align: center; + color: $fallback--text; + color: var(--text, $fallback--text); + } +} + +</style> diff --git a/src/components/search_bar/search_bar.js b/src/components/search_bar/search_bar.js new file mode 100644 index 00000000..b8a792ee --- /dev/null +++ b/src/components/search_bar/search_bar.js @@ -0,0 +1,27 @@ +const SearchBar = { + data: () => ({ + searchTerm: undefined, + hidden: true, + error: false, + loading: false + }), + watch: { + '$route': function (route) { + if (route.name === 'search') { + this.searchTerm = route.query.query + } + } + }, + methods: { + find (searchTerm) { + this.$router.push({ name: 'search', query: { query: searchTerm } }) + this.$refs.searchInput.focus() + }, + toggleHidden () { + this.hidden = !this.hidden + this.$emit('toggled', this.hidden) + } + } +} + +export default SearchBar diff --git a/src/components/user_finder/user_finder.vue b/src/components/search_bar/search_bar.vue index 39d49237..4d5a1aec 100644 --- a/src/components/user_finder/user_finder.vue +++ b/src/components/search_bar/search_bar.vue @@ -1,36 +1,36 @@ <template> <div> - <div class="user-finder-container"> + <div class="search-bar-container"> <i v-if="loading" - class="icon-spin4 user-finder-icon animate-spin-slow" + class="icon-spin4 finder-icon animate-spin-slow" /> <a v-if="hidden" href="#" - :title="$t('finder.find_user')" + :title="$t('nav.search')" ><i - class="icon-user-plus user-finder-icon" + class="button-icon icon-search" @click.prevent.stop="toggleHidden" /></a> <template v-else> <input - id="user-finder-input" - ref="userSearchInput" - v-model="username" - class="user-finder-input" - :placeholder="$t('finder.find_user')" + id="search-bar-input" + ref="searchInput" + v-model="searchTerm" + class="search-bar-input" + :placeholder="$t('nav.search')" type="text" - @keyup.enter="findUser(username)" + @keyup.enter="find(searchTerm)" > <button class="btn search-button" - @click="findUser(username)" + @click="find(searchTerm)" > <i class="icon-search" /> </button> <i - class="button-icon icon-cancel user-finder-icon" + class="button-icon icon-cancel" @click.prevent.stop="toggleHidden" /> </template> @@ -38,22 +38,24 @@ </div> </template> -<script src="./user_finder.js"></script> +<script src="./search_bar.js"></script> <style lang="scss"> @import '../../_variables.scss'; -.user-finder-container { +.search-bar-container { max-width: 100%; display: inline-flex; align-items: baseline; vertical-align: baseline; + justify-content: flex-end; - .user-finder-input, + .search-bar-input, .search-button { height: 29px; } - .user-finder-input { + + .search-bar-input { // TODO: do this properly without a rough guesstimate of 2 icons + paddings max-width: calc(100% - 30px - 30px - 20px); } @@ -62,6 +64,10 @@ margin-left: .5em; margin-right: .5em; } + + .icon-cancel { + cursor: pointer; + } } </style> diff --git a/src/components/side_drawer/side_drawer.vue b/src/components/side_drawer/side_drawer.vue index 80b75ce5..5b2d4473 100644 --- a/src/components/side_drawer/side_drawer.vue +++ b/src/components/side_drawer/side_drawer.vue @@ -100,8 +100,8 @@ </ul> <ul> <li @click="toggleDrawer"> - <router-link :to="{ name: 'user-search' }"> - {{ $t("nav.user_search") }} + <router-link :to="{ name: 'search' }"> + {{ $t("nav.search") }} </router-link> </li> <li diff --git a/src/components/tab_switcher/tab_switcher.js b/src/components/tab_switcher/tab_switcher.js index 81e4d333..67835231 100644 --- a/src/components/tab_switcher/tab_switcher.js +++ b/src/components/tab_switcher/tab_switcher.js @@ -4,7 +4,7 @@ import './tab_switcher.scss' export default Vue.component('tab-switcher', { name: 'TabSwitcher', - props: ['renderOnlyFocused', 'onSwitch'], + props: ['renderOnlyFocused', 'onSwitch', 'customActive'], data () { return { active: this.$slots.default.findIndex(_ => _.tag) @@ -24,6 +24,14 @@ export default Vue.component('tab-switcher', { } this.active = index } + }, + isActiveTab (index) { + const customActiveIndex = this.$slots.default.findIndex(slot => { + const dataFilter = slot.data && slot.data.attrs && slot.data.attrs['data-filter'] + return this.customActive && this.customActive === dataFilter + }) + + return customActiveIndex > -1 ? customActiveIndex === index : index === this.active } }, render (h) { @@ -33,7 +41,7 @@ export default Vue.component('tab-switcher', { const classesTab = ['tab'] const classesWrapper = ['tab-wrapper'] - if (index === this.active) { + if (this.isActiveTab(index)) { classesTab.push('active') classesWrapper.push('active') } diff --git a/src/components/user_card/user_card.js b/src/components/user_card/user_card.js index 92cd0e54..e019ebbd 100644 --- a/src/components/user_card/user_card.js +++ b/src/components/user_card/user_card.js @@ -1,5 +1,6 @@ import UserAvatar from '../user_avatar/user_avatar.vue' import RemoteFollow from '../remote_follow/remote_follow.vue' +import ProgressButton from '../progress_button/progress_button.vue' import ModerationTools from '../moderation_tools/moderation_tools.vue' import { hex2rgb } from '../../services/color_convert/color_convert.js' import { requestFollow, requestUnfollow } from '../../services/follow_manipulate/follow_manipulate' @@ -104,7 +105,8 @@ export default { components: { UserAvatar, RemoteFollow, - ModerationTools + ModerationTools, + ProgressButton }, methods: { followUser () { @@ -135,6 +137,12 @@ export default { unmuteUser () { this.$store.dispatch('unmuteUser', this.user.id) }, + subscribeUser () { + return this.$store.dispatch('subscribeUser', this.user.id) + }, + unsubscribeUser () { + return this.$store.dispatch('unsubscribeUser', this.user.id) + }, setProfileView (v) { if (this.switcher) { const store = this.$store diff --git a/src/components/user_card/user_card.vue b/src/components/user_card/user_card.vue index 5a5a4881..f987fbbb 100644 --- a/src/components/user_card/user_card.vue +++ b/src/components/user_card/user_card.vue @@ -112,101 +112,120 @@ </div> </div> <div - v-if="isOtherUser" + v-if="loggedIn && isOtherUser" class="user-interactions" > - <div - v-if="loggedIn" - class="follow" - > - <span v-if="user.following"> - <!--Following them!--> - <button - class="pressed" - :disabled="followRequestInProgress" - :title="$t('user_card.follow_unfollow')" - @click="unfollowUser" - > - <template v-if="followRequestInProgress"> - {{ $t('user_card.follow_progress') }} - </template> - <template v-else> - {{ $t('user_card.following') }} - </template> - </button> - </span> - <span v-if="!user.following"> - <button - :disabled="followRequestInProgress" - :title="followRequestSent ? $t('user_card.follow_again') : ''" - @click="followUser" - > - <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> - </span> + <div v-if="!user.following"> + <button + class="btn btn-default btn-block" + :disabled="followRequestInProgress" + :title="followRequestSent ? $t('user_card.follow_again') : ''" + @click="followUser" + > + <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> + </div> + <div v-else-if="followRequestInProgress"> + <button + class="btn btn-default btn-block pressed" + disabled + :title="$t('user_card.follow_unfollow')" + @click="unfollowUser" + > + {{ $t('user_card.follow_progress') }} + </button> </div> <div - v-if="isOtherUser && loggedIn" - class="mute" + v-else + class="btn-group" > - <span v-if="user.muted"> - <button - class="pressed" - @click="unmuteUser" - > - {{ $t('user_card.muted') }} - </button> - </span> - <span v-if="!user.muted"> - <button @click="muteUser"> - {{ $t('user_card.mute') }} - </button> - </span> + <button + class="btn btn-default pressed" + :title="$t('user_card.follow_unfollow')" + @click="unfollowUser" + > + {{ $t('user_card.following') }} + </button> + <ProgressButton + v-if="!user.subscribed" + class="btn btn-default" + :click="subscribeUser" + :title="$t('user_card.subscribe')" + > + <i class="icon-bell-alt" /> + </ProgressButton> + <ProgressButton + v-else + class="btn btn-default pressed" + :click="unsubscribeUser" + :title="$t('user_card.unsubscribe')" + > + <i class="icon-bell-ringing-o" /> + </ProgressButton> </div> - <div v-if="!loggedIn && user.is_local"> - <RemoteFollow :user="user" /> + + <div> + <button + v-if="user.muted" + class="btn btn-default btn-block pressed" + @click="unmuteUser" + > + {{ $t('user_card.muted') }} + </button> + <button + v-else + class="btn btn-default btn-block" + @click="muteUser" + > + {{ $t('user_card.mute') }} + </button> </div> - <div - v-if="isOtherUser && loggedIn" - class="block" - > - <span v-if="user.statusnet_blocking"> - <button - class="pressed" - @click="unblockUser" - > - {{ $t('user_card.blocked') }} - </button> - </span> - <span v-if="!user.statusnet_blocking"> - <button @click="blockUser"> - {{ $t('user_card.block') }} - </button> - </span> + + <div> + <button + v-if="user.statusnet_blocking" + class="btn btn-default btn-block pressed" + @click="unblockUser" + > + {{ $t('user_card.blocked') }} + </button> + <button + v-else + class="btn btn-default btn-block" + @click="blockUser" + > + {{ $t('user_card.block') }} + </button> </div> - <div - v-if="isOtherUser && loggedIn" - class="block" - > - <span> - <button @click="reportUser"> - {{ $t('user_card.report') }} - </button> - </span> + + <div> + <button + class="btn btn-default btn-block" + @click="reportUser" + > + {{ $t('user_card.report') }} + </button> </div> + <ModerationTools v-if="loggedIn.role === "admin"" :user="user" /> </div> + <div + v-if="!loggedIn && user.is_local" + class="user-interactions" + > + <RemoteFollow :user="user" /> + </div> </div> </div> <div @@ -487,40 +506,22 @@ display: flex; flex-flow: row wrap; justify-content: space-between; - margin-right: -.75em; - div { + > * { flex: 1 0 0; - margin-right: .75em; - margin-bottom: .6em; + margin: 0 .75em .6em 0; white-space: nowrap; } - .mute { - max-width: 220px; - min-height: 28px; - } - - .follow { - max-width: 220px; - min-height: 28px; - } - button { - width: 100%; - height: 100%; margin: 0; - } - - .remote-button { - height: 28px !important; - width: 92%; - } - .pressed { - border-bottom-color: rgba(255, 255, 255, 0.2); - border-top-color: rgba(0, 0, 0, 0.2); + &.pressed { + // TODO: This should be themed. + border-bottom-color: rgba(255, 255, 255, 0.2); + border-top-color: rgba(0, 0, 0, 0.2); + } } } } diff --git a/src/components/user_finder/user_finder.js b/src/components/user_finder/user_finder.js deleted file mode 100644 index 27153f45..00000000 --- a/src/components/user_finder/user_finder.js +++ /dev/null @@ -1,20 +0,0 @@ -const UserFinder = { - data: () => ({ - username: undefined, - hidden: true, - error: false, - loading: false - }), - methods: { - findUser (username) { - this.$router.push({ name: 'user-search', query: { query: username } }) - this.$refs.userSearchInput.focus() - }, - toggleHidden () { - this.hidden = !this.hidden - this.$emit('toggled', this.hidden) - } - } -} - -export default UserFinder diff --git a/src/components/user_profile/user_profile.js b/src/components/user_profile/user_profile.js index 7eb4ed3a..39b99dac 100644 --- a/src/components/user_profile/user_profile.js +++ b/src/components/user_profile/user_profile.js @@ -3,7 +3,6 @@ import UserCard from '../user_card/user_card.vue' import FollowCard from '../follow_card/follow_card.vue' import Timeline from '../timeline/timeline.vue' import Conversation from '../conversation/conversation.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' @@ -132,7 +131,6 @@ const UserProfile = { Timeline, FollowerList, FriendList, - ModerationTools, FollowCard, Conversation } diff --git a/src/components/user_search/user_search.js b/src/components/user_search/user_search.js deleted file mode 100644 index 5c29d8f2..00000000 --- a/src/components/user_search/user_search.js +++ /dev/null @@ -1,49 +0,0 @@ -import FollowCard from '../follow_card/follow_card.vue' -import map from 'lodash/map' - -const userSearch = { - components: { - FollowCard - }, - props: [ - 'query' - ], - data () { - return { - username: '', - userIds: [], - loading: false - } - }, - computed: { - users () { - return this.userIds.map(userId => this.$store.getters.findUser(userId)) - } - }, - mounted () { - this.search(this.query) - }, - watch: { - query (newV) { - this.search(newV) - } - }, - methods: { - newQuery (query) { - this.$router.push({ name: 'user-search', query: { query } }) - this.$refs.userSearchInput.focus() - }, - search (query) { - if (!query) { - return - } - this.loading = true - this.userIds = [] - this.$store.dispatch('searchUsers', query) - .then((res) => { this.userIds = map(res, 'id') }) - .finally(() => { this.loading = false }) - } - } -} - -export default userSearch diff --git a/src/components/user_search/user_search.vue b/src/components/user_search/user_search.vue deleted file mode 100644 index e1c6074c..00000000 --- a/src/components/user_search/user_search.vue +++ /dev/null @@ -1,57 +0,0 @@ -<template> - <div class="user-search panel panel-default"> - <div class="panel-heading"> - {{ $t('nav.user_search') }} - </div> - <div class="user-search-input-container"> - <input - ref="userSearchInput" - v-model="username" - class="user-finder-input" - :placeholder="$t('finder.find_user')" - @keyup.enter="newQuery(username)" - > - <button - class="btn search-button" - @click="newQuery(username)" - > - <i class="icon-search" /> - </button> - </div> - <div - v-if="loading" - class="text-center loading-icon" - > - <i class="icon-spin3 animate-spin" /> - </div> - <div - v-else - class="panel-body" - > - <FollowCard - v-for="user in users" - :key="user.id" - :user="user" - class="list-item" - /> - </div> - </div> -</template> - -<script src="./user_search.js"></script> - -<style lang="scss"> -.user-search-input-container { - margin: 0.5em; - display: flex; - justify-content: center; - - .search-button { - margin-left: 0.5em; - } -} - -.loading-icon { - padding: 1em; -} -</style> |
