Use ShareWith and filter shares on the fly
Signed-off-by: John Molakvoæ (skjnldsv) <skjnldsv@protonmail.com>
This commit is contained in:
parent
e060cfdfc7
commit
e9d84d87f5
|
@ -216,10 +216,10 @@ class ApiController extends Controller {
|
||||||
try {
|
try {
|
||||||
if ($keyValuePairs['access']) {
|
if ($keyValuePairs['access']) {
|
||||||
$keyValuePairs['access']['users'] = array_map(function (array $user): string {
|
$keyValuePairs['access']['users'] = array_map(function (array $user): string {
|
||||||
return $user['id'];
|
return $user['shareWith'];
|
||||||
}, $keyValuePairs['access']['users']);
|
}, $keyValuePairs['access']['users']);
|
||||||
$keyValuePairs['access']['groups'] = array_map(function (array $group): string {
|
$keyValuePairs['access']['groups'] = array_map(function (array $group): string {
|
||||||
return $group['id'];
|
return $group['shareWith'];
|
||||||
}, $keyValuePairs['access']['groups']);
|
}, $keyValuePairs['access']['groups']);
|
||||||
}
|
}
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
|
|
|
@ -234,7 +234,7 @@ class FormsService {
|
||||||
$user = $this->userManager->get($userId);
|
$user = $this->userManager->get($userId);
|
||||||
if ($user instanceof IUser) {
|
if ($user instanceof IUser) {
|
||||||
return [
|
return [
|
||||||
'id' => $userId,
|
'shareWith' => $userId,
|
||||||
'displayName' => $user->getDisplayName(),
|
'displayName' => $user->getDisplayName(),
|
||||||
'shareType' => IShare::TYPE_USER
|
'shareType' => IShare::TYPE_USER
|
||||||
];
|
];
|
||||||
|
@ -252,7 +252,7 @@ class FormsService {
|
||||||
$group = $this->groupManager->get($groupId);
|
$group = $this->groupManager->get($groupId);
|
||||||
if ($group instanceof IGroup) {
|
if ($group instanceof IGroup) {
|
||||||
return [
|
return [
|
||||||
'id' => $groupId,
|
'shareWith' => $groupId,
|
||||||
'displayName' => $group->getDisplayName(),
|
'displayName' => $group->getDisplayName(),
|
||||||
'shareType' => IShare::TYPE_GROUP
|
'shareType' => IShare::TYPE_GROUP
|
||||||
];
|
];
|
||||||
|
|
|
@ -35,7 +35,7 @@
|
||||||
:searchable="true"
|
:searchable="true"
|
||||||
:user-select="true"
|
:user-select="true"
|
||||||
label="displayName"
|
label="displayName"
|
||||||
track-by="id"
|
track-by="shareWith"
|
||||||
@search-change="asyncFind"
|
@search-change="asyncFind"
|
||||||
@select="addShare">
|
@select="addShare">
|
||||||
<template #noOptions>
|
<template #noOptions>
|
||||||
|
@ -48,7 +48,7 @@
|
||||||
|
|
||||||
<TransitionGroup :css="false" tag="ul" class="shared-list">
|
<TransitionGroup :css="false" tag="ul" class="shared-list">
|
||||||
<!-- TODO: Iterate two times, will be cleaner, one for users, one for groups -->
|
<!-- TODO: Iterate two times, will be cleaner, one for users, one for groups -->
|
||||||
<li v-for="(item, index) in sortedShares" :key="item.id + '-' + item.shareType" :data-index="index">
|
<li v-for="(item, index) in sortedShares" :key="item.shareWith + '-' + item.shareType" :data-index="index">
|
||||||
<UserDiv v-bind="item" />
|
<UserDiv v-bind="item" />
|
||||||
<div class="options">
|
<div class="options">
|
||||||
<a class="icon icon-delete svg delete-form" @click="removeShare(item)" />
|
<a class="icon icon-delete svg delete-form" @click="removeShare(item)" />
|
||||||
|
@ -120,13 +120,17 @@ export default {
|
||||||
/**
|
/**
|
||||||
* Multiseelct options. Recommendations by default,
|
* Multiseelct options. Recommendations by default,
|
||||||
* direct search when search query is valid.
|
* direct search when search query is valid.
|
||||||
|
* Filter out existing shares
|
||||||
* @returns {Array}
|
* @returns {Array}
|
||||||
*/
|
*/
|
||||||
options() {
|
options() {
|
||||||
|
const shares = [...this.userShares, ...this.groupShares]
|
||||||
if (this.isValidQuery) {
|
if (this.isValidQuery) {
|
||||||
return this.suggestions
|
// Filter out existing shares
|
||||||
|
return this.suggestions.filter(item => !shares.find(share => share.shareWith === item.shareWith && share.shareType === item.shareType))
|
||||||
}
|
}
|
||||||
return this.recommendations
|
// Filter out existing shares
|
||||||
|
return this.recommendations.filter(item => !shares.find(share => share.shareWith === item.shareWith && share.shareType === item.shareType))
|
||||||
},
|
},
|
||||||
|
|
||||||
noResultText() {
|
noResultText() {
|
||||||
|
@ -144,8 +148,8 @@ export default {
|
||||||
methods: {
|
methods: {
|
||||||
removeShare(item) {
|
removeShare(item) {
|
||||||
// Filter out the removed item
|
// Filter out the removed item
|
||||||
const users = this.userShares.filter(user => !(user.id === item.id && !item.isGroup))
|
const users = this.userShares.filter(user => !(user.shareWith === item.shareWith && item.shareType === this.SHARE_TYPES.SHARE_TYPE_USER))
|
||||||
const groups = this.groupShares.filter(group => !(group.id === item.id && item.isGroup))
|
const groups = this.groupShares.filter(group => !(group.shareWith === item.shareWith && item.shareType === this.SHARE_TYPES.SHARE_TYPE_GROUP))
|
||||||
this.$emit('update:shares', { users, groups })
|
this.$emit('update:shares', { users, groups })
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -157,11 +161,13 @@ export default {
|
||||||
const users = this.userShares.slice()
|
const users = this.userShares.slice()
|
||||||
const groups = this.groupShares.slice()
|
const groups = this.groupShares.slice()
|
||||||
const newShare = {
|
const newShare = {
|
||||||
id: share.shareWith,
|
shareWith: share.shareWith,
|
||||||
displayName: share.displayName,
|
displayName: share.displayName,
|
||||||
shareType: share.shareType,
|
shareType: share.shareType,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: detect if already present
|
||||||
|
|
||||||
if (share.shareType === this.SHARE_TYPES.SHARE_TYPE_USER) {
|
if (share.shareType === this.SHARE_TYPES.SHARE_TYPE_USER) {
|
||||||
users.push(newShare)
|
users.push(newShare)
|
||||||
} else if (share.shareType === this.SHARE_TYPES.SHARE_TYPE_GROUP) {
|
} else if (share.shareType === this.SHARE_TYPES.SHARE_TYPE_GROUP) {
|
||||||
|
@ -178,7 +184,7 @@ export default {
|
||||||
return 0
|
return 0
|
||||||
},
|
},
|
||||||
|
|
||||||
async asyncFind(query, id) {
|
async asyncFind(query) {
|
||||||
// save current query to check if we display
|
// save current query to check if we display
|
||||||
// recommendations or search results
|
// recommendations or search results
|
||||||
this.query = query.trim()
|
this.query = query.trim()
|
||||||
|
@ -227,11 +233,11 @@ export default {
|
||||||
const rawSuggestions = Object.values(data).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
|
// remove invalid data and format to user-select layout
|
||||||
const exactSuggestions = this.filterOutExistingShares(rawExactSuggestions)
|
const exactSuggestions = this.filterOutUnwantedShares(rawExactSuggestions)
|
||||||
.map(share => this.formatForMultiselect(share))
|
.map(share => this.formatForMultiselect(share))
|
||||||
// sort by type so we can get user&groups first...
|
// sort by type so we can get user&groups first...
|
||||||
.sort((a, b) => a.shareType - b.shareType)
|
.sort((a, b) => a.shareType - b.shareType)
|
||||||
const suggestions = this.filterOutExistingShares(rawSuggestions)
|
const suggestions = this.filterOutUnwantedShares(rawSuggestions)
|
||||||
.map(share => this.formatForMultiselect(share))
|
.map(share => this.formatForMultiselect(share))
|
||||||
// sort by type so we can get user&groups first...
|
// sort by type so we can get user&groups first...
|
||||||
.sort((a, b) => a.shareType - b.shareType)
|
.sort((a, b) => a.shareType - b.shareType)
|
||||||
|
@ -275,7 +281,7 @@ export default {
|
||||||
const rawRecommendations = Object.values(exact).reduce((arr, elem) => arr.concat(elem), [])
|
const rawRecommendations = Object.values(exact).reduce((arr, elem) => arr.concat(elem), [])
|
||||||
|
|
||||||
// remove invalid data and format to user-select layout
|
// remove invalid data and format to user-select layout
|
||||||
this.recommendations = this.filterOutExistingShares(rawRecommendations)
|
this.recommendations = this.filterOutUnwantedShares(rawRecommendations)
|
||||||
.map(share => this.formatForMultiselect(share))
|
.map(share => this.formatForMultiselect(share))
|
||||||
|
|
||||||
this.loading = false
|
this.loading = false
|
||||||
|
@ -283,13 +289,12 @@ export default {
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Filter out existing shares from
|
* Filter out unwated shares
|
||||||
* the provided shares search results
|
|
||||||
*
|
*
|
||||||
* @param {Object[]} shares the array of shares object
|
* @param {Object[]} shares the array of shares object
|
||||||
* @returns {Object[]}
|
* @returns {Object[]}
|
||||||
*/
|
*/
|
||||||
filterOutExistingShares(shares) {
|
filterOutUnwantedShares(shares) {
|
||||||
return shares.reduce((arr, share) => {
|
return shares.reduce((arr, share) => {
|
||||||
// only check proper objects
|
// only check proper objects
|
||||||
if (typeof share !== 'object') {
|
if (typeof share !== 'object') {
|
||||||
|
@ -303,17 +308,6 @@ export default {
|
||||||
return arr
|
return arr
|
||||||
}
|
}
|
||||||
|
|
||||||
// Filter out existing shares
|
|
||||||
if (share.value.shareType === this.SHARE_TYPES.SHARE_TYPE_USER) {
|
|
||||||
if (this.userShares.find(user => user.id === share.value.shareWith)) {
|
|
||||||
return arr
|
|
||||||
}
|
|
||||||
} else if (share.value.shareType === this.SHARE_TYPES.SHARE_TYPE_GROUP) {
|
|
||||||
if (this.groupShares.find(group => group.id === share.value.shareWith)) {
|
|
||||||
return arr
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ALL GOOD
|
// ALL GOOD
|
||||||
// let's add the suggestion
|
// let's add the suggestion
|
||||||
arr.push(share)
|
arr.push(share)
|
||||||
|
@ -337,6 +331,8 @@ export default {
|
||||||
isNoUser: result.value.shareType !== this.SHARE_TYPES.SHARE_TYPE_USER,
|
isNoUser: result.value.shareType !== this.SHARE_TYPES.SHARE_TYPE_USER,
|
||||||
displayName: result.name || result.label,
|
displayName: result.name || result.label,
|
||||||
icon: this.shareTypeToIcon(result.value.shareType),
|
icon: this.shareTypeToIcon(result.value.shareType),
|
||||||
|
// Vue unique binding to render within Multiselect's AvatarSelectOption
|
||||||
|
key: result.uuid || result.value.shareWith + '-' + result.value.shareType + '-' + result.name || result.label,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="user-row">
|
<div class="user-row">
|
||||||
<Avatar :user="id" :display-name="computedDisplayName" :is-no-user="isNoUser" />
|
<Avatar :user="shareWith" :display-name="computedDisplayName" :is-no-user="isNoUser" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -37,7 +37,7 @@ export default {
|
||||||
mixins: [ShareTypes],
|
mixins: [ShareTypes],
|
||||||
|
|
||||||
props: {
|
props: {
|
||||||
id: {
|
shareWith: {
|
||||||
type: String,
|
type: String,
|
||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
|
|
|
@ -128,7 +128,7 @@ import moment from '@nextcloud/moment'
|
||||||
import { subscribe, unsubscribe } from '@nextcloud/event-bus'
|
import { subscribe, unsubscribe } from '@nextcloud/event-bus'
|
||||||
import { getLocale, getDayNamesShort, getMonthNamesShort } from '@nextcloud/l10n'
|
import { getLocale, getDayNamesShort, getMonthNamesShort } from '@nextcloud/l10n'
|
||||||
|
|
||||||
import ShareDiv from '../components/shareDiv'
|
import ShareDiv from '../components/ShareDiv'
|
||||||
import ViewsMixin from '../mixins/ViewsMixin'
|
import ViewsMixin from '../mixins/ViewsMixin'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
|
Loading…
Reference in a new issue