Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nextcloud/photos.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJohn Molakvoæ (skjnldsv) <skjnldsv@protonmail.com>2019-11-07 21:45:14 +0300
committerJohn Molakvoæ (skjnldsv) <skjnldsv@protonmail.com>2019-11-07 21:45:14 +0300
commitae28cc9b2d79568ae069e3f25ed29791986791d0 (patch)
tree64142d5c99b2b0c392bc8e22a4ea536fd5c9f816 /src
parent9c94a3e10fb3345ed57df27f44d51dde2f7ff733 (diff)
Added navigation, albums, init tags
Signed-off-by: John Molakvoæ (skjnldsv) <skjnldsv@protonmail.com>
Diffstat (limited to 'src')
-rw-r--r--src/Photos.vue (renamed from src/Gallery.vue)20
-rw-r--r--src/components/Folder.vue27
-rw-r--r--src/components/Grid.vue87
-rw-r--r--src/components/Navigation.vue16
-rw-r--r--src/main.js6
-rw-r--r--src/router/index.js68
-rw-r--r--src/services/DavClient.js3
-rw-r--r--src/services/FileList.js24
-rw-r--r--src/services/FolderInfo.js14
-rw-r--r--src/services/PhotoSearch.js6
-rw-r--r--src/services/SystemTags.js56
-rw-r--r--src/store/index.js2
-rw-r--r--src/store/systemtags.js99
-rw-r--r--src/utils/ParseFile.js37
-rw-r--r--src/views/Albums.vue (renamed from src/views/Grid.vue)60
-rw-r--r--src/views/Tags.vue111
16 files changed, 545 insertions, 91 deletions
diff --git a/src/Gallery.vue b/src/Photos.vue
index cb9a8882..ec26f323 100644
--- a/src/Gallery.vue
+++ b/src/Photos.vue
@@ -22,6 +22,17 @@
<template>
<Content app-name="photos">
+ <AppNavigation>
+ <AppNavigationItem :to="{name: 'root'}"
+ class="app-navigation__photos"
+ :title="t('photos', 'Your photos')"
+ icon="icon-photos" />
+ <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: 'maps'}" :title="t('photos', 'Locations')" icon="icon-address" />
+ </AppNavigation>
<AppContent :class="{ 'icon-loading': loading }">
<router-view v-show="!loading" :loading.sync="loading" />
@@ -34,6 +45,8 @@
<script>
import Content from '@nextcloud/vue/dist/Components/Content'
import AppContent from '@nextcloud/vue/dist/Components/AppContent'
+import AppNavigation from '@nextcloud/vue/dist/Components/AppNavigation'
+import AppNavigationItem from '@nextcloud/vue/dist/Components/AppNavigationItem'
import svgplaceholder from './assets/img-placeholder.svg'
export default {
@@ -41,6 +54,8 @@ export default {
components: {
Content,
AppContent,
+ AppNavigation,
+ AppNavigationItem,
},
data: function() {
return {
@@ -50,3 +65,8 @@ export default {
},
}
</script>
+<style lang="scss" scoped>
+.app-navigation__photos::v-deep .app-navigation-entry-icon.icon-photos {
+ background-size: 20px;
+}
+</style>
diff --git a/src/components/Folder.vue b/src/components/Folder.vue
index 5dec6b5a..de2db5a6 100644
--- a/src/components/Folder.vue
+++ b/src/components/Folder.vue
@@ -23,7 +23,7 @@
<template>
<router-link :class="{'folder--clear': isEmpty}"
class="folder"
- :to="folder.filename"
+ :to="to"
:aria-label="ariaLabel">
<transition name="fade">
<div v-show="loaded"
@@ -39,8 +39,8 @@
</transition>
<div
class="folder-name">
- <span :class="{'icon-white': !isEmpty}"
- class="folder-name__icon icon-folder"
+ <span :class="[!isEmpty ? 'icon-white' : 'icon-dark', icon]"
+ class="folder-name__icon"
role="img" />
<p :id="ariaUuid" class="folder-name__name">
{{ folder.basename }}
@@ -66,6 +66,10 @@ export default {
type: Object,
required: true,
},
+ icon: {
+ type: String,
+ default: 'icon-folder',
+ },
},
data() {
@@ -106,6 +110,20 @@ export default {
ariaLabel() {
return t('photos', 'Open the "{name}" sub-directory', { name: this.folder.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
+ * does not encode afterwards
+ */
+ to() {
+ const route = Object.assign({}, this.$route, {
+ // always remove first slash
+ params: { path: this.folder.filename.substr(1) }
+ });
+ return decodeURIComponent(this.$router.resolve(route).resolved.path)
+ },
},
async created() {
@@ -215,6 +233,9 @@ $name-height: 1.2rem;
.folder {
// if no img, let's display the folder icon as default black
&--clear {
+ .folder-name__icon {
+ opacity: .3;
+ }
.folder-name__name {
color: var(--color-main-text);
text-shadow: 0 0 8px var(--color-main-background);
diff --git a/src/components/Grid.vue b/src/components/Grid.vue
new file mode 100644
index 00000000..85023f5a
--- /dev/null
+++ b/src/components/Grid.vue
@@ -0,0 +1,87 @@
+<!--
+ - @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/>.
+ -
+ -->
+
+<template>
+ <!-- Folder content -->
+ <transition-group
+ class="photos-grid"
+ role="grid"
+ name="list"
+ tag="div">
+ <slot />
+ <div key="footer" role="none" class="photos-grid__footer-spacer" />
+ </transition-group>
+</template>
+
+<script>
+export default {
+ name: 'Grid',
+}
+</script>
+
+<style scoped lang="scss">
+.photos-grid {
+ display: grid;
+ align-items: center;
+ justify-content: center;
+ gap: 8px;
+ grid-template-columns: repeat(10, 1fr);
+ position: relative;
+
+ // always put one more row of grid for the spacer
+ &__footer-spacer {
+ // always add one row, so placing it on the first
+ // column will always add one more
+ grid-column: 1;
+ // same height as the width
+ padding-bottom: 100%;
+ }
+}
+
+.list-move {
+ transition: transform var(--animation-quick);
+}
+
+// TODO: use mixins/GridSizes as soon as node-sass supports it
+// needs node-sass 5.0 (with libsass 3.6)
+// https://github.com/sass/node-sass/pull/2312
+$previous: 0;
+@each $size, $config in get('sizes') {
+ $count: map-get($config, 'count');
+ $marginTop: map-get($config, 'marginTop');
+ $marginW: map-get($config, 'marginW');
+
+ // if this is the last entry, only use min-width
+ $rule: '(min-width: #{$previous}px) and (max-width: #{$size}px)';
+ @if $size == 'max' {
+ $rule: '(min-width: #{$previous}px)';
+ }
+
+ @media #{$rule} {
+ .photos-grid {
+ padding: #{$marginTop}px #{$marginW}px #{$marginW}px #{$marginW}px;
+ grid-template-columns: repeat($count, 1fr);
+ }
+ }
+ $previous: $size;
+}
+</style>
diff --git a/src/components/Navigation.vue b/src/components/Navigation.vue
index facbdf10..df1c3f0f 100644
--- a/src/components/Navigation.vue
+++ b/src/components/Navigation.vue
@@ -89,11 +89,25 @@ export default {
}
return t('photos', 'Back to {folder}', { folder: this.parentName })
},
+
+ /**
+ * 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
+ * does not encode afterwards
+ */
+ to() {
+ const route = Object.assign({}, this.$route, {
+ // always remove first slash
+ params: { path: this.parentPath.substr(1) }
+ });
+ return decodeURIComponent(this.$router.resolve(route).resolved.path)
+ },
},
methods: {
folderUp() {
- this.$router.push(this.parentPath)
+ this.$router.push(this.to)
},
},
}
diff --git a/src/main.js b/src/main.js
index 595ecb95..5e4a96d3 100644
--- a/src/main.js
+++ b/src/main.js
@@ -26,7 +26,7 @@ import { sync } from 'vuex-router-sync'
import { translate, translatePlural } from '@nextcloud/l10n'
import Vue from 'vue'
-import Gallery from './Gallery'
+import Photos from './Photos'
import router from './router'
import store from './store'
@@ -49,8 +49,8 @@ Vue.prototype.n = translatePlural
export default new Vue({
el: '#content',
// eslint-disable-next-line vue/match-component-file-name
- name: 'GalleryRoot',
+ name: 'PhotosRoot',
router,
store,
- render: h => h(Gallery),
+ render: h => h(Photos),
})
diff --git a/src/router/index.js b/src/router/index.js
index 80dcdd5e..df464138 100644
--- a/src/router/index.js
+++ b/src/router/index.js
@@ -24,10 +24,17 @@ import { generateUrl } from '@nextcloud/router'
import Router from 'vue-router'
import Vue from 'vue'
-import Grid from '../views/Grid'
+import Albums from '../views/Albums'
+import Tags from '../views/Tags'
Vue.use(Router)
+// shortcut to properly format the path prop
+const props = route => ({
+ // always lead current path with a slash
+ path: `/${route.params.path ? route.params.path : ''}`,
+})
+
export default new Router({
mode: 'history',
// if index.php is in the url AND we got this far, then it's working:
@@ -37,20 +44,65 @@ export default new Router({
routes: [
{
path: '/',
- component: Grid,
- props: route => ({
- // always lead current path with a slash
- path: `/${route.params.path ? route.params.path : ''}`,
- }),
+ component: Albums,
name: 'root',
+ },
+ {
+ path: '/albums',
+ component: Albums,
+ name: 'albums',
+ props,
+ children: [
+ {
+ path: ':path*',
+ name: 'path',
+ component: Albums,
+ },
+ ],
+ },
+ {
+ path: '/shared',
+ component: Albums,
+ name: 'shared',
+ props,
+ children: [
+ {
+ path: ':path*',
+ name: 'path',
+ component: Albums,
+ },
+ ],
+ },
+ {
+ path: '/favorites',
+ component: Tags,
+ name: 'favorites',
+ props,
children: [
{
path: ':path*',
name: 'path',
- component: Grid,
+ component: Tags,
},
],
},
- { path: '*', redirect: { name: 'root' } },
+ {
+ path: '/tags',
+ component: Tags,
+ name: 'tags',
+ props,
+ children: [
+ {
+ path: ':path*',
+ name: 'path',
+ component: Tags,
+ },
+ ],
+ },
+ {
+ path: '/maps',
+ name: 'maps',
+ redirect: '',
+ },
],
})
diff --git a/src/services/DavClient.js b/src/services/DavClient.js
index acdfdf1b..c91b57e8 100644
--- a/src/services/DavClient.js
+++ b/src/services/DavClient.js
@@ -24,14 +24,13 @@ import webdav from 'webdav'
import axios from '@nextcloud/axios'
import parseUrl from 'url-parse'
import { generateRemoteUrl } from '@nextcloud/router'
-import { getCurrentUser } from '@nextcloud/auth'
// force our axios
const patcher = webdav.getPatcher()
patcher.patch('request', axios)
// init webdav client
-const remote = generateRemoteUrl(`dav/files/${getCurrentUser().uid}`)
+const remote = generateRemoteUrl(`dav`)
const client = webdav.createClient(remote)
export const remotePath = parseUrl(remote).pathname
diff --git a/src/services/FileList.js b/src/services/FileList.js
index 2ee84328..80e9df6d 100644
--- a/src/services/FileList.js
+++ b/src/services/FileList.js
@@ -20,12 +20,14 @@
*
*/
+import { getCurrentUser } from '@nextcloud/auth'
import { getSingleValue, getValueForKey, parseXML, propsToStat } from 'webdav/dist/interface/dav'
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'
/**
* List files from a folder and filter out unwanted mimes
@@ -46,6 +48,8 @@ export default async function(path, options) {
details: true,
}, options)
+ const prefixPath = `/files/${getCurrentUser().uid}`
+
/**
* Fetch listing
*
@@ -54,7 +58,7 @@ export default async function(path, options) {
* see https://github.com/perry-mitchell/webdav-client/blob/baf858a4856d44ae19ac12cb10c469b3e6c41ae4/source/interface/directoryContents.js#L11
*/
let response = null
- const { data } = await client.customRequest(path, options)
+ const { data } = await client.customRequest(prefixPath + path, options)
.then(handleResponseCode)
.then(res => {
response = res
@@ -64,14 +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(entry => {
- return Object.assign({
- id: parseInt(entry.props.fileid),
- isFavorite: entry.props.favorite !== '0',
- hasPreview: entry.props['has-preview'] !== 'false',
- }, entry)
- })
+ const list = data.map(data => parseFile(data, prefixPath))
// filter all the files and folders
let folder = {}
@@ -91,6 +88,15 @@ export default async function(path, options) {
return { folder, folders, files }
}
+/**
+ * Modified function to include the root requested folder
+ * Into the returned data
+ *
+ * @param {Object} result the request result
+ * @param {string} serverBasePath server base path
+ * @param {boolean} isDetailed detailed request
+ * @returns {Array}
+ */
function getDirectoryFiles(result, serverBasePath, isDetailed = false) {
const serverBase = pathPosix.join(serverBasePath, '/')
// Extract the response items (directory contents)
diff --git a/src/services/FolderInfo.js b/src/services/FolderInfo.js
index b95d7c67..6d65b57a 100644
--- a/src/services/FolderInfo.js
+++ b/src/services/FolderInfo.js
@@ -20,8 +20,10 @@
*
*/
+import { getCurrentUser } from '@nextcloud/auth'
import client from './DavClient'
import request from './DavRequest'
+import parseFile from '../utils/ParseFile'
/**
* List files from a folder and filter out unwanted mimes
@@ -33,17 +35,13 @@ export default async function(path) {
// getDirectoryContents doesn't accept / for root
const fixedPath = path === '/' ? '' : path
+ const prefixPath = `/files/${getCurrentUser().uid}`
+
// fetch listing
- const response = await client.stat(fixedPath, {
+ const response = await client.stat(prefixPath + fixedPath, {
data: request,
details: true,
})
- const entry = response.data
- return Object.assign({
- id: parseInt(entry.props.fileid),
- isFavorite: entry.props.favorite !== '0',
- hasPreview: entry.props['has-preview'] !== 'false',
- }, entry)
-
+ return parseFile(response.data, prefixPath)
}
diff --git a/src/services/PhotoSearch.js b/src/services/PhotoSearch.js
index b780ba2c..e4546bb4 100644
--- a/src/services/PhotoSearch.js
+++ b/src/services/PhotoSearch.js
@@ -20,8 +20,10 @@
*
*/
-import client from './DavClient'
+import { generateRemoteUrl } from '@nextcloud/router'
import { getCurrentUser } from '@nextcloud/auth'
+import client from './DavClient'
+import parseFile from '../utils/ParseFile'
/**
* List files from a folder and filter out unwanted mimes
@@ -35,7 +37,7 @@ export default async function() {
headers: {
'content-Type': 'text/xml',
},
- url: '/remote.php/dav/',
+ url: generateRemoteUrl(`dav`),
data: `<?xml version="1.0" encoding="UTF-8"?>
<d:searchrequest xmlns:d="DAV:"
xmlns:oc="http://owncloud.org/ns"
diff --git a/src/services/SystemTags.js b/src/services/SystemTags.js
new file mode 100644
index 00000000..a8ce55eb
--- /dev/null
+++ b/src/services/SystemTags.js
@@ -0,0 +1,56 @@
+/**
+ * @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 client from './DavClient'
+import { generateRemoteUrl } from '@nextcloud/router'
+
+/**
+ * List files from a folder and filter out unwanted mimes
+ *
+ * @returns {Array} the file list
+ */
+export default async function() {
+ const response = await client.getDirectoryContents('/systemtags/', {
+ data: `<?xml version="1.0"?>
+ <d:propfind xmlns:d="DAV:"
+ xmlns:oc="http://owncloud.org/ns">
+ <d:prop>
+ <oc:id />
+ <oc:display-name />
+ <oc:user-visible />
+ <oc:user-assignable />
+ <oc:can-assign />
+ </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)
+
+}
diff --git a/src/store/index.js b/src/store/index.js
index d7593570..e48270b7 100644
--- a/src/store/index.js
+++ b/src/store/index.js
@@ -25,12 +25,14 @@ import Vuex, { Store } from 'vuex'
import files from './files'
import folders from './folders'
+import systemtags from './systemtags'
Vue.use(Vuex)
export default new Store({
modules: {
files,
folders,
+ systemtags,
},
strict: process.env.NODE_ENV !== 'production',
diff --git a/src/store/systemtags.js b/src/store/systemtags.js
new file mode 100644
index 00000000..8f213e9e
--- /dev/null
+++ b/src/store/systemtags.js
@@ -0,0 +1,99 @@
+/**
+ * @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 Vue from 'vue'
+
+const state = {
+ paths: {},
+ tags: {},
+}
+
+const mutations = {
+ /**
+ * Index folders paths and ids
+ *
+ * @param {Object} state vuex state
+ * @param {Object} data destructuring object
+ * @param {number} data.id current folder id
+ * @param {Array} data.files list of files
+ */
+ 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()
+ })
+
+ // Set folder list
+ Vue.set(state.tags, id, list.map(file => file.id))
+ }
+ },
+
+ /**
+ * Index folders paths and ids
+ *
+ * @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
+ */
+ addPath(state, { path, id }) {
+ Vue.set(state.paths, path, id)
+ },
+}
+
+const getters = {
+ tags: state => state.tags,
+ tag: state => id => state.tags[id],
+ tagId: state => path => state.paths[path],
+}
+
+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
+ */
+ 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 }))
+ },
+
+ /**
+ * Index folders paths and ids
+ *
+ * @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
+ */
+ addPath(context, { path, id }) {
+ context.commit('addPath', { path, id })
+ },
+}
+
+export default { state, mutations, getters, actions }
diff --git a/src/utils/ParseFile.js b/src/utils/ParseFile.js
new file mode 100644
index 00000000..8d9d9baf
--- /dev/null
+++ b/src/utils/ParseFile.js
@@ -0,0 +1,37 @@
+/**
+ * @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/>.
+ *
+ */
+
+/**
+ * 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 })
+}
diff --git a/src/views/Grid.vue b/src/views/Albums.vue
index 849fd99b..98642e3d 100644
--- a/src/views/Grid.vue
+++ b/src/views/Albums.vue
@@ -33,16 +33,11 @@
</EmptyContent>
<!-- Folder content -->
- <transition-group v-else
- class="photos-grid"
- role="grid"
- name="list"
- tag="div">
+ <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" />
- <div key="footer" role="none" class="photos-grid__footer-spacer" />
- </transition-group>
+ </Grid>
</template>
<script>
@@ -55,16 +50,18 @@ import getPictures from '../services/FileList'
import EmptyContent from './EmptyContent'
import Folder from '../components/Folder'
import File from '../components/File'
+import Grid from '../components/Grid'
import Navigation from '../components/Navigation'
import cancelableRequest from '../utils/CancelableRequest'
export default {
- name: 'Grid',
+ name: 'Albums',
components: {
EmptyContent,
File,
Folder,
+ Grid,
Navigation,
},
props: {
@@ -205,50 +202,3 @@ export default {
}
</script>
-
-<style lang="scss">
-.photos-grid {
- display: grid;
- align-items: center;
- justify-content: center;
- gap: 8px;
- grid-template-columns: repeat(10, 1fr);
- position: relative;
- // always put one more row of grid for the spacer
- &__footer-spacer {
- // always add one row, so placing it on the first
- // column will always add one more
- grid-column: 1;
- // same height as the width
- padding-bottom: 100%;
- }
-}
-
-.list-move {
- transition: transform var(--animation-quick);
-}
-
-// TODO: use mixins/GridSizes as soon as node-sass supports it
-// needs node-sass 5.0 (with libsass 3.6)
-// https://github.com/sass/node-sass/pull/2312
-$previous: 0;
-@each $size, $config in get('sizes') {
- $count: map-get($config, 'count');
- $marginTop: map-get($config, 'marginTop');
- $marginW: map-get($config, 'marginW');
-
- // if this is the last entry, only use min-width
- $rule: '(min-width: #{$previous}px) and (max-width: #{$size}px)';
- @if $size == 'max' {
- $rule: '(min-width: #{$previous}px)';
- }
-
- @media #{$rule} {
- .photos-grid {
- padding: #{$marginTop}px #{$marginW}px #{$marginW}px #{$marginW}px;
- grid-template-columns: repeat($count, 1fr);
- }
- }
- $previous: $size;
-}
-</style>
diff --git a/src/views/Tags.vue b/src/views/Tags.vue
new file mode 100644
index 00000000..8180b2bc
--- /dev/null
+++ b/src/views/Tags.vue
@@ -0,0 +1,111 @@
+<!--
+ - @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/>.
+ -
+ -->
+
+<template>
+ <!-- Errors handlers-->
+ <!-- <EmptyContent v-if="error === 404" illustration-name="folder">
+ {{ t('photos', 'This folder does not exists') }}
+ </EmptyContent>
+ <EmptyContent v-else-if="error">
+ {{ t('photos', 'An error occurred') }}
+ </EmptyContent>
+ <EmptyContent v-else-if="!loading && isEmpty" illustration-name="empty">
+ {{ t('photos', 'This folder does not contain pictures') }}
+ </EmptyContent> -->
+
+ <!-- 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" />
+ <File v-for="file in fileList" :key="file.id" v-bind="file" />
+ </Grid> -->
+ <span>Test</span>
+</template>
+
+<script>
+import { mapGetters } from 'vuex'
+
+import getSystemTags from '../services/SystemTags'
+
+import EmptyContent from './EmptyContent'
+import Folder from '../components/Folder'
+import File from '../components/File'
+import Grid from '../components/Grid'
+import Navigation from '../components/Navigation'
+
+import cancelableRequest from '../utils/CancelableRequest'
+
+export default {
+ name: 'Tags',
+ components: {
+ EmptyContent,
+ File,
+ Folder,
+ Grid,
+ Navigation,
+ },
+ props: {
+ path: {
+ type: String,
+ default: '/',
+ },
+ loading: {
+ type: Boolean,
+ required: true,
+ },
+ },
+
+ data() {
+ return {
+ error: null,
+ cancelRequest: () => {},
+ }
+ },
+
+ computed: {
+ // global lists
+ ...mapGetters([
+ 'files',
+ 'tags',
+ ]),
+ },
+
+ watch: {
+ path(path) {
+ console.debug('changed:', path)
+ this.fetchFolderContent()
+ },
+ },
+
+ async beforeMount() {
+ console.debug('beforemount: GRID')
+ this.fetchFolderContent()
+ },
+
+ methods: {
+ async fetchFolderContent() {
+ await getSystemTags()
+ },
+ },
+
+}
+</script>