Skip to content
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
4 changes: 2 additions & 2 deletions packages/design-system/src/components/OcDrop/OcMobileDrop.vue
Original file line number Diff line number Diff line change
Expand Up @@ -158,11 +158,11 @@ onMounted(() => {
return
}

document.querySelector(toggle).addEventListener('click', show)
document.querySelector(toggle)?.addEventListener('click', show)
})

onBeforeUnmount(() => {
document.querySelector(toggle).removeEventListener('click', show)
document.querySelector(toggle)?.removeEventListener('click', show)
if (unref(drawer)) {
closeDrawer(unref(drawer).id)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
<template>
<div class="fixed flex flex-col items-end bottom-[20px] right-[20px]">
<div
class="fixed flex flex-col items-end bottom-[20px] right-[20px] z-[calc(var(--z-index-modal)-1)]"
>
<template v-if="expanded">
<oc-button
v-for="item in items"
Expand All @@ -16,6 +18,7 @@
</oc-button>
</template>
<oc-button
:id="buttonId"
class="rounded-full size-14"
appearance="filled"
color-role="primary"
Expand All @@ -34,6 +37,11 @@ import { RouteLocationRaw } from 'vue-router'
import { useGettext } from 'vue3-gettext'

export interface Props {
/**
* @docs The id of the primary action button.
* @default ''
*/
buttonId?: string
/**
* @docs The aria label of the primary action button.
* @default 'Open actions menu'
Expand Down Expand Up @@ -64,8 +72,9 @@ export interface Props {
}

const {
mode = 'menu',
buttonId = '',
ariaLabel = '',
mode = 'menu',
items = [],
handler = null,
to = null
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<div
id="admin-settings-app-bar"
ref="appBarRef"
class="py-2 px-4 bg-role-surface top-0 z-20"
class="pb-2 px-4 bg-role-surface top-0 z-20"
:class="{ sticky: isSticky }"
>
<div class="flex justify-between items-center h-13">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ exports[`Spaces view > loading states > should render spaces list after loading
<main class="flex app-content size-full rounded-l-xl">
<div class="admin-settings-wrapper flex-1 flex size-full flex-nowrap sm:flex-wrap">
<div id="admin-settings-view-wrapper" class="flex-1 size-full flex-wrap overflow-y-auto">
<div id="admin-settings-app-bar" class="py-2 px-4 bg-role-surface top-0 z-20 sticky">
<div id="admin-settings-app-bar" class="pb-2 px-4 bg-role-surface top-0 z-20 sticky">
<div class="flex justify-between items-center h-13">
<oc-breadcrumb-stub items="[object Object]" contextmenupadding="medium" id="admin-settings-breadcrumb" maxwidth="-1" mobilebreakpoint="sm" showcontextactions="false" truncationoffset="2" variation="default"></oc-breadcrumb-stub>
<!--v-if-->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ exports[`Users view > list view > renders initially warning if filters are manda
<main class="flex app-content size-full rounded-l-xl">
<div class="admin-settings-wrapper flex-1 flex size-full flex-nowrap sm:flex-wrap">
<div id="admin-settings-view-wrapper" class="flex-1 size-full flex-wrap overflow-y-auto">
<div id="admin-settings-app-bar" class="py-2 px-4 bg-role-surface top-0 z-20 sticky">
<div id="admin-settings-app-bar" class="pb-2 px-4 bg-role-surface top-0 z-20 sticky">
<div class="flex justify-between items-center h-13">
<oc-breadcrumb-stub items="[object Object]" contextmenupadding="medium" id="admin-settings-breadcrumb" maxwidth="-1" mobilebreakpoint="sm" showcontextactions="false" truncationoffset="2" variation="default"></oc-breadcrumb-stub>
<!--v-if-->
Expand Down Expand Up @@ -65,7 +65,7 @@ exports[`Users view > list view > renders list initially 1`] = `
<main class="flex app-content size-full rounded-l-xl">
<div class="admin-settings-wrapper flex-1 flex size-full flex-nowrap sm:flex-wrap">
<div id="admin-settings-view-wrapper" class="flex-1 size-full flex-wrap overflow-y-auto">
<div id="admin-settings-app-bar" class="py-2 px-4 bg-role-surface top-0 z-20 sticky">
<div id="admin-settings-app-bar" class="pb-2 px-4 bg-role-surface top-0 z-20 sticky">
<div class="flex justify-between items-center h-13">
<oc-breadcrumb-stub items="[object Object]" contextmenupadding="medium" id="admin-settings-breadcrumb" maxwidth="-1" mobilebreakpoint="sm" showcontextactions="false" truncationoffset="2" variation="default"></oc-breadcrumb-stub>
<!--v-if-->
Expand Down
225 changes: 4 additions & 221 deletions packages/web-app-files/src/components/AppBar/CreateAndUpload.vue
Original file line number Diff line number Diff line change
@@ -1,132 +1,6 @@
<template>
<div v-if="showActions" class="create-and-upload-actions inline-flex mr-2 gap-2">
<div v-oc-tooltip="newButtonTooltip">
<oc-button
id="create-or-upload-menu-btn"
key="create-or-upload-menu-btn-enabled"
v-oc-tooltip="limitedScreenSpace ? $gettext('Create or Upload') : ''"
:aria-label="newButtonAriaLabel"
appearance="filled"
:disabled="!canUpload"
>
<oc-icon name="add" />
<span v-if="!limitedScreenSpace" v-text="$gettext('Create or Upload')" />
</oc-button>
</div>
<oc-drop
:title="$gettext('Create or Upload')"
drop-id="create-or-upload-drop"
toggle="#create-or-upload-menu-btn"
class="w-auto min-w-3xs"
mode="click"
close-on-click
padding-size="small"
@show-drop="showDrop"
>
<oc-list
id="create-list"
:class="areFileExtensionsShown ? 'sm:min-w-xs' : null"
class="py-2 sm:first:pt-0 sm:last:pb-0"
>
<li>
<oc-button
id="new-folder-btn"
class="w-full"
justify-content="left"
appearance="raw"
@click="createNewFolderAction"
>
<resource-icon
:resource="folderIconResource"
size="medium"
class="[&_svg]:h-5.5! sm:[&_svg]:h-full"
/>
<span v-text="$gettext('Folder')" />
</oc-button>
</li>
</oc-list>
<oc-list v-if="canUpload" id="upload-list" class="py-2 sm:first:pt-0 sm:last:pb-0 border-t">
<li>
<resource-upload btn-class="w-full" :btn-label="$gettext('Files Upload')" />
</li>
<li>
<resource-upload
btn-class="w-full"
:btn-label="$gettext('Folder Upload')"
:is-folder="true"
/>
</li>
</oc-list>
<oc-list
v-if="extensionActions.length"
id="extension-list"
class="py-2 sm:first:pt-0 sm:last:pb-0 border-t"
>
<li
v-for="(action, key) in extensionActions"
:key="`${key}-${actionKeySuffix}`"
v-oc-tooltip="
isActionDisabled(action) && action.disabledTooltip ? action.disabledTooltip() : null
"
>
<oc-button
class="w-full"
:class="action.class"
appearance="raw"
justify-content="left"
:disabled="isActionDisabled(action)"
@click="() => action.handler()"
>
<oc-icon :name="getActionIcon(action)" fill-type="line" />
<span v-text="action.label()"
/></oc-button>
</li>
</oc-list>
<oc-list
v-for="(group, groupIndex) in createFileActionsGroups"
:key="`file-creation-group-${groupIndex}`"
class="py-2 sm:first:pt-0 sm:last:pb-0 border-t"
>
<li
v-for="(fileAction, fileActionIndex) in group"
:key="`file-creation-item-${groupIndex}-${fileActionIndex}`"
>
<oc-button
appearance="raw"
class="w-full"
justify-content="left"
:class="['new-file-btn-' + fileAction.ext]"
@click="() => fileAction.handler()"
>
<resource-icon
:resource="getIconResource(fileAction)"
size="medium"
class="[&_svg]:h-5.5! sm:[&_svg]:h-full"
/>
<span>{{ fileAction.label() }}</span>
<span v-if="areFileExtensionsShown && fileAction.ext" class="ml-auto text-sm">
{{ fileAction.ext }}
</span>
</oc-button>
</li>
</oc-list>
<oc-list class="py-2 sm:first:pt-0 sm:last:pb-0 border-t">
<li>
<oc-button
id="new-shortcut-btn"
class="w-full"
justify-content="left"
appearance="raw"
@click="createNewShortcutAction"
>
<oc-icon name="external-link" size="medium" />
<span v-text="$gettext('Shortcut')" />
<span v-if="areFileExtensionsShown" class="ml-auto text-sm" v-text="'url'" />
</oc-button>
</li>
</oc-list>
</oc-drop>
<div v-if="showPasteHereButton" id="clipboard-btns" class="oc-button-group">
<div v-if="showActions" class="create-and-upload-actions inline-flex gap-2">
<div v-if="showPasteHereButton" id="clipboard-btns" class="oc-button-group mr-2">
<oc-button
v-oc-tooltip="pasteHereButtonTooltip"
:disabled="isPasteHereButtonDisabled"
Expand All @@ -153,33 +27,24 @@
import { useEventListener } from '@vueuse/core'
import {
ClipboardActions,
FileAction,
isLocationPublicActive,
useClipboardStore,
useFileActionsCreateNewShortcut,
useMessages,
useResourcesStore,
useRoute,
useSpacesStore,
useUserStore,
useActiveLocation,
useFileActionsCreateNewFile,
useFileActionsCreateNewFolder,
useFileActionsPaste,
useClientService
} from '@opencloud-eu/web-pkg'

import { computed, onMounted, onBeforeUnmount, unref, watch, ref } from 'vue'
import { Resource, SpaceResource, isPublicSpaceResource } from '@opencloud-eu/web-client'
import { computed, onMounted, onBeforeUnmount, unref, watch } from 'vue'
import { SpaceResource, isPublicSpaceResource } from '@opencloud-eu/web-client'
import { useService, useUpload, UppyService, UploadResult } from '@opencloud-eu/web-pkg'
import { HandleUpload } from '../../HandleUpload'
import { useGettext } from 'vue3-gettext'
import { useExtensionRegistry } from '@opencloud-eu/web-pkg'
import { Action, ResourceIcon } from '@opencloud-eu/web-pkg'
import { v4 as uuidV4 } from 'uuid'
import { storeToRefs } from 'pinia'
import { uploadMenuExtensionPoint } from '../../extensionPoints'
import ResourceUpload from './Upload/ResourceUpload.vue'

const { space, limitedScreenSpace = false } = defineProps<{
space: SpaceResource
Expand All @@ -206,8 +71,6 @@ const { currentFolder } = storeToRefs(resourcesStore)

const isPublicLocation = useActiveLocation(isLocationPublicActive, 'files-public-link')

const areFileExtensionsShown = computed(() => unref(resourcesStore.areFileExtensionsShown))

const computedSpace = computed(() => space)

useUpload({ uppyService })
Expand All @@ -233,58 +96,10 @@ const pasteFileAction = () => {
return unref(pasteFileActions)[0].handler({ space: unref(computedSpace) })
}

const { actions: createNewFolder } = useFileActionsCreateNewFolder({ space: computedSpace })
const createNewFolderAction = () => {
return unref(createNewFolder)[0].handler()
}

const { actions: createNewShortcut } = useFileActionsCreateNewShortcut({ space: computedSpace })
const createNewShortcutAction = () => {
return unref(createNewShortcut)[0].handler()
}

const { actions: createNewFileActions } = useFileActionsCreateNewFile({ space: computedSpace })

const createFileActionsGroups = computed(() => {
const result: FileAction[][] = []
const externalFileActions = unref(createNewFileActions).filter(({ isExternal }) => isExternal)
if (externalFileActions.length) {
result.push(externalFileActions)
}
const appFileActions = unref(createNewFileActions).filter(({ isExternal }) => !isExternal)
if (appFileActions.length) {
result.push(appFileActions)
}
return result
})

const extensionRegistry = useExtensionRegistry()
const extensionActions = computed(() => {
return [
...extensionRegistry.requestExtensions(uploadMenuExtensionPoint).map((e) => e.action)
].filter((e) => e.isVisible())
})

const canUpload = computed(() => {
return unref(currentFolder)?.canUpload({ user: userStore.user })
})

const actionKeySuffix = ref(uuidV4())
const showDrop = () => {
// force actions to be re-rendered when the drop is being opened
actionKeySuffix.value = uuidV4()
}

const isActionDisabled = (action: Action) => {
return action.isDisabled ? action.isDisabled() : false
}

const getActionIcon = (action: Action) => {
return typeof action.icon === 'function'
? action.icon({ space: unref(computedSpace) })
: action.icon
}

useEventListener(document, 'paste', (event: ClipboardEvent) => {
// Ignore file in clipboard if there are already files from OpenCloud in the clipboard
if (unref(clipboardResources).length || !unref(canUpload)) {
Expand Down Expand Up @@ -394,43 +209,11 @@ watch(
{ immediate: true }
)

const getIconResource = (fileHandler: FileAction) => {
return { type: 'file', extension: fileHandler.ext } as Resource
}

const showPasteHereButton = computed(() => {
return unref(clipboardResources) && unref(clipboardResources).length !== 0
})

const showActions = computed(() => {
return unref(canUpload) || !unref(isPublicLocation)
})

const newButtonTooltip = computed(() => {
if (!unref(canUpload)) {
return $gettext('You have no permission to create or upload files')
}
return null
})
const newButtonAriaLabel = computed(() => {
if (unref(newButtonTooltip)) {
return unref(newButtonTooltip)
}

return $gettext('Create or upload')
})

const folderIconResource = computed(() => {
return { isFolder: true, extension: '' } as Resource
})
</script>
<style>
@reference '@opencloud-eu/design-system/tailwind';

@layer utilities {
.create-and-upload-actions .oc-drop .oc-icon svg {
/* reset the resource icon height because the ResourceIcon component messes with it */
@apply h-5.5;
}
}x
</style>
Loading