-
-
- {{ title }}
+
-
- {{ message }}
+
+
+
+
+
+
+
diff --git a/packages/web-app-files/src/components/FilesList/ListInfo.vue b/packages/web-app-files/src/components/FilesList/ListInfo.vue
index 3138edc27e9..49df2730e06 100644
--- a/packages/web-app-files/src/components/FilesList/ListInfo.vue
+++ b/packages/web-app-files/src/components/FilesList/ListInfo.vue
@@ -71,10 +71,11 @@ export default defineComponent({
}
)
const itemSize = formatFileSize(this.size, this.$language.current)
+ const size = parseFloat(this.size?.toString())
let translated
if (this.showSpaces) {
translated =
- this.size > 0
+ size > 0
? this.$ngettext(
'%{ itemsCount } item with %{ itemSize } in total (%{ filesStr}, %{foldersStr}, %{spacesStr})',
'%{ itemsCount } items with %{ itemSize } in total (%{ filesStr}, %{foldersStr}, %{spacesStr})',
@@ -87,7 +88,7 @@ export default defineComponent({
)
} else {
translated =
- this.size > 0
+ size > 0
? this.$ngettext(
'%{ itemsCount } item with %{ itemSize } in total (%{ filesStr}, %{foldersStr})',
'%{ itemsCount } items with %{ itemSize } in total (%{ filesStr}, %{foldersStr})',
diff --git a/packages/web-app-files/src/components/FilesList/ResourceTable.vue b/packages/web-app-files/src/components/FilesList/ResourceTable.vue
index 3c68ca2e3e4..5b0657f9e17 100644
--- a/packages/web-app-files/src/components/FilesList/ResourceTable.vue
+++ b/packages/web-app-files/src/components/FilesList/ResourceTable.vue
@@ -17,6 +17,7 @@
:sort-by="sortBy"
:sort-dir="sortDir"
:lazy="lazyLoading"
+ :grouping-settings="groupingSettings"
padding-x="medium"
@highlight="fileClicked"
@row-mounted="rowMounted"
@@ -67,6 +68,9 @@
:is-resource-clickable="isResourceClickable(item.id)"
:folder-link="folderLink(item)"
:parent-folder-link="parentFolderLink(item)"
+ :parent-folder-link-icon-additional-attributes="
+ parentFolderLinkIconAdditionalAttributes(item)
+ "
:class="{ 'resource-table-resource-cut': isResourceCut(item) }"
@click="emitFileClick(item)"
/>
@@ -245,10 +249,13 @@ import {
} from 'web-app-files/src/router'
import get from 'lodash-es/get'
+// ODS component import is necessary here for CERN to overwrite OcTable
+import OcTable from 'design-system/src/components/OcTable/OcTable.vue'
+
const TAGS_MINIMUM_SCREEN_WIDTH = 850
export default defineComponent({
- components: { ContextMenuQuickAction },
+ components: { ContextMenuQuickAction, OcTable },
props: {
/**
* Resources to be displayed in the table.
@@ -420,6 +427,14 @@ export default defineComponent({
type: Object as PropType
,
required: false,
default: null
+ },
+ /**
+ * This is only relevant for CERN and can be ignored in any other cases.
+ */
+ groupingSettings: {
+ type: Object,
+ required: false,
+ default: null
}
},
emits: [
@@ -562,6 +577,15 @@ export default defineComponent({
wrap: 'nowrap',
width: 'shrink'
},
+ {
+ name: 'status',
+ prop: 'disabled',
+ title: this.$gettext('Status'),
+ type: 'slot',
+ alignH: 'right',
+ wrap: 'nowrap',
+ width: 'shrink'
+ },
this.hasTags
? {
name: 'tags',
@@ -753,6 +777,21 @@ export default defineComponent({
resource: file
})
},
+ parentFolderLinkIconAdditionalAttributes(file) {
+ // Identify if resource is project space or is part of a project space and the resource is located in its root
+ if (
+ isProjectSpaceResource(file) ||
+ (isProjectSpaceResource(this.getInternalSpace(file.storageId) || ({} as Resource)) &&
+ file.path.split('/').length === 2)
+ ) {
+ return {
+ name: 'layout-grid',
+ 'fill-type': 'fill'
+ }
+ }
+
+ return {}
+ },
fileDragged(file) {
this.addSelectedResource(file)
},
diff --git a/packages/web-app-files/src/components/Search/List.vue b/packages/web-app-files/src/components/Search/List.vue
index 6e2dcaeaa70..3dedb02a5c2 100644
--- a/packages/web-app-files/src/components/Search/List.vue
+++ b/packages/web-app-files/src/components/Search/List.vue
@@ -144,6 +144,12 @@ import { eventBus, useCapabilityFilesFullTextSearch } from 'web-pkg'
import ItemFilter from 'web-pkg/src/components/ItemFilter.vue'
import { isLocationCommonActive } from 'web-app-files/src/router'
import ItemFilterToggle from 'web-pkg/src/components/ItemFilterToggle.vue'
+import { useKeyboardActions } from 'web-pkg/src/composables/keyboardActions'
+import {
+ useKeyboardTableNavigation,
+ useKeyboardTableMouseActions,
+ useKeyboardTableActions
+} from 'web-app-files/src/composables/keyboardActions'
const visibilityObserver = new VisibilityObserver()
@@ -190,6 +196,16 @@ export default defineComponent({
const fullTextSearchEnabled = useCapabilityFilesFullTextSearch()
const searchTermQuery = useRouteQuery('term')
+ const scopeQuery = useRouteQuery('scope')
+ const doUseScope = useRouteQuery('useScope')
+
+ const resourcesView = useResourcesViewDefaults()
+
+ const keyActions = useKeyboardActions('files-view')
+ useKeyboardTableNavigation(keyActions, resourcesView.paginatedResources)
+ useKeyboardTableMouseActions(keyActions)
+ useKeyboardTableActions(keyActions)
+
const searchTerm = computed(() => {
return queryItemAsString(unref(searchTermQuery))
})
@@ -234,6 +250,9 @@ export default defineComponent({
if (fullTextQuery) {
term = `+Content:"${unref(searchTerm)}"`
}
+ if (unref(scopeQuery) && unref(doUseScope) === 'true') {
+ term += ` scope:${unref(scopeQuery)}`
+ }
const tagsQuery = queryItemAsString(unref(tagParam))
if (tagsQuery) {
@@ -275,11 +294,10 @@ export default defineComponent({
watch(
() => unref(route).query,
(newVal, oldVal) => {
- const filters = ['q_fullText', 'q_tags']
+ const filters = ['q_fullText', 'q_tags', 'useScope']
const isChange =
newVal?.term !== oldVal?.term ||
filters.some((f) => newVal[f] ?? undefined !== oldVal[f] ?? undefined)
-
if (isChange && isLocationCommonActive(router, 'files-common-search')) {
emit('search', buildSearchTerm(true))
}
@@ -289,7 +307,7 @@ export default defineComponent({
return {
...useFileActions({ store }),
- ...useResourcesViewDefaults(),
+ ...resourcesView,
loadAvailableTagsTask,
fileListHeaderY,
fullTextSearchEnabled,
diff --git a/packages/web-app-files/src/components/Search/Preview.vue b/packages/web-app-files/src/components/Search/Preview.vue
index c1def68a98d..7af8a8b96c2 100644
--- a/packages/web-app-files/src/components/Search/Preview.vue
+++ b/packages/web-app-files/src/components/Search/Preview.vue
@@ -12,6 +12,7 @@
:is-path-displayed="true"
:is-resource-clickable="false"
:parent-folder-link="parentFolderLink"
+ :parent-folder-link-icon-additional-attributes="parentFolderLinkIconAdditionalAttributes"
:parent-folder-name-default="defaultParentFolderName"
:is-thumbnail-displayed="displayThumbnails"
@parent-folder-clicked="parentFolderClicked"
@@ -29,7 +30,7 @@ import { computed, defineComponent, ref, unref } from 'vue'
import { mapGetters } from 'vuex'
import { createLocationShares, createLocationSpaces } from '../../router'
import { basename, dirname } from 'path'
-import { useCapabilityShareJailEnabled } from 'web-pkg/src/composables'
+import { useCapabilityShareJailEnabled, useGetMatchingSpace } from 'web-pkg/src/composables'
import { buildShareSpaceResource, isProjectSpaceResource, Resource } from 'web-client/src/helpers'
import { configurationManager } from 'web-pkg/src/configuration'
import { eventBus } from 'web-pkg/src/services/eventBus'
@@ -53,6 +54,7 @@ export default defineComponent({
}
},
setup(props) {
+ const { getInternalSpace } = useGetMatchingSpace()
const previewData = ref()
const resource = computed((): Resource => {
return {
@@ -65,6 +67,7 @@ export default defineComponent({
})
return {
...useFileActions(),
+ getInternalSpace,
hasShareJail: useCapabilityShareJailEnabled(),
previewData,
resource
@@ -142,6 +145,24 @@ export default defineComponent({
return createLocationSpaces('files-spaces-projects')
}
return this.createFolderLink(dirname(this.resource.path), this.resource.parentFolderId)
+ },
+
+ parentFolderLinkIconAdditionalAttributes() {
+ // Identify if resource is project space or is part of a project space and the resource is located in its root
+ if (
+ isProjectSpaceResource(this.resource) ||
+ (isProjectSpaceResource(
+ this.getInternalSpace(this.resource.storageId) || ({} as Resource)
+ ) &&
+ this.resource.path.split('/').length === 2)
+ ) {
+ return {
+ name: 'layout-grid',
+ 'fill-type': 'fill'
+ }
+ }
+
+ return {}
}
},
mounted() {
diff --git a/packages/web-app-files/src/components/Shares/SharedWithMeSection.vue b/packages/web-app-files/src/components/Shares/SharedWithMeSection.vue
index 9a34765c994..12884962815 100644
--- a/packages/web-app-files/src/components/Shares/SharedWithMeSection.vue
+++ b/packages/web-app-files/src/components/Shares/SharedWithMeSection.vue
@@ -29,6 +29,7 @@
:header-position="fileListHeaderY"
:sort-by="sortBy"
:sort-dir="sortDir"
+ :grouping-settings="groupingSettings"
@file-click="triggerDefaultAction"
@row-mounted="rowMounted"
@sort="sortHandler"
@@ -181,6 +182,14 @@ export default defineComponent({
fileListHeaderY: {
type: Number,
default: 0
+ },
+ /**
+ * This is only relevant for CERN and can be ignored in any other cases.
+ */
+ groupingSettings: {
+ type: Object,
+ required: false,
+ default: null
}
},
setup() {
diff --git a/packages/web-app-files/src/components/SideBar/Details/FileDetails.vue b/packages/web-app-files/src/components/SideBar/Details/FileDetails.vue
index c687b592097..6c09803c07b 100644
--- a/packages/web-app-files/src/components/SideBar/Details/FileDetails.vue
+++ b/packages/web-app-files/src/components/SideBar/Details/FileDetails.vue
@@ -485,8 +485,9 @@ export default defineComponent({
eventBus.publish(SideBarEventTopics.setActivePanel, 'versions')
},
getTagLink(tag) {
+ const currentTerm = unref(this.$router.currentRoute).query?.term
return createLocationCommon('files-common-search', {
- query: { term: `Tags:"${tag}"`, provider: 'files.sdk' }
+ query: { provider: 'files.sdk', q_tags: tag, ...(currentTerm && { term: currentTerm }) }
})
},
getTagComponentAttrs(tag) {
diff --git a/packages/web-app-files/src/components/SideBar/Shares/Collaborators/EditDropdown.vue b/packages/web-app-files/src/components/SideBar/Shares/Collaborators/EditDropdown.vue
index f2fe4eab03c..83ed3e37325 100644
--- a/packages/web-app-files/src/components/SideBar/Shares/Collaborators/EditDropdown.vue
+++ b/packages/web-app-files/src/components/SideBar/Shares/Collaborators/EditDropdown.vue
@@ -58,7 +58,7 @@
@click="option.method"
>
-
+
diff --git a/packages/web-app-files/src/components/SideBar/Shares/Collaborators/InviteCollaborator/InviteCollaboratorForm.vue b/packages/web-app-files/src/components/SideBar/Shares/Collaborators/InviteCollaborator/InviteCollaboratorForm.vue
index 0d19f0f2b31..e3fe4963125 100644
--- a/packages/web-app-files/src/components/SideBar/Shares/Collaborators/InviteCollaborator/InviteCollaboratorForm.vue
+++ b/packages/web-app-files/src/components/SideBar/Shares/Collaborators/InviteCollaborator/InviteCollaboratorForm.vue
@@ -46,19 +46,15 @@
:share-types="selectedCollaborators.map((c) => c.value.shareType)"
@option-change="collaboratorExpiryChanged"
/>
-
-
-
-
@@ -93,7 +89,7 @@ import {
useStore
} from 'web-pkg/src/composables'
-import { defineComponent, inject } from 'vue'
+import { defineComponent, inject, ref, unref, watch } from 'vue'
import { Resource } from 'web-client'
import { useShares } from 'web-app-files/src/composables'
@@ -126,6 +122,22 @@ export default defineComponent({
setup() {
const store = useStore()
const clientService = useClientService()
+ const saving = ref(false)
+ const savingDelayed = ref(false)
+
+ watch(saving, (newValue) => {
+ if (!newValue) {
+ savingDelayed.value = false
+ return
+ }
+ setTimeout(() => {
+ if (!unref(saving)) {
+ savingDelayed.value = false
+ return
+ }
+ savingDelayed.value = true
+ }, 700)
+ })
return {
resource: inject('resource'),
hasResharing: useCapabilityFilesSharingResharing(store),
@@ -133,6 +145,8 @@ export default defineComponent({
hasShareJail: useCapabilityShareJailEnabled(store),
hasRoleCustomPermissions: useCapabilityFilesSharingAllowCustomPermissions(store),
clientService,
+ saving,
+ savingDelayed,
...useShares()
}
},
@@ -145,7 +159,6 @@ export default defineComponent({
selectedCollaborators: [],
selectedRole: null,
customPermissions: null,
- saving: false,
expirationDate: null,
searchQuery: ''
}
@@ -187,7 +200,7 @@ export default defineComponent({
},
methods: {
- ...mapActions(['showMessage']),
+ ...mapActions(['showMessage', 'showErrorMessage']),
...mapActions('Files', ['addShare']),
...mapActions('runtime/spaces', ['addSpaceMember']),
@@ -351,11 +364,11 @@ export default defineComponent({
this.showMessage({ title: this.$gettext('Share was added successfully') })
}
errors.forEach((e) => {
- this.showMessage({
- title: this.$gettext('Failed to add share for %{displayName}', {
+ this.showErrorMessage({
+ title: this.$gettext('Failed to add share for "%{displayName}"', {
displayName: e.displayName
}),
- status: 'danger'
+ error: e.error
})
})
@@ -379,4 +392,8 @@ export default defineComponent({
.role-selection-dropdown {
max-width: 150px;
}
+#new-collaborators-form-create-button {
+ padding-left: 30px;
+ padding-right: 30px;
+}
diff --git a/packages/web-app-files/src/components/SideBar/Shares/Collaborators/ListItem.vue b/packages/web-app-files/src/components/SideBar/Shares/Collaborators/ListItem.vue
index 1e21f9c10dc..ab679a5b471 100644
--- a/packages/web-app-files/src/components/SideBar/Shares/Collaborators/ListItem.vue
+++ b/packages/web-app-files/src/components/SideBar/Shares/Collaborators/ListItem.vue
@@ -373,7 +373,7 @@ export default defineComponent({
}
},
methods: {
- ...mapActions(['showMessage']),
+ ...mapActions(['showMessage', 'showErrorMessage']),
...mapActions('Files', ['changeShare']),
...mapActions('runtime/spaces', ['changeSpaceMember']),
@@ -394,9 +394,9 @@ export default defineComponent({
this.saveShareChanges({ role, permissions, expirationDate })
} catch (e) {
console.error(e)
- this.showMessage({
+ this.showErrorMessage({
title: this.$gettext('Failed to apply new permissions'),
- status: 'danger'
+ error: e
})
}
},
@@ -408,9 +408,9 @@ export default defineComponent({
this.saveShareChanges({ role, permissions, expirationDate })
} catch (e) {
console.error(e)
- this.showMessage({
+ this.showErrorMessage({
title: this.$gettext('Failed to apply expiration date'),
- status: 'danger'
+ error: e
})
}
},
@@ -437,9 +437,9 @@ export default defineComponent({
this.showMessage({ title: this.$gettext('Share successfully changed') })
} catch (e) {
console.error(e)
- this.showMessage({
+ this.showErrorMessage({
title: this.$gettext('Error while editing the share.'),
- status: 'danger'
+ error: e
})
}
}
diff --git a/packages/web-app-files/src/components/SideBar/Shares/FileLinks.vue b/packages/web-app-files/src/components/SideBar/Shares/FileLinks.vue
index 3f8d7c5cc80..0adad067537 100644
--- a/packages/web-app-files/src/components/SideBar/Shares/FileLinks.vue
+++ b/packages/web-app-files/src/components/SideBar/Shares/FileLinks.vue
@@ -346,7 +346,7 @@ export default defineComponent({
},
methods: {
...mapActions('Files', ['addLink', 'updateLink', 'removeLink']),
- ...mapActions(['showMessage', 'createModal', 'hideModal']),
+ ...mapActions(['showMessage', 'showErrorMessage', 'createModal', 'hideModal']),
...mapMutations('Files', ['REMOVE_FILES']),
toggleLinkListCollapsed() {
@@ -479,9 +479,9 @@ export default defineComponent({
} catch (e) {
onError(e)
console.error(e)
- this.showMessage({
+ this.showErrorMessage({
title: this.$gettext('Failed to create link'),
- status: 'danger'
+ error: e
})
return
}
@@ -501,9 +501,9 @@ export default defineComponent({
} catch (e) {
onError(e)
console.error(e)
- this.showMessage({
+ this.showErrorMessage({
title: this.$gettext('Failed to update link'),
- status: 'danger'
+ error: e
})
return
}
@@ -559,9 +559,9 @@ export default defineComponent({
}
} catch (e) {
console.error(e)
- this.showMessage({
+ this.showErrorMessage({
title: this.$gettext('Failed to delete link'),
- status: 'danger'
+ error: e
})
}
},
diff --git a/packages/web-app-files/src/components/SideBar/Shares/FileShares.vue b/packages/web-app-files/src/components/SideBar/Shares/FileShares.vue
index 3073dcd140f..b344036b24a 100644
--- a/packages/web-app-files/src/components/SideBar/Shares/FileShares.vue
+++ b/packages/web-app-files/src/components/SideBar/Shares/FileShares.vue
@@ -272,7 +272,7 @@ export default defineComponent({
},
methods: {
...mapActions('Files', ['deleteShare', 'addShare']),
- ...mapActions(['createModal', 'hideModal', 'showMessage']),
+ ...mapActions(['createModal', 'hideModal', 'showMessage', 'showErrorMessage']),
...mapMutations('Files', ['REMOVE_FILES']),
getDeniedShare(collaborator: Share): Share {
@@ -376,9 +376,9 @@ export default defineComponent({
})
} catch (e) {
console.error(e)
- this.showMessage({
+ this.showErrorMessage({
title: this.$gettext('Failed to deny access'),
- status: 'danger'
+ error: e
})
}
} else {
@@ -398,9 +398,9 @@ export default defineComponent({
})
} catch (e) {
console.error(e)
- this.showMessage({
+ this.showErrorMessage({
title: this.$gettext('Failed to grant access'),
- status: 'danger'
+ error: e
})
}
}
@@ -449,9 +449,9 @@ export default defineComponent({
}
} catch (error) {
console.error(error)
- this.showMessage({
+ this.showErrorMessage({
title: this.$gettext('Failed to remove share'),
- status: 'danger'
+ error
})
}
},
diff --git a/packages/web-app-files/src/components/SideBar/Shares/Links/DetailsAndEdit.vue b/packages/web-app-files/src/components/SideBar/Shares/Links/DetailsAndEdit.vue
index a7aa31a35e8..22567c7e843 100644
--- a/packages/web-app-files/src/components/SideBar/Shares/Links/DetailsAndEdit.vue
+++ b/packages/web-app-files/src/components/SideBar/Shares/Links/DetailsAndEdit.vue
@@ -7,7 +7,10 @@
class="edit-public-link-role-dropdown-toggle oc-text-left"
gap-size="none"
>
-
+
{{ formatVersionDate(item) }}{{ formatVersionDateRelative(item) }}
-
{{
@@ -61,6 +62,7 @@ import { defineComponent, inject, ref, Ref } from 'vue'
import { isShareSpaceResource, Resource, SpaceResource } from 'web-client/src/helpers'
import { SharePermissions } from 'web-client/src/helpers/share'
import { useDownloadFile } from 'web-pkg/src/composables/download/useDownloadFile'
+import { formatDateFromJSDate } from 'web-pkg/src/helpers'
export default defineComponent({
name: 'FileVersions',
@@ -136,12 +138,18 @@ export default defineComponent({
const version = this.currentVersionId(file)
return this.downloadFile(this.resource, version)
},
- formatVersionDate(file) {
+ formatVersionDateRelative(file) {
return formatRelativeDateFromHTTP(
file.fileInfo[DavProperty.LastModifiedDate],
this.$language.current
)
},
+ formatVersionDate(file) {
+ return formatDateFromJSDate(
+ new Date(file.fileInfo[DavProperty.LastModifiedDate]),
+ this.$language.current
+ )
+ },
formatVersionFileSize(file) {
return formatFileSize(file.fileInfo[DavProperty.ContentLength], this.$language.current)
}
diff --git a/packages/web-app-files/src/components/Spaces/SpaceHeader.vue b/packages/web-app-files/src/components/Spaces/SpaceHeader.vue
index 737d0b2d85b..0be2c3a62b1 100644
--- a/packages/web-app-files/src/components/Spaces/SpaceHeader.vue
+++ b/packages/web-app-files/src/components/Spaces/SpaceHeader.vue
@@ -21,7 +21,7 @@