Skip to content

Commit

Permalink
Add Albums view
Browse files Browse the repository at this point in the history
Signed-off-by: Louis Chemineau <louis@chmn.me>
  • Loading branch information
artonge committed Aug 4, 2022
1 parent a26a89a commit a2d299a
Show file tree
Hide file tree
Showing 31 changed files with 2,521 additions and 807 deletions.
136 changes: 136 additions & 0 deletions src/components/AlbumCover.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
<!--
- @copyright Copyright (c) 2022 Louis Chemineau <louis@chmn.me>
-
- @author Louis Chemineau <louis@chmn.me>
-
- @license AGPL-3.0-or-later
-
- 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>
<router-link class="album-cover" :to="`/albums/${albumId}`">
<img class="album-cover__image" :src="coverUrl">
<div class="album-cover__details">
<div class="album-cover__details__first-line">
<h2 class="album-cover__details__name">
<!-- TODO: Remove "All" -->
{{ album.name || "All" }}
</h2>
<div class="album-cover__details__state">
<ShareVariant v-if="album.isShared" />
<AccountMultiple v-if="album.isCollaborative" />
</div>
</div>
<div class="album-cover__details__second-line">
{{ prettyCreationDate }} ⸱ {{ n('photos', '%n item', '%n items', album.itemCount,) }}
</div>
</div>
</router-link>
</template>

<script>

import { mapGetters } from 'vuex'
import ShareVariant from 'vue-material-design-icons/ShareVariant'
import AccountMultiple from 'vue-material-design-icons/AccountMultiple'

import moment from '@nextcloud/moment'
import { generateUrl } from '@nextcloud/router'

export default {
name: 'AlbumCover',

components: {
ShareVariant,
AccountMultiple,
},

props: {
albumId: {
type: String,
required: true,
},
},

computed: {
...mapGetters([
'files',
'albums',
]),

/**
* @return {Album}
*/
album() {
return this.albums[this.albumId]
},

/**
* @return {string}
*/
coverUrl() {
return generateUrl(`/core/preview?fileId=${this.album.cover}&x=${512}&y=${512}&forceIcon=0&a=1`)
},

/**
* @param {string}
*/
prettyCreationDate() {
return moment.unix(this.album.creationDate).format('MMMM YYYY')
},
},
}
</script>

<style lang="scss" scoped>
.album-cover {
display: flex;
flex-direction: column;

&__image {
width: 350px;
height: 350px;
object-fit: none;
border-radius: 12px;

@media only screen and (max-width: 1200px) {
width: 250px;
height: 250px;
}
}

&__details {
display: flex;
flex-direction: column;

&__first-line {
display: flex;
}

&__second-line {
display: flex;
color: var(--color-text-lighter);
}

&__name {
flex-grow: 1;
margin: 0;
font-weight: normal;
}
}

}
</style>
216 changes: 216 additions & 0 deletions src/components/AlbumCreationForm.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,216 @@
<!--
- @copyright Copyright (c) 2022 Louis Chemineau <louis@chmn.me>
-
- @author Louis Chemineau <louis@chmn.me>
-
- @license AGPL-3.0-or-later
-
- 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>
<form v-if="!showCollaboratorView" class="album-creation-form">
<div class="form-inputs">
<input ref="nameInput"
v-model="albumName"
type="text"
name="name"
required
autofocus="true"
:placeholder="t('photos', 'Name of the new album')">
<label>
<MapMarker /><input v-model="albumLocation"
type="text"
name="location"
:placeholder="t('photos', 'Add location')">
</label>
</div>
<div class="form-buttons">
<span class="left-buttons">
<Button v-if="displayBackButton"
:aria-label="t('photo', 'Go back to the previous view')"
type="tertiary"
@click="back">
{{ t('photo', 'Back') }}
</Button>
</span>
<span class="right-buttons">

<Button :aria-label="t('photo', 'Go to the add collaborators view.')"
type="secondary"
:disabled="albumName.trim() === '' || loading"
@click="showCollaboratorView = true">
<template #icon>
<AccountMultiplePlus />
</template>
{{ t('photo', 'Add collaborators') }}
</Button>
<Button :aria-label="t('photo', 'Create the album.')"
type="primary"
:disabled="albumName.trim() === '' || loading"
@click="createAlbum">
<template #icon>
<Loader v-if="loading" />
<Send v-else />
</template>
{{ t('photo', 'Create album') }}
</Button>
</span>
</div>
</form>
<CollaboratorsSelectionForm v-else
class="add-collaborators-form"
@cancel="showCollaboratorView = true"
@submit="createAlbum">
<template slot-scope="{collaborators}">
<span class="left-buttons">
<Button :aria-label="t('photo', 'Back to the new album form.')"
type="tertiary"
@click="showCollaboratorView = false">
{{ t('photo', 'Back') }}
</Button>
</span>
<span class="right-buttons">
<Button :aria-label="t('photo', 'Create the album.')"
type="primary"
:disabled="albumName.trim() === '' || loading"
@click="createAlbum(collaborators)">
<template #icon>
<Loader v-if="loading" />
<Send v-else />
</template>
{{ t('photo', 'Create album') }}
</Button>
</span>
</template>
</CollaboratorsSelectionForm>
</template>
<script>
import MapMarker from 'vue-material-design-icons/MapMarker'
import AccountMultiplePlus from 'vue-material-design-icons/AccountMultiplePlus'
import Send from 'vue-material-design-icons/Send'

import { Button } from '@nextcloud/vue'

import Loader from '../components/Loader.vue'
import CollaboratorsSelectionForm from '../components/CollaboratorsSelectionForm.vue'

export default {
name: 'AlbumCreationForm',

components: {
Button,
MapMarker,
AccountMultiplePlus,
Send,
Loader,
CollaboratorsSelectionForm,
},

props: {
displayBackButton: {
type: Boolean,
default: false,
},
},

data() {
return {
showCollaboratorView: false,
albumName: '',
albumLocation: '',
loading: false,
}
},

mounted() {
this.$nextTick(() => {
this.$refs.nameInput.focus()
})
},

methods: {
async createAlbum(collaborators = []) {
try {
this.loading = true
const album = await this.$store.dispatch('createAlbum', {
album: {
name: this.albumName,
location: this.albumLocation,
collaborators,
},
})
this.$emit('album-created', { album })
} finally {
this.loading = false
}
},

back() {
this.$emit('back')
},
},
}
</script>
<style lang="scss" scoped>
.album-creation-form {
display: flex;
flex-direction: column;
height: 350px;
padding: 16px;

.form-title {
font-weight: bold;
}

.form-subtitle {
color: var(--color-text-lighter);
}

.form-inputs {
flex-grow: 1;
justify-items: flex-end;

input {
width: 100%;
}

label {
display: flex;
margin-top: 16px;

::v-deep svg {
margin-right: 12px;
}
}
}

.form-buttons {
display: flex;
justify-content: space-between;

.left-buttons, .right-buttons {
display: flex;
}

.right-buttons {
justify-content: flex-end;
}

button {
margin-right: 16px;
}
}
}
</style>
Loading

0 comments on commit a2d299a

Please sign in to comment.