Skip to content

Commit

Permalink
feat: share context UI elements
Browse files Browse the repository at this point in the history
  • Loading branch information
enjeck committed Apr 3, 2024
1 parent 50cb388 commit 2851b3e
Show file tree
Hide file tree
Showing 3 changed files with 303 additions and 0 deletions.
10 changes: 10 additions & 0 deletions src/shared/components/ncContextResource/NcContextResource.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
<div>
<ResourceForm :resources="localResource" @add="addResource" />
<ResourceList :resources="localResource" @remove="removeResource" />
<ResourceSharees :select-users="true" :select-groups="false" :sharees.sync="sharees" />
<ResourceSharePermissions :resources="localResource" />
</div>
</div>
</template>
Expand All @@ -11,11 +13,15 @@
import { mapGetters } from 'vuex'
import ResourceForm from './ResourceForm.vue'
import ResourceList from './ResourceList.vue'
import ResourceSharePermissions from './ResourceSharePermissions.vue'
import ResourceSharees from './ResourceSharees.vue'
export default {
components: {
ResourceForm,
ResourceList,
ResourceSharePermissions,
ResourceSharees,
},
props: {
Expand All @@ -29,6 +35,10 @@ export default {
type: Array,
default: () => ([]),
},
sharees: {
type: Array,
default: () => ([]),
},
},
data() {
Expand Down
106 changes: 106 additions & 0 deletions src/shared/components/ncContextResource/ResourceSharePermissions.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
<template>
<div>
<h3>{{ t('tables', 'Sharing') }}</h3>
<ul v-if="resources && resources.length > 0" class="shares-list">
<div v-for="resource in resources"
:key="resource.key"
class="row">
<div class="fix-col-2">
<div style="display:flex; align-items: center; padding: 10px;">
{{ resource.emoji }} &nbsp; {{ resource.title }}
</div>
</div>
<div class="fix-col-2" style="justify-content: end;">
<NcActions :force-menu="true">
<template>
<NcActionCaption :name="t('tables', 'Permissions')" />
<NcActionCheckbox
:disabled="true"
@check="updatePermission(resource, 'read', true)"
@uncheck="updatePermission(resource, 'read', false)">
{{ t('tables', 'Read data') }}
</NcActionCheckbox>
<!-- <NcActionCheckbox :checked.sync="share.permissionRead"
:disabled="share.permissionManage || share.permissionUpdate || share.permissionDelete"
@check="updatePermission(share, 'read', true)"
@uncheck="updatePermission(share, 'read', false)">
{{ t('tables', 'Read data') }}
</NcActionCheckbox>
<NcActionCheckbox :checked.sync="share.permissionCreate"
:disabled="share.permissionManage"
@check="updatePermission(share, 'create', true)"
@uncheck="updatePermission(share, 'create', false)">
{{ t('tables', 'Create data') }}
</NcActionCheckbox>
<NcActionCheckbox :checked.sync="share.permissionUpdate"
:disabled="share.permissionManage"
@check="updatePermission(share, 'update', true)"
@uncheck="updatePermission(share, 'update', false)">
{{ t('tables', 'Update data') }}
</NcActionCheckbox>
<NcActionCheckbox :checked.sync="share.permissionDelete"
:disabled="share.permissionManage"
@check="updatePermission(share, 'delete', true)"
@uncheck="updatePermission(share, 'delete', false)">
{{ t('tables', 'Delete data') }}
</NcActionCheckbox> -->
</template>
</NcActions>
</div>
</div>
</ul>
<div v-else>
{{ t('tables', 'No shares') }}
</div>
</div>
</template>

<script>
import { NcActions, NcActionCheckbox, NcActionCaption } from '@nextcloud/vue'
export default {
components: {
NcActions,
NcActionCheckbox,
NcActionCaption,
},
props: {
resources: {
type: Array,
default: () => ([]),
},
},
data() {
return {
loading: false,
}
},
methods: {
updatePermission(share, permission, value) {
this.$emit('update', { id: share.id, permission, value })
},
},
}
</script>

<style lang="scss" scoped>
.shares-list li {
display: flex;
justify-content: space-between;
line-height: 44px;
}
.high-line-height {
line-height: 35px;
}
.manage-button {
display: flex;
justify-content: center;
}
</style>
187 changes: 187 additions & 0 deletions src/shared/components/ncContextResource/ResourceSharees.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,187 @@
<template>
<div class="row space-B">
<h3>{{ t('tables', 'Share with accounts or groups') }}</h3>
<NcSelect v-model="value" style="width: 100%;" :loading="loading" :options="options"
:value="sharees"
:placeholder="getPlaceholder()"
:searchable="true" :get-option-key="(option) => option.key"
label="displayName"
:aria-label-combobox="getPlaceholder()" :user-select="true"
:close-on-select="false"
:multiple="true"
@search="asyncFind" @input="addShare">
<template #noResult>
{{ noResultText }}
</template>
</NcSelect>
</div>
</template>

<script>
import { generateOcsUrl } from '@nextcloud/router'
import { getCurrentUser } from '@nextcloud/auth'
import axios from '@nextcloud/axios'
import debounce from 'debounce'
import { NcSelect } from '@nextcloud/vue'
import formatting from '../../../shared/mixins/formatting.js'
import ShareTypes from '../../mixins/shareTypesMixin.js'
import { showError } from '@nextcloud/dialogs'
import '@nextcloud/dialogs/style.css'
export default {
components: {
NcSelect,
},
mixins: [ShareTypes, formatting],
props: {
sharees: {
type: Array,
default: () => ([]),
},
selectUsers: {
type: Boolean,
default: true,
},
selectGroups: {
type: Boolean,
default: false,
},
},
data() {
return {
query: '',
value: '',
loading: false,
minSearchStringLength: 1,
maxAutocompleteResults: 20,
suggestions: [],
}
},
computed: {
localValue: {
get() {
return this.newOwnerUserId
},
set(v) {
console.info('newOwnerUserId set to ', v)
this.$emit('update:newOwnerUserId', v)
},
},
isValidQuery() {
return this.query?.trim() && this.query.length >= this.minSearchStringLength
},
options() {
if (this.isValidQuery) {
return this.suggestions
}
return []
},
noResultText() {
if (this.loading) {
return t('tables', 'Searching …')
}
return t('tables', 'No elements found.')
},
userId() {
return getCurrentUser().uid
},
},
methods: {
addShare(selectedItem) {
if (selectedItem) {
this.localValue = selectedItem.user
} else {
this.localValue = ''
}
},
getShareTypes() {
const types = []
if (this.selectUsers) {
types.push(this.SHARE_TYPES.SHARE_TYPE_USER)
}
if (this.selectGroups) {
types.push(this.SHARE_TYPES.SHARE_TYPE_GROUP)
}
return types
},
getShareTypeString() {
if (this.selectUsers && !this.selectGroups) {
return 'User'
} else if (!this.selectUsers && this.selectGroups) {
return 'Group'
} else {
return 'User or group'
}
},
getPlaceholder() {
return t('tables', '{shareTypeString}...', { shareTypeString: this.getShareTypeString() })
},
async asyncFind(query) {
this.query = query.trim()
if (this.isValidQuery) {
this.loading = true
await this.debounceGetSuggestions(query)
}
},
async getSuggestions(search) {
this.loading = true
const shareTypes = this.getShareTypes()
let shareTypeQueryString = ''
shareTypes.forEach(shareType => {
shareTypeQueryString += `&shareTypes[]=${shareType}`
})
const url = generateOcsUrl(`core/autocomplete/get?search=${search}${shareTypeQueryString}&limit=${this.maxAutocompleteResults}`)
try {
const res = await axios.get(url)
const rawSuggestions = res.data.ocs.data.map(autocompleteResult => {
return {
user: autocompleteResult.id,
displayName: autocompleteResult.label,
icon: autocompleteResult.icon,
isUser: autocompleteResult.source.startsWith('users'),
key: autocompleteResult.source + '-' + autocompleteResult.id,
}
})
this.suggestions = this.filterOutCurrentUser(rawSuggestions)
this.loading = false
} catch (err) {
console.debug(err)
showError(t('tables', 'Failed to fetch {shareTypeString}', { shareTypeString: this.getShareTypeString().toLowerCase() }))
}
},
debounceGetSuggestions: debounce(function(...args) {
this.getSuggestions(...args)
}, 300),
filterOutCurrentUser(list) {
return list.filter((item) => !(item.isUser && item.user === getCurrentUser().uid))
},
},
}
</script>
<style lang="scss" scoped>
.multiselect {
width: 100% !important;
max-width: 100% !important;
}
</style>

0 comments on commit 2851b3e

Please sign in to comment.