Skip to content

Commit

Permalink
Added file preview
Browse files Browse the repository at this point in the history
Added new component FileItem wrapped around oc-file to
better encapsulated the formatting methods as computed properties
instead of using the mixin.
Added preview support in file list loaded using mediaSource.
  • Loading branch information
Vincent Petry committed Mar 18, 2020
1 parent d115983 commit ba359d1
Show file tree
Hide file tree
Showing 8 changed files with 177 additions and 17 deletions.
19 changes: 8 additions & 11 deletions apps/files/src/components/AllFilesList.vue
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,12 @@
<oc-star class="uk-display-block" @click.native.stop="toggleFileFavorite(item)" :shining="item.starred" />
</div>
<div class="uk-text-truncate uk-width-expand" :ref="index === 0 ? 'firstRowNameColumn' : null">
<oc-file @click.native.stop="item.type === 'folder' ? navigateTo(item.path.substr(1)) : openFileActionBar(item)"
:name="$_ocFileName(item)" :extension="item.extension" class="file-row-name" :icon="fileTypeIcon(item)"
:filename="item.name" :key="item.id"/>
<file-item
@click.native.stop="item.type === 'folder' ? navigateTo(item.path.substr(1)) : openFileActionBar(item)"
:item="item"
:show-path="$_isFavoritesList"
class="file-row-name"
:key="item.id"/>
<oc-spinner
v-if="actionInProgress(item)"
size="small"
Expand Down Expand Up @@ -111,6 +114,7 @@
</template>
<script>
import FileList from './FileList.vue'
import FileItem from './FileItem.vue'
import NoContentMessage from './NoContentMessage.vue'
import { mapGetters, mapActions, mapState } from 'vuex'
Expand All @@ -124,6 +128,7 @@ export default {
name: 'AllFilesList',
components: {
FileList,
FileItem,
StatusIndicators,
NoContentMessage,
SortableColumnHeader
Expand Down Expand Up @@ -237,14 +242,6 @@ export default {
file: item
})
},
$_ocFileName (item) {
if (this.$_isFavoritesList) {
const pathSplit = item.path.substr(1).split('/')
if (pathSplit.length === 2) return `${pathSplit[pathSplit.length - 2]}/${item.basename}`
if (pathSplit.length > 2) return `…/${pathSplit[pathSplit.length - 2]}/${item.basename}`
}
return item.basename
},
isActionEnabled (item, action) {
return action.isEnabled(item, this.parentFolder)
Expand Down
10 changes: 7 additions & 3 deletions apps/files/src/components/Collaborators/SharedFilesList.vue
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,11 @@
</template>
<template #rowColumns="{ item }">
<div class="uk-text-truncate uk-width-expand">
<oc-file @click.native.stop="item.type === 'folder' ? navigateTo(item.path.substr(1)) : openFileActionBar(item)"
:name="item.basename" :extension="item.extension" class="file-row-name" :icon="fileTypeIcon(item)"
:filename="item.name" :key="item.path" />
<file-item
@click.native.stop="item.type === 'folder' ? navigateTo(item.path.substr(1)) : openFileActionBar(item)"
:item="item"
class="file-row-name"
:key="item.path" />
<oc-spinner
v-if="actionInProgress(item)"
size="small"
Expand Down Expand Up @@ -110,6 +112,7 @@ import { mapGetters, mapActions } from 'vuex'
import Mixins from '../../mixins'
import FileActions from '../../fileactions'
import FileList from '../FileList.vue'
import FileItem from '../FileItem.vue'
import NoContentMessage from '../NoContentMessage.vue'
import SortableColumnHeader from '../FilesLists/SortableColumnHeader.vue'
import { shareTypes } from '../../helpers/shareTypes'
Expand All @@ -119,6 +122,7 @@ export default {
name: 'SharedFilesList',
components: {
FileList,
FileItem,
NoContentMessage,
SortableColumnHeader
},
Expand Down
95 changes: 95 additions & 0 deletions apps/files/src/components/FileItem.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
<template>
<oc-file
:name="fileName"
:extension="item.extension"
:icon="fileTypeIcon"
:iconUrl="previewUrl"
:filename="item.name"
/>
</template>
<script>
import queryString from 'query-string'
import fileTypeIconMappings from '../fileTypeIconMappings.json'
export default {
name: 'FileItem',
props: {
/**
* The html element used for the avatar container.
* `div, span`
*/
item: {
type: Object
},
showPath: {
type: Boolean,
default: false
}
},
data: function () {
return {
previewUrl: undefined
}
},
computed: {
fileName () {
if (this.showPath) {
const pathSplit = this.item.path.substr(1).split('/')
if (pathSplit.length === 2) return `${pathSplit[pathSplit.length - 2]}/${this.item.basename}`
if (pathSplit.length > 2) return `…/${pathSplit[pathSplit.length - 2]}/${this.item.basename}`
}
return this.item.basename
},
// FIXME: duplicate in mixin
fileTypeIcon () {
if (this.item.type === 'folder') {
return 'folder'
}
const icon = fileTypeIconMappings[this.item.extension]
if (icon) return `${icon}`
return 'x-office-document'
}
},
mounted () {
this.loadPreview()
},
methods: {
loadPreview () {
// TODO: check if previews are globally enabled (requires capability entry)
if (this.item.type === 'folder') {
return
}
const query = queryString.stringify({
x: this.thumbDimensions,
y: this.thumbDimensions,
c: this.item.etag,
scalingup: 0,
preview: 1,
a: 1
})
let previewPath
if (this.publicPage()) {
previewPath = [
'..',
'dav',
'public-files',
this.item.path
].join('/')
} else {
previewPath = [
'..',
'dav',
'files',
this.$store.getters.user.id,
this.item.path
].join('/')
}
const previewUrl = this.$client.files.getFileUrl(previewPath) + '?' + query
this.mediaSource(previewUrl, 'url', this.requestHeaders).then(dataUrl => {
this.previewUrl = dataUrl
})
}
}
}
</script>
10 changes: 7 additions & 3 deletions apps/files/src/components/Trashbin.vue
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,11 @@
</template>
<template #rowColumns="{ item }">
<div class="uk-text-truncate uk-width-expand">
<oc-file
:name="$_ocTrashbin_fileName(item)" :extension="item.extension" class="file-row-name" :icon="fileTypeIcon(item)"
:filename="item.name" :key="item.id"/>
<file-item
:item="item"
class="file-row-name"
:key="item.id"
/>
</div>
<div class="uk-text-meta uk-text-nowrap uk-width-small uk-text-right" :class="{ 'uk-visible@s' : !_sidebarOpen, 'uk-hidden' : _sidebarOpen }">
{{ formDateFromNow(item.deleteTimestamp) }}
Expand All @@ -58,6 +60,7 @@
import { mapGetters, mapActions } from 'vuex'
import Mixins from '../mixins'
import FileList from './FileList.vue'
import FileItem from './FileItem.vue'
import NoContentMessage from './NoContentMessage.vue'
import OcDialogPrompt from './ocDialogPrompt.vue'
import SortableColumnHeader from './FilesLists/SortableColumnHeader.vue'
Expand All @@ -69,6 +72,7 @@ export default {
components: {
OcDialogPrompt,
FileList,
FileItem,
NoContentMessage,
SortableColumnHeader
},
Expand Down
15 changes: 15 additions & 0 deletions apps/files/src/mixins.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,21 @@ export default {

_sidebarOpen () {
return this.highlightedFile !== null
},

requestHeaders () {
if (!this.publicPage()) {
return null
}

const headers = new Headers()
headers.append('X-Requested-With', 'XMLHttpRequest')

const password = this.publicLinkPassword
if (password) {
headers.append('Authorization', 'Basic ' + Buffer.from('public:' + password).toString('base64'))
}
return headers
}
},
methods: {
Expand Down
10 changes: 10 additions & 0 deletions tests/acceptance/features/webUIFiles/fileList.feature
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,13 @@ Feature: User can view files inside a folder
And the user opens folder "empty-thing" directly on the webUI
Then there should be no resources listed on the webUI

@issue-276
Scenario: Thumbnails are loaded for known file types
When the user uploads file "new-lorem.txt" using the webUI
Then the resource "new-lorem.txt" should have a thumbnail displayed on the webUI

@issue-276
Scenario: Thumbnails are not loaded for known file types
When the user uploads file "new-data.zip" using the webUI
Then the resource "new-data.zip" should have a file type icon displayed on the webUI

21 changes: 21 additions & 0 deletions tests/acceptance/pageObjects/FilesPageElement/filesList.js
Original file line number Diff line number Diff line change
Expand Up @@ -368,6 +368,24 @@ module.exports = {
.useCss()
return this
},
getResourceThumbnail: async function (resourceName) {
const fileRowIconSelector = this.getFileRowSelectorByFileName(resourceName) + this.elements.fileIconInFileRow.selector
let iconUrl = null
await this.waitForFileVisible(resourceName)
await this.useXpath()
.getAttribute(
fileRowIconSelector,
'src',
(result) => {
if (result.value && result.value.error) {
this.assert.fail(result.value.error)
}
iconUrl = result.value
}
)
.useCss()
return iconUrl
},
/**
* Wait for A filerow with given path to be visible
* This only works in the favorites page as it uses the whole path of a file rather than just the name
Expand Down Expand Up @@ -719,6 +737,9 @@ module.exports = {
fileLinkInFileRow: {
selector: '//span[contains(@class, "file-row-name")]'
},
fileIconInFileRow: {
selector: '//span[contains(@class, "file-row-name")]//*[local-name() = "svg"]|img'
},
notMarkedFavoriteInFileRow: {
selector: '//span[contains(@class, "oc-star-dimm")]',
locateStrategy: 'xpath'
Expand Down
14 changes: 14 additions & 0 deletions tests/acceptance/stepDefinitions/filesContext.js
Original file line number Diff line number Diff line change
Expand Up @@ -926,3 +926,17 @@ When('the user has set the sort order of the {string} column to descending order
When('the user has set the sort order of the {string} column to ascending order', async function (column) {
await _setFilesTableSort(column, false)
})
Then('the file/folder/resource {string} should have a thumbnail displayed on the webUI', async function (resource) {
const iconUrl = await client
.page
.FilesPageElement.filesList()
.getResourceThumbnail(resource)
assert.ok(iconUrl && iconUrl.startsWith('blob:'), 'Icon URL expected to be set when thumbnail is displayed')
})
Then('the file/folder/resource {string} should have a file type icon displayed on the webUI', async function (resource) {
const iconUrl = await client
.page
.FilesPageElement.filesList()
.getResourceThumbnail(resource)
assert.strictEqual(null, iconUrl, 'No icon URL expected when file type icon is displayed')
})

0 comments on commit ba359d1

Please sign in to comment.