From 5efb52b9f563ae7d6b5383d054a6c21fee676b68 Mon Sep 17 00:00:00 2001 From: syuilo Date: Tue, 31 Oct 2017 22:35:31 +0900 Subject: wip --- src/api/endpoints/channels/create.ts | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 src/api/endpoints/channels/create.ts (limited to 'src/api/endpoints/channels') diff --git a/src/api/endpoints/channels/create.ts b/src/api/endpoints/channels/create.ts new file mode 100644 index 0000000000..74b089dfc3 --- /dev/null +++ b/src/api/endpoints/channels/create.ts @@ -0,0 +1,29 @@ +/** + * Module dependencies + */ +import $ from 'cafy'; +import Channel from '../../models/channel'; +import serialize from '../../serializers/channel'; + +/** + * Create a channel + * + * @param {any} params + * @param {any} user + * @return {Promise} + */ +module.exports = async (params, user) => new Promise(async (res, rej) => { + // Get 'title' parameter + const [title, titleErr] = $(params.title).string().range(1, 100).$; + if (titleErr) return rej('invalid title param'); + + // Create a channel + const channel = await Channel.insert({ + created_at: new Date(), + user_id: user._id, + title: title + }); + + // Response + res(await serialize(channel)); +}); -- cgit v1.2.3-freya From f87ec61e96a8c1f070abefc6a3b5f7e68e24705d Mon Sep 17 00:00:00 2001 From: syuilo Date: Tue, 31 Oct 2017 23:11:22 +0900 Subject: wip --- src/api/endpoints.ts | 3 ++ src/api/endpoints/channels/show.ts | 31 +++++++++++++++++++++ src/web/app/desktop/router.js | 26 +++++++++++------ src/web/app/desktop/tags/index.js | 1 + src/web/app/desktop/tags/pages/channel.tag | 43 +++++++++++++++++++++++++++++ src/web/app/desktop/tags/pages/channels.tag | 2 +- src/web/app/desktop/tags/pages/user.tag | 2 +- 7 files changed, 97 insertions(+), 11 deletions(-) create mode 100644 src/api/endpoints/channels/show.ts create mode 100644 src/web/app/desktop/tags/pages/channel.tag (limited to 'src/api/endpoints/channels') diff --git a/src/api/endpoints.ts b/src/api/endpoints.ts index 26177b8775..45b83fc9e5 100644 --- a/src/api/endpoints.ts +++ b/src/api/endpoints.ts @@ -484,6 +484,9 @@ const endpoints: Endpoint[] = [ minInterval: ms('10seconds') } }, + { + name: 'channels/show' + }, ]; export default endpoints; diff --git a/src/api/endpoints/channels/show.ts b/src/api/endpoints/channels/show.ts new file mode 100644 index 0000000000..8861e54594 --- /dev/null +++ b/src/api/endpoints/channels/show.ts @@ -0,0 +1,31 @@ +/** + * Module dependencies + */ +import $ from 'cafy'; +import { default as Channel, IChannel } from '../../models/channel'; +import serialize from '../../serializers/channel'; + +/** + * Show a channel + * + * @param {any} params + * @param {any} user + * @return {Promise} + */ +module.exports = (params, user) => new Promise(async (res, rej) => { + // Get 'channel_id' parameter + const [channelId, channelIdErr] = $(params.channel_id).id().$; + if (channelIdErr) return rej('invalid channel_id param'); + + // Fetch channel + const channel: IChannel = await Channel.findOne({ + _id: channelId + }); + + if (channel === null) { + return rej('channel not found'); + } + + // Serialize + res(await serialize(channel, user)); +}); diff --git a/src/web/app/desktop/router.js b/src/web/app/desktop/router.js index 51738f3afa..d9300cc69a 100644 --- a/src/web/app/desktop/router.js +++ b/src/web/app/desktop/router.js @@ -7,15 +7,16 @@ const route = require('page'); let page = null; export default me => { - route('/', index); - route('/i>mentions', mentions); - route('/channel', channels); - route('/post::post', post); - route('/search::query', search); - route('/:user', user.bind(null, 'home')); - route('/:user/graphs', user.bind(null, 'graphs')); - route('/:user/:post', post); - route('*', notFound); + route('/', index); + route('/i>mentions', mentions); + route('/channel', channels); + route('/channel/:channel', channel); + route('/post::post', post); + route('/search::query', search); + route('/:user', user.bind(null, 'home')); + route('/:user/graphs', user.bind(null, 'graphs')); + route('/:user/:post', post); + route('*', notFound); function index() { me ? home() : entrance(); @@ -55,6 +56,12 @@ export default me => { mount(el); } + function channel(ctx) { + const el = document.createElement('mk-channel-page'); + el.setAttribute('id', ctx.params.channel); + mount(el); + } + function channels() { mount(document.createElement('mk-channels-page')); } @@ -72,6 +79,7 @@ export default me => { }; function mount(content) { + document.documentElement.style.background = '#313a42'; document.documentElement.removeAttribute('data-page'); if (page) page.unmount(); const body = document.getElementById('app'); diff --git a/src/web/app/desktop/tags/index.js b/src/web/app/desktop/tags/index.js index 6d49006526..7fdeb6884d 100644 --- a/src/web/app/desktop/tags/index.js +++ b/src/web/app/desktop/tags/index.js @@ -61,6 +61,7 @@ require('./pages/user.tag'); require('./pages/post.tag'); require('./pages/search.tag'); require('./pages/not-found.tag'); +require('./pages/channel.tag'); require('./pages/channels.tag'); require('./autocomplete-suggestion.tag'); require('./progress-dialog.tag'); diff --git a/src/web/app/desktop/tags/pages/channel.tag b/src/web/app/desktop/tags/pages/channel.tag new file mode 100644 index 0000000000..4fa172f99d --- /dev/null +++ b/src/web/app/desktop/tags/pages/channel.tag @@ -0,0 +1,43 @@ + + +
+

{ parent.channel.title }

+
+
+ + +
diff --git a/src/web/app/desktop/tags/pages/channels.tag b/src/web/app/desktop/tags/pages/channels.tag index 03fae3c8d1..220f1ca50e 100644 --- a/src/web/app/desktop/tags/pages/channels.tag +++ b/src/web/app/desktop/tags/pages/channels.tag @@ -18,7 +18,7 @@ this.new = () => { const title = window.prompt('%i18n:desktop.tags.mk-channels-page.channel-title%'); - this.api('bbs/channels/create', { + this.api('channels/create', { title: title }).then(channel => { location.href = '/channel/' + channel.id; diff --git a/src/web/app/desktop/tags/pages/user.tag b/src/web/app/desktop/tags/pages/user.tag index 864fe22735..811ca5c0fd 100644 --- a/src/web/app/desktop/tags/pages/user.tag +++ b/src/web/app/desktop/tags/pages/user.tag @@ -16,7 +16,7 @@ this.refs.ui.refs.user.on('user-fetched', user => { Progress.set(0.5); - document.title = user.name + ' | Misskey' + document.title = user.name + ' | Misskey'; }); this.refs.ui.refs.user.on('loaded', () => { -- cgit v1.2.3-freya From 346c2959e058fa445ebb82e71eb37ef023ba6bd4 Mon Sep 17 00:00:00 2001 From: syuilo Date: Wed, 1 Nov 2017 00:10:30 +0900 Subject: wip --- src/api/endpoints.ts | 3 + src/api/endpoints/channels/posts.ts | 79 +++++++++++++++++++++ src/web/app/common/scripts/channel-stream.js | 14 ++++ src/web/app/desktop/tags/pages/channel.tag | 87 ++++++++++++++++++++++++ src/web/app/desktop/tags/pages/drive-chooser.tag | 44 ++++++++++++ 5 files changed, 227 insertions(+) create mode 100644 src/api/endpoints/channels/posts.ts create mode 100644 src/web/app/common/scripts/channel-stream.js create mode 100644 src/web/app/desktop/tags/pages/drive-chooser.tag (limited to 'src/api/endpoints/channels') diff --git a/src/api/endpoints.ts b/src/api/endpoints.ts index 45b83fc9e5..88c01d4e7f 100644 --- a/src/api/endpoints.ts +++ b/src/api/endpoints.ts @@ -487,6 +487,9 @@ const endpoints: Endpoint[] = [ { name: 'channels/show' }, + { + name: 'channels/posts' + }, ]; export default endpoints; diff --git a/src/api/endpoints/channels/posts.ts b/src/api/endpoints/channels/posts.ts new file mode 100644 index 0000000000..fa91fb93ee --- /dev/null +++ b/src/api/endpoints/channels/posts.ts @@ -0,0 +1,79 @@ +/** + * Module dependencies + */ +import $ from 'cafy'; +import { default as Channel, IChannel } from '../../models/channel'; +import { default as Post, IPost } from '../../models/post'; +import serialize from '../../serializers/post'; + +/** + * Show a posts of a channel + * + * @param {any} params + * @param {any} user + * @return {Promise} + */ +module.exports = (params, user) => new Promise(async (res, rej) => { + // Get 'limit' parameter + const [limit = 1000, limitErr] = $(params.limit).optional.number().range(1, 1000).$; + if (limitErr) return rej('invalid limit param'); + + // Get 'since_id' parameter + const [sinceId, sinceIdErr] = $(params.since_id).optional.id().$; + if (sinceIdErr) return rej('invalid since_id param'); + + // Get 'max_id' parameter + const [maxId, maxIdErr] = $(params.max_id).optional.id().$; + if (maxIdErr) return rej('invalid max_id param'); + + // Check if both of since_id and max_id is specified + if (sinceId && maxId) { + return rej('cannot set since_id and max_id'); + } + + // Get 'channel_id' parameter + const [channelId, channelIdErr] = $(params.channel_id).id().$; + if (channelIdErr) return rej('invalid channel_id param'); + + // Fetch channel + const channel: IChannel = await Channel.findOne({ + _id: channelId + }); + + if (channel === null) { + return rej('channel not found'); + } + + //#region Construct query + const sort = { + _id: -1 + }; + + const query = { + channel_id: channel._id + } as any; + + if (sinceId) { + sort._id = 1; + query._id = { + $gt: sinceId + }; + } else if (maxId) { + query._id = { + $lt: maxId + }; + } + //#endregion Construct query + + // Issue query + const posts = await Post + .find(query, { + limit: limit, + sort: sort + }); + + // Serialize + res(await Promise.all(posts.map(async (post) => + await serialize(post, user) + ))); +}); diff --git a/src/web/app/common/scripts/channel-stream.js b/src/web/app/common/scripts/channel-stream.js new file mode 100644 index 0000000000..38e7d91132 --- /dev/null +++ b/src/web/app/common/scripts/channel-stream.js @@ -0,0 +1,14 @@ +'use strict'; + +import Stream from './stream'; + +/** + * Channel stream connection + */ +class Connection extends Stream { + constructor() { + super('channel'); + } +} + +export default Connection; diff --git a/src/web/app/desktop/tags/pages/channel.tag b/src/web/app/desktop/tags/pages/channel.tag index 4fa172f99d..8a3034f40c 100644 --- a/src/web/app/desktop/tags/pages/channel.tag +++ b/src/web/app/desktop/tags/pages/channel.tag @@ -2,6 +2,8 @@

{ parent.channel.title }

+ +
+ + +
+ { post.user.name } +
+
+ { post.text } +
+ + +
+ + +

{ reply.user.name }への返信: (or キャンセル)

+ + + + + +
diff --git a/src/web/app/desktop/tags/pages/drive-chooser.tag b/src/web/app/desktop/tags/pages/drive-chooser.tag new file mode 100644 index 0000000000..49741ad40c --- /dev/null +++ b/src/web/app/desktop/tags/pages/drive-chooser.tag @@ -0,0 +1,44 @@ + + +
+ + + +
+ + + +
-- cgit v1.2.3-freya From 71c3e11708dad327924bdcb95193d44c2b11a907 Mon Sep 17 00:00:00 2001 From: syuilo Date: Wed, 1 Nov 2017 01:38:19 +0900 Subject: wip --- src/api/endpoints/channels/create.ts | 3 ++- src/api/endpoints/posts/create.ts | 17 +++++++++++++++ src/api/models/channel.ts | 1 + src/api/serializers/post.ts | 8 ++++++- src/web/app/desktop/tags/pages/channel.tag | 35 +++++++++++++++++++++++++----- src/web/app/desktop/tags/timeline.tag | 4 ++++ src/web/app/mobile/tags/timeline.tag | 4 ++++ 7 files changed, 65 insertions(+), 7 deletions(-) (limited to 'src/api/endpoints/channels') diff --git a/src/api/endpoints/channels/create.ts b/src/api/endpoints/channels/create.ts index 74b089dfc3..e0c0e0192a 100644 --- a/src/api/endpoints/channels/create.ts +++ b/src/api/endpoints/channels/create.ts @@ -21,7 +21,8 @@ module.exports = async (params, user) => new Promise(async (res, rej) => { const channel = await Channel.insert({ created_at: new Date(), user_id: user._id, - title: title + title: title, + index: 0 }); // Response diff --git a/src/api/endpoints/posts/create.ts b/src/api/endpoints/posts/create.ts index e0a02fa4a0..183cabf135 100644 --- a/src/api/endpoints/posts/create.ts +++ b/src/api/endpoints/posts/create.ts @@ -153,6 +153,16 @@ module.exports = (params, user: IUser, app) => new Promise(async (res, rej) => { if (repost && !isQuote) { return rej('チャンネル内部では引用ではないRepostをすることはできません'); } + } else { + // 返信対象の投稿がチャンネルへの投稿だったらダメ + if (inReplyToPost && inReplyToPost.channel_id != null) { + return rej('チャンネル外部からチャンネル内部の投稿に返信することはできません'); + } + + // Repost対象の投稿がチャンネルへの投稿だったらダメ + if (repost && repost.channel_id != null) { + return rej('チャンネル外部からチャンネル内部の投稿をRepostすることはできません'); + } } // Get 'poll' parameter @@ -199,6 +209,7 @@ module.exports = (params, user: IUser, app) => new Promise(async (res, rej) => { const post = await Post.insert({ created_at: new Date(), channel_id: channel ? channel._id : undefined, + index: channel ? channel.index + 1 : undefined, media_ids: files ? files.map(file => file._id) : undefined, reply_to_id: inReplyToPost ? inReplyToPost._id : undefined, repost_id: repost ? repost._id : undefined, @@ -217,6 +228,12 @@ module.exports = (params, user: IUser, app) => new Promise(async (res, rej) => { // ----------------------------------------------------------- // Post processes + Channel.update({ _id: channel._id }, { + $inc: { + index: 1 + } + }); + User.update({ _id: user._id }, { $set: { latest_post: post diff --git a/src/api/models/channel.ts b/src/api/models/channel.ts index 79edb71367..c80e84dbc8 100644 --- a/src/api/models/channel.ts +++ b/src/api/models/channel.ts @@ -10,4 +10,5 @@ export type IChannel = { created_at: Date; title: string; user_id: mongo.ObjectID; + index: number; }; diff --git a/src/api/serializers/post.ts b/src/api/serializers/post.ts index df917a8595..7d40df2d6a 100644 --- a/src/api/serializers/post.ts +++ b/src/api/serializers/post.ts @@ -8,6 +8,7 @@ import Reaction from '../models/post-reaction'; import { IUser } from '../models/user'; import Vote from '../models/poll-vote'; import serializeApp from './app'; +import serializeChannel from './channel'; import serializeUser from './user'; import serializeDriveFile from './drive-file'; import parse from '../common/text'; @@ -76,8 +77,13 @@ const self = ( _post.app = await serializeApp(_post.app_id); } + // Populate channel + if (_post.channel_id) { + _post.channel = await serializeChannel(_post.channel_id); + } + + // Populate media if (_post.media_ids) { - // Populate media _post.media = await Promise.all(_post.media_ids.map(async fileId => await serializeDriveFile(fileId) )); diff --git a/src/web/app/desktop/tags/pages/channel.tag b/src/web/app/desktop/tags/pages/channel.tag index 8a3034f40c..ebd26f07b8 100644 --- a/src/web/app/desktop/tags/pages/channel.tag +++ b/src/web/app/desktop/tags/pages/channel.tag @@ -2,8 +2,9 @@

{ parent.channel.title }

- - + +
+
@@ -57,9 +60,13 @@
- { post.user.name } + { post.index }: + { post.user.name } + + ID:{ post.user.username }
+ >>{ post.reply_to.index } { post.text }
-

{ reply.user.name }への返信: (or キャンセル)

+

>>{ reply.index } ({ reply.user.name }): [x]