summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorsyuilo <syuilotan@yahoo.co.jp>2018-04-20 13:31:43 +0900
committersyuilo <syuilotan@yahoo.co.jp>2018-04-20 13:31:43 +0900
commit4953842ff1c65fc850c856e11598e9901ff7c6e1 (patch)
treef06129067250842ee44a975235a054cc27b3dc44 /src
parent:art: (diff)
downloadsharkey-4953842ff1c65fc850c856e11598e9901ff7c6e1.tar.gz
sharkey-4953842ff1c65fc850c856e11598e9901ff7c6e1.tar.bz2
sharkey-4953842ff1c65fc850c856e11598e9901ff7c6e1.zip
:v:
Diffstat (limited to 'src')
-rw-r--r--src/client/app/common/views/components/note-menu.vue10
-rw-r--r--src/client/app/desktop/script.ts2
-rw-r--r--src/client/app/desktop/views/pages/favorites.vue73
-rw-r--r--src/models/favorite.ts34
-rw-r--r--src/server/api/endpoints.ts6
-rw-r--r--src/server/api/endpoints/i/favorites.ts59
6 files changed, 159 insertions, 25 deletions
diff --git a/src/client/app/common/views/components/note-menu.vue b/src/client/app/common/views/components/note-menu.vue
index 877d2c16bb..3e4be425d9 100644
--- a/src/client/app/common/views/components/note-menu.vue
+++ b/src/client/app/common/views/components/note-menu.vue
@@ -2,6 +2,7 @@
<div class="mk-note-menu">
<div class="backdrop" ref="backdrop" @click="close"></div>
<div class="popover" :class="{ compact }" ref="popover">
+ <button @click="favorite">%i18n:@favorite%</button>
<button v-if="note.userId == os.i.id" @click="pin">%i18n:@pin%</button>
<a v-if="note.uri" :href="note.uri" target="_blank">%i18n:@remote%</a>
</div>
@@ -58,6 +59,14 @@ export default Vue.extend({
});
},
+ favorite() {
+ (this as any).api('notes/favorites/create', {
+ noteId: this.note.id
+ }).then(() => {
+ this.$destroy();
+ });
+ },
+
close() {
(this.$refs.backdrop as any).style.pointerEvents = 'none';
anime({
@@ -142,6 +151,7 @@ $border-color = rgba(27, 31, 35, 0.15)
> a
display block
padding 8px 16px
+ width 100%
&:hover
color $theme-color-foreground
diff --git a/src/client/app/desktop/script.ts b/src/client/app/desktop/script.ts
index 8d95d81775..3b0ed48cd0 100644
--- a/src/client/app/desktop/script.ts
+++ b/src/client/app/desktop/script.ts
@@ -25,6 +25,7 @@ import updateBanner from './api/update-banner';
import MkIndex from './views/pages/index.vue';
import MkUser from './views/pages/user/user.vue';
+import MkFavorites from './views/pages/favorites.vue';
import MkSelectDrive from './views/pages/selectdrive.vue';
import MkDrive from './views/pages/drive.vue';
import MkHomeCustomize from './views/pages/home-customize.vue';
@@ -50,6 +51,7 @@ init(async (launch) => {
routes: [
{ path: '/', name: 'index', component: MkIndex },
{ path: '/i/customize-home', component: MkHomeCustomize },
+ { path: '/i/favorites', component: MkFavorites },
{ path: '/i/messaging/:user', component: MkMessagingRoom },
{ path: '/i/drive', component: MkDrive },
{ path: '/i/drive/folder/:folder', component: MkDrive },
diff --git a/src/client/app/desktop/views/pages/favorites.vue b/src/client/app/desktop/views/pages/favorites.vue
new file mode 100644
index 0000000000..d908c08f7c
--- /dev/null
+++ b/src/client/app/desktop/views/pages/favorites.vue
@@ -0,0 +1,73 @@
+<template>
+<mk-ui>
+ <main v-if="!fetching">
+ <template v-for="favorite in favorites">
+ <mk-note-detail :note="favorite.note" :key="favorite.note.id"/>
+ </template>
+ <a v-if="existMore" @click="more">さらに読み込む</a>
+ </main>
+</mk-ui>
+</template>
+
+<script lang="ts">
+import Vue from 'vue';
+import Progress from '../../../common/scripts/loading';
+
+export default Vue.extend({
+ data() {
+ return {
+ fetching: true,
+ favorites: [],
+ existMore: false,
+ moreFetching: false
+ };
+ },
+ created() {
+ this.fetch();
+ },
+ methods: {
+ fetch() {
+ Progress.start();
+ this.fetching = true;
+
+ (this as any).api('i/favorites', {
+ limit: 11
+ }).then(favorites => {
+ if (favorites.length == 11) {
+ this.existMore = true;
+ favorites.pop();
+ }
+
+ this.favorites = favorites;
+ this.fetching = false;
+
+ Progress.done();
+ });
+ },
+ more() {
+ this.moreFetching = true;
+ (this as any).api('i/favorites', {
+ limit: 11,
+ maxId: this.favorites[this.favorites.length - 1].id
+ }).then(favorites => {
+ if (favorites.length == 11) {
+ this.existMore = true;
+ favorites.pop();
+ } else {
+ this.existMore = false;
+ }
+
+ this.favorites = this.favorites.concat(favorites);
+ this.moreFetching = false;
+ });
+ }
+ }
+});
+</script>
+
+<style lang="stylus" scoped>
+main
+ margin 0 auto
+ padding 16px
+ max-width 700px
+</style>
diff --git a/src/models/favorite.ts b/src/models/favorite.ts
index 5387b29457..d24833f191 100644
--- a/src/models/favorite.ts
+++ b/src/models/favorite.ts
@@ -1,5 +1,7 @@
import * as mongo from 'mongodb';
+import deepcopy = require('deepcopy');
import db from '../db/mongodb';
+import { pack as packNote } from './note';
const Favorite = db.get<IFavorite>('favorites');
Favorite.createIndex(['userId', 'noteId'], { unique: true });
@@ -38,3 +40,35 @@ export async function deleteFavorite(favorite: string | mongo.ObjectID | IFavori
_id: f._id
});
}
+
+/**
+ * Pack a favorite for API response
+ */
+export const pack = (
+ favorite: any,
+ me: any
+) => new Promise<any>(async (resolve, reject) => {
+ let _favorite: any;
+
+ // Populate the favorite if 'favorite' is ID
+ if (mongo.ObjectID.prototype.isPrototypeOf(favorite)) {
+ _favorite = await Favorite.findOne({
+ _id: favorite
+ });
+ } else if (typeof favorite === 'string') {
+ _favorite = await Favorite.findOne({
+ _id: new mongo.ObjectID(favorite)
+ });
+ } else {
+ _favorite = deepcopy(favorite);
+ }
+
+ // Rename _id to id
+ _favorite.id = _favorite._id;
+ delete _favorite._id;
+
+ // Populate note
+ _favorite.note = await packNote(_favorite.noteId, me);
+
+ resolve(_favorite);
+});
diff --git a/src/server/api/endpoints.ts b/src/server/api/endpoints.ts
index 7cf49debe9..3686918147 100644
--- a/src/server/api/endpoints.ts
+++ b/src/server/api/endpoints.ts
@@ -234,6 +234,12 @@ const endpoints: Endpoint[] = [
},
{
+ name: 'i/favorites',
+ withCredential: true,
+ kind: 'favorites-read'
+ },
+
+ {
name: 'othello/match',
withCredential: true
},
diff --git a/src/server/api/endpoints/i/favorites.ts b/src/server/api/endpoints/i/favorites.ts
index b40f2b3887..f390ef9ec7 100644
--- a/src/server/api/endpoints/i/favorites.ts
+++ b/src/server/api/endpoints/i/favorites.ts
@@ -2,43 +2,52 @@
* Module dependencies
*/
import $ from 'cafy';
-import Favorite from '../../../../models/favorite';
-import { pack } from '../../../../models/note';
+import Favorite, { pack } from '../../../../models/favorite';
/**
- * Get followers of a user
- *
- * @param {any} params
- * @param {any} user
- * @return {Promise<any>}
+ * Get favorited notes
*/
module.exports = (params, user) => new Promise(async (res, rej) => {
// Get 'limit' parameter
const [limit = 10, limitErr] = $(params.limit).optional.number().range(1, 100).$;
if (limitErr) return rej('invalid limit param');
- // Get 'offset' parameter
- const [offset = 0, offsetErr] = $(params.offset).optional.number().min(0).$;
- if (offsetErr) return rej('invalid offset param');
+ // Get 'sinceId' parameter
+ const [sinceId, sinceIdErr] = $(params.sinceId).optional.id().$;
+ if (sinceIdErr) return rej('invalid sinceId param');
- // Get 'sort' parameter
- const [sort = 'desc', sortError] = $(params.sort).optional.string().or('desc asc').$;
- if (sortError) return rej('invalid sort param');
+ // Get 'untilId' parameter
+ const [untilId, untilIdErr] = $(params.untilId).optional.id().$;
+ if (untilIdErr) return rej('invalid untilId param');
+
+ // Check if both of sinceId and untilId is specified
+ if (sinceId && untilId) {
+ return rej('cannot set sinceId and untilId');
+ }
+
+ const query = {
+ userId: user._id
+ } as any;
+
+ const sort = {
+ _id: -1
+ };
+
+ if (sinceId) {
+ sort._id = 1;
+ query._id = {
+ $gt: sinceId
+ };
+ } else if (untilId) {
+ query._id = {
+ $lt: untilId
+ };
+ }
// Get favorites
const favorites = await Favorite
- .find({
- userId: user._id
- }, {
- limit: limit,
- skip: offset,
- sort: {
- _id: sort == 'asc' ? 1 : -1
- }
- });
+ .find(query, { limit, sort });
// Serialize
- res(await Promise.all(favorites.map(async favorite =>
- await pack(favorite.noteId)
- )));
+ res(await Promise.all(favorites.map(favorite => pack(favorite, user))));
});