diff --git a/changelog/unreleased/enhancement-resources-tiles-view b/changelog/unreleased/enhancement-resources-tiles-view
index 5c5d0fac35b..3ca966aa8aa 100644
--- a/changelog/unreleased/enhancement-resources-tiles-view
+++ b/changelog/unreleased/enhancement-resources-tiles-view
@@ -2,8 +2,12 @@ Enhancement: Add tiles view for resource display
We've added a switch to change from the known resource table to a tiles view.
The change gets saved to the url and persisted across resource navigation.
+Tiles can be dynamically resized on screens bigger than mobile, using the "display customization options" dropdown.
https://github.com/owncloud/web/pull/7991
+https://github.com/owncloud/web/pull/8372
https://github.com/owncloud/web/issues/6378
https://github.com/owncloud/web/issues/6379
https://github.com/owncloud/web/issues/6380
+https://github.com/owncloud/web/issues/8367
+https://github.com/owncloud/web/issues/8368
diff --git a/packages/design-system/src/tokens/ods/size.yaml b/packages/design-system/src/tokens/ods/size.yaml
index f6b739af19f..1ac18295e8a 100644
--- a/packages/design-system/src/tokens/ods/size.yaml
+++ b/packages/design-system/src/tokens/ods/size.yaml
@@ -22,3 +22,8 @@ size:
value: 22px
form-check-default:
value: 14px
+ tiles:
+ resize-step:
+ value: 12rem
+ default:
+ value: 14rem
diff --git a/packages/web-app-files/src/components/AppBar/ViewOptions.vue b/packages/web-app-files/src/components/AppBar/ViewOptions.vue
index 7e89aa5e891..8248ee31ac7 100644
--- a/packages/web-app-files/src/components/AppBar/ViewOptions.vue
+++ b/packages/web-app-files/src/components/AppBar/ViewOptions.vue
@@ -62,6 +62,21 @@
@change="itemsPerPage = $event"
/>
+
+
+
+
@@ -91,6 +106,10 @@ export default defineComponent({
name: ViewModeConstants.queryName,
defaultValue: ViewModeConstants.defaultModeName
})
+ const viewSizeQuery = useRouteQueryPersisted({
+ name: ViewModeConstants.tilesSizeQueryName,
+ defaultValue: ViewModeConstants.tilesSizeDefault.toString()
+ })
watch(
[perPageQuery, viewModeQuery],
(params) => {
@@ -102,6 +121,7 @@ export default defineComponent({
return {
ViewModeConstants,
viewModeCurrent: viewModeQuery,
+ viewSizeCurrent: viewSizeQuery,
itemsPerPage: perPageQuery,
queryParamsLoading
}
@@ -112,6 +132,9 @@ export default defineComponent({
viewOptionsButtonLabel() {
return this.$gettext('Display customization options of the files list')
},
+ resizeTilesLabel() {
+ return this.$gettext('Tile size')
+ },
hiddenFilesShownModel: {
get() {
@@ -137,6 +160,11 @@ export default defineComponent({
setViewMode(mode) {
this.viewModeCurrent = mode.name
},
+ setTilesViewSize() {
+ document
+ .querySelector(':root')
+ .style.setProperty(`--oc-size-tiles-resize-step`, `${this.viewSizeCurrent * 12}rem`)
+ },
updateHiddenFilesShownModel(event) {
this.hiddenFilesShownModel = event
},
@@ -170,4 +198,39 @@ export default defineComponent({
margin-top: var(--oc-space-small);
}
}
+
+.oc-range {
+ -webkit-appearance: none;
+ -webkit-transition: 0.2s;
+ border-radius: 0.3rem;
+ background: var(--oc-color-input-border);
+ height: 0.5rem;
+ opacity: 0.7;
+ outline: none;
+ transition: opacity 0.2s;
+ width: 100%;
+ max-width: 50%;
+
+ &:hover {
+ opacity: 1;
+ }
+
+ &::-webkit-slider-thumb {
+ -webkit-appearance: none;
+ appearance: none;
+ background: var(--oc-color-swatch-primary-default);
+ border-radius: 50%;
+ cursor: pointer;
+ height: 1rem;
+ width: 1rem;
+ }
+
+ &::-moz-range-thumb {
+ background: var(--oc-color-swatch-primary-default);
+ border-radius: 50%;
+ cursor: pointer;
+ height: 1rem;
+ width: 1rem;
+ }
+}
diff --git a/packages/web-app-files/src/components/FilesList/ResourceTiles.vue b/packages/web-app-files/src/components/FilesList/ResourceTiles.vue
index d9d9006eeca..ab49da21272 100644
--- a/packages/web-app-files/src/components/FilesList/ResourceTiles.vue
+++ b/packages/web-app-files/src/components/FilesList/ResourceTiles.vue
@@ -1,17 +1,15 @@
-
-
+
+
@@ -26,20 +24,20 @@
:id="`space-context-btn-${resource.getDomSelector()}`"
:ref="
(el) => {
- tileRefs.dropBtns[index] = el
+ tileRefs.dropBtns[resource.id] = el
}
"
v-oc-tooltip="contextMenuLabel"
:aria-label="contextMenuLabel"
appearance="raw"
- @click="resetDropPosition($event, index, tileRefs.dropBtns[index])"
+ @click="resetDropPosition($event, resource.id, tileRefs.dropBtns[resource.id])"
>
,
default: () => []
},
- tileWidth: {
- type: String,
- default: ''
+ resizable: {
+ type: Boolean,
+ default: false
},
targetRouteCallback: {
type: Function,
@@ -210,12 +208,22 @@ export default defineComponent({
.oc-tiles {
column-gap: 1rem;
display: grid;
- grid-template-columns: repeat(auto-fill, 14rem);
+ grid-template-columns: repeat(auto-fill, var(--oc-size-tiles-default));
justify-content: flex-start;
row-gap: 1rem;
- &.small-tiles {
- grid-template-columns: repeat(auto-fill, 12rem);
+ &.resizableTiles {
+ grid-template-columns: repeat(auto-fill, var(--oc-size-tiles-resize-step));
+ }
+
+ @media only screen and (max-width: 640px) {
+ grid-template-columns: 80%;
+ justify-content: center;
+ padding: var(--oc-space-medium) 0;
+
+ &.resizableTiles {
+ grid-template-columns: 80%;
+ }
}
}
diff --git a/packages/web-app-files/src/composables/resourcesViewDefaults/useResourcesViewDefaults.ts b/packages/web-app-files/src/composables/resourcesViewDefaults/useResourcesViewDefaults.ts
index e923f30e307..a02f8f2e739 100644
--- a/packages/web-app-files/src/composables/resourcesViewDefaults/useResourcesViewDefaults.ts
+++ b/packages/web-app-files/src/composables/resourcesViewDefaults/useResourcesViewDefaults.ts
@@ -17,7 +17,7 @@ import { Resource } from 'web-client'
import { useSelectedResources, SelectedResourcesResult } from '../selection'
import { ReadOnlyRef } from 'web-pkg'
import { ScrollToResult, useScrollTo } from '../scrollTo'
-import { useViewMode, ViewModeConstants } from '../viewMode'
+import { useViewMode, useViewSize, ViewModeConstants } from '../viewMode'
interface ResourcesViewDefaultsOptions {
loadResourcesTask?: Task
@@ -37,7 +37,7 @@ type ResourcesViewDefaultsResult = {
sortBy: ReadOnlyRef
sortDir: ReadOnlyRef
viewMode: ReadOnlyRef
-
+ viewSize: ReadOnlyRef
selectedResources: Ref
selectedResourcesIds: Ref<(string | number)[]>
isResourceInSelection(resource: Resource): boolean
@@ -72,6 +72,10 @@ export const useResourcesViewDefaults = (
const currentViewMode = computed((): string => queryItemAsString(currentViewModeQuery.value))
const viewMode = useViewMode(currentViewMode)
+ const currentTilesSizeQuery = useRouteQuery('tiles-size', '1')
+ const currentTilesSize = computed((): string => String(currentTilesSizeQuery.value))
+ const viewSize = useViewSize(currentTilesSize)
+
const paginationPageQuery = useRouteQuery('page', '1')
const paginationPage = computed((): number => parseInt(String(paginationPageQuery.value)))
const { items: paginatedResources, total: paginationPages } = usePagination({
@@ -92,6 +96,7 @@ export const useResourcesViewDefaults = (
storeItems,
fields,
viewMode,
+ viewSize,
paginatedResources,
paginationPages,
paginationPage,
diff --git a/packages/web-app-files/src/composables/viewMode/constants.ts b/packages/web-app-files/src/composables/viewMode/constants.ts
index 6f3ee0253ae..7e2b75da88b 100644
--- a/packages/web-app-files/src/composables/viewMode/constants.ts
+++ b/packages/web-app-files/src/composables/viewMode/constants.ts
@@ -31,4 +31,6 @@ export abstract class ViewModeConstants {
}
}
static readonly queryName: string = 'view-mode'
+ static readonly tilesSizeDefault: number = 1
+ static readonly tilesSizeQueryName: string = 'tiles-size'
}
diff --git a/packages/web-app-files/src/composables/viewMode/useViewMode.ts b/packages/web-app-files/src/composables/viewMode/useViewMode.ts
index 4628ab796cd..845ed8d0142 100644
--- a/packages/web-app-files/src/composables/viewMode/useViewMode.ts
+++ b/packages/web-app-files/src/composables/viewMode/useViewMode.ts
@@ -14,3 +14,15 @@ export function useViewMode(options: ComputedRef): ComputedRef {
})
return computed(() => queryItemAsString(unref(viewModeQuery)))
}
+
+export function useViewSize(options: ComputedRef): ComputedRef {
+ if (options) {
+ return computed(() => unref(options))
+ }
+
+ const viewModeSize = useRouteQueryPersisted({
+ name: ViewModeConstants.tilesSizeQueryName,
+ defaultValue: ViewModeConstants.tilesSizeDefault.toString()
+ })
+ return computed(() => String(unref(viewModeSize)))
+}
diff --git a/packages/web-app-files/src/views/spaces/GenericSpace.vue b/packages/web-app-files/src/views/spaces/GenericSpace.vue
index 1780f617fa3..9c629ece438 100644
--- a/packages/web-app-files/src/views/spaces/GenericSpace.vue
+++ b/packages/web-app-files/src/views/spaces/GenericSpace.vue
@@ -48,7 +48,7 @@
v-else-if="viewMode === ViewModeConstants.tilesView.name"
:data="paginatedResources"
class="oc-px-m oc-pt-l"
- tile-width="small"
+ :resizable="true"
:target-route-callback="resourceTargetRouteCallback"
:space="space"
@rowMounted="rowMounted"
diff --git a/packages/web-app-files/tests/mocks/useResourcesViewDefaultsMock.ts b/packages/web-app-files/tests/mocks/useResourcesViewDefaultsMock.ts
index e1cb1122edf..d6a9a7fa70c 100644
--- a/packages/web-app-files/tests/mocks/useResourcesViewDefaultsMock.ts
+++ b/packages/web-app-files/tests/mocks/useResourcesViewDefaultsMock.ts
@@ -31,6 +31,7 @@ export const useResourcesViewDefaultsMock = (
scrollToResource: jest.fn(),
scrollToResourceFromRoute: jest.fn(),
viewMode: ref('resource-table'),
+ viewSize: ref('1'),
...options
}
}
diff --git a/packages/web-app-files/tests/unit/components/AppBar/ViewOptions.spec.ts b/packages/web-app-files/tests/unit/components/AppBar/ViewOptions.spec.ts
index 2c02598b988..6b877679ab5 100644
--- a/packages/web-app-files/tests/unit/components/AppBar/ViewOptions.spec.ts
+++ b/packages/web-app-files/tests/unit/components/AppBar/ViewOptions.spec.ts
@@ -55,19 +55,32 @@ describe('ViewOptions component', () => {
const viewModeSwitchButtons = wrapper.find('.viewmode-switch-buttons')
expect(viewModeSwitchButtons.html()).toMatchSnapshot()
})
+ it('displays a tile-resize range slider in dropdown if currentViewMode is resource-tiles', async () => {
+ const { wrapper } = getWrapper(
+ {},
+ {
+ viewModes: [ViewModeConstants.condensedTable, ViewModeConstants.default]
+ },
+ 'resource-tiles'
+ )
+
+ const filesViewOptions = wrapper.find('#files-view-options-drop')
+ expect(filesViewOptions.html()).toMatchSnapshot()
+ })
})
function getWrapper(
{ perPage = '100' } = {},
props?: {
viewModes: ViewMode[]
- }
+ },
+ currentViewMode = ''
) {
jest.mocked(useRouteQueryPersisted).mockImplementation(() => ref(perPage))
const storeOptions = { ...defaultStoreMockOptions }
const store = createStore(storeOptions)
- const mocks = defaultComponentMocks()
+ const mocks = { ...defaultComponentMocks(), viewModeCurrent: currentViewMode }
return {
storeOptions,
mocks,
diff --git a/packages/web-app-files/tests/unit/components/AppBar/__snapshots__/ViewOptions.spec.ts.snap b/packages/web-app-files/tests/unit/components/AppBar/__snapshots__/ViewOptions.spec.ts.snap
index b8ffee2832e..0453cca5518 100644
--- a/packages/web-app-files/tests/unit/components/AppBar/__snapshots__/ViewOptions.spec.ts.snap
+++ b/packages/web-app-files/tests/unit/components/AppBar/__snapshots__/ViewOptions.spec.ts.snap
@@ -1,5 +1,36 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
+exports[`ViewOptions component displays a tile-resize range slider in dropdown if currentViewMode is resource-tiles 1`] = `
+
+`;
+
exports[`ViewOptions component sets the correct initial files page limit 1`] = `
@@ -25,6 +56,7 @@ exports[`ViewOptions component sets the correct initial files page limit 1`] = `
+