summaryrefslogtreecommitdiffstats
path: root/src/services
diff options
context:
space:
mode:
authorJohn Molakvoæ (skjnldsv) <skjnldsv@protonmail.com>2021-03-15 11:48:15 +0100
committerJohn Molakvoæ (skjnldsv) <skjnldsv@protonmail.com>2021-05-30 10:28:56 +0200
commit77cc60e0edd627d3bbed63f0e34b13822b387baf (patch)
treecb8c26f64f3fb88175dd8ad90d1347865321dfb6 /src/services
parent21c5e699ffa394c45094e898af0f5192cf239bee (diff)
New member button and virtual list
Signed-off-by: John Molakvoæ (skjnldsv) <skjnldsv@protonmail.com>
Diffstat (limited to 'src/services')
-rw-r--r--src/services/circles.d.ts101
-rw-r--r--src/services/circles.ts (renamed from src/services/circles.js)62
-rw-r--r--src/services/collaborationAutocompletion.js141
3 files changed, 280 insertions, 24 deletions
diff --git a/src/services/circles.d.ts b/src/services/circles.d.ts
new file mode 100644
index 00000000..3f8de3ee
--- /dev/null
+++ b/src/services/circles.d.ts
@@ -0,0 +1,101 @@
+/**
+ * @copyright Copyright (c) 2021 John Molakvoæ <skjnldsv@protonmail.com>
+ *
+ * @author John Molakvoæ <skjnldsv@protonmail.com>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+import { MemberLevel, MemberType } from '../models/constants';
+interface MemberPairs {
+ id: string;
+ type: MemberType;
+}
+/**
+ * Get the circles list without the members
+ *
+ * @returns {Array}
+ */
+export declare const getCircles: () => Promise<any>;
+/**
+ * Create a new circle
+ *
+ * @param {string} name the circle name
+ * @returns {Object}
+ */
+export declare const createCircle: (name: string) => Promise<any>;
+/**
+ * Delete an existing circle
+ *
+ * @param {string} circleId the circle name
+ * @returns {Object}
+ */
+export declare const deleteCircle: (circleId: string) => Promise<any>;
+/**
+ * Join a circle
+ *
+ * @param {string} circleId the circle name
+ * @returns {Array}
+ */
+export declare const joinCircle: (circleId: string) => Promise<any>;
+/**
+ * Leave a circle
+ *
+ * @param {string} circleId the circle name
+ * @returns {Array}
+ */
+export declare const leaveCircle: (circleId: string) => Promise<any>;
+/**
+ * Get the circle members without the members
+ *
+ * @param {string} circleId the circle id
+ * @returns {Array}
+ */
+export declare const getCircleMembers: (circleId: string) => Promise<any>;
+/**
+ * Search a potential circle member
+ *
+ * @param {string} term the search query
+ * @returns {Array}
+ */
+export declare const searchMember: (term: string) => Promise<any>;
+/**
+ * Add a circle member
+ *
+ * @param {string} circleId the circle id
+ * @param {string} members the member id
+ * @returns {Array}
+ */
+export declare const addMembers: (circleId: string, members: Array<MemberPairs>) => Promise<any>;
+/**
+ * Delete a circle member
+ *
+ * @param {string} circleId the circle id
+ * @param {string} memberId the member id
+ * @returns {Array}
+ */
+export declare const deleteMember: (circleId: string, memberId: string) => Promise<unknown[]>;
+/**
+ * change a member level
+ * @see levels file src/models/constants.js
+ *
+ * @param {string} circleId the circle id
+ * @param {string} memberId the member id
+ * @param {number} level the new member level
+ * @returns {Array}
+ */
+export declare const changeMemberLevel: (circleId: string, memberId: string, level: MemberLevel) => Promise<unknown[]>;
+export {};
diff --git a/src/services/circles.js b/src/services/circles.ts
index 544a944b..5d30c42e 100644
--- a/src/services/circles.js
+++ b/src/services/circles.ts
@@ -22,9 +22,12 @@
import axios from '@nextcloud/axios'
import { generateOcsUrl } from '@nextcloud/router'
-import { CIRCLES_MEMBER_LEVELS } from '../models/constants'
+import { MemberLevel, MemberLevels, MemberType } from '../models/constants'
-const baseApi = generateOcsUrl('apps/circles', 2)
+interface MemberPairs {
+ id: string,
+ type: MemberType
+}
/**
* Get the circles list without the members
@@ -32,7 +35,7 @@ const baseApi = generateOcsUrl('apps/circles', 2)
* @returns {Array}
*/
export const getCircles = async function() {
- const response = await axios.get(baseApi + 'circles')
+ const response = await axios.get(generateOcsUrl('apps/circles/circles'))
return response.data.ocs.data
}
@@ -42,8 +45,8 @@ export const getCircles = async function() {
* @param {string} name the circle name
* @returns {Object}
*/
-export const createCircle = async function(name) {
- const response = await axios.post(baseApi + 'circles', {
+export const createCircle = async function(name: string) {
+ const response = await axios.post(generateOcsUrl('apps/circles/circles'), {
name,
})
return response.data.ocs.data
@@ -55,8 +58,8 @@ export const createCircle = async function(name) {
* @param {string} circleId the circle name
* @returns {Object}
*/
-export const deleteCircle = async function(circleId) {
- const response = await axios.delete(baseApi + `circles/${circleId}`)
+export const deleteCircle = async function(circleId: string) {
+ const response = await axios.delete(generateOcsUrl('apps/circles/circles/{circleId}', { circleId }))
return response.data.ocs.data
}
@@ -66,8 +69,8 @@ export const deleteCircle = async function(circleId) {
* @param {string} circleId the circle name
* @returns {Array}
*/
-export const joinCircle = async function(circleId) {
- const response = await axios.put(baseApi + `circles/${circleId}/join`)
+export const joinCircle = async function(circleId: string) {
+ const response = await axios.put(generateOcsUrl('apps/circles/circles/{circleId}/join', { circleId }))
return response.data.ocs.data
}
@@ -77,8 +80,8 @@ export const joinCircle = async function(circleId) {
* @param {string} circleId the circle name
* @returns {Array}
*/
-export const leaveCircle = async function(circleId) {
- const response = await axios.put(baseApi + `circles/${circleId}/leave`)
+export const leaveCircle = async function(circleId: string) {
+ const response = await axios.put(generateOcsUrl('apps/circles/circles/{circleId}/leave', { circleId }))
return response.data.ocs.data
}
@@ -88,21 +91,32 @@ export const leaveCircle = async function(circleId) {
* @param {string} circleId the circle id
* @returns {Array}
*/
-export const getCircleMembers = async function(circleId) {
- const response = await axios.get(baseApi + `circles/${circleId}/members`)
- return Object.values(response.data.ocs.data)
+export const getCircleMembers = async function(circleId: string) {
+ const response = await axios.get(generateOcsUrl('apps/circles/circles/{circleId}/members', { circleId }))
+ return response.data.ocs.data
+}
+
+/**
+ * Search a potential circle member
+ *
+ * @param {string} term the search query
+ * @returns {Array}
+ */
+export const searchMember = async function(term: string) {
+ const response = await axios.get(generateOcsUrl('apps/circles/search?term={term}', { term }))
+ return response.data.ocs.data
}
/**
* Add a circle member
*
* @param {string} circleId the circle id
- * @param {string} memberId the member id
+ * @param {string} members the member id
* @returns {Array}
*/
-export const addMember = async function(circleId, memberId) {
- const response = await axios.delete(baseApi + `circles/${circleId}/members/${memberId}`)
- return Object.values(response.data.ocs.data)
+export const addMembers = async function(circleId: string, members: Array<MemberPairs>) {
+ const response = await axios.post(generateOcsUrl('apps/circles/circles/{circleId}/members/multi', { circleId }), { members })
+ return response.data.ocs.data
}
/**
@@ -112,8 +126,8 @@ export const addMember = async function(circleId, memberId) {
* @param {string} memberId the member id
* @returns {Array}
*/
-export const deleteMember = async function(circleId, memberId) {
- const response = await axios.delete(baseApi + `circles/${circleId}/members/${memberId}`)
+export const deleteMember = async function(circleId: string, memberId: string) {
+ const response = await axios.delete(generateOcsUrl('apps/circles/circles/{circleId}/members/{memberId}', { circleId, memberId }))
return Object.values(response.data.ocs.data)
}
@@ -126,12 +140,12 @@ export const deleteMember = async function(circleId, memberId) {
* @param {number} level the new member level
* @returns {Array}
*/
-export const changeMemberLevel = async function(circleId, memberId, level) {
- if (!(level in CIRCLES_MEMBER_LEVELS)) {
- throw new Error('Invalid level. Valid levels are', CIRCLES_MEMBER_LEVELS)
+export const changeMemberLevel = async function(circleId: string, memberId: string, level: MemberLevel) {
+ if (!(level in MemberLevels)) {
+ throw new Error('Invalid level.')
}
- const response = await axios.put(baseApi + `circles/${circleId}/members/${memberId}}/level`, {
+ const response = await axios.put(generateOcsUrl('apps/circles/circles/{circleId}/members/{memberId}/level', { circleId, memberId }), {
level,
})
return Object.values(response.data.ocs.data)
diff --git a/src/services/collaborationAutocompletion.js b/src/services/collaborationAutocompletion.js
new file mode 100644
index 00000000..f7200387
--- /dev/null
+++ b/src/services/collaborationAutocompletion.js
@@ -0,0 +1,141 @@
+
+/**
+ * @copyright Copyright (c) 2018 John Molakvoæ <skjnldsv@protonmail.com>
+ *
+ * @author John Molakvoæ <skjnldsv@protonmail.com>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+import axios from '@nextcloud/axios'
+import { generateOcsUrl } from '@nextcloud/router'
+
+const maxAutocompleteResults = parseInt(OC.config['sharing.maxAutocompleteResults'], 10) || 25
+
+export const shareType = [
+ OC.Share.SHARE_TYPE_USER,
+ OC.Share.SHARE_TYPE_GROUP,
+ // OC.Share.SHARE_TYPE_REMOTE,
+ // OC.Share.SHARE_TYPE_REMOTE_GROUP,
+ OC.Share.SHARE_TYPE_CIRCLE,
+ // OC.Share.SHARE_TYPE_ROOM,
+ // OC.Share.SHARE_TYPE_GUEST,
+ // OC.Share.SHARE_TYPE_DECK,
+ OC.Share.SHARE_TYPE_EMAIL,
+]
+
+/**
+ * Get suggestions
+ *
+ * @param {string} search the search query
+ */
+export const getSuggestions = async function(search) {
+ const request = await axios.get(generateOcsUrl('apps/files_sharing/api/v1/sharees'), {
+ params: {
+ format: 'json',
+ itemType: 'file',
+ search,
+ perPage: maxAutocompleteResults,
+ shareType,
+ },
+ })
+
+ const data = request.data.ocs.data
+ const exact = request.data.ocs.data.exact
+ data.exact = [] // removing exact from general results
+
+ // flatten array of arrays
+ const rawExactSuggestions = Object.values(exact).reduce((arr, elem) => arr.concat(elem), [])
+ const rawSuggestions = Object.values(data).reduce((arr, elem) => arr.concat(elem), [])
+
+ // remove invalid data and format to user-select layout
+ const exactSuggestions = rawExactSuggestions
+ .filter(result => typeof result === 'object')
+ .map(share => formatResults(share))
+ // sort by type so we can get user&groups first...
+ .sort((a, b) => a.shareType - b.shareType)
+ const suggestions = rawSuggestions
+ .filter(result => typeof result === 'object')
+ .map(share => formatResults(share))
+ // sort by type so we can get user&groups first...
+ .sort((a, b) => a.shareType - b.shareType)
+
+ const allSuggestions = exactSuggestions.concat(suggestions)
+
+ // Count occurances of display names in order to provide a distinguishable description if needed
+ const nameCounts = allSuggestions.reduce((nameCounts, result) => {
+ if (!result.displayName) {
+ return nameCounts
+ }
+ if (!nameCounts[result.displayName]) {
+ nameCounts[result.displayName] = 0
+ }
+ nameCounts[result.displayName]++
+ return nameCounts
+ }, {})
+
+ const finalResults = allSuggestions.map(item => {
+ // Make sure that items with duplicate displayName get the shareWith applied as a description
+ if (nameCounts[item.displayName] > 1 && !item.desc) {
+ return { ...item, desc: item.shareWithDisplayNameUnique }
+ }
+ return item
+ })
+
+ console.info('suggestions', finalResults)
+
+ return finalResults
+}
+
+/**
+ * Get the sharing recommendations
+ */
+export const getRecommendations = async function() {
+ const request = await axios.get(generateOcsUrl('apps/files_sharing/api/v1/sharees_recommended'), {
+ params: {
+ format: 'json',
+ itemType: 'file',
+ shareType,
+ },
+ })
+
+ // flatten array of arrays
+ const exact = request.data.ocs.data.exact
+ const recommendations = Object.values(exact).reduce((arr, elem) => arr.concat(elem), [])
+
+ // remove invalid data and format to user-select layout
+ const finalResults = recommendations
+ .map(share => formatResults(share))
+
+ console.info('recommendations', finalResults)
+
+ return finalResults
+}
+
+const formatResults = function(result) {
+ const type = `picker-${result.value.shareType}`
+ return {
+ label: result.label,
+ id: `${type}-${result.value.shareWith}`,
+ // If this is a user, set as user for avatar display by UserBubble
+ user: result.value.shareType === OC.Share.SHARE_TYPE_USER
+ ? result.value.shareWith
+ : null,
+ type,
+ ...result.value,
+ }
+}