summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorDevlin Junker <devlin.junker@gmail.com>2023-09-26 14:39:38 -0700
committerDevlin Junker <devlin.junker@gmail.com>2023-09-26 14:42:50 -0700
commitb7179b5858c2f3393407777e5ba0d9c6b0e9720b (patch)
treeebc8bee1a6635250653db33c40f251c65d584b9f /src
parent2ebd898a1b049e6f4dbd3f8a2ca5ff2d04814bb1 (diff)
working share component
Signed-off-by: Devlin Junker <devlin.junker@gmail.com>
Diffstat (limited to 'src')
-rw-r--r--src/components/ShareItem.vue138
-rw-r--r--src/components/Sidebar.vue2
-rw-r--r--src/components/feed-display/FeedItemRow.vue20
-rw-r--r--src/dataservices/share.service.ts28
4 files changed, 179 insertions, 9 deletions
diff --git a/src/components/ShareItem.vue b/src/components/ShareItem.vue
new file mode 100644
index 000000000..c7898330c
--- /dev/null
+++ b/src/components/ShareItem.vue
@@ -0,0 +1,138 @@
+<template>
+ <NcModal @close="$emit('close')">
+ <div id="share-item">
+ <form name="feedform">
+ <fieldset>
+ <input v-model="userName"
+ type="text"
+ :placeholder="t('news', 'User Name')"
+ name="user"
+ pattern="[^\s]+"
+ required
+ autofocus
+ @keyup="debounceSearchUsers()">
+
+ <div class="user-bubble-container">
+ <NcLoadingIcon v-if="searching" />
+ <NcUserBubble v-for="user in users"
+ v-else-if="!searching"
+ :key="user.shareName"
+ :size="30"
+ :display-name="user.displayName"
+ :primary="selected.map((val) => { return val.shareName }).includes(user.shareName)"
+ :user="user.shareName"
+ @click="clickUser(user)" />
+ </div>
+
+ <NcButton :wide="true"
+ type="primary"
+ :disabled="selected.length === 0"
+ @click="share()">
+ <template v-if="selected.length === 0">
+ {{ t("news", "Share") }}
+ </template>
+ <template v-else-if="selected.length === 1">
+ {{ t("news", "Share with") + ' ' + selected[0].displayName }}
+ </template>
+ <template v-else-if="selected.length > 1">
+ {{ t("news", "Share with {num} users", { num: selected.length }) }}
+ </template>
+ </NcButton>
+ </fieldset>
+ </form>
+ </div>
+ </NcModal>
+</template>
+
+<script lang="ts">
+
+import Vue from 'vue'
+import _ from 'lodash'
+
+import NcModal from '@nextcloud/vue/dist/Components/NcModal.js'
+import NcButton from '@nextcloud/vue/dist/Components/NcButton.js'
+import NcUserBubble from '@nextcloud/vue/dist/Components/NcUserBubble.js'
+import NcLoadingIcon from '@nextcloud/vue/dist/Components/NcLoadingIcon.js'
+
+import { ShareService } from '../dataservices/share.service'
+
+export default Vue.extend({
+ components: {
+ NcModal,
+ NcButton,
+ NcUserBubble,
+ NcLoadingIcon,
+ },
+ props: {
+ itemId: {
+ type: Number,
+ required: true,
+ },
+ },
+ data: () => {
+ return {
+ userName: '',
+ users: [],
+ selected: [],
+ searching: false,
+ } as any
+ },
+ created() {
+ this.debounceSearchUsers = _.debounce(this.searchUsers, 800)
+ },
+ methods: {
+ clickUser(user: any) {
+ const selectedUsers = this.selected.map((val: any) => { return val.shareName })
+ if (selectedUsers.includes(user.shareName)) {
+ this.selected.splice(selectedUsers.indexOf(user.shareName), 1)
+ } else {
+ this.selected.push(user)
+ }
+ },
+
+ async searchUsers() {
+ this.users = []
+ this.searching = true
+ const response = await ShareService.fetchUsers(this.userName)
+ this.searching = false
+
+ for (const user of response.data.ocs.data.users) {
+ this.users.push({ displayName: user.label, shareName: user.value.shareWith })
+ }
+ },
+
+ /**
+ * Shares an item with another use in the same nextcloud instance
+ */
+ async share() {
+ await ShareService.share(this.itemId, this.selected.map((val: any) => { return val.shareName }))
+
+ this.$emit('close')
+ },
+ },
+})
+
+</script>
+
+<style>
+#share-item .user-bubble__content * {
+ cursor: pointer;
+}
+
+#share-item fieldset {
+ padding: 16px;
+}
+
+#share-item input {
+ width: 90%;
+}
+
+#share-item .user-bubble-container {
+ margin: 10px;
+}
+
+#share-item .user-bubble__wrapper {
+ margin: 5px 10px;
+}
+
+</style>
diff --git a/src/components/Sidebar.vue b/src/components/Sidebar.vue
index 392c0ccfb..f29e6503e 100644
--- a/src/components/Sidebar.vue
+++ b/src/components/Sidebar.vue
@@ -84,7 +84,7 @@
</NcCounterBubble>
</template>
<template #actions>
- <SidebarFeedLinkActions v-if="topLevelItem.name === undefined" :feed-id="topLevelItem.id" />
+ <SidebarFeedLinkActions v-if="topLevelItem.name === undefined && !topLevelItem.url.includes('news/sharedwithme')" :feed-id="topLevelItem.id" />
<NcActionButton v-if="topLevelItem.name !== undefined" icon="icon-checkmark" @click="markFolderRead(topLevelItem)">
{{ t("news", "Mark read") }}
diff --git a/src/components/feed-display/FeedItemRow.vue b/src/components/feed-display/FeedItemRow.vue
index 03670295a..854f83633 100644
--- a/src/components/feed-display/FeedItemRow.vue
+++ b/src/components/feed-display/FeedItemRow.vue
@@ -1,5 +1,6 @@
<template>
<div class="feed-item-row" @click="select()">
+ <ShareItem v-if="showShareMenu" :item-id="shareItem" @close="closeShareMenu()" />
<div class="link-container">
<a class="external"
target="_blank"
@@ -28,14 +29,9 @@
<EyeIcon v-if="item.unread && !keepUnread" @click="toggleKeepUnread(item)" />
<EyeCheckIcon v-if="!item.unread && !keepUnread" @click="toggleKeepUnread(item)" />
<EyeLockIcon v-if="keepUnread" class="keep-unread" @click="toggleKeepUnread(item)" />
- <NcActions :force-menu="true">
- <template #icon>
- <ShareVariant />
- </template>
- <NcActionButton>
- <template #default>
- <!-- TODO: Share Menu --> TODO
- </template>
+ <NcActions>
+ <NcActionButton :title="t('news', 'Share within Instance')" @click="shareItem = item.id; showShareMenu = true">
+ {{ t('news', 'Share') }}
<template #icon>
<ShareVariant />
</template>
@@ -60,6 +56,8 @@ import ShareVariant from 'vue-material-design-icons/ShareVariant.vue'
import NcActions from '@nextcloud/vue/dist/Components/NcActions.js'
import NcActionButton from '@nextcloud/vue/dist/Components/NcActionButton.js'
+import ShareItem from '../ShareItem.vue'
+
import { Feed } from '../../types/Feed'
import { FeedItem } from '../../types/FeedItem'
import { ACTIONS, MUTATIONS } from '../../store'
@@ -76,6 +74,7 @@ export default Vue.extend({
RssIcon,
NcActions,
NcActionButton,
+ ShareItem,
},
props: {
item: {
@@ -86,6 +85,8 @@ export default Vue.extend({
data: () => {
return {
keepUnread: false,
+ showShareMenu: false,
+ shareItem: undefined,
}
},
computed: {
@@ -142,6 +143,9 @@ export default Vue.extend({
toggleStarred(item: FeedItem): void {
this.$store.dispatch(item.starred ? ACTIONS.UNSTAR_ITEM : ACTIONS.STAR_ITEM, { item })
},
+ closeShareMenu() {
+ this.showShareMenu = false
+ },
},
})
diff --git a/src/dataservices/share.service.ts b/src/dataservices/share.service.ts
new file mode 100644
index 000000000..c060bc3f0
--- /dev/null
+++ b/src/dataservices/share.service.ts
@@ -0,0 +1,28 @@
+import { AxiosResponse } from 'axios'
+import axios from '@nextcloud/axios'
+import { generateOcsUrl } from '@nextcloud/router'
+
+export class ShareService {
+
+ /**
+ * Retrieves all of users matching the search term
+ *
+ * @param query {String} search string
+ * @return {AxiosResponse} Folders contained in data.folders property
+ */
+ static fetchUsers(query: string): Promise<AxiosResponse> {
+ return axios.get(generateOcsUrl(`apps/files_sharing/api/v1/sharees?search=${query}&itemType=news_item&perPage=5/`))
+ }
+
+ static async share(id: number, users: string[]): Promise<boolean> {
+ const promises = []
+ for (const shareName of users) {
+ promises.push(axios.post(`items/${id}/share/${shareName}`))
+ }
+
+ await Promise.all(promises)
+
+ return true
+ }
+
+}