Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: move "Shared via"-indicator in sidebar to context menu #11626

Merged
merged 2 commits into from
Sep 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
Enhancement: Move permanent link indicator

The permanent link indicator has been moved to the top right of the sharing sidebar panel. This is ensures that it's always visible, no matter if there are shares present or not.

https://github.com/owncloud/web/pull/11606
https://github.com/owncloud/web/issues/11602
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
Enhancement: Redesign sidebar link section in sharing panel

The design of the sidebar link section in the sharing panel has been aligned with the people sharing section.

https://github.com/owncloud/web/pull/11606
https://github.com/owncloud/web/issues/11602
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<template>
<div
v-if="option.hasSwitch"
class="action-menu-item item-has-switch oc-p-s oc-flex oc-flex-center"
>
<oc-icon :name="option.icon" fill-type="line" size="medium" variation="passive" />
<oc-switch
class="oc-ml-s oc-flex oc-width-1-1"
:checked="option.isChecked.value"
:class="option.class"
:label="option.title"
@update:checked="option.method"
/>
</div>
<oc-button
v-else
appearance="raw"
class="oc-p-s action-menu-item"
:class="option.class"
:type="option.to ? 'router-link' : 'button'"
:to="option.to"
v-bind="option.additionalAttributes || {}"
@click="option.method"
>
<oc-icon :name="option.icon" fill-type="line" size="medium" />
<span v-text="option.title" />
</oc-button>
</template>

<script lang="ts">
import { defineComponent, PropType } from 'vue'
import { EditOption } from './EditDropdown.vue'

export default defineComponent({
name: 'ContextMenuItem',
props: {
option: {
type: Object as PropType<EditOption>,
required: true
}
}
})
</script>
Original file line number Diff line number Diff line change
@@ -1,85 +1,48 @@
<template>
<span class="oc-flex oc-flex-middle">
<div v-oc-tooltip="dropButtonTooltip">
<oc-button
:id="editShareBtnId"
class="collaborator-edit-dropdown-options-btn"
:aria-label="
isLocked ? dropButtonTooltip : $gettext('Open context menu with share editing options')
"
appearance="raw"
:disabled="isLocked"
>
<oc-icon name="more-2" />
</oc-button>
</div>
<div class="oc-flex oc-flex-middle">
<oc-button
:id="editShareBtnId"
v-oc-tooltip="dropButtonTooltip"
class="collaborator-edit-dropdown-options-btn"
:aria-label="
isLocked ? dropButtonTooltip : $gettext('Open context menu with share editing options')
"
appearance="raw"
:disabled="isLocked"
>
<oc-icon name="more-2" />
</oc-button>
<oc-drop
ref="expirationDateDrop"
:toggle="'#' + editShareBtnId"
mode="click"
padding-size="small"
>
<oc-list class="collaborator-edit-dropdown-options-list" :aria-label="shareEditOptions">
<li v-for="(option, i) in options" :key="i" class="oc-rounded oc-menu-item-hover">
<context-menu-item :option="option" />
</li>
<li v-if="sharedParentRoute" class="oc-rounded oc-menu-item-hover">
<context-menu-item :option="navigateToParentOption" />
</li>
</oc-list>
<oc-list
v-if="canEditOrDelete"
class="collaborator-edit-dropdown-options-list collaborator-edit-dropdown-options-list-remove"
>
<li
v-if="canEditOrDelete && isExpirationSupported"
class="oc-rounded oc-menu-item-hover files-collaborators-expiration"
class="oc-rounded oc-menu-item-hover"
:class="{ 'oc-pt-s': options.length > 0 || sharedParentRoute }"
>
<oc-button
class="files-collaborators-expiration-button oc-p-s action-menu-item"
data-testid="recipient-datepicker-btn"
appearance="raw"
@click="showDatePickerModal"
>
<oc-icon name="calendar-event" fill-type="line" size="medium" variation="passive" />
<span v-if="isExpirationDateSet" v-text="$gettext('Edit expiration date')" />
<span v-else v-text="$gettext('Set expiration date')" />
</oc-button>
<oc-button
v-if="isRemoveExpirationPossible"
class="remove-expiration-date oc-p-s action-menu-item"
data-testid="collaborator-remove-expiration-btn oc-p-s action-menu-item"
appearance="raw"
@click="removeExpirationDate"
>
<oc-icon name="calendar-close" />
<span v-text="$gettext('Remove expiration date')" />
</oc-button>
</li>
<li v-for="(option, i) in options" :key="i" class="oc-rounded oc-menu-item-hover">
<template v-if="option.enabled">
<div
v-if="option.hasSwitch"
class="action-menu-item item-has-switch oc-p-s oc-flex oc-flex-center"
>
<oc-icon :name="option.icon" fill-type="line" size="medium" variation="passive" />
<oc-switch
class="oc-ml-s oc-flex oc-width-1-1 oc-button-justify-content-space-between"
:checked="isShareDenied"
:class="option.class"
:label="option.title"
@update:checked="option.method"
/>
</div>
<oc-button
v-else
appearance="raw"
class="oc-p-s action-menu-item"
:class="option.class"
v-bind="option.additionalAttributes || {}"
@click="option.method"
>
<oc-icon :name="option.icon" fill-type="line" size="medium" variation="passive" />
<span v-text="option.title" />
</oc-button>
</template>
<context-menu-item :option="removeShareOption" />
</li>
</oc-list>
</oc-drop>
</span>
</div>
</template>

<script lang="ts">
import { computed, defineComponent, inject, Ref } from 'vue'
import { computed, defineComponent, inject, PropType, Ref, unref, useTemplateRef } from 'vue'
import { DateTime } from 'luxon'
import uniqueId from 'design-system/src/utils/uniqueId'
import { OcDrop } from 'design-system/src/components'
Expand All @@ -88,9 +51,23 @@ import { isProjectSpaceResource } from '@ownclouders/web-client'
import { useConfigStore, useModals } from '@ownclouders/web-pkg'
import { useGettext } from 'vue3-gettext'
import DatePickerModal from '../../../Modals/DatePickerModal.vue'
import { RouteLocationNamedRaw } from 'vue-router'
import ContextMenuItem from './ContextMenuItem.vue'

export type EditOption = {
icon: string
title: string
additionalAttributes?: Record<string, string>
class?: string
hasSwitch?: boolean
isChecked?: Ref<boolean>
method?: (args?: unknown) => void
to?: RouteLocationNamedRaw
}

export default defineComponent({
name: 'EditDropdown',
components: { ContextMenuItem },
props: {
expirationDate: {
type: String,
Expand Down Expand Up @@ -120,6 +97,10 @@ export default defineComponent({
isLocked: {
type: Boolean,
default: false
},
sharedParentRoute: {
type: Object as PropType<RouteLocationNamedRaw>,
default: undefined
}
},
emits: [
Expand All @@ -134,6 +115,9 @@ export default defineComponent({
const { $gettext } = language
const configStore = useConfigStore()
const { dispatchModal } = useModals()
const expirationDateDrop = useTemplateRef<typeof OcDrop>('expirationDateDrop')

const resource = inject<Ref<Resource>>('resource')

const toggleShareDenied = (value: boolean) => {
emit('setDenyShare', value)
Expand All @@ -147,52 +131,94 @@ export default defineComponent({
return ''
})

const navigateToParentOption = computed<EditOption>(() => {
return {
title: $gettext('Navigate to parent'),
icon: 'folder-shared',
class: 'navigate-to-parent',
to: props.sharedParentRoute
}
})

const removeShareOption = computed<EditOption>(() => {
return {
title: isProjectSpaceResource(unref(resource))
? $gettext('Remove member')
: $gettext('Remove share'),
method: () => {
emit('removeShare')
},
class: 'remove-share',
icon: 'delete-bin-5',
additionalAttributes: {
'data-testid': 'collaborator-remove-share-btn'
}
}
})

return {
configStore,
resource: inject<Ref<Resource>>('resource'),
resource,
expirationDateDrop,
toggleShareDenied,
dropButtonTooltip,
dispatchModal
dispatchModal,
navigateToParentOption,
removeShareOption
}
},
computed: {
options() {
return [
{
title: isProjectSpaceResource(this.resource)
? this.$gettext('Remove member')
: this.$gettext('Remove share'),
method: this.removeShare,
class: 'remove-share',
enabled: this.canEditOrDelete,
icon: 'delete-bin-5',
additionalAttributes: {
'data-testid': 'collaborator-remove-share-btn'
}
},
options(): EditOption[] {
const result: EditOption[] = [
{
title: this.$gettext('Access details'),
method: this.showAccessDetails,
enabled: true,
icon: 'information',
class: 'show-access-details'
},
{
}
]

if (this.deniable) {
result.push({
title: this.$gettext('Deny access'),
method: this.toggleShareDenied,
enabled: this.deniable,
icon: 'stop-circle',
class: 'deny-share',
hasSwitch: true
},
{
hasSwitch: true,
isChecked: computed(() => this.isShareDenied)
})
}

if (this.canEditOrDelete && this.isExpirationSupported) {
result.push({
title: this.isExpirationDateSet
? this.$gettext('Edit expiration date')
: this.$gettext('Set expiration date'),
class: 'set-expiration-date recipient-datepicker-btn',
icon: 'calendar-event',
method: this.showDatePickerModal
})
}

if (this.isRemoveExpirationPossible) {
result.push({
title: this.$gettext('Remove expiration date'),
class: 'remove-expiration-date',
icon: 'calendar-close',
method: this.removeExpirationDate
})
}

if (this.configStore.options.isRunningOnEos) {
result.push({
title: this.$gettext('Notify via mail'),
method: () => this.$emit('notifyShare'),
enabled: this.configStore.options.isRunningOnEos,
icon: 'mail',
class: 'notify-via-mail'
}
]
})
}

return result
},

editShareBtnId() {
Expand Down Expand Up @@ -225,10 +251,7 @@ export default defineComponent({
methods: {
removeExpirationDate() {
this.$emit('expirationDateChanged', { expirationDateTime: null })
;(this.$refs.expirationDateDrop as InstanceType<typeof OcDrop>).hide()
},
removeShare() {
this.$emit('removeShare')
this.expirationDateDrop.hide()
},
showAccessDetails() {
this.$emit('showAccessDetails')
Expand All @@ -255,10 +278,17 @@ export default defineComponent({
})
</script>
<style lang="scss">
.collaborator-edit-dropdown-options-list .action-menu-item {
width: 100%;
justify-content: flex-start;
color: var(--oc-color-swatch-passive-default);
gap: var(--oc-space-small);
.collaborator-edit-dropdown-options-list {
&-remove {
margin-top: var(--oc-space-small) !important;
border-top: 1px solid var(--oc-color-border) !important;
}

.action-menu-item {
width: 100%;
justify-content: flex-start;
color: var(--oc-color-swatch-passive-default);
gap: var(--oc-space-small);
}
}
</style>
Loading