mirror of https://github.com/nextcloud/calendar
Implement circle sharing by @jakobroehrl
Signed-off-by: Georg Ehrke <developer@georgehrke.com>
This commit is contained in:
parent
5066abb6eb
commit
3e2fcb4c07
|
@ -156,7 +156,8 @@
|
||||||
.avatar {
|
.avatar {
|
||||||
width: 32px;
|
width: 32px;
|
||||||
height: 32px;
|
height: 32px;
|
||||||
background-color: #DBDBDB;
|
background-color: var(--color-border-dark);
|
||||||
|
background-size: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.avatar.published {
|
.avatar.published {
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
@include icon-black-white('briefcase', 'calendar', 5);
|
@include icon-black-white('briefcase', 'calendar', 5);
|
||||||
|
@include icon-black-white('circle', 'calendar', 1);
|
||||||
@include icon-black-white('color-picker', 'calendar', 1);
|
@include icon-black-white('color-picker', 'calendar', 1);
|
||||||
@include icon-black-white('embed', 'calendar', 1);
|
@include icon-black-white('embed', 'calendar', 1);
|
||||||
@include icon-black-white('eye', 'calendar', 4);
|
@include icon-black-white('eye', 'calendar', 4);
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 57 57" width="64" height="64"><path d="M7 29A21 21 0 0 1 29 7m10 40a21 21 0 0 1-29-8m29-29a21 21 0 0 1 8 29" fill="none" stroke="#000" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/><circle cx="29" cy="7" r="7"/><circle cx="39" cy="-10" r="7" transform="rotate(90)"/><circle cx="39" cy="-47" r="7" transform="rotate(90)"/></svg>
|
After Width: | Height: | Size: 400 B |
|
@ -1,6 +1,9 @@
|
||||||
<!--
|
<!--
|
||||||
- @copyright Copyright (c) 2019 Georg Ehrke <oc.list@georgehrke.com>
|
- @copyright Copyright (c) 2019 Georg Ehrke <oc.list@georgehrke.com>
|
||||||
|
- @copyright Copyright (c) 2019 Jakob Röhrl <jakob.roehrl@web.de>
|
||||||
|
-
|
||||||
- @author Georg Ehrke <oc.list@georgehrke.com>
|
- @author Georg Ehrke <oc.list@georgehrke.com>
|
||||||
|
- @author Jakob Röhrl <jakob.roehrl@web.de>
|
||||||
-
|
-
|
||||||
- @license GNU AGPL version 3 or any later version
|
- @license GNU AGPL version 3 or any later version
|
||||||
-
|
-
|
||||||
|
@ -35,7 +38,7 @@
|
||||||
track-by="user"
|
track-by="user"
|
||||||
label="user"
|
label="user"
|
||||||
@search-change="findSharee"
|
@search-change="findSharee"
|
||||||
@input="shareCalendar">
|
@change="shareCalendar">
|
||||||
<span slot="noResult">{{ $t('calendar', 'No users or groups') }}</span>
|
<span slot="noResult">{{ $t('calendar', 'No users or groups') }}</span>
|
||||||
</multiselect>
|
</multiselect>
|
||||||
</li>
|
</li>
|
||||||
|
@ -43,7 +46,9 @@
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import client from '../../../services/caldavService.js'
|
import client from '../../../services/caldavService.js'
|
||||||
|
import HttpClient from '@nextcloud/axios'
|
||||||
import debounce from 'debounce'
|
import debounce from 'debounce'
|
||||||
|
import { generateOcsUrl } from '@nextcloud/router'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'CalendarListItemSharingSearch',
|
name: 'CalendarListItemSharingSearch',
|
||||||
|
@ -69,14 +74,16 @@ export default {
|
||||||
* @param {string} data.displayName the displayName
|
* @param {string} data.displayName the displayName
|
||||||
* @param {string} data.uri the sharing principalScheme uri
|
* @param {string} data.uri the sharing principalScheme uri
|
||||||
* @param {Boolean} data.isGroup is this a group ?
|
* @param {Boolean} data.isGroup is this a group ?
|
||||||
|
* @param {Boolean} data.isCircle is this a circle-group ?
|
||||||
*/
|
*/
|
||||||
shareCalendar({ user, displayName, uri, isGroup }) {
|
shareCalendar({ user, displayName, uri, isGroup, isCircle }) {
|
||||||
this.$store.dispatch('shareCalendar', {
|
this.$store.dispatch('shareCalendar', {
|
||||||
calendar: this.calendar,
|
calendar: this.calendar,
|
||||||
user,
|
user,
|
||||||
displayName,
|
displayName,
|
||||||
uri,
|
uri,
|
||||||
isGroup
|
isGroup,
|
||||||
|
isCircle
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -87,11 +94,10 @@ export default {
|
||||||
*/
|
*/
|
||||||
findSharee: debounce(async function(query) {
|
findSharee: debounce(async function(query) {
|
||||||
const hiddenPrincipalSchemes = []
|
const hiddenPrincipalSchemes = []
|
||||||
|
const hiddenUrls = []
|
||||||
this.calendar.shares.forEach((share) => {
|
this.calendar.shares.forEach((share) => {
|
||||||
hiddenPrincipalSchemes.push(share.uri)
|
hiddenPrincipalSchemes.push(share.uri)
|
||||||
})
|
})
|
||||||
|
|
||||||
const hiddenUrls = []
|
|
||||||
if (this.$store.getters.getCurrentUserPrincipal) {
|
if (this.$store.getters.getCurrentUserPrincipal) {
|
||||||
hiddenUrls.push(this.$store.getters.getCurrentUserPrincipal.url)
|
hiddenUrls.push(this.$store.getters.getCurrentUserPrincipal.url)
|
||||||
}
|
}
|
||||||
|
@ -101,35 +107,100 @@ export default {
|
||||||
|
|
||||||
this.isLoading = true
|
this.isLoading = true
|
||||||
this.usersOrGroups = []
|
this.usersOrGroups = []
|
||||||
if (query.length > 0) {
|
|
||||||
const results = await client.principalPropertySearchByDisplayname(query)
|
|
||||||
this.usersOrGroups = results.reduce((list, result) => {
|
|
||||||
if (hiddenPrincipalSchemes.includes(result.principalScheme)) {
|
|
||||||
return list
|
|
||||||
}
|
|
||||||
if (hiddenUrls.includes(result.url)) {
|
|
||||||
return list
|
|
||||||
}
|
|
||||||
|
|
||||||
if (['GROUP', 'INDIVIDUAL'].indexOf(result.calendarUserType) > -1) {
|
if (query.length > 0) {
|
||||||
|
const davPromise = this.findShareesFromDav(query, hiddenPrincipalSchemes, hiddenUrls)
|
||||||
|
const ocsPromise = this.findShareesFromCircles(query, hiddenPrincipalSchemes, hiddenUrls)
|
||||||
|
|
||||||
|
return Promise.all([davPromise, ocsPromise]).then(([davResults, ocsResults]) => {
|
||||||
|
this.usersOrGroups = [
|
||||||
|
...davResults,
|
||||||
|
...ocsResults
|
||||||
|
]
|
||||||
|
|
||||||
|
this.isLoading = false
|
||||||
|
this.inputGiven = true
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
this.inputGiven = false
|
||||||
|
this.isLoading = false
|
||||||
|
}
|
||||||
|
}, 500),
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {String} query The search query
|
||||||
|
* @param {String[]} hiddenPrincipals A list of principals to exclude from search results
|
||||||
|
* @param {String[]} hiddenUrls A list of urls to exclude from search results
|
||||||
|
* @returns {Promise<Object[]>}
|
||||||
|
*/
|
||||||
|
async findShareesFromDav(query, hiddenPrincipals, hiddenUrls) {
|
||||||
|
return client.principalPropertySearchByDisplayname(query)
|
||||||
|
.then(results => {
|
||||||
|
return results.reduce((list, result) => {
|
||||||
|
if (hiddenPrincipals.includes(result.principalScheme)) {
|
||||||
|
return list
|
||||||
|
}
|
||||||
|
if (hiddenUrls.includes(result.url)) {
|
||||||
|
return list
|
||||||
|
}
|
||||||
|
|
||||||
|
// Don't show resources and rooms
|
||||||
|
if (!['GROUP', 'INDIVIDUAL'].includes(result.calendarUserType)) {
|
||||||
|
return list
|
||||||
|
}
|
||||||
|
|
||||||
const isGroup = result.calendarUserType === 'GROUP'
|
const isGroup = result.calendarUserType === 'GROUP'
|
||||||
list.push({
|
list.push({
|
||||||
user: result[isGroup ? 'groupId' : 'userId'],
|
user: result[isGroup ? 'groupId' : 'userId'],
|
||||||
displayName: result.displayname,
|
displayName: result.displayname,
|
||||||
icon: isGroup ? 'icon-group' : 'icon-user',
|
icon: isGroup ? 'icon-group' : 'icon-user',
|
||||||
uri: result.principalScheme,
|
uri: result.principalScheme,
|
||||||
isGroup
|
isGroup,
|
||||||
|
isCircle: false,
|
||||||
|
isNoUser: isGroup,
|
||||||
|
search: query
|
||||||
})
|
})
|
||||||
}
|
return list
|
||||||
return list
|
}, [])
|
||||||
}, [])
|
})
|
||||||
this.isLoading = false
|
},
|
||||||
this.inputGiven = true
|
/**
|
||||||
} else {
|
*
|
||||||
this.inputGiven = false
|
* @param {String} query The search query
|
||||||
this.isLoading = false
|
* @param {String[]} hiddenPrincipals A list of principals to exclude from search results
|
||||||
}
|
* @param {String[]} hiddenUrls A list of urls to exclude from search results
|
||||||
}, 500)
|
* @returns {Promise<Object[]>}
|
||||||
|
*/
|
||||||
|
async findShareesFromCircles(query, hiddenPrincipals, hiddenUrls) {
|
||||||
|
return HttpClient.get(generateOcsUrl('apps/files_sharing/api/v1') + 'sharees', {
|
||||||
|
params: {
|
||||||
|
format: 'json',
|
||||||
|
search: query,
|
||||||
|
perPage: 200,
|
||||||
|
itemType: 'principals'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(() => [])
|
||||||
|
.then(results => results.data.ocs.data.circles)
|
||||||
|
.then(circles => {
|
||||||
|
return circles.filter((circle) => {
|
||||||
|
return !hiddenPrincipals.includes('principal:principals/circles/' + circle.value.shareWith)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.then(circles => {
|
||||||
|
return circles.map(circle => ({
|
||||||
|
user: circle.label,
|
||||||
|
displayName: circle.label,
|
||||||
|
icon: 'icon-circle',
|
||||||
|
uri: 'principal:principals/circles/' + circle.value.shareWith,
|
||||||
|
isGroup: false,
|
||||||
|
isCircle: true,
|
||||||
|
isNoUser: true,
|
||||||
|
search: query
|
||||||
|
}))
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
|
|
||||||
<template slot="icon">
|
<template slot="icon">
|
||||||
<div v-if="sharee.isGroup" class="avatar icon-group" />
|
<div v-if="sharee.isGroup" class="avatar icon-group" />
|
||||||
|
<div v-else-if="sharee.isCircle" class="avatar icon-circle" />
|
||||||
<Avatar v-else :user="sharee.id" :display-name="sharee.displayName" />
|
<Avatar v-else :user="sharee.id" :display-name="sharee.displayName" />
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
|
@ -117,15 +117,20 @@ export function mapDavCollectionToCalendar(calendar) {
|
||||||
*/
|
*/
|
||||||
export function mapDavShareeToSharee(sharee) {
|
export function mapDavShareeToSharee(sharee) {
|
||||||
const id = btoa(sharee.href)
|
const id = btoa(sharee.href)
|
||||||
const name = sharee['common-name']
|
let name = sharee['common-name']
|
||||||
? sharee['common-name']
|
? sharee['common-name']
|
||||||
: id
|
: sharee.href
|
||||||
|
|
||||||
|
if (sharee.href.startsWith('principal:principals/groups/') && name === sharee.href) {
|
||||||
|
name = sharee.href.substr(28)
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
displayName: name,
|
displayName: name,
|
||||||
id: id,
|
id: id,
|
||||||
writeable: sharee.access[0].endsWith('read-write'),
|
writeable: sharee.access[0].endsWith('read-write'),
|
||||||
isGroup: sharee.href.indexOf('principal:principals/groups/') === 0,
|
isGroup: sharee.href.indexOf('principal:principals/groups/') === 0,
|
||||||
|
isCircle: sharee.href.indexOf('principal:principals/circles/') === 0,
|
||||||
uri: sharee.href
|
uri: sharee.href
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -199,12 +199,13 @@ const mutations = {
|
||||||
* @param {string} data.uri the sharing principalScheme uri
|
* @param {string} data.uri the sharing principalScheme uri
|
||||||
* @param {Boolean} data.isGroup is this a group ?
|
* @param {Boolean} data.isGroup is this a group ?
|
||||||
*/
|
*/
|
||||||
shareCalendar(state, { calendar, user, displayName, uri, isGroup }) {
|
shareCalendar(state, { calendar, user, displayName, uri, isGroup, isCircle }) {
|
||||||
const newSharee = {
|
const newSharee = {
|
||||||
displayName,
|
displayName,
|
||||||
id: user,
|
id: user,
|
||||||
writeable: false,
|
writeable: false,
|
||||||
isGroup,
|
isGroup,
|
||||||
|
isCircle,
|
||||||
uri
|
uri
|
||||||
}
|
}
|
||||||
state.calendarsById[calendar.id].shares.push(newSharee)
|
state.calendarsById[calendar.id].shares.push(newSharee)
|
||||||
|
@ -567,11 +568,11 @@ const actions = {
|
||||||
* @param {string} data.uri the sharing principalScheme uri
|
* @param {string} data.uri the sharing principalScheme uri
|
||||||
* @param {Boolean} data.isGroup is this a group ?
|
* @param {Boolean} data.isGroup is this a group ?
|
||||||
*/
|
*/
|
||||||
async shareCalendar(context, { calendar, user, displayName, uri, isGroup }) {
|
async shareCalendar(context, { calendar, user, displayName, uri, isGroup, isCircle }) {
|
||||||
// Share calendar with entered group or user
|
// Share calendar with entered group or user
|
||||||
try {
|
try {
|
||||||
await calendar.dav.share(uri)
|
await calendar.dav.share(uri)
|
||||||
context.commit('shareCalendar', { calendar, user, displayName, uri, isGroup })
|
context.commit('shareCalendar', { calendar, user, displayName, uri, isGroup, isCircle })
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw error
|
throw error
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue