summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohn Molakvoæ (skjnldsv) <skjnldsv@protonmail.com>2019-11-12 07:12:36 +0100
committerJohn Molakvoæ (skjnldsv) <skjnldsv@protonmail.com>2019-11-13 08:45:29 +0100
commit2366aaf6ad5d607762f9453884bfb600f13b2c93 (patch)
treee318f5f0cb18a4444479f24e134730961eddd6a1
parentae28cc9b2d79568ae069e3f25ed29791986791d0 (diff)
Tags
Signed-off-by: John Molakvoæ (skjnldsv) <skjnldsv@protonmail.com>
-rw-r--r--css/icons.scss2
-rw-r--r--img/photos.svg2
-rw-r--r--package-lock.json3
-rw-r--r--package.json1
-rw-r--r--src/Photos.vue2
-rw-r--r--src/components/Folder.vue31
-rw-r--r--src/components/Navigation.vue13
-rw-r--r--src/patchedRequest.js3
-rw-r--r--src/router/index.js20
-rw-r--r--src/services/FileList.js8
-rw-r--r--src/services/FolderInfo.js4
-rw-r--r--src/services/PhotoSearch.js2
-rw-r--r--src/services/SystemTags.js22
-rw-r--r--src/store/folders.js5
-rw-r--r--src/store/systemtags.js66
-rw-r--r--src/utils/fileUtils.js125
-rw-r--r--src/utils/numberUtil.js (renamed from src/utils/ParseFile.js)21
-rw-r--r--src/views/Albums.vue2
-rw-r--r--src/views/Tags.vue71
-rw-r--r--webpack.common.js1
20 files changed, 288 insertions, 116 deletions
diff --git a/css/icons.scss b/css/icons.scss
index 88e42707..ba8dcef9 100644
--- a/css/icons.scss
+++ b/css/icons.scss
@@ -24,4 +24,4 @@
@include icon-color('folder', 'filetypes', $color-black, 1, true);
}
-@include icon-black-white('photos', 'photos', 1);
+@include icon-black-white('photos', 'photos', 2);
diff --git a/img/photos.svg b/img/photos.svg
index 90c3fdb6..6046f92b 100644
--- a/img/photos.svg
+++ b/img/photos.svg
@@ -1 +1 @@
-<svg xmlns="http://www.w3.org/2000/svg" height="32" width="32" version="1"><g transform="translate(-11.5 2.5)"><path d="M20.5 7.5a1 1 0 00-1 1v17c0 .5.6 1 1 1h20c.5 0 1-.5 1-1v-17c0-.4-.5-1-1-1zM21 9h19v14.5H21z"/><circle cx="24.8" cy="13" r="2.3"/><path d="M38.4 15.5L35 20.2 33.6 22l-1.2-1.4-3.5-3.5-4.5 4.3-3.6 3.3h19.9v-6.6zM14.5 2.5a1 1 0 00-1 1v17c0 .5.6 1 1 1h6v-3H15V4h19v3.5h1.5v-4c0-.4-.5-1-1-1h-20z"/></g></svg> \ No newline at end of file
+<svg xmlns="http://www.w3.org/2000/svg" height="32" width="32" version="1"><g transform="translate(-11.5 2.5)"><path d="M20.5 7.5a1 1 0 00-1 1v17c0 .5.6 1 1 1h20c.5 0 1-.5 1-1v-17c0-.4-.5-1-1-1zM21 9h19v14.5H21z"/><circle cx="24.8" cy="13" r="2.3"/><path d="M38.4 15.5L35 20.2 33.6 22l-1.2-1.4-3.5-3.5-4.5 4.3-3.6 3.3h19.9v-6.6l-2.3-2.6zM14.5.5a1 1 0 00-1 1v17c0 .5.6 1 1 1h5.9v-3H15V2h19v6.6h1.5V1.5c0-.4-.5-1-1-1h-20z"/></g></svg> \ No newline at end of file
diff --git a/package-lock.json b/package-lock.json
index 39a3b402..7a8031b8 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1853,8 +1853,7 @@
"camelcase": {
"version": "5.3.1",
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
- "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
- "dev": true
+ "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg=="
},
"camelcase-keys": {
"version": "2.1.0",
diff --git a/package.json b/package.json
index abc6819f..4ee8bf4a 100644
--- a/package.json
+++ b/package.json
@@ -36,6 +36,7 @@
"@nextcloud/l10n": "^0.2.1",
"@nextcloud/router": "^0.1.0",
"@nextcloud/vue": "^1.1.0",
+ "camelcase": "^5.3.1",
"cdav-library": "git+https://github.com/nextcloud/cdav-library.git",
"path-posix": "^1.0.0",
"qs": "^6.9.0",
diff --git a/src/Photos.vue b/src/Photos.vue
index ec26f323..49b83e13 100644
--- a/src/Photos.vue
+++ b/src/Photos.vue
@@ -30,7 +30,7 @@
<AppNavigationItem to="/favorites" :title="t('photos', 'Favorites')" icon="icon-favorite" />
<AppNavigationItem :to="{name: 'albums'}" :title="t('photos', 'Your albums')" icon="icon-files-dark" />
<AppNavigationItem :to="{name: 'shared'}" :title="t('photos', 'Shared albums')" icon="icon-share" />
- <AppNavigationItem :to="{name: 'tags'}" :title="t('photos', 'Tags')" icon="icon-tag" />
+ <AppNavigationItem :to="{name: 'tags'}" :title="t('photos', 'Tagged photos')" icon="icon-tag" />
<AppNavigationItem :to="{name: 'maps'}" :title="t('photos', 'Locations')" icon="icon-address" />
</AppNavigation>
<AppContent :class="{ 'icon-loading': loading }">
diff --git a/src/components/Folder.vue b/src/components/Folder.vue
index de2db5a6..c04e17a9 100644
--- a/src/components/Folder.vue
+++ b/src/components/Folder.vue
@@ -43,7 +43,7 @@
class="folder-name__icon"
role="img" />
<p :id="ariaUuid" class="folder-name__name">
- {{ folder.basename }}
+ {{ basename }}
</p>
</div>
<div class="cover" role="none" />
@@ -62,8 +62,16 @@ export default {
inheritAttrs: false,
props: {
- folder: {
- type: Object,
+ basename: {
+ type: String,
+ required: true,
+ },
+ filename: {
+ type: String,
+ required: true,
+ },
+ id: {
+ type: Number,
required: true,
},
icon: {
@@ -88,7 +96,7 @@ export default {
// files list of the current folder
folderContent() {
- return this.folders[this.folder.id]
+ return this.folders[this.id]
},
fileList() {
return this.folderContent
@@ -105,23 +113,24 @@ export default {
},
ariaUuid() {
- return `folder-${this.folder.id}`
+ return `folder-${this.id}`
},
ariaLabel() {
- return t('photos', 'Open the "{name}" sub-directory', { name: this.folder.basename })
+ return t('photos', 'Open the "{name}" sub-directory', { name: this.basename })
},
/**
* We do not want encoded slashes when browsing by folder
* so we generate a new valid route object, get the final url back
- * decode it and use it as a direct string, which vue-router
+ * decode it and use it as a direct string, which vue-router
* does not encode afterwards
+ * @returns {string}
*/
to() {
const route = Object.assign({}, this.$route, {
// always remove first slash
- params: { path: this.folder.filename.substr(1) }
- });
+ params: { path: this.filename.substr(1) },
+ })
return decodeURIComponent(this.$router.resolve(route).resolved.path)
},
},
@@ -133,9 +142,9 @@ export default {
try {
// get data
- const { files, folders } = await request(this.folder.filename)
+ const { files, folders } = await request(this.filename)
// this.cancelRequest('Stop!')
- this.$store.dispatch('updateFolders', { id: this.folder.id, files, folders })
+ this.$store.dispatch('updateFolders', { id: this.id, files, folders })
this.$store.dispatch('updateFiles', { folder: this.folder, files, folders })
} catch (error) {
if (error.response && error.response.status) {
diff --git a/src/components/Navigation.vue b/src/components/Navigation.vue
index df1c3f0f..a0d4c92c 100644
--- a/src/components/Navigation.vue
+++ b/src/components/Navigation.vue
@@ -56,6 +56,10 @@ export default {
type: String,
required: true,
},
+ rootTitle: {
+ type: String,
+ default: t('photos', 'Photos'),
+ },
id: {
type: Number,
required: true,
@@ -68,7 +72,7 @@ export default {
},
name() {
if (this.isRoot) {
- return t('photos', 'Photos')
+ return this.rootTitle
}
return this.basename
},
@@ -93,14 +97,15 @@ export default {
/**
* We do not want encoded slashes when browsing by folder
* so we generate a new valid route object, get the final url back
- * decode it and use it as a direct string, which vue-router
+ * decode it and use it as a direct string, which vue-router
* does not encode afterwards
+ * @returns {string}
*/
to() {
const route = Object.assign({}, this.$route, {
// always remove first slash
- params: { path: this.parentPath.substr(1) }
- });
+ params: { path: this.parentPath.substr(1) },
+ })
return decodeURIComponent(this.$router.resolve(route).resolved.path)
},
},
diff --git a/src/patchedRequest.js b/src/patchedRequest.js
index 6b1eb267..ae23b19d 100644
--- a/src/patchedRequest.js
+++ b/src/patchedRequest.js
@@ -21,7 +21,6 @@
*/
const request = require('webdav/dist/request')
-const merge = require('webdav/dist/merge')
const oldPrepareRequestOptions = request.prepareRequestOptions
@@ -32,7 +31,7 @@ const oldPrepareRequestOptions = request.prepareRequestOptions
request.prepareRequestOptions = function(requestOptions, methodOptions) {
// add our cancelToken support
if (methodOptions.cancelToken && typeof methodOptions.cancelToken === 'object') {
- requestOptions.cancelToken = merge(requestOptions.cancelToken || {}, methodOptions.cancelToken)
+ requestOptions.cancelToken = Object.assign({}, requestOptions.cancelToken || {}, methodOptions.cancelToken)
}
// exploit old method
oldPrepareRequestOptions(requestOptions, methodOptions)
diff --git a/src/router/index.js b/src/router/index.js
index df464138..d4d9caa6 100644
--- a/src/router/index.js
+++ b/src/router/index.js
@@ -55,7 +55,7 @@ export default new Router({
children: [
{
path: ':path*',
- name: 'path',
+ name: 'albumspath',
component: Albums,
},
],
@@ -68,7 +68,7 @@ export default new Router({
children: [
{
path: ':path*',
- name: 'path',
+ name: 'sharedpath',
component: Albums,
},
],
@@ -77,24 +77,18 @@ export default new Router({
path: '/favorites',
component: Tags,
name: 'favorites',
- props,
- children: [
- {
- path: ':path*',
- name: 'path',
- component: Tags,
- },
- ],
},
{
path: '/tags',
component: Tags,
name: 'tags',
- props,
+ props: route => ({
+ tagname: route.params.tagname,
+ }),
children: [
{
- path: ':path*',
- name: 'path',
+ path: ':tagname',
+ name: 'tagname',
component: Tags,
},
],
diff --git a/src/services/FileList.js b/src/services/FileList.js
index 80e9df6d..c473aad8 100644
--- a/src/services/FileList.js
+++ b/src/services/FileList.js
@@ -26,8 +26,7 @@ import { handleResponseCode, processResponsePayload } from 'webdav/dist/response
import { normaliseHREF, normalisePath } from 'webdav/dist/url'
import client, { remotePath } from './DavClient'
import pathPosix from 'path-posix'
-import request from './DavRequest'
-import parseFile from '../utils/ParseFile'
+import { genFileInfo } from '../utils/fileUtils'
/**
* List files from a folder and filter out unwanted mimes
@@ -37,6 +36,8 @@ import parseFile from '../utils/ParseFile'
* @returns {Array} the file list
*/
export default async function(path, options) {
+
+ console.trace();
options = Object.assign({
method: 'PROPFIND',
headers: {
@@ -44,7 +45,6 @@ export default async function(path, options) {
Depth: options.deep ? 'infinity' : 1,
},
responseType: 'text',
- data: request,
details: true,
}, options)
@@ -68,7 +68,7 @@ export default async function(path, options) {
.then(result => getDirectoryFiles(result, remotePath, options.details))
.then(files => processResponsePayload(response, files, options.details))
- const list = data.map(data => parseFile(data, prefixPath))
+ const list = data.map(data => genFileInfo(data, prefixPath))
// filter all the files and folders
let folder = {}
diff --git a/src/services/FolderInfo.js b/src/services/FolderInfo.js
index 6d65b57a..b58ddb79 100644
--- a/src/services/FolderInfo.js
+++ b/src/services/FolderInfo.js
@@ -23,7 +23,7 @@
import { getCurrentUser } from '@nextcloud/auth'
import client from './DavClient'
import request from './DavRequest'
-import parseFile from '../utils/ParseFile'
+import { genFileInfo } from '../utils/fileUtils'
/**
* List files from a folder and filter out unwanted mimes
@@ -43,5 +43,5 @@ export default async function(path) {
details: true,
})
- return parseFile(response.data, prefixPath)
+ return genFileInfo(response.data, prefixPath)
}
diff --git a/src/services/PhotoSearch.js b/src/services/PhotoSearch.js
index e4546bb4..8d3789ea 100644
--- a/src/services/PhotoSearch.js
+++ b/src/services/PhotoSearch.js
@@ -23,7 +23,7 @@
import { generateRemoteUrl } from '@nextcloud/router'
import { getCurrentUser } from '@nextcloud/auth'
import client from './DavClient'
-import parseFile from '../utils/ParseFile'
+import { genFileInfo } from '../utils/fileUtils'
/**
* List files from a folder and filter out unwanted mimes
diff --git a/src/services/SystemTags.js b/src/services/SystemTags.js
index a8ce55eb..c0244a31 100644
--- a/src/services/SystemTags.js
+++ b/src/services/SystemTags.js
@@ -21,15 +21,17 @@
*/
import client from './DavClient'
-import { generateRemoteUrl } from '@nextcloud/router'
+import { genFileInfo } from '../utils/fileUtils'
/**
- * List files from a folder and filter out unwanted mimes
+ * List system tags
*
+ * @param {String} path the path relative to the user root
+ * @param {Object} [options] optional options for axios
* @returns {Array} the file list
*/
-export default async function() {
- const response = await client.getDirectoryContents('/systemtags/', {
+export default async function(path, options = {}) {
+ const response = await client.getDirectoryContents('/systemtags/', Object.assign({}, {
data: `<?xml version="1.0"?>
<d:propfind xmlns:d="DAV:"
xmlns:oc="http://owncloud.org/ns">
@@ -42,15 +44,7 @@ export default async function() {
</d:prop>
</d:propfind>`,
details: true,
- })
-
- console.info(response)
-
- const entry = response.data
- return Object.assign({
- id: parseInt(entry.props.fileid),
- isFavorite: entry.props.favorite !== '0',
- hasPreview: entry.props['has-preview'] !== 'false',
- }, entry)
+ }, options))
+ return response.data.map(data => genFileInfo(data))
}
diff --git a/src/store/folders.js b/src/store/folders.js
index 559d3ef2..1075900d 100644
--- a/src/store/folders.js
+++ b/src/store/folders.js
@@ -20,6 +20,7 @@
*
*/
import Vue from 'vue'
+import { sortCompare } from '../utils/fileUtils'
const state = {
paths: {},
@@ -39,9 +40,7 @@ const mutations = {
if (files.length > 0) {
const t0 = performance.now()
// sort by last modified
- const list = files.sort((a, b) => {
- return new Date(b.lastmod).getTime() - new Date(a.lastmod).getTime()
- })
+ const list = files.sort((a, b) => sortCompare(a, b, 'lastmod'))
// Set folder list
Vue.set(state.folders, id, list.map(file => file.id))
diff --git a/src/store/systemtags.js b/src/store/systemtags.js
index 8f213e9e..4a49e13e 100644
--- a/src/store/systemtags.js
+++ b/src/store/systemtags.js
@@ -20,50 +20,56 @@
*
*/
import Vue from 'vue'
+import { sortCompare } from '../utils/fileUtils'
const state = {
- paths: {},
tags: {},
+ names: {},
}
const mutations = {
/**
- * Index folders paths and ids
+ * Order and save tags
*
* @param {Object} state vuex state
- * @param {Object} data destructuring object
- * @param {number} data.id current folder id
- * @param {Array} data.files list of files
+ * @param {Array} tags the tags list
*/
- updateTags(state, { id, files }) {
- if (files.length > 0) {
- // sort by last modified
- const list = files.sort((a, b) => {
- return new Date(b.lastmod).getTime() - new Date(a.lastmod).getTime()
- })
+ updateTags(state, tags) {
+ if (tags.length > 0) {
+ // sort by basename
+ const list = tags.sort((a, b) => sortCompare(a, b, 'displayName'))
- // Set folder list
- Vue.set(state.tags, id, list.map(file => file.id))
+ // store tag and its index
+ list.forEach(tag => {
+ Vue.set(state.tags, tag.id, tag)
+ Vue.set(state.tags[tag.id], 'files', [])
+ Vue.set(state.names, tag.displayName, tag.id)
+ })
}
},
/**
- * Index folders paths and ids
+ * Update tag files list
*
* @param {Object} state vuex state
* @param {Object} data destructuring object
- * @param {string} data.path path of this folder
- * @param {number} data.id id of this folder
+ * @param {number} data.id current tag id
+ * @param {Object[]} data.files list of files
*/
- addPath(state, { path, id }) {
- Vue.set(state.paths, path, id)
+ updateTag(state, { id, files }) {
+ // sort by last modified
+ const list = files.sort((a, b) => sortCompare(a, b, 'lastmod'))
+
+ // overwrite list
+ Vue.set(state.tags[id], 'files', list.map(file => file.id))
},
}
const getters = {
tags: state => state.tags,
+ tagsNames: state => state.names,
tag: state => id => state.tags[id],
- tagId: state => path => state.paths[path],
+ tagId: state => name => state.names[name],
}
const actions = {
@@ -71,28 +77,22 @@ const actions = {
* Update files and folders
*
* @param {Object} context vuex context
- * @param {Object} data destructuring object
- * @param {number} data.id current folder id
- * @param {Array} data.files list of files
- * @param {Array} data.folders list of folders
+ * @param {Array} tags the tag list
*/
- updateTags(context, { id, files, folders }) {
- context.commit('updateTags', { id, files })
-
- // then add each folders path indexes
- folders.forEach(folder => context.commit('addPath', { path: folder.filename, id: folder.id }))
+ updateTags(context, tags) {
+ context.commit('updateTags', tags)
},
/**
- * Index folders paths and ids
+ * Update tag files list
*
* @param {Object} context vuex context
* @param {Object} data destructuring object
- * @param {string} data.path path of this folder
- * @param {number} data.id id of this folder
+ * @param {number} data.id current tag id
+ * @param {Object[]} data.files list of files
*/
- addPath(context, { path, id }) {
- context.commit('addPath', { path, id })
+ updateTag(context, { id, files }) {
+ context.commit('updateTag', { id, files })
},
}
diff --git a/src/utils/fileUtils.js b/src/utils/fileUtils.js
new file mode 100644
index 00000000..ce18c08f
--- /dev/null
+++ b/src/utils/fileUtils.js
@@ -0,0 +1,125 @@
+/**
+ * @copyright Copyright (c) 2019 John Molakvoæ <skjnldsv@protonmail.com>
+ *
+ * @author John Molakvoæ <skjnldsv@protonmail.com>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+import camelcase from 'camelcase'
+import { isNumber } from './numberUtil'
+
+/**
+ * Get an url encoded path
+ *
+ * @param {String} path the full path
+ * @returns {string} url encoded file path
+ */
+const encodeFilePath = function(path) {
+ const pathSections = (path.startsWith('/') ? path : `/${path}`).split('/')
+ let relativePath = ''
+ pathSections.forEach((section) => {
+ if (section !== '') {
+ relativePath += '/' + encodeURIComponent(section)
+ }
+ })
+ return relativePath
+}
+
+/**
+ * Extract dir and name from file path
+ *
+ * @param {String} path the full path
+ * @returns {String[]} [dirPath, fileName]
+ */
+const extractFilePaths = function(path) {
+ const pathSections = path.split('/')
+ const fileName = pathSections[pathSections.length - 1]
+ const dirPath = pathSections.slice(0, pathSections.length - 1).join('/')
+ return [dirPath, fileName]
+}
+
+/**
+ * Sorting comparison function
+ *
+ * @param {Object} fileInfo1 file 1 fileinfo
+ * @param {Object} fileInfo2 file 2 fileinfo
+ * @param {string} key key to sort with
+ * @param {boolean} [asc=true] sort ascending?
+ * @returns {number}
+ */
+const sortCompare = function(fileInfo1, fileInfo2, key, asc = true) {
+
+ // favorite always first
+ if (fileInfo1.isFavorite && !fileInfo2.isFavorite) {
+ return -1
+ } else if (!fileInfo1.isFavorite && fileInfo2.isFavorite) {
+ return 1
+ }
+
+ // if this is a number, let's sort by integer
+ if (isNumber(fileInfo1[key]) && isNumber(fileInfo2[key])) {
+ return asc
+ ? Number(fileInfo2[key]) - Number(fileInfo1[key])
+ : Number(fileInfo1[key]) - Number(fileInfo2[key])
+ }
+
+ // else we sort by string, so let's sort directories first
+ if (fileInfo1.type === 'directory' && fileInfo2.type !== 'directory') {
+ return asc ? -1 : 1
+ } else if (fileInfo1.type !== 'directory' && fileInfo2.type === 'directory') {
+ return asc ? 1 : -1
+ }
+
+ // if this is a date, let's sort by date
+ if (isNumber(new Date(fileInfo1[key]).getTime()) && isNumber(new Date(fileInfo2[key])).getTime()) {
+ return asc
+ ? new Date(fileInfo2[key]).getTime() - new Date(fileInfo1[key]).getTime()
+ : new Date(fileInfo1[key]).getTime() - new Date(fileInfo2[key]).getTime()
+ }
+
+ // finally sort by name
+ return asc
+ ? fileInfo1[key].localeCompare(fileInfo2[key], OC.getLanguage())
+ : -fileInfo1[key].localeCompare(fileInfo2[key], OC.getLanguage())
+}
+
+const genFileInfo = function(obj) {
+ const fileInfo = {}
+
+ Object.keys(obj).forEach(key => {
+ const data = obj[key]
+
+ // flatten object if any
+ if (!!data && typeof data === 'object') {
+ Object.assign(fileInfo, genFileInfo(data))
+ } else {
+ // format key and add it to the fileInfo
+ if (data === 'false') {
+ fileInfo[camelcase(key)] = false
+ } else if (data === 'true') {
+ fileInfo[camelcase(key)] = true
+ } else {
+ fileInfo[camelcase(key)] = isNumber(data)
+ ? Number(data)
+ : data
+ }
+ }
+ })
+ return fileInfo
+}
+
+export { encodeFilePath, extractFilePaths, sortCompare, genFileInfo }
diff --git a/src/utils/ParseFile.js b/src/utils/numberUtil.js
index 8d9d9baf..0c3a96e5 100644
--- a/src/utils/ParseFile.js
+++ b/src/utils/numberUtil.js
@@ -20,18 +20,11 @@
*
*/
-/**
- * Format a file into a usable fileinfo object
- *
- * @param {Object} fileData file data returned by the webdav lib
- * @param {String} prefixPath path to substract from the files
- * @returns {Object}
- */
-export default function(fileData, prefixPath = '') {
- const filename = fileData.filename.replace(prefixPath, '/').replace(/^\/\//, '/')
- return Object.assign({
- id: parseInt(fileData.props.fileid),
- isFavorite: fileData.props.favorite !== '0',
- hasPreview: fileData.props['has-preview'] !== 'false',
- }, fileData, { filename })
+const isNumber = function(num) {
+ if (!num) {
+ return false
+ }
+ return Number(num).toString() === num.toString()
}
+
+export { isNumber }
diff --git a/src/views/Albums.vue b/src/views/Albums.vue
index 98642e3d..2338a3c7 100644
--- a/src/views/Albums.vue
+++ b/src/views/Albums.vue
@@ -35,7 +35,7 @@
<!-- Folder content -->
<Grid v-else>
<Navigation v-if="folder" key="navigation" v-bind="folder" />
- <Folder v-for="dir in folderList" :key="dir.id" :folder="dir" />
+ <Folder v-for="dir in folderList" :key="dir.id" v-bind="dir" />
<File v-for="file in fileList" :key="file.id" v-bind="file" />
</Grid>
</template>
diff --git a/src/views/Tags.vue b/src/views/Tags.vue
index 8180b2bc..069b99f4 100644
--- a/src/views/Tags.vue
+++ b/src/views/Tags.vue
@@ -33,12 +33,23 @@
</EmptyContent> -->
<!-- Folder content -->
+ <Grid v-if="isRoot">
+ <Navigation v-if="tag"
+ key="navigation"
+ :basename="tagname"
+ :filename="'/' + tagname"
+ :root-title="t('photos', 'Tags')" />
+ <Folder v-for="id in tagsNames"
+ :key="id"
+ v-bind="tags[id]"
+ :basename="tags[id].displayName"
+ icon="icon-tag" />
+ </Grid>
<!-- <Grid v-else>
<Navigation v-if="folder" key="navigation" v-bind="folder" />
<Folder v-for="dir in folderList" :key="dir.id" :folder="dir" />
<File v-for="file in fileList" :key="file.id" v-bind="file" />
</Grid> -->
- <span>Test</span>
</template>
<script>
@@ -64,9 +75,9 @@ export default {
Navigation,
}