aboutsummaryrefslogtreecommitdiffstats
path: root/apps/files_sharing/src/components/SharingEntry.vue
diff options
context:
space:
mode:
Diffstat (limited to 'apps/files_sharing/src/components/SharingEntry.vue')
-rw-r--r--apps/files_sharing/src/components/SharingEntry.vue436
1 files changed, 92 insertions, 344 deletions
diff --git a/apps/files_sharing/src/components/SharingEntry.vue b/apps/files_sharing/src/components/SharingEntry.vue
index 2d29aaf1dc6..342b40ce384 100644
--- a/apps/files_sharing/src/components/SharingEntry.vue
+++ b/apps/files_sharing/src/components/SharingEntry.vue
@@ -1,199 +1,101 @@
<!--
- - @copyright Copyright (c) 2019 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/>.
- -
- -->
+ - SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
+ - SPDX-License-Identifier: AGPL-3.0-or-later
+-->
<template>
<li class="sharing-entry">
- <Avatar class="sharing-entry__avatar"
- :is-no-user="share.type !== SHARE_TYPES.SHARE_TYPE_USER"
+ <NcAvatar class="sharing-entry__avatar"
+ :is-no-user="share.type !== ShareType.User"
:user="share.shareWith"
:display-name="share.shareWithDisplayName"
- :tooltip-message="share.type === SHARE_TYPES.SHARE_TYPE_USER ? share.shareWith : ''"
:menu-position="'left'"
:url="share.shareWithAvatar" />
- <component :is="share.shareWithLink ? 'a' : 'div'"
- v-tooltip.auto="tooltip"
- :href="share.shareWithLink"
- class="sharing-entry__desc">
- <h5>{{ title }}<span v-if="!isUnique" class="sharing-entry__desc-unique"> ({{ share.shareWithDisplayNameUnique }})</span></h5>
- <p v-if="hasStatus">
- <span>{{ share.status.icon || '' }}</span>
- <span>{{ share.status.message || '' }}</span>
- </p>
- </component>
- <Actions menu-align="right"
- class="sharing-entry__actions"
- @close="onMenuClose">
- <template v-if="share.canEdit">
- <!-- edit permission -->
- <ActionCheckbox ref="canEdit"
- :checked.sync="canEdit"
- :value="permissionsEdit"
- :disabled="saving || !canSetEdit">
- {{ t('files_sharing', 'Allow editing') }}
- </ActionCheckbox>
- <!-- create permission -->
- <ActionCheckbox v-if="isFolder"
- ref="canCreate"
- :checked.sync="canCreate"
- :value="permissionsCreate"
- :disabled="saving || !canSetCreate">
- {{ t('files_sharing', 'Allow creating') }}
- </ActionCheckbox>
-
- <!-- delete permission -->
- <ActionCheckbox v-if="isFolder"
- ref="canDelete"
- :checked.sync="canDelete"
- :value="permissionsDelete"
- :disabled="saving || !canSetDelete">
- {{ t('files_sharing', 'Allow deleting') }}
- </ActionCheckbox>
-
- <!-- reshare permission -->
- <ActionCheckbox v-if="config.isResharingAllowed"
- ref="canReshare"
- :checked.sync="canReshare"
- :value="permissionsShare"
- :disabled="saving || !canSetReshare">
- {{ t('files_sharing', 'Allow resharing') }}
- </ActionCheckbox>
-
- <!-- expiration date -->
- <ActionCheckbox :checked.sync="hasExpirationDate"
- :disabled="config.isDefaultInternalExpireDateEnforced || saving"
- @uncheck="onExpirationDisable">
- {{ config.isDefaultInternalExpireDateEnforced
- ? t('files_sharing', 'Expiration date enforced')
- : t('files_sharing', 'Set expiration date') }}
- </ActionCheckbox>
- <ActionInput v-if="hasExpirationDate"
- ref="expireDate"
- v-tooltip.auto="{
- content: errors.expireDate,
- show: errors.expireDate,
- trigger: 'manual'
- }"
- :class="{ error: errors.expireDate}"
- :disabled="saving"
- :lang="lang"
- :value="share.expireDate"
- value-type="format"
- icon="icon-calendar-dark"
- type="date"
- :disabled-date="disabledDate"
- @update:value="onExpirationChange">
- {{ t('files_sharing', 'Enter a date') }}
- </ActionInput>
-
- <!-- note -->
- <template v-if="canHaveNote">
- <ActionCheckbox :checked.sync="hasNote"
- :disabled="saving"
- @uncheck="queueUpdate('note')">
- {{ t('files_sharing', 'Note to recipient') }}
- </ActionCheckbox>
- <ActionTextEditable v-if="hasNote"
- ref="note"
- v-tooltip.auto="{
- content: errors.note,
- show: errors.note,
- trigger: 'manual'
- }"
- :class="{ error: errors.note}"
- :disabled="saving"
- :value="share.newNote || share.note"
- icon="icon-edit"
- @update:value="onNoteChange"
- @submit="onNoteSubmit" />
- </template>
+ <div class="sharing-entry__summary">
+ <component :is="share.shareWithLink ? 'a' : 'div'"
+ :title="tooltip"
+ :aria-label="tooltip"
+ :href="share.shareWithLink"
+ class="sharing-entry__summary__desc">
+ <span>{{ title }}
+ <span v-if="!isUnique" class="sharing-entry__summary__desc-unique">
+ ({{ share.shareWithDisplayNameUnique }})
+ </span>
+ <small v-if="hasStatus && share.status.message">({{ share.status.message }})</small>
+ </span>
+ </component>
+ <SharingEntryQuickShareSelect :share="share"
+ :file-info="fileInfo"
+ @open-sharing-details="openShareDetailsForCustomSettings(share)" />
+ </div>
+ <ShareExpiryTime v-if="share && share.expireDate" :share="share" />
+ <NcButton v-if="share.canEdit"
+ class="sharing-entry__action"
+ data-cy-files-sharing-share-actions
+ :aria-label="t('files_sharing', 'Open Sharing Details')"
+ type="tertiary"
+ @click="openSharingDetails(share)">
+ <template #icon>
+ <DotsHorizontalIcon :size="20" />
</template>
-
- <ActionButton v-if="share.canDelete"
- icon="icon-close"
- :disabled="saving"
- @click.prevent="onDelete">
- {{ t('files_sharing', 'Unshare') }}
- </ActionButton>
- </Actions>
+ </NcButton>
</li>
</template>
<script>
-import Avatar from '@nextcloud/vue/dist/Components/Avatar'
-import Actions from '@nextcloud/vue/dist/Components/Actions'
-import ActionButton from '@nextcloud/vue/dist/Components/ActionButton'
-import ActionCheckbox from '@nextcloud/vue/dist/Components/ActionCheckbox'
-import ActionInput from '@nextcloud/vue/dist/Components/ActionInput'
-import ActionTextEditable from '@nextcloud/vue/dist/Components/ActionTextEditable'
-import Tooltip from '@nextcloud/vue/dist/Directives/Tooltip'
+import { ShareType } from '@nextcloud/sharing'
+
+import NcButton from '@nextcloud/vue/components/NcButton'
+import NcSelect from '@nextcloud/vue/components/NcSelect'
+import NcAvatar from '@nextcloud/vue/components/NcAvatar'
+import DotsHorizontalIcon from 'vue-material-design-icons/DotsHorizontal.vue'
-import SharesMixin from '../mixins/SharesMixin'
+import ShareExpiryTime from './ShareExpiryTime.vue'
+import SharingEntryQuickShareSelect from './SharingEntryQuickShareSelect.vue'
+
+import SharesMixin from '../mixins/SharesMixin.js'
+import ShareDetails from '../mixins/ShareDetails.js'
export default {
name: 'SharingEntry',
components: {
- Actions,
- ActionButton,
- ActionCheckbox,
- ActionInput,
- ActionTextEditable,
- Avatar,
- },
-
- directives: {
- Tooltip,
+ NcButton,
+ NcAvatar,
+ DotsHorizontalIcon,
+ NcSelect,
+ ShareExpiryTime,
+ SharingEntryQuickShareSelect,
},
- mixins: [SharesMixin],
-
- data() {
- return {
- permissionsEdit: OC.PERMISSION_UPDATE,
- permissionsCreate: OC.PERMISSION_CREATE,
- permissionsDelete: OC.PERMISSION_DELETE,
- permissionsRead: OC.PERMISSION_READ,
- permissionsShare: OC.PERMISSION_SHARE,
- }
- },
+ mixins: [SharesMixin, ShareDetails],
computed: {
title() {
let title = this.share.shareWithDisplayName
- if (this.share.type === this.SHARE_TYPES.SHARE_TYPE_GROUP) {
+
+ const showAsInternal = this.config.showFederatedSharesAsInternal
+ || (this.share.isTrustedServer && this.config.showFederatedSharesToTrustedServersAsInternal)
+
+ if (this.share.type === ShareType.Group || (this.share.type === ShareType.RemoteGroup && showAsInternal)) {
title += ` (${t('files_sharing', 'group')})`
- } else if (this.share.type === this.SHARE_TYPES.SHARE_TYPE_ROOM) {
+ } else if (this.share.type === ShareType.Room) {
title += ` (${t('files_sharing', 'conversation')})`
- } else if (this.share.type === this.SHARE_TYPES.SHARE_TYPE_REMOTE) {
+ } else if (this.share.type === ShareType.Remote && !showAsInternal) {
title += ` (${t('files_sharing', 'remote')})`
- } else if (this.share.type === this.SHARE_TYPES.SHARE_TYPE_REMOTE_GROUP) {
+ } else if (this.share.type === ShareType.RemoteGroup) {
title += ` (${t('files_sharing', 'remote group')})`
- } else if (this.share.type === this.SHARE_TYPES.SHARE_TYPE_GUEST) {
+ } else if (this.share.type === ShareType.Guest) {
title += ` (${t('files_sharing', 'guest')})`
}
+ if (!this.isShareOwner && this.share.ownerDisplayName) {
+ title += ' ' + t('files_sharing', 'by {initiator}', {
+ initiator: this.share.ownerDisplayName,
+ })
+ }
return title
},
-
tooltip() {
if (this.share.owner !== this.share.uidFileOwner) {
const data = {
@@ -202,10 +104,9 @@ export default {
user: this.share.shareWithDisplayName,
owner: this.share.ownerDisplayName,
}
-
- if (this.share.type === this.SHARE_TYPES.SHARE_TYPE_GROUP) {
+ if (this.share.type === ShareType.Group) {
return t('files_sharing', 'Shared with the group {user} by {owner}', data)
- } else if (this.share.type === this.SHARE_TYPES.SHARE_TYPE_ROOM) {
+ } else if (this.share.type === ShareType.Room) {
return t('files_sharing', 'Shared with the conversation {user} by {owner}', data)
}
@@ -214,185 +115,19 @@ export default {
return null
},
- canHaveNote() {
- return !this.isRemote
- },
-
- isRemote() {
- return this.share.type === this.SHARE_TYPES.SHARE_TYPE_REMOTE
- || this.share.type === this.SHARE_TYPES.SHARE_TYPE_REMOTE_GROUP
- },
-
- /**
- * Can the sharer set whether the sharee can edit the file ?
- *
- * @return {boolean}
- */
- canSetEdit() {
- // If the owner revoked the permission after the resharer granted it
- // the share still has the permission, and the resharer is still
- // allowed to revoke it too (but not to grant it again).
- return (this.fileInfo.sharePermissions & OC.PERMISSION_UPDATE) || this.canEdit
- },
-
- /**
- * Can the sharer set whether the sharee can create the file ?
- *
- * @return {boolean}
- */
- canSetCreate() {
- // If the owner revoked the permission after the resharer granted it
- // the share still has the permission, and the resharer is still
- // allowed to revoke it too (but not to grant it again).
- return (this.fileInfo.sharePermissions & OC.PERMISSION_CREATE) || this.canCreate
- },
-
- /**
- * Can the sharer set whether the sharee can delete the file ?
- *
- * @return {boolean}
- */
- canSetDelete() {
- // If the owner revoked the permission after the resharer granted it
- // the share still has the permission, and the resharer is still
- // allowed to revoke it too (but not to grant it again).
- return (this.fileInfo.sharePermissions & OC.PERMISSION_DELETE) || this.canDelete
- },
-
- /**
- * Can the sharer set whether the sharee can reshare the file ?
- *
- * @return {boolean}
- */
- canSetReshare() {
- // If the owner revoked the permission after the resharer granted it
- // the share still has the permission, and the resharer is still
- // allowed to revoke it too (but not to grant it again).
- return (this.fileInfo.sharePermissions & OC.PERMISSION_SHARE) || this.canReshare
- },
-
- /**
- * Can the sharee edit the shared file ?
- */
- canEdit: {
- get() {
- return this.share.hasUpdatePermission
- },
- set(checked) {
- this.updatePermissions({ isEditChecked: checked })
- },
- },
-
- /**
- * Can the sharee create the shared file ?
- */
- canCreate: {
- get() {
- return this.share.hasCreatePermission
- },
- set(checked) {
- this.updatePermissions({ isCreateChecked: checked })
- },
- },
-
- /**
- * Can the sharee delete the shared file ?
- */
- canDelete: {
- get() {
- return this.share.hasDeletePermission
- },
- set(checked) {
- this.updatePermissions({ isDeleteChecked: checked })
- },
- },
-
- /**
- * Can the sharee reshare the file ?
- */
- canReshare: {
- get() {
- return this.share.hasSharePermission
- },
- set(checked) {
- this.updatePermissions({ isReshareChecked: checked })
- },
- },
-
- /**
- * Is this share readable
- * Needed for some federated shares that might have been added from file drop links
- */
- hasRead: {
- get() {
- return this.share.hasReadPermission
- },
- },
-
- /**
- * Is the current share a folder ?
- *
- * @return {boolean}
- */
- isFolder() {
- return this.fileInfo.type === 'dir'
- },
-
- /**
- * Does the current share have an expiration date
- *
- * @return {boolean}
- */
- hasExpirationDate: {
- get() {
- return this.config.isDefaultInternalExpireDateEnforced || !!this.share.expireDate
- },
- set(enabled) {
- this.share.expireDate = enabled
- ? this.config.defaultInternalExpirationDateString !== ''
- ? this.config.defaultInternalExpirationDateString
- : moment().format('YYYY-MM-DD')
- : ''
- },
- },
-
- dateMaxEnforced() {
- if (!this.isRemote) {
- return this.config.isDefaultInternalExpireDateEnforced
- && moment().add(1 + this.config.defaultInternalExpireDate, 'days')
- } else {
- return this.config.isDefaultRemoteExpireDateEnforced
- && moment().add(1 + this.config.defaultRemoteExpireDate, 'days')
- }
- },
-
/**
* @return {boolean}
*/
hasStatus() {
- if (this.share.type !== this.SHARE_TYPES.SHARE_TYPE_USER) {
+ if (this.share.type !== ShareType.User) {
return false
}
return (typeof this.share.status === 'object' && !Array.isArray(this.share.status))
},
-
},
methods: {
- updatePermissions({ isEditChecked = this.canEdit, isCreateChecked = this.canCreate, isDeleteChecked = this.canDelete, isReshareChecked = this.canReshare } = {}) {
- // calc permissions if checked
- const permissions = 0
- | (this.hasRead ? this.permissionsRead : 0)
- | (isCreateChecked ? this.permissionsCreate : 0)
- | (isDeleteChecked ? this.permissionsDelete : 0)
- | (isEditChecked ? this.permissionsEdit : 0)
- | (isReshareChecked ? this.permissionsShare : 0)
-
- this.share.permissions = permissions
- this.queueUpdate('permissions')
- },
-
/**
* Save potential changed data on menu close
*/
@@ -408,21 +143,34 @@ export default {
display: flex;
align-items: center;
height: 44px;
- &__desc {
+ &__summary {
+ padding: 8px;
+ padding-inline-start: 10px;
display: flex;
flex-direction: column;
- justify-content: space-between;
- padding: 8px;
- line-height: 1.2em;
- p {
- color: var(--color-text-maxcontrast);
- }
- &-unique {
- color: var(--color-text-maxcontrast);
+ justify-content: center;
+ align-items: flex-start;
+ flex: 1 0;
+ min-width: 0;
+
+ &__desc {
+ display: inline-block;
+ padding-bottom: 0;
+ line-height: 1.2em;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+
+ p,
+ small {
+ color: var(--color-text-maxcontrast);
+ }
+
+ &-unique {
+ color: var(--color-text-maxcontrast);
+ }
}
}
- &__actions {
- margin-left: auto;
- }
+
}
</style>