wip
This commit is contained in:
parent
9bf5dc67f5
commit
17d62b689d
6 changed files with 215 additions and 4 deletions
57
src/client/pages/user/clips.vue
Normal file
57
src/client/pages/user/clips.vue
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<MkPagination :pagination="pagination" #default="{items}" ref="list">
|
||||||
|
<MkA v-for="item in items" :key="item.id" :to="`/clips/${item.id}`" class="item _panel _vMargin">
|
||||||
|
<b>{{ item.name }}</b>
|
||||||
|
<div v-if="item.description" class="description">{{ item.description }}</div>
|
||||||
|
</MkA>
|
||||||
|
</MkPagination>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { defineComponent } from 'vue';
|
||||||
|
import MkPagination from '@/components/ui/pagination.vue';
|
||||||
|
import { userPage, acct } from '../../filters/user';
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
components: {
|
||||||
|
MkPagination,
|
||||||
|
},
|
||||||
|
|
||||||
|
props: {
|
||||||
|
user: {
|
||||||
|
type: Object,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
pagination: {
|
||||||
|
endpoint: 'users/clips',
|
||||||
|
limit: 20,
|
||||||
|
params: {
|
||||||
|
userId: this.user.id,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
watch: {
|
||||||
|
user() {
|
||||||
|
this.$refs.list.reload();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
userPage,
|
||||||
|
|
||||||
|
acct
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
|
||||||
|
</style>
|
|
@ -60,12 +60,15 @@
|
||||||
<div class="main">
|
<div class="main">
|
||||||
<div class="nav _vMargin">
|
<div class="nav _vMargin">
|
||||||
<MkA :to="userPage(user)" :class="{ active: page === 'index' }" class="link">
|
<MkA :to="userPage(user)" :class="{ active: page === 'index' }" class="link">
|
||||||
|
<Fa :icon="faCommentAlt" class="icon"/>
|
||||||
<span>{{ $t('notes') }}</span>
|
<span>{{ $t('notes') }}</span>
|
||||||
</MkA>
|
</MkA>
|
||||||
<MkA :to="userPage(user, 'clips')" :class="{ active: page === 'clips' }" class="link">
|
<MkA :to="userPage(user, 'clips')" :class="{ active: page === 'clips' }" class="link">
|
||||||
|
<Fa :icon="faPaperclip" class="icon"/>
|
||||||
<span>{{ $t('clips') }}</span>
|
<span>{{ $t('clips') }}</span>
|
||||||
</MkA>
|
</MkA>
|
||||||
<MkA :to="userPage(user, 'pages')" :class="{ active: page === 'pages' }" class="link">
|
<MkA :to="userPage(user, 'pages')" :class="{ active: page === 'pages' }" class="link">
|
||||||
|
<Fa :icon="faFileAlt" class="icon"/>
|
||||||
<span>{{ $t('pages') }}</span>
|
<span>{{ $t('pages') }}</span>
|
||||||
</MkA>
|
</MkA>
|
||||||
<div class="actions">
|
<div class="actions">
|
||||||
|
@ -83,6 +86,8 @@
|
||||||
</template>
|
</template>
|
||||||
<XFollowList v-else-if="page === 'following'" type="following" :user="user" class="_vMargin"/>
|
<XFollowList v-else-if="page === 'following'" type="following" :user="user" class="_vMargin"/>
|
||||||
<XFollowList v-else-if="page === 'followers'" type="followers" :user="user" class="_vMargin"/>
|
<XFollowList v-else-if="page === 'followers'" type="followers" :user="user" class="_vMargin"/>
|
||||||
|
<XClips v-else-if="page === 'clips'" :user="user" class="_vMargin"/>
|
||||||
|
<XPages v-else-if="page === 'pages'" :user="user" class="_vMargin"/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -193,8 +198,8 @@
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { defineComponent, defineAsyncComponent, computed } from 'vue';
|
import { defineComponent, defineAsyncComponent, computed } from 'vue';
|
||||||
import { faExclamationTriangle, faEllipsisH, faRobot, faLock, faBookmark, faChartBar, faImage, faBirthdayCake, faMapMarker } from '@fortawesome/free-solid-svg-icons';
|
import { faExclamationTriangle, faEllipsisH, faRobot, faLock, faBookmark, faChartBar, faImage, faBirthdayCake, faMapMarker, faPaperclip, faFileAlt } from '@fortawesome/free-solid-svg-icons';
|
||||||
import { faCalendarAlt, faBookmark as farBookmark } from '@fortawesome/free-regular-svg-icons';
|
import { faCalendarAlt, faBookmark as farBookmark, faCommentAlt } from '@fortawesome/free-regular-svg-icons';
|
||||||
import * as age from 's-age';
|
import * as age from 's-age';
|
||||||
import XUserTimeline from './index.timeline.vue';
|
import XUserTimeline from './index.timeline.vue';
|
||||||
import XNote from '@/components/note.vue';
|
import XNote from '@/components/note.vue';
|
||||||
|
@ -221,6 +226,8 @@ export default defineComponent({
|
||||||
MkFolder,
|
MkFolder,
|
||||||
MkTab,
|
MkTab,
|
||||||
XFollowList: defineAsyncComponent(() => import('./follow-list.vue')),
|
XFollowList: defineAsyncComponent(() => import('./follow-list.vue')),
|
||||||
|
XClips: defineAsyncComponent(() => import('./clips.vue')),
|
||||||
|
XPages: defineAsyncComponent(() => import('./pages.vue')),
|
||||||
XPhotos: defineAsyncComponent(() => import('./index.photos.vue')),
|
XPhotos: defineAsyncComponent(() => import('./index.photos.vue')),
|
||||||
XActivity: defineAsyncComponent(() => import('./index.activity.vue')),
|
XActivity: defineAsyncComponent(() => import('./index.activity.vue')),
|
||||||
},
|
},
|
||||||
|
@ -251,7 +258,7 @@ export default defineComponent({
|
||||||
error: null,
|
error: null,
|
||||||
parallaxAnimationId: null,
|
parallaxAnimationId: null,
|
||||||
narrow: null,
|
narrow: null,
|
||||||
faExclamationTriangle, faEllipsisH, faRobot, faLock, faBookmark, farBookmark, faChartBar, faImage, faBirthdayCake, faMapMarker, faCalendarAlt
|
faExclamationTriangle, faEllipsisH, faRobot, faLock, faBookmark, farBookmark, faChartBar, faImage, faBirthdayCake, faMapMarker, faCalendarAlt, faCommentAlt, faPaperclip, faFileAlt,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -471,7 +478,8 @@ export default defineComponent({
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
margin-top: var(--margin);
|
margin-top: var(--margin);
|
||||||
font-size: 120%;
|
//font-size: 120%;
|
||||||
|
font-weight: bold;
|
||||||
|
|
||||||
> .link {
|
> .link {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
|
@ -479,6 +487,10 @@ export default defineComponent({
|
||||||
text-align: center;
|
text-align: center;
|
||||||
border-bottom: solid 3px transparent;
|
border-bottom: solid 3px transparent;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
&.active {
|
&.active {
|
||||||
color: var(--accent);
|
color: var(--accent);
|
||||||
border-bottom-color: var(--accent);
|
border-bottom-color: var(--accent);
|
||||||
|
|
56
src/client/pages/user/pages.vue
Normal file
56
src/client/pages/user/pages.vue
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<MkPagination :pagination="pagination" #default="{items}" ref="list">
|
||||||
|
<MkPagePreview v-for="page in items" :page="page" :key="page.id" class="_vMargin"/>
|
||||||
|
</MkPagination>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { defineComponent } from 'vue';
|
||||||
|
import MkPagePreview from '@/components/page-preview.vue';
|
||||||
|
import MkPagination from '@/components/ui/pagination.vue';
|
||||||
|
import { userPage, acct } from '../../filters/user';
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
components: {
|
||||||
|
MkPagination,
|
||||||
|
MkPagePreview,
|
||||||
|
},
|
||||||
|
|
||||||
|
props: {
|
||||||
|
user: {
|
||||||
|
type: Object,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
pagination: {
|
||||||
|
endpoint: 'users/pages',
|
||||||
|
limit: 20,
|
||||||
|
params: {
|
||||||
|
userId: this.user.id,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
watch: {
|
||||||
|
user() {
|
||||||
|
this.$refs.list.reload();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
userPage,
|
||||||
|
|
||||||
|
acct
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
|
||||||
|
</style>
|
|
@ -24,6 +24,12 @@ export class ClipRepository extends Repository<Clip> {
|
||||||
isPublic: clip.isPublic,
|
isPublic: clip.isPublic,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public packMany(
|
||||||
|
clips: Clip[],
|
||||||
|
) {
|
||||||
|
return Promise.all(clips.map(x => this.pack(x)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const packedClipSchema = {
|
export const packedClipSchema = {
|
||||||
|
|
40
src/server/api/endpoints/users/clips.ts
Normal file
40
src/server/api/endpoints/users/clips.ts
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
import $ from 'cafy';
|
||||||
|
import { ID } from '../../../../misc/cafy-id';
|
||||||
|
import define from '../../define';
|
||||||
|
import { Clips } from '../../../../models';
|
||||||
|
import { makePaginationQuery } from '../../common/make-pagination-query';
|
||||||
|
|
||||||
|
export const meta = {
|
||||||
|
tags: ['users', 'clips'],
|
||||||
|
|
||||||
|
params: {
|
||||||
|
userId: {
|
||||||
|
validator: $.type(ID),
|
||||||
|
},
|
||||||
|
|
||||||
|
limit: {
|
||||||
|
validator: $.optional.num.range(1, 100),
|
||||||
|
default: 10
|
||||||
|
},
|
||||||
|
|
||||||
|
sinceId: {
|
||||||
|
validator: $.optional.type(ID),
|
||||||
|
},
|
||||||
|
|
||||||
|
untilId: {
|
||||||
|
validator: $.optional.type(ID),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default define(meta, async (ps, user) => {
|
||||||
|
const query = makePaginationQuery(Clips.createQueryBuilder('clip'), ps.sinceId, ps.untilId)
|
||||||
|
.andWhere(`clip.userId = :userId`, { userId: ps.userId })
|
||||||
|
.andWhere('clip.isPublic = true');
|
||||||
|
|
||||||
|
const clips = await query
|
||||||
|
.take(ps.limit!)
|
||||||
|
.getMany();
|
||||||
|
|
||||||
|
return await Clips.packMany(clips);
|
||||||
|
});
|
40
src/server/api/endpoints/users/pages.ts
Normal file
40
src/server/api/endpoints/users/pages.ts
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
import $ from 'cafy';
|
||||||
|
import { ID } from '../../../../misc/cafy-id';
|
||||||
|
import define from '../../define';
|
||||||
|
import { Pages } from '../../../../models';
|
||||||
|
import { makePaginationQuery } from '../../common/make-pagination-query';
|
||||||
|
|
||||||
|
export const meta = {
|
||||||
|
tags: ['users', 'pages'],
|
||||||
|
|
||||||
|
params: {
|
||||||
|
userId: {
|
||||||
|
validator: $.type(ID),
|
||||||
|
},
|
||||||
|
|
||||||
|
limit: {
|
||||||
|
validator: $.optional.num.range(1, 100),
|
||||||
|
default: 10
|
||||||
|
},
|
||||||
|
|
||||||
|
sinceId: {
|
||||||
|
validator: $.optional.type(ID),
|
||||||
|
},
|
||||||
|
|
||||||
|
untilId: {
|
||||||
|
validator: $.optional.type(ID),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default define(meta, async (ps, user) => {
|
||||||
|
const query = makePaginationQuery(Pages.createQueryBuilder('page'), ps.sinceId, ps.untilId)
|
||||||
|
.andWhere(`page.userId = :userId`, { userId: ps.userId })
|
||||||
|
.andWhere('page.visibility = \'public\'');
|
||||||
|
|
||||||
|
const pages = await query
|
||||||
|
.take(ps.limit!)
|
||||||
|
.getMany();
|
||||||
|
|
||||||
|
return await Pages.packMany(pages);
|
||||||
|
});
|
Loading…
Reference in a new issue