Prechádzať zdrojové kódy

Add new searchUsersThreads route for results for just threads or just users

sbkwgh 6 rokov pred
rodič
commit
48340ebad4

+ 8 - 2
frontend/src/components/routes/Search.vue

@@ -6,7 +6,10 @@
 				<h2>Threads</h2>
 				<thread-display v-for='thread in threads.slice(0, 3)' :key='thread.id' :thread='thread'></thread-display>
 
-				<div class='search__more search__item' v-if='threads.length > 3'>
+				<div
+					class='search__more search__item' v-if='threads.length > 3'
+					@click='$router.push("/search/threads/" + $route.params.q)'
+				>
 					<span class='fa fa-fw fa-comments'></span>
 					View all matching threads
 				</div>
@@ -25,7 +28,10 @@
 				<h2>Users</h2>
 				<user-display v-for='user in users.slice(0, 5)' :key='user.id' :user='user'></user-display>
 				
-				<div class='search__item search__more' v-if='users.length > 5'>
+				<div
+					class='search__item search__more' v-if='users.length > 5'
+					@click='$router.push("/search/users/" + $route.params.q)'
+				>
 					<span class='fa fa-fw fa-user'></span>
 					View all matching users
 				</div>

+ 162 - 0
frontend/src/components/routes/SearchUsersThreads.vue

@@ -0,0 +1,162 @@
+<template>
+	<div class='route_container'>
+		<h1>Results for {{searchType}} containing '{{$route.params.q}}'</h1>
+		
+		<transition name='fade' mode='out-in'>
+			<div class='search__results' key='results' v-if='results && results.length'>
+				<scroll-load
+					:loading='loading'
+					@loadNext='loadNextPage'
+				>
+
+					<template v-if='searchType === "users"'>
+						<user-display
+							v-for='result in results'
+							:key='result.id'
+							:user='result'
+						>
+						</user-display>
+						
+						<user-placeholder
+							v-if='loading'
+							v-for='n in next'
+							:key='n'
+						></user-placeholder>
+					</template>
+
+					<template v-if='searchType === "threads"'>
+						<thread-display
+							v-for='result in results'
+							:key='result.id'
+							:thread='result'
+						>
+						</thread-display>
+						
+						<thread-display-placeholder
+							v-if='loading'
+							v-for='n in next'
+							:key='n'
+						>
+						</thread-display-placeholder>
+					</template>
+
+				</scroll-load>
+			</div>
+
+			<div
+				class='overlay_message search__overlay_message'
+				v-else-if='results && !results.length'
+				key='no results'
+			>
+				<span class='fa fa-exclamation-circle'></span>
+				No {{searchType}} found
+			</div>
+
+			<div key='loading' v-else>
+				<user-placeholder v-if='searchType === "users"'>
+				</user-placeholder>
+
+				<thread-display-placeholder v-if='searchType === "threads"'>
+				</thread-display-placeholder>
+			</div>
+		</transition>
+	</div>
+</template>
+
+<script>
+	import ScrollLoad from '../ScrollLoad'
+	import UserDisplay from '../UserDisplay'
+	import UserPlaceholder from '../UserPlaceholder'
+	import ThreadDisplay from '../ThreadDisplay'
+	import ThreadDisplayPlaceholder from '../ThreadDisplayPlaceholder'
+
+	import AjaxErrorHandler from '../../assets/js/errorHandler'
+	import logger from '../../assets/js/logger'
+
+	export default {
+		name: 'Search',
+		components: {
+			ScrollLoad,
+			UserDisplay,
+			UserPlaceholder,
+			ThreadDisplay,
+			ThreadDisplayPlaceholder
+		},
+		data () {
+			return {
+				results: null,
+				next: 0,
+				offset: 0,
+
+				loading: false
+			}
+		},
+		computed: {
+			searchType () {
+				let name = this.$route.name;
+
+				if(name === 'search/users') {
+					return 'users';
+				} else if (name === 'search/threads') {
+					return 'threads';
+				}
+			}
+		},
+		methods: {
+			getResults () {
+				this.$store.dispatch('setTitle', 'Search | ' + this.$route.params.q)
+			
+				this.axios
+					.get(`/api/v1/search/${this.searchType.slice(0, -1)}?q=${this.$route.params.q}`)
+					.then(res => {
+						this.results = res.data[this.searchType]
+						this.next = res.data.next
+						this.offset = res.data.offset
+					})
+					.catch(AjaxErrorHandler(this.$store))
+			},
+			loadNextPage () {
+				if(!this.next) return
+
+				this.loading = true
+
+				this.axios
+					.get(
+						`/api/v1/search/${this.searchType.slice(0, -1)}?q=${this.$route.params.q}&offset=${this.offset}`
+					)
+					.then(res => {
+						this.results.push(...res.data[this.searchType])
+						this.next = res.data.next
+						this.offset = res.data.offset
+
+						this.loading = false
+					})
+					.catch(e => {
+						this.loading = false
+						AjaxErrorHandler(this.$store)(e)
+					})
+			}
+		},
+		watch: {
+			'$route.params': 'getResults'
+		},
+		mounted () {
+			this.$store.dispatch('setTitle', 'Search | ' + this.$route.params.q)
+			this.getResults()
+
+			logger('search')
+		}
+	}
+</script>
+
+<style lang='scss' scoped>
+	.search {
+		@at-root #{&}__overlay_message {
+			margin-top: 5rem;
+
+			@at-root #{&}--loading span {
+				margin-bottom: 1rem;
+			}
+		}
+	}
+</style>

+ 4 - 0
frontend/src/main.js

@@ -36,7 +36,9 @@ const P = () => import('./components/routes/P')
 const Start = () => import('./components/routes/Start')
 const Thread = () => import('./components/routes/Thread')
 const ThreadNew = () => import('./components/routes/ThreadNew')
+
 const Search = () => import('./components/routes/Search')
+const SearchUsersThreads = () => import('./components/routes/SearchUsersThreads')
 
 const User = () => import('./components/routes/User')
 const UserPosts = () => import('./components/routes/UserPosts')
@@ -70,6 +72,8 @@ const router = new VueRouter({
 		{ path: '/thread/:slug/:id/:post_number', name: 'thread-post', component: Thread },
 		{ path: '/thread/new', component: ThreadNew },
 		{ path: '/search/:q', component: Search },
+		{ path: '/search/users/:q', component: SearchUsersThreads, name: 'search/users' },
+		{ path: '/search/threads/:q', component: SearchUsersThreads, name: 'search/threads' },
 		{ path: '/user/:username', redirect: '/user/:username/posts', component: User, children: [
 			{ path: 'posts', component: UserPosts },
 			{ path: 'threads', component: UserThreads }

+ 1 - 1
routes/search.js

@@ -103,7 +103,7 @@ router.get('/user', async (req, res, next) => {
 
 		res.json({
 			users,
-			offset: users.length? users.slice(-1)[0].id : null,
+			offset: users.length < limit ? null : offset + limit,
 			next: users.length < limit ? null : limit
 		})