Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Select root folder for timeline #515

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions lib/Controller/PageController.php
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,10 @@ public function index(): TemplateResponse {
$this->initialStateService->provideInitialState($this->appName, 'image-mimes', Application::IMAGE_MIMES);
$this->initialStateService->provideInitialState($this->appName, 'video-mimes', Application::VIDEO_MIMES);
$this->initialStateService->provideInitialState($this->appName, 'maps', $this->appManager->isEnabledForUser('maps') === true);

// User Settings
$this->initialStateService->provideInitialState($this->appName, 'croppedLayout', $this->config->getUserValue($user->getUid(), Application::APP_ID, 'croppedLayout', 'false'));
$this->initialStateService->provideInitialState($this->appName, 'timelineRootFolder', $this->config->getUserValue($user->getUid(), Application::APP_ID, 'timelineRootFolder', '/'));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should probably limit the allowed keys here:

$user = $this->userSession->getUser();

As a safety mesure 🤔

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure what you mean

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

setUserConfig allows anything, and will put it straight into the db.
Meaning we could override existing values. We should check if the $key is either timelineRootFolder or croppedLayout and throw otherwise as a safety measure

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok gotcha


Util::addScript(Application::APP_ID, 'photos-main');
Util::addStyle(Application::APP_ID, 'icons');
Expand Down
31 changes: 27 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
"@essentials/request-timeout": "^1.3.0",
"@nextcloud/auth": "^1.3.0",
"@nextcloud/axios": "^1.4.0",
"@nextcloud/dialogs": "^3.0.0",
"@nextcloud/event-bus": "^1.2.0",
"@nextcloud/initial-state": "^1.2.0",
"@nextcloud/l10n": "^1.4.1",
Expand Down
3 changes: 3 additions & 0 deletions src/Photos.vue
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
</template>
<template #footer>
<AppNavigationSettings :title="t('photos', 'Settings')">
<TimelineSettings />
<CroppedLayoutSettings />
</AppNavigationSettings>
</template>
Expand Down Expand Up @@ -70,6 +71,7 @@ import AppNavigationItem from '@nextcloud/vue/dist/Components/AppNavigationItem'
import AppNavigationSettings from '@nextcloud/vue/dist/Components/AppNavigationSettings'

import CroppedLayoutSettings from './components/Settings/CroppedLayoutSettings'
import TimelineSettings from './components/Settings/TimelineSettings'
import svgplaceholder from './assets/file-placeholder.svg'
import imgplaceholder from './assets/image.svg'
import videoplaceholder from './assets/video.svg'
Expand All @@ -80,6 +82,7 @@ export default {
components: {
Content,
CroppedLayoutSettings,
TimelineSettings,
AppContent,
AppNavigation,
AppNavigationItem,
Expand Down
7 changes: 7 additions & 0 deletions src/components/Settings/CroppedLayoutSettings.vue
Original file line number Diff line number Diff line change
Expand Up @@ -46,3 +46,10 @@ export default {
],
}
</script>

<style scoped>
.section {
padding: 10px;
margin-bottom: 5px;
}
</style>
73 changes: 73 additions & 0 deletions src/components/Settings/TimelineSettings.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
<!--
- @copyright Copyright (c) 2020 Corentin Mors
-
- @license GNU AGPL version 3 or any later version
-
- @author Corentin Mors <medias@pixelswap.fr>
-
- 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>
<div class="section">
<h2>{{ t('photos', 'Timeline') }}</h2>

<p>{{ t('photos', 'Folder for the timeline') }} : {{ timelineRootFolder }}/</p>
<button
@click="pickRootFolder">
{{ t('photos', 'Choose folder') }}
</button>
</div>
</template>

<script>
import { getFilePickerBuilder } from '@nextcloud/dialogs'
import UserConfig from '../../mixins/UserConfig'

export default {
name: 'TimelineSettings',

mixins: [
UserConfig,
],

methods: {
pickRootFolder() {
const picker = getFilePickerBuilder(t('photos', 'Choose a folder to display in the timeline'))
.setMultiSelect(false)
.addMimeTypeFilter('httpd/unix-directory')
.setModal(true)
.setType(1)
.allowDirectories(true)
.build()

return picker
.pick()
.then((dest) => {
this.timelineRootFolder = dest
this.updateSetting('timelineRootFolder')
location.reload()
})
},
},
}
</script>

<style scoped>
.section {
padding: 10px;
margin-bottom: 5px;
}
</style>
2 changes: 2 additions & 0 deletions src/mixins/UserConfig.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,9 @@ const eventName = 'photos:user-config-changed'
export default {
data() {
const croppedLayoutLocalStorage = localStorage.getItem('photos:croppedLayout')
const timelineRootFolderLocalStorage = localStorage.getItem('photos:timelineRootFolder')
return {
timelineRootFolder: timelineRootFolderLocalStorage || loadState('photos', 'timelineRootFolder'),
croppedLayout: croppedLayoutLocalStorage !== null
? croppedLayoutLocalStorage === 'true'
: loadState('photos', 'croppedLayout') === 'true',
Expand Down
22 changes: 14 additions & 8 deletions src/services/PhotoSearch.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,11 @@ export default async function(onlyFavorites = false, options = {}) {
page: 0, // start at the first page
perPage: sizes.max.count * 10, // ten rows of the max width
mimesType: allMimes, // all mimes types
rootFolder: '',
}, options)

const prefixPath = `/files/${getCurrentUser().uid}`
const davPath = `/files/${getCurrentUser().uid}`
const prefixPath = `${davPath}${options.rootFolder}`

// generating the search or condition
// based on the allowed mimetypes
Expand All @@ -68,6 +70,15 @@ export default async function(onlyFavorites = false, options = {}) {
</d:eq>`
: ''

const eqOwner = options.rootFolder === ''
? `<d:eq>
<d:prop>
<oc:owner-id/>
</d:prop>
<d:literal>${getCurrentUser().uid}</d:literal>
</d:eq>`
: ''
Comment on lines +74 to +80
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is needed to not have the shares as results.
Why did you need to put a condition on it?
It should not cause any issues like it was before :)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The owner filter is only allowed on the root. Dav throws this error if you try on subfolders. What do you think then?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Then it should be fixed on server.
cc @rullzer and @icewind1991 :)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.


options = Object.assign({
method: 'SEARCH',
headers: {
Expand Down Expand Up @@ -97,12 +108,7 @@ export default async function(onlyFavorites = false, options = {}) {
${orMime}
</d:or>
${eqFavorites}
<d:eq>
<d:prop>
<oc:owner-id/>
</d:prop>
<d:literal>${getCurrentUser().uid}</d:literal>
</d:eq>
${eqOwner}
</d:and>
</d:where>
<d:orderby>
Expand All @@ -126,6 +132,6 @@ export default async function(onlyFavorites = false, options = {}) {
return response.data
.map(data => genFileInfo(data))
// remove prefix path from full file path
.map(data => Object.assign({}, data, { filename: data.filename.replace(prefixPath, '') }))
.map(data => Object.assign({}, data, { filename: data.filename.replace(davPath, '') }))

}
4 changes: 3 additions & 1 deletion src/views/Timeline.vue
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ import Loader from '../components/Loader'

import cancelableRequest from '../utils/CancelableRequest'
import GridConfigMixin from '../mixins/GridConfig'
import UserConfig from '../mixins/UserConfig'
import { allMimes } from '../services/AllowedMimes'

export default {
Expand All @@ -80,7 +81,7 @@ export default {
VirtualGrid,
Navigation,
},
mixins: [GridConfigMixin],
mixins: [GridConfigMixin, UserConfig],
props: {
loading: {
type: Boolean,
Expand Down Expand Up @@ -237,6 +238,7 @@ export default {
page: this.page,
perPage: numberOfImagesPerBatch,
mimesType: this.mimesType,
rootFolder: this.timelineRootFolder,
})

// If we get less files than requested that means we got to the end
Expand Down