検索結果を内部コンポーネントに

This commit is contained in:
syuilo 2019-02-15 14:52:21 +09:00
parent e8719ff6e6
commit 957a1149e0
No known key found for this signature in database
GPG key ID: BDC4C49D06AB9D69
4 changed files with 128 additions and 50 deletions

View file

@ -18,7 +18,6 @@ import MkUserFollowingOrFollowers from './views/pages/user-following-or-follower
import MkSelectDrive from './views/pages/selectdrive.vue'; import MkSelectDrive from './views/pages/selectdrive.vue';
import MkDrive from './views/pages/drive.vue'; import MkDrive from './views/pages/drive.vue';
import MkMessagingRoom from './views/pages/messaging-room.vue'; import MkMessagingRoom from './views/pages/messaging-room.vue';
import MkSearch from './views/pages/search.vue';
import MkReversi from './views/pages/games/reversi.vue'; import MkReversi from './views/pages/games/reversi.vue';
import MkShare from './views/pages/share.vue'; import MkShare from './views/pages/share.vue';
import MkFollow from '../common/views/pages/follow.vue'; import MkFollow from '../common/views/pages/follow.vue';
@ -133,6 +132,7 @@ init(async (launch, os) => {
? { path: '/', name: 'index', component: MkDeck, children: [ ? { path: '/', name: 'index', component: MkDeck, children: [
{ path: '/@:user', name: 'user', component: () => import('./views/deck/deck.user-column.vue').then(m => m.default) }, { path: '/@:user', name: 'user', component: () => import('./views/deck/deck.user-column.vue').then(m => m.default) },
{ path: '/notes/:note', name: 'note', component: () => import('./views/deck/deck.note-column.vue').then(m => m.default) }, { path: '/notes/:note', name: 'note', component: () => import('./views/deck/deck.note-column.vue').then(m => m.default) },
{ path: '/search', component: () => import('./views/deck/deck.search-column.vue').then(m => m.default) },
{ path: '/tags/:tag', name: 'tag', component: () => import('./views/deck/deck.hashtag-column.vue').then(m => m.default) }, { path: '/tags/:tag', name: 'tag', component: () => import('./views/deck/deck.hashtag-column.vue').then(m => m.default) },
{ path: '/featured', component: () => import('./views/deck/deck.featured-column.vue').then(m => m.default) }, { path: '/featured', component: () => import('./views/deck/deck.featured-column.vue').then(m => m.default) },
{ path: '/i/favorites', component: () => import('./views/deck/deck.favorites-column.vue').then(m => m.default) } { path: '/i/favorites', component: () => import('./views/deck/deck.favorites-column.vue').then(m => m.default) }
@ -141,6 +141,7 @@ init(async (launch, os) => {
{ path: '', name: 'index', component: MkHomeTimeline }, { path: '', name: 'index', component: MkHomeTimeline },
{ path: '/@:user', name: 'user', component: () => import('./views/home/user/user.vue').then(m => m.default) }, { path: '/@:user', name: 'user', component: () => import('./views/home/user/user.vue').then(m => m.default) },
{ path: '/notes/:note', name: 'note', component: () => import('./views/home/note.vue').then(m => m.default) }, { path: '/notes/:note', name: 'note', component: () => import('./views/home/note.vue').then(m => m.default) },
{ path: '/search', component: () => import('./views/home/search.vue').then(m => m.default) },
{ path: '/tags/:tag', name: 'tag', component: () => import('./views/home/tag.vue').then(m => m.default) }, { path: '/tags/:tag', name: 'tag', component: () => import('./views/home/tag.vue').then(m => m.default) },
{ path: '/featured', component: () => import('./views/home/featured.vue').then(m => m.default) }, { path: '/featured', component: () => import('./views/home/featured.vue').then(m => m.default) },
{ path: '/i/favorites', component: () => import('./views/home/favorites.vue').then(m => m.default) } { path: '/i/favorites', component: () => import('./views/home/favorites.vue').then(m => m.default) }
@ -150,7 +151,6 @@ init(async (launch, os) => {
{ path: '/i/drive/folder/:folder', component: MkDrive }, { path: '/i/drive/folder/:folder', component: MkDrive },
{ path: '/i/settings', component: MkSettings }, { path: '/i/settings', component: MkSettings },
{ path: '/selectdrive', component: MkSelectDrive }, { path: '/selectdrive', component: MkSelectDrive },
{ path: '/search', component: MkSearch },
{ path: '/share', component: MkShare }, { path: '/share', component: MkShare },
{ path: '/games/reversi/:game?', component: MkReversi }, { path: '/games/reversi/:game?', component: MkReversi },
{ path: '/@:user/following', name: 'userFollowing', component: MkUserFollowingOrFollowers }, { path: '/@:user/following', name: 'userFollowing', component: MkUserFollowingOrFollowers },

View file

@ -0,0 +1,99 @@
<template>
<x-column>
<span slot="header">
<fa icon="search"/><span>{{ q }}</span>
</span>
<div>
<x-notes ref="timeline" :more="existMore ? more : null"/>
</div>
</x-column>
</template>
<script lang="ts">
import Vue from 'vue';
import XColumn from './deck.column.vue';
import XNotes from './deck.notes.vue';
const limit = 20;
export default Vue.extend({
components: {
XColumn,
XNotes
},
data() {
return {
fetching: true,
moreFetching: false,
existMore: false,
offset: 0,
empty: false,
notAvailable: false
};
},
computed: {
q(): string {
return this.$route.query.q;
}
},
watch: {
$route: 'fetch'
},
created() {
this.fetch();
},
methods: {
fetch() {
this.fetching = true;
(this.$refs.timeline as any).init(() => new Promise((res, rej) => {
this.$root.api('notes/search', {
limit: limit + 1,
offset: this.offset,
query: this.q
}).then(notes => {
if (notes.length == 0) this.empty = true;
if (notes.length == limit + 1) {
notes.pop();
this.existMore = true;
}
res(notes);
this.fetching = false;
}, (e: string) => {
this.fetching = false;
if (e === 'searching not available') this.notAvailable = true;
});
}));
},
more() {
this.offset += limit;
const promise = this.$root.api('notes/search', {
limit: limit + 1,
offset: this.offset,
query: this.q
});
promise.then(notes => {
if (notes.length == limit + 1) {
notes.pop();
} else {
this.existMore = false;
}
for (const n of notes) {
(this.$refs.timeline as any).append(n);
}
this.moreFetching = false;
});
return promise;
}
}
});
</script>

View file

@ -1,12 +1,14 @@
<template> <template>
<mk-ui> <div class="oxgbmvii">
<header :class="$style.header"> <div class="notes">
<h1>{{ q }}</h1> <header>
<span><fa icon="search"/> {{ q }}</span>
</header> </header>
<p :class="$style.notAvailable" v-if="!fetching && notAvailable">{{ $t('not-available') }}</p> <p v-if="!fetching && notAvailable">{{ $t('not-available') }}</p>
<p :class="$style.empty" v-if="!fetching && empty"><fa icon="search"/> {{ $t('not-found', { q }) }}</p> <p v-if="!fetching && empty"><fa icon="search"/> {{ $t('not-found', { q }) }}</p>
<mk-notes ref="timeline" :class="$style.notes" :more="existMore ? more : null"/> <mk-notes ref="timeline" :more="existMore ? more : null"/>
</mk-ui> </div>
</div>
</template> </template>
<script lang="ts"> <script lang="ts">
@ -106,45 +108,23 @@ export default Vue.extend({
}); });
</script> </script>
<style lang="stylus" module> <style lang="stylus" scoped>
.header .oxgbmvii
width 100% > .notes
max-width 600px background var(--face)
margin 0 auto box-shadow var(--shadow)
color #555 border-radius var(--round)
.notes
max-width 600px
margin 0 auto
border solid 1px rgba(#000, 0.075)
border-radius 6px
overflow hidden overflow hidden
.empty > header
display block padding 0 8px
margin 0 auto z-index 10
padding 32px background var(--faceHeader)
max-width 400px box-shadow 0 var(--lineWidth) var(--desktopTimelineHeaderShadow)
text-align center
color #999
> [data-icon] > span
display block padding 0 8px
margin-bottom 16px font-size 0.9em
font-size 3em line-height 42px
color #ccc color var(--text)
.notAvailable
display block
margin 0 auto
padding 32px
max-width 400px
text-align center
color #999
> [data-icon]
display block
margin-bottom 16px
font-size 3em
color #ccc
</style> </style>

View file

@ -98,7 +98,6 @@ export default Vue.extend({
box-shadow var(--shadow) box-shadow var(--shadow)
border-radius var(--round) border-radius var(--round)
overflow hidden overflow hidden
overflow hidden
.empty .empty
display block display block