diff options
Diffstat (limited to 'src/client/app/common/views/pages')
| -rw-r--r-- | src/client/app/common/views/pages/explore.vue | 4 | ||||
| -rw-r--r-- | src/client/app/common/views/pages/follow-requests.vue | 68 | ||||
| -rw-r--r-- | src/client/app/common/views/pages/pages.vue | 5 | ||||
| -rw-r--r-- | src/client/app/common/views/pages/user-group-editor.vue | 180 | ||||
| -rw-r--r-- | src/client/app/common/views/pages/user-groups.vue | 63 | ||||
| -rw-r--r-- | src/client/app/common/views/pages/user-list-editor.vue | 180 | ||||
| -rw-r--r-- | src/client/app/common/views/pages/user-lists.vue | 63 |
7 files changed, 563 insertions, 0 deletions
diff --git a/src/client/app/common/views/pages/explore.vue b/src/client/app/common/views/pages/explore.vue index d0e98035f8..bf0d7ab574 100644 --- a/src/client/app/common/views/pages/explore.vue +++ b/src/client/app/common/views/pages/explore.vue @@ -116,6 +116,10 @@ export default Vue.extend({ }, created() { + this.$emit('init', { + title: this.$t('@.explore'), + icon: faHashtag + }); this.$root.api('hashtags/list', { sort: '+attachedLocalUsers', attachedToLocalUserOnly: true, diff --git a/src/client/app/common/views/pages/follow-requests.vue b/src/client/app/common/views/pages/follow-requests.vue new file mode 100644 index 0000000000..860efefd93 --- /dev/null +++ b/src/client/app/common/views/pages/follow-requests.vue @@ -0,0 +1,68 @@ +<template> +<div> + <ui-container :body-togglable="true"> + <template #header>{{ $t('received-follow-requests') }}</template> + <div v-if="!fetching"> + <sequential-entrance animation="entranceFromTop" delay="25" tag="div" class="mcbzkkaw"> + <div v-for="req in requests"> + <router-link :key="req.id" :to="req.follower | userPage"> + <mk-user-name :user="req.follower"/> + </router-link> + <span> + <a @click="accept(req.follower)">{{ $t('accept') }}</a>|<a @click="reject(req.follower)">{{ $t('reject') }}</a> + </span> + </div> + </sequential-entrance> + </div> + </ui-container> +</div> +</template> + +<script lang="ts"> +import Vue from 'vue'; +import i18n from '../../../i18n'; +import Progress from '../../scripts/loading'; + +export default Vue.extend({ + i18n: i18n('common/views/pages/follow-requests.vue'), + data() { + return { + fetching: true, + requests: [] + }; + }, + mounted() { + Progress.start(); + this.$root.api('following/requests/list').then(requests => { + this.fetching = false; + this.requests = requests; + Progress.done(); + }); + }, + methods: { + accept(user) { + this.$root.api('following/requests/accept', { userId: user.id }).then(() => { + this.requests = this.requests.filter(r => r.follower.id != user.id); + }); + }, + reject(user) { + this.$root.api('following/requests/reject', { userId: user.id }).then(() => { + this.requests = this.requests.filter(r => r.follower.id != user.id); + }); + } + } +}); +</script> + +<style lang="stylus" scoped> +.mcbzkkaw + > div + display flex + padding 16px + border solid 1px var(--faceDivider) + border-radius 4px + + > span + margin 0 0 0 auto + +</style> diff --git a/src/client/app/common/views/pages/pages.vue b/src/client/app/common/views/pages/pages.vue index 751ea72374..d658728a19 100644 --- a/src/client/app/common/views/pages/pages.vue +++ b/src/client/app/common/views/pages/pages.vue @@ -50,6 +50,11 @@ export default Vue.extend({ }, created() { this.fetch(); + + this.$emit('init', { + title: this.$t('@.pages'), + icon: faStickyNote + }); }, methods: { async fetch() { diff --git a/src/client/app/common/views/pages/user-group-editor.vue b/src/client/app/common/views/pages/user-group-editor.vue new file mode 100644 index 0000000000..c658d0c6ff --- /dev/null +++ b/src/client/app/common/views/pages/user-group-editor.vue @@ -0,0 +1,180 @@ +<template> +<div class="ivrbakop"> + <ui-container v-if="group"> + <template #header><fa :icon="faUsers"/> {{ group.name }}</template> + + <section> + <ui-margin> + <ui-button @click="rename"><fa :icon="faICursor"/> {{ $t('rename') }}</ui-button> + <ui-button @click="del"><fa :icon="faTrashAlt"/> {{ $t('delete') }}</ui-button> + </ui-margin> + </section> + </ui-container> + + <ui-container> + <template #header><fa :icon="faUsers"/> {{ $t('users') }}</template> + + <section> + <ui-margin> + <ui-button @click="add"><fa :icon="faPlus"/> {{ $t('add-user') }}</ui-button> + </ui-margin> + <sequential-entrance animation="entranceFromTop" delay="25"> + <div class="kjlrfbes" v-for="user in users"> + <div> + <a :href="user | userPage"> + <mk-avatar class="avatar" :user="user" :disable-link="true"/> + </a> + </div> + <div> + <header> + <b><mk-user-name :user="user"/></b> + <span class="username">@{{ user | acct }}</span> + </header> + <div> + <a @click="remove(user)">{{ $t('remove-user') }}</a> + </div> + </div> + </div> + </sequential-entrance> + </section> + </ui-container> +</div> +</template> + +<script lang="ts"> +import Vue from 'vue'; +import i18n from '../../../i18n'; +import { faICursor, faUsers, faPlus } from '@fortawesome/free-solid-svg-icons'; +import { faTrashAlt } from '@fortawesome/free-regular-svg-icons'; + +export default Vue.extend({ + i18n: i18n('common/views/components/user-group-editor.vue'), + + props: { + groupId: { + required: true + } + }, + + data() { + return { + group: null, + users: [], + faICursor, faTrashAlt, faUsers, faPlus + }; + }, + + created() { + this.$root.api('users/groups/show', { + groupId: this.groupId + }).then(group => { + this.group = group; + this.fetchUsers(); + this.$emit('init', { + title: this.group.name, + icon: faUsers + }); + }); + }, + + methods: { + fetchUsers() { + this.$root.api('users/show', { + userIds: this.group.userIds + }).then(users => { + this.users = users; + }); + }, + + rename() { + this.$root.dialog({ + title: this.$t('rename'), + input: { + default: this.group.name + } + }).then(({ canceled, result: name }) => { + if (canceled) return; + this.$root.api('users/groups/update', { + groupId: this.group.id, + name: name + }); + }); + }, + + del() { + this.$root.dialog({ + type: 'warning', + text: this.$t('delete-are-you-sure').replace('$1', this.group.name), + showCancelButton: true + }).then(({ canceled }) => { + if (canceled) return; + + this.$root.api('users/groups/delete', { + groupId: this.group.id + }).then(() => { + this.$root.dialog({ + type: 'success', + text: this.$t('deleted') + }); + }).catch(e => { + this.$root.dialog({ + type: 'error', + text: e + }); + }); + }); + }, + + remove(user: any) { + this.$root.api('users/groups/pull', { + groupId: this.group.id, + userId: user.id + }).then(() => { + this.fetchUsers(); + }); + }, + + async add() { + const { result: user } = await this.$root.dialog({ + user: { + local: true + } + }); + if (user == null) return; + this.$root.api('users/groups/push', { + groupId: this.group.id, + userId: user.id + }).then(() => { + this.fetchUsers(); + }); + } + } +}); +</script> + +<style lang="stylus" scoped> +.ivrbakop + .kjlrfbes + display flex + padding 16px + border-top solid 1px var(--faceDivider) + + > div:first-child + > a + > .avatar + width 64px + height 64px + + > div:last-child + flex 1 + padding-left 16px + + @media (max-width 500px) + font-size 14px + + > header + > .username + margin-left 8px + opacity 0.7 + +</style> diff --git a/src/client/app/common/views/pages/user-groups.vue b/src/client/app/common/views/pages/user-groups.vue new file mode 100644 index 0000000000..336772799b --- /dev/null +++ b/src/client/app/common/views/pages/user-groups.vue @@ -0,0 +1,63 @@ +<template> +<ui-container> + <template #header><fa :icon="faUsers"/> {{ $t('user-groups') }}</template> + <ui-margin> + <ui-button @click="add"><fa :icon="faPlus"/> {{ $t('create-group') }}</ui-button> + </ui-margin> + <div class="hwgkdrbl" v-for="group in groups" :key="group.id"> + <ui-hr/> + <ui-margin> + <router-link :to="`/i/groups/${group.id}`">{{ group.name }}</router-link> + </ui-margin> + </div> +</ui-container> +</template> + +<script lang="ts"> +import Vue from 'vue'; +import i18n from '../../../i18n'; +import { faUsers, faPlus } from '@fortawesome/free-solid-svg-icons'; + +export default Vue.extend({ + i18n: i18n('common/views/components/user-groups.vue'), + data() { + return { + fetching: true, + groups: [], + faUsers, faPlus + }; + }, + mounted() { + this.$root.api('users/groups/owned').then(groups => { + this.fetching = false; + this.groups = groups; + }); + + this.$emit('init', { + title: this.$t('user-groups'), + icon: faUsers + }); + }, + methods: { + add() { + this.$root.dialog({ + title: this.$t('group-name'), + input: true + }).then(async ({ canceled, result: name }) => { + if (canceled) return; + const list = await this.$root.api('users/groups/create', { + name + }); + + this.groups.push(list) + }); + }, + } +}); +</script> + +<style lang="stylus" scoped> +.hwgkdrbl + display block + +</style> diff --git a/src/client/app/common/views/pages/user-list-editor.vue b/src/client/app/common/views/pages/user-list-editor.vue new file mode 100644 index 0000000000..6b2fd75f85 --- /dev/null +++ b/src/client/app/common/views/pages/user-list-editor.vue @@ -0,0 +1,180 @@ +<template> +<div class="cudqjmnl"> + <ui-container v-if="list"> + <template #header><fa :icon="faListUl"/> {{ list.name }}</template> + + <section class="fwvevrks"> + <ui-margin> + <ui-button @click="rename"><fa :icon="faICursor"/> {{ $t('rename') }}</ui-button> + <ui-button @click="del"><fa :icon="faTrashAlt"/> {{ $t('delete') }}</ui-button> + </ui-margin> + </section> + </ui-container> + + <ui-container> + <template #header><fa :icon="faUsers"/> {{ $t('users') }}</template> + + <section> + <ui-margin> + <ui-button @click="add"><fa :icon="faPlus"/> {{ $t('add-user') }}</ui-button> + </ui-margin> + <sequential-entrance animation="entranceFromTop" delay="25"> + <div class="phcqulfl" v-for="user in users"> + <div> + <a :href="user | userPage"> + <mk-avatar class="avatar" :user="user" :disable-link="true"/> + </a> + </div> + <div> + <header> + <b><mk-user-name :user="user"/></b> + <span class="username">@{{ user | acct }}</span> + </header> + <div> + <a @click="remove(user)">{{ $t('remove-user') }}</a> + </div> + </div> + </div> + </sequential-entrance> + </section> + </ui-container> +</div> +</template> + +<script lang="ts"> +import Vue from 'vue'; +import i18n from '../../../i18n'; +import { faListUl, faICursor, faUsers, faPlus } from '@fortawesome/free-solid-svg-icons'; +import { faTrashAlt } from '@fortawesome/free-regular-svg-icons'; + +export default Vue.extend({ + i18n: i18n('common/views/components/user-list-editor.vue'), + + props: { + listId: { + required: true + } + }, + + data() { + return { + list: null, + users: [], + faListUl, faICursor, faTrashAlt, faUsers, faPlus + }; + }, + + created() { + this.$root.api('users/lists/show', { + listId: this.listId + }).then(list => { + this.list = list; + this.fetchUsers(); + this.$emit('init', { + title: this.list.name, + icon: faListUl + }); + }); + }, + + methods: { + fetchUsers() { + this.$root.api('users/show', { + userIds: this.list.userIds + }).then(users => { + this.users = users; + }); + }, + + rename() { + this.$root.dialog({ + title: this.$t('rename'), + input: { + default: this.list.name + } + }).then(({ canceled, result: name }) => { + if (canceled) return; + this.$root.api('users/lists/update', { + listId: this.list.id, + name: name + }); + }); + }, + + del() { + this.$root.dialog({ + type: 'warning', + text: this.$t('delete-are-you-sure').replace('$1', this.list.name), + showCancelButton: true + }).then(({ canceled }) => { + if (canceled) return; + + this.$root.api('users/lists/delete', { + listId: this.list.id + }).then(() => { + this.$root.dialog({ + type: 'success', + text: this.$t('deleted') + }); + }).catch(e => { + this.$root.dialog({ + type: 'error', + text: e + }); + }); + }); + }, + + remove(user: any) { + this.$root.api('users/lists/pull', { + listId: this.list.id, + userId: user.id + }).then(() => { + this.fetchUsers(); + }); + }, + + async add() { + const { result: user } = await this.$root.dialog({ + user: { + local: true + } + }); + if (user == null) return; + this.$root.api('users/lists/push', { + listId: this.list.id, + userId: user.id + }).then(() => { + this.fetchUsers(); + }); + } + } +}); +</script> + +<style lang="stylus" scoped> +.cudqjmnl + .phcqulfl + display flex + padding 16px + border-top solid 1px var(--faceDivider) + + > div:first-child + > a + > .avatar + width 64px + height 64px + + > div:last-child + flex 1 + padding-left 16px + + @media (max-width 500px) + font-size 14px + + > header + > .username + margin-left 8px + opacity 0.7 + +</style> diff --git a/src/client/app/common/views/pages/user-lists.vue b/src/client/app/common/views/pages/user-lists.vue new file mode 100644 index 0000000000..4c09eca6ce --- /dev/null +++ b/src/client/app/common/views/pages/user-lists.vue @@ -0,0 +1,63 @@ +<template> +<ui-container> + <template #header><fa :icon="faListUl"/> {{ $t('user-lists') }}</template> + <ui-margin> + <ui-button @click="add"><fa :icon="faPlus"/> {{ $t('create-list') }}</ui-button> + </ui-margin> + <div class="cpqqyrst" v-for="list in lists" :key="list.id"> + <ui-hr/> + <ui-margin> + <router-link :to="`/i/lists/${list.id}`">{{ list.name }}</router-link> + </ui-margin> + </div> +</ui-container> +</template> + +<script lang="ts"> +import Vue from 'vue'; +import i18n from '../../../i18n'; +import { faListUl, faPlus } from '@fortawesome/free-solid-svg-icons'; + +export default Vue.extend({ + i18n: i18n('common/views/components/user-lists.vue'), + data() { + return { + fetching: true, + lists: [], + faListUl, faPlus + }; + }, + mounted() { + this.$root.api('users/lists/list').then(lists => { + this.fetching = false; + this.lists = lists; + }); + + this.$emit('init', { + title: this.$t('user-lists'), + icon: faListUl + }); + }, + methods: { + add() { + this.$root.dialog({ + title: this.$t('list-name'), + input: true + }).then(async ({ canceled, result: name }) => { + if (canceled) return; + const list = await this.$root.api('users/lists/create', { + name + }); + + this.lists.push(list) + }); + }, + } +}); +</script> + +<style lang="stylus" scoped> +.cpqqyrst + display block + +</style> |