Skip to content

Commit

Permalink
Add drop down menu to app top bar (#11057)
Browse files Browse the repository at this point in the history
* Add drop down menu to app top bar

* Add changelog item
  • Loading branch information
AlexAndBear committed Jun 18, 2024
1 parent 791396b commit bbf67bb
Show file tree
Hide file tree
Showing 8 changed files with 145 additions and 68 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
Enhancement: add action drop down top app top bar

We've added an action drop down with various file actions to the app top bar,
so the user can now call different actions like download, directly from the app.

https://github.com/owncloud/web/pull/11057
https://github.com/owncloud/web/issues/11019
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<audio :key="`media-audio-${file.id}`" controls preload="preload" :autoplay="isAutoPlayEnabled">
<source :src="file.url" :type="file.mimeType" />
</audio>
<p class="oc-text-muted oc-text-small" v-if="audioText" v-text="audioText"></p>
<p v-if="audioText" class="oc-text-muted oc-text-small" v-text="audioText"></p>
</div>
</template>
<script lang="ts">
Expand Down
99 changes: 84 additions & 15 deletions packages/web-pkg/src/components/AppTemplates/AppWrapper.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
<app-top-bar
v-if="!loading && !loadingError"
:main-actions="fileActions"
:drop-down-menu-sections="dropDownMenuSections"
:drop-down-action-options="dropDownActionOptions"
:resource="resource"
@close="closeApp"
/>
Expand Down Expand Up @@ -57,11 +59,16 @@ import {
useAppsStore,
useConfigStore,
useResourcesStore,
FileContentOptions
FileContentOptions,
useFileActionsCopyQuickLink,
useFileActionsDownloadFile,
useFileActionsShowDetails,
useFileActionsShowShares,
FileActionOptions,
FileAction
} from '../../composables'
import {
Action,
ActionOptions,
Modifier,
Key,
useAppMeta,
Expand Down Expand Up @@ -127,6 +134,11 @@ export default defineComponent({
const configStore = useConfigStore()
const resourcesStore = useResourcesStore()
const { actions: createQuickLinkActions } = useFileActionsCopyQuickLink()
const { actions: downloadFileActions } = useFileActionsDownloadFile()
const { actions: showDetailsActions } = useFileActionsShowDetails()
const { actions: showSharesActions } = useFileActionsShowShares()
const applicationName = ref('')
const resource: Ref<Resource> = ref()
const space: Ref<SpaceResource> = ref()
Expand Down Expand Up @@ -411,21 +423,76 @@ export default defineComponent({
save()
})
const fileActions = computed((): Action<ActionOptions>[] => [
{
name: 'save-file',
disabledTooltip: () => '',
isVisible: () => unref(isEditor),
isDisabled: () => isReadOnly.value || !isDirty.value,
componentType: 'button',
icon: 'save',
id: 'app-save-action',
label: () => 'Save',
handler: () => {
save()
const fileActionsSave = computed<FileAction[]>(() => {
return [
{
name: 'save-file',
disabledTooltip: () => '',
isVisible: () => unref(isEditor),
isDisabled: () => isReadOnly.value || !isDirty.value,
componentType: 'button',
icon: 'save',
id: 'app-save-action',
label: () => 'Save',
handler: () => {
save()
}
}
]
})
const actionOptions = computed<FileActionOptions>(() => {
return {
space: unref(space),
resources: [unref(resource)]
}
])
})
const menuItemsContext = computed(() => {
return [...unref(fileActionsSave)].filter((item) => item.isVisible(unref(actionOptions)))
})
const menuItemsShare = computed(() => {
return [...unref(showSharesActions), ...unref(createQuickLinkActions)].filter((item) =>
item.isVisible(unref(actionOptions))
)
})
const menuItemsActions = computed(() => {
return [...unref(downloadFileActions)].filter((item) => item.isVisible(unref(actionOptions)))
})
const menuItemsSidebar = computed(() => {
return [...unref(showDetailsActions)].filter((item) => item.isVisible(unref(actionOptions)))
})
const dropDownMenuSections = computed(() => {
const sections = []
if (unref(menuItemsContext).length) {
sections.push({
name: 'context',
items: unref(menuItemsContext)
})
}
if (unref(menuItemsShare).length) {
sections.push({
name: 'share',
items: unref(menuItemsShare)
})
}
if (unref(menuItemsActions).length) {
sections.push({
name: 'actions',
items: unref(menuItemsActions)
})
}
if (unref(menuItemsSidebar).length) {
sections.push({
name: 'sidebar',
items: unref(menuItemsSidebar)
})
}
return sections
})
const fileActions = computed((): Action[] => [...unref(fileActionsSave)])
onBeforeRouteLeave((_to, _from, next) => {
if (unref(isDirty)) {
Expand Down Expand Up @@ -472,6 +539,8 @@ export default defineComponent({
return {
...useSideBar(),
dropDownMenuSections,
dropDownActionOptions: actionOptions,
isEditor,
closeApp,
fileActions,
Expand Down
67 changes: 40 additions & 27 deletions packages/web-pkg/src/components/AppTopBar.vue
Original file line number Diff line number Diff line change
Expand Up @@ -18,26 +18,7 @@
/>
</div>
<div class="oc-flex main-actions">
<template v-if="mainActions.length && resource">
<context-action-menu
:menu-sections="[
{
name: 'main-actions',
items: mainActions
.filter((action) => action.isVisible())
.map((action) => {
return { ...action, class: 'oc-p-xs', hideLabel: true }
})
}
]"
:action-options="{
resources: [resource]
}"
appearance="raw-inverse"
variation="brand"
/>
</template>
<template v-if="dropDownActions.length">
<template v-if="dropDownMenuSections.length">
<oc-button
id="oc-openfile-contextmenu-trigger"
v-oc-tooltip="contextMenuLabel"
Expand All @@ -57,11 +38,30 @@
@click.stop.prevent
>
<context-action-menu
:menu-sections="[{ name: 'dropdown-actions', items: dropDownActions }]"
:action-options="{ resources: [resource] }"
:menu-sections="dropDownMenuSections"
:action-options="dropDownActionOptions"
/>
</oc-drop>
</template>
<template v-if="mainActions.length && resource">
<context-action-menu
:menu-sections="[
{
name: 'main-actions',
items: mainActions
.filter((action) => action.isVisible())
.map((action) => {
return { ...action, class: 'oc-p-xs', hideLabel: true }
})
}
]"
:action-options="{
resources: [resource]
}"
appearance="raw-inverse"
variation="brand"
/>
</template>
<oc-button
id="app-top-bar-close"
v-oc-tooltip="closeButtonLabel"
Expand All @@ -80,9 +80,15 @@

<script lang="ts">
import { computed, defineComponent, PropType, unref } from 'vue'
import ContextActionMenu from './ContextActions/ContextActionMenu.vue'
import ContextActionMenu, { MenuSection } from './ContextActions/ContextActionMenu.vue'
import { useGettext } from 'vue3-gettext'
import { Action, useFolderLink, useGetMatchingSpace, useResourcesStore } from '../composables'
import {
Action,
FileActionOptions,
useFolderLink,
useGetMatchingSpace,
useResourcesStore
} from '../composables'
import ResourceListItem from './FilesList/ResourceListItem.vue'
import { Resource, isPublicSpaceResource, isShareSpaceResource } from '@ownclouders/web-client'
Expand All @@ -93,9 +99,16 @@ export default defineComponent({
ResourceListItem
},
props: {
dropDownActions: {
type: Array as PropType<Action[]>,
default: (): Action[] => []
dropDownMenuSections: {
type: Array as PropType<MenuSection[]>,
default: (): MenuSection[] => []
},
dropDownActionOptions: {
type: Object as PropType<FileActionOptions>,
default: (): FileActionOptions => ({
space: null,
resources: []
})
},
mainActions: {
type: Array as PropType<Action[]>,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import { defineComponent, PropType } from 'vue'
import ActionMenuItem from './ActionMenuItem.vue'
import { Action, ActionOptions } from '../../composables'
type MenuSection = {
export type MenuSection = {
name: string
items: Action[]
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import { isLocationTrashActive } from '../../../router'
import { eventBus } from '../../../services/eventBus'
import { SideBarEventTopics } from '../../sideBar'
import { computed, unref } from 'vue'
import { computed } from 'vue'
import { useGettext } from 'vue3-gettext'
import { useIsFilesAppActive } from '../helpers'
import { useRouter } from '../../router'
import { FileAction } from '../types'
import { useResourcesStore } from '../../piniaStores'
Expand All @@ -13,7 +12,6 @@ export const useFileActionsShowDetails = () => {
const resourcesStore = useResourcesStore()

const { $gettext } = useGettext()
const isFilesAppActive = useIsFilesAppActive()

const actions = computed((): FileAction[] => [
{
Expand All @@ -25,11 +23,6 @@ export const useFileActionsShowDetails = () => {
// we don't have details in the trashbin, yet.
// remove trashbin route rule once we have them.
isVisible: ({ resources }) => {
// sidebar is currently only available inside files app
if (!unref(isFilesAppActive)) {
return false
}

if (isLocationTrashActive(router, 'files-trash-generic')) {
return false
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { isLocationTrashActive } from '../../../router'
import { ShareResource } from '@ownclouders/web-client'
import { eventBus } from '../../../services'
import { SideBarEventTopics } from '../../sideBar'
import { computed, unref } from 'vue'
import { computed } from 'vue'
import { useGettext } from 'vue3-gettext'
import { useIsFilesAppActive } from '../helpers'
import { useRouter } from '../../router'
Expand All @@ -29,11 +29,6 @@ export const useFileActionsShowShares = () => {
label: () => $gettext('Share'),
handler,
isVisible: ({ space, resources }) => {
// sidebar is currently only available inside files app
if (!unref(isFilesAppActive)) {
return false
}

if (isLocationTrashActive(router, 'files-trash-generic')) {
return false
}
Expand Down
Loading

0 comments on commit bbf67bb

Please sign in to comment.