forked from FoundKeyGang/FoundKey
検索結果を内部コンポーネントに
This commit is contained in:
parent
e8719ff6e6
commit
957a1149e0
4 changed files with 128 additions and 50 deletions
|
@ -18,7 +18,6 @@ import MkUserFollowingOrFollowers from './views/pages/user-following-or-follower
|
|||
import MkSelectDrive from './views/pages/selectdrive.vue';
|
||||
import MkDrive from './views/pages/drive.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 MkShare from './views/pages/share.vue';
|
||||
import MkFollow from '../common/views/pages/follow.vue';
|
||||
|
@ -133,6 +132,7 @@ init(async (launch, os) => {
|
|||
? { path: '/', name: 'index', component: MkDeck, children: [
|
||||
{ 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: '/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: '/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) }
|
||||
|
@ -141,6 +141,7 @@ init(async (launch, os) => {
|
|||
{ path: '', name: 'index', component: MkHomeTimeline },
|
||||
{ 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: '/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: '/featured', component: () => import('./views/home/featured.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/settings', component: MkSettings },
|
||||
{ path: '/selectdrive', component: MkSelectDrive },
|
||||
{ path: '/search', component: MkSearch },
|
||||
{ path: '/share', component: MkShare },
|
||||
{ path: '/games/reversi/:game?', component: MkReversi },
|
||||
{ path: '/@:user/following', name: 'userFollowing', component: MkUserFollowingOrFollowers },
|
||||
|
|
99
src/client/app/desktop/views/deck/deck.search-column.vue
Normal file
99
src/client/app/desktop/views/deck/deck.search-column.vue
Normal 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>
|
|
@ -1,12 +1,14 @@
|
|||
<template>
|
||||
<mk-ui>
|
||||
<header :class="$style.header">
|
||||
<h1>{{ q }}</h1>
|
||||
</header>
|
||||
<p :class="$style.notAvailable" v-if="!fetching && notAvailable">{{ $t('not-available') }}</p>
|
||||
<p :class="$style.empty" v-if="!fetching && empty"><fa icon="search"/> {{ $t('not-found', { q }) }}</p>
|
||||
<mk-notes ref="timeline" :class="$style.notes" :more="existMore ? more : null"/>
|
||||
</mk-ui>
|
||||
<div class="oxgbmvii">
|
||||
<div class="notes">
|
||||
<header>
|
||||
<span><fa icon="search"/> {{ q }}</span>
|
||||
</header>
|
||||
<p v-if="!fetching && notAvailable">{{ $t('not-available') }}</p>
|
||||
<p v-if="!fetching && empty"><fa icon="search"/> {{ $t('not-found', { q }) }}</p>
|
||||
<mk-notes ref="timeline" :more="existMore ? more : null"/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
|
@ -106,45 +108,23 @@ export default Vue.extend({
|
|||
});
|
||||
</script>
|
||||
|
||||
<style lang="stylus" module>
|
||||
.header
|
||||
width 100%
|
||||
max-width 600px
|
||||
margin 0 auto
|
||||
color #555
|
||||
<style lang="stylus" scoped>
|
||||
.oxgbmvii
|
||||
> .notes
|
||||
background var(--face)
|
||||
box-shadow var(--shadow)
|
||||
border-radius var(--round)
|
||||
overflow hidden
|
||||
|
||||
.notes
|
||||
max-width 600px
|
||||
margin 0 auto
|
||||
border solid 1px rgba(#000, 0.075)
|
||||
border-radius 6px
|
||||
overflow hidden
|
||||
> header
|
||||
padding 0 8px
|
||||
z-index 10
|
||||
background var(--faceHeader)
|
||||
box-shadow 0 var(--lineWidth) var(--desktopTimelineHeaderShadow)
|
||||
|
||||
.empty
|
||||
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
|
||||
|
||||
.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
|
||||
> span
|
||||
padding 0 8px
|
||||
font-size 0.9em
|
||||
line-height 42px
|
||||
color var(--text)
|
||||
</style>
|
|
@ -98,7 +98,6 @@ export default Vue.extend({
|
|||
box-shadow var(--shadow)
|
||||
border-radius var(--round)
|
||||
overflow hidden
|
||||
overflow hidden
|
||||
|
||||
.empty
|
||||
display block
|
||||
|
|
Loading…
Reference in a new issue