wip
This commit is contained in:
parent
f87ec61e96
commit
346c2959e0
5 changed files with 227 additions and 0 deletions
|
@ -487,6 +487,9 @@ const endpoints: Endpoint[] = [
|
||||||
{
|
{
|
||||||
name: 'channels/show'
|
name: 'channels/show'
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: 'channels/posts'
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
export default endpoints;
|
export default endpoints;
|
||||||
|
|
79
src/api/endpoints/channels/posts.ts
Normal file
79
src/api/endpoints/channels/posts.ts
Normal file
|
@ -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<any>}
|
||||||
|
*/
|
||||||
|
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)
|
||||||
|
)));
|
||||||
|
});
|
14
src/web/app/common/scripts/channel-stream.js
Normal file
14
src/web/app/common/scripts/channel-stream.js
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
import Stream from './stream';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Channel stream connection
|
||||||
|
*/
|
||||||
|
class Connection extends Stream {
|
||||||
|
constructor() {
|
||||||
|
super('channel');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Connection;
|
|
@ -2,6 +2,8 @@
|
||||||
<mk-ui ref="ui">
|
<mk-ui ref="ui">
|
||||||
<main if={ !parent.fetching }>
|
<main if={ !parent.fetching }>
|
||||||
<h1>{ parent.channel.title }</h1>
|
<h1>{ parent.channel.title }</h1>
|
||||||
|
<mk-channel-post each={ parent.posts } post={ this }/>
|
||||||
|
<mk-channel-form channel={ parent.channel }/>
|
||||||
</main>
|
</main>
|
||||||
</mk-ui>
|
</mk-ui>
|
||||||
<style>
|
<style>
|
||||||
|
@ -14,12 +16,15 @@
|
||||||
</style>
|
</style>
|
||||||
<script>
|
<script>
|
||||||
import Progress from '../../../common/scripts/loading';
|
import Progress from '../../../common/scripts/loading';
|
||||||
|
import ChannelStream from '../../../common/scripts/channel-stream';
|
||||||
|
|
||||||
this.mixin('api');
|
this.mixin('api');
|
||||||
|
|
||||||
this.id = this.opts.id;
|
this.id = this.opts.id;
|
||||||
this.fetching = true;
|
this.fetching = true;
|
||||||
this.channel = null;
|
this.channel = null;
|
||||||
|
this.posts = null;
|
||||||
|
this.connection = new ChannelStream();
|
||||||
|
|
||||||
this.on('mount', () => {
|
this.on('mount', () => {
|
||||||
document.documentElement.style.background = '#efefef';
|
document.documentElement.style.background = '#efefef';
|
||||||
|
@ -38,6 +43,88 @@
|
||||||
|
|
||||||
document.title = channel.title + ' | Misskey'
|
document.title = channel.title + ' | Misskey'
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.api('channels/posts', {
|
||||||
|
channel_id: this.id
|
||||||
|
}).then(posts => {
|
||||||
|
this.update({
|
||||||
|
posts: posts
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
</mk-channel-page>
|
</mk-channel-page>
|
||||||
|
|
||||||
|
<mk-channel-post>
|
||||||
|
<header>
|
||||||
|
<b>{ post.user.name }</b>
|
||||||
|
</header>
|
||||||
|
<div>
|
||||||
|
{ post.text }
|
||||||
|
</div>
|
||||||
|
<style>
|
||||||
|
:scope
|
||||||
|
display block
|
||||||
|
margin 0
|
||||||
|
padding 0
|
||||||
|
|
||||||
|
> header
|
||||||
|
> b
|
||||||
|
color #008000
|
||||||
|
|
||||||
|
</style>
|
||||||
|
<script>
|
||||||
|
this.post = this.opts.post;
|
||||||
|
</script>
|
||||||
|
</mk-channel-post>
|
||||||
|
|
||||||
|
<mk-channel-form>
|
||||||
|
<p if={ reply }>{ reply.user.name }への返信: (or <a onclick={ clearReply }>キャンセル</a>)</p>
|
||||||
|
<textarea ref="text" disabled={ wait }></textarea>
|
||||||
|
<button class={ wait: wait } ref="submit" disabled={ wait || (refs.text.value.length == 0) } onclick={ post }>
|
||||||
|
{ wait ? 'やってます' : 'やる' }<mk-ellipsis if={ wait }/>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
:scope
|
||||||
|
display block
|
||||||
|
|
||||||
|
</style>
|
||||||
|
<script>
|
||||||
|
this.mixin('api');
|
||||||
|
|
||||||
|
this.channel = this.opts.channel;
|
||||||
|
|
||||||
|
this.clearReply = () => {
|
||||||
|
this.update({
|
||||||
|
reply: null
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
this.clear = () => {
|
||||||
|
this.clearReply();
|
||||||
|
this.refs.text.value = '';
|
||||||
|
};
|
||||||
|
|
||||||
|
this.post = e => {
|
||||||
|
this.update({
|
||||||
|
wait: true
|
||||||
|
});
|
||||||
|
|
||||||
|
this.api('posts/create', {
|
||||||
|
text: this.refs.text.value,
|
||||||
|
reply_to_id: this.reply ? this.reply.id : undefined,
|
||||||
|
channel_id: this.channel.id
|
||||||
|
}).then(data => {
|
||||||
|
this.clear();
|
||||||
|
}).catch(err => {
|
||||||
|
alert('失敗した');
|
||||||
|
}).then(() => {
|
||||||
|
this.update({
|
||||||
|
wait: false
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
</script>
|
||||||
|
</mk-channel-form>
|
||||||
|
|
44
src/web/app/desktop/tags/pages/drive-chooser.tag
Normal file
44
src/web/app/desktop/tags/pages/drive-chooser.tag
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
<mk-drive-chooser>
|
||||||
|
<mk-drive-browser ref="browser" multiple={ parent.multiple }/>
|
||||||
|
<div>
|
||||||
|
<button class="upload" title="PCからドライブにファイルをアップロード" onclick={ upload }><i class="fa fa-upload"></i></button>
|
||||||
|
<button class="cancel" onclick={ close }>キャンセル</button>
|
||||||
|
<button class="ok" onclick={ parent.ok }>決定</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
:scope
|
||||||
|
display block
|
||||||
|
height 100%
|
||||||
|
|
||||||
|
</style>
|
||||||
|
<script>
|
||||||
|
this.multiple = this.opts.multiple != null ? this.opts.multiple : false;
|
||||||
|
|
||||||
|
this.on('mount', () => {
|
||||||
|
this.refs.browser.on('selected', file => {
|
||||||
|
this.files = [file];
|
||||||
|
this.ok();
|
||||||
|
});
|
||||||
|
|
||||||
|
this.refs.browser.on('change-selection', files => {
|
||||||
|
this.update({
|
||||||
|
files: files
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
this.upload = () => {
|
||||||
|
this.refs.browser.selectLocalFile();
|
||||||
|
};
|
||||||
|
|
||||||
|
this.close = () => {
|
||||||
|
window.close();
|
||||||
|
};
|
||||||
|
|
||||||
|
this.ok = () => {
|
||||||
|
window.opener.cb(this.multiple ? this.files : this.files[0]);
|
||||||
|
window.close();
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
</mk-drive-chooser>
|
Loading…
Reference in a new issue