album: refactor picker
Signed-off-by: Varun Patil <radialapps@gmail.com>pull/767/head
parent
5890daba1a
commit
d32793e9c0
|
@ -1,5 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<svg width="800px" height="800px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
||||||
<rect width="24" height="24" fill="none"/>
|
|
||||||
<path d="M5 13.3636L8.03559 16.3204C8.42388 16.6986 9.04279 16.6986 9.43108 16.3204L19 7" stroke="#000000" stroke-linecap="round" stroke-linejoin="round"/>
|
|
||||||
</svg>
|
|
Before Width: | Height: | Size: 350 B |
|
@ -13,38 +13,31 @@
|
||||||
albumName: album.name,
|
albumName: album.name,
|
||||||
})
|
})
|
||||||
"
|
"
|
||||||
@click.prevent="() => {}"
|
@click.prevent="toggleAlbumSelection(album)"
|
||||||
>
|
>
|
||||||
<template #icon>
|
<template #icon>
|
||||||
<XImg v-if="album.last_added_photo !== -1" class="album__image" :src="toCoverUrl(album.last_added_photo)" />
|
<XImg v-if="album.last_added_photo !== -1" class="album__image" :src="toCoverUrl(album.last_added_photo)" />
|
||||||
<div v-else class="album__image album__image--placeholder">
|
<div v-else class="album__image album__image--placeholder">
|
||||||
<ImageMultiple :size="32" />
|
<ImageMultipleIcon :size="32" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template #subtitle>
|
<template #subtitle>
|
||||||
<div @click.prevent="pickAlbum(album)">
|
<div>
|
||||||
{{ getSubtitle(album) }}
|
{{ getSubtitle(album) }}
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template #extra>
|
<template #extra>
|
||||||
<div
|
<div
|
||||||
v-if="!selectedAlbums.has(album)"
|
|
||||||
class="check-circle-icon check-circle-icon--inactive"
|
|
||||||
@click.prevent="toggleAlbumSelection(album)"
|
|
||||||
>
|
|
||||||
<XImg :src="checkmarkIcon" />
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
v-if="selectedAlbums.has(album)"
|
|
||||||
class="check-circle-icon"
|
class="check-circle-icon"
|
||||||
@click.prevent="toggleAlbumSelection(album)"
|
:class="{
|
||||||
|
'check-circle-icon--active': selection.has(album),
|
||||||
|
}"
|
||||||
>
|
>
|
||||||
<XImg :src="checkmarkIcon" />
|
<CheckIcon :size="20" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
</NcListItem>
|
</NcListItem>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
|
@ -56,24 +49,21 @@
|
||||||
@click="showAlbumCreationForm = true"
|
@click="showAlbumCreationForm = true"
|
||||||
>
|
>
|
||||||
<template #icon>
|
<template #icon>
|
||||||
<Plus />
|
<PlusIcon />
|
||||||
</template>
|
</template>
|
||||||
{{ t('memories', 'Create new album') }}
|
{{ t('memories', 'Create new album') }}
|
||||||
</NcButton>
|
</NcButton>
|
||||||
|
|
||||||
<div class="submit-btn-wrapper">
|
<div class="submit-btn-wrapper">
|
||||||
<NcButton
|
<NcButton :aria-label="t('memories', 'Save')" class="new-album-button" type="primary" @click="submit">
|
||||||
:aria-label="t('memories', `Add to ${selectedCount} albums.`)"
|
{{ t('memories', 'Save changes') }}
|
||||||
class="new-album-button"
|
|
||||||
type="primary"
|
|
||||||
@click="submit"
|
|
||||||
>
|
|
||||||
{{ t('memories', 'Add to albums') }}
|
|
||||||
</NcButton>
|
</NcButton>
|
||||||
<span class="remove-notice" v-if="unselectedCount > 0">
|
<span class="remove-notice" v-if="deselection.size > 0">
|
||||||
{{ t('memories', 'And remove from') }} {{ n('memories', '{n} album', '{n} albums', unselectedCount , {
|
{{
|
||||||
n: unselectedCount,
|
n('memories', 'Removed from {n} album', 'Removed from {n} albums', deselection.size, {
|
||||||
})}}
|
n: this.deselection.size,
|
||||||
|
})
|
||||||
|
}}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -94,9 +84,6 @@ import { defineComponent } from 'vue';
|
||||||
import { getCurrentUser } from '@nextcloud/auth';
|
import { getCurrentUser } from '@nextcloud/auth';
|
||||||
|
|
||||||
import AlbumForm from './AlbumForm.vue';
|
import AlbumForm from './AlbumForm.vue';
|
||||||
import Plus from 'vue-material-design-icons/Plus.vue';
|
|
||||||
import ImageMultiple from 'vue-material-design-icons/ImageMultiple.vue';
|
|
||||||
import checkmarkIcon from '../../assets/checkmark.svg';
|
|
||||||
|
|
||||||
import axios from '@nextcloud/axios';
|
import axios from '@nextcloud/axios';
|
||||||
|
|
||||||
|
@ -108,6 +95,10 @@ import { IAlbum, IPhoto } from '../../types';
|
||||||
import { API } from '../../services/API';
|
import { API } from '../../services/API';
|
||||||
import { PropType } from 'vue';
|
import { PropType } from 'vue';
|
||||||
|
|
||||||
|
import PlusIcon from 'vue-material-design-icons/Plus.vue';
|
||||||
|
import ImageMultipleIcon from 'vue-material-design-icons/ImageMultiple.vue';
|
||||||
|
import CheckIcon from 'vue-material-design-icons/Check.vue';
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'AlbumPicker',
|
name: 'AlbumPicker',
|
||||||
props: {
|
props: {
|
||||||
|
@ -119,29 +110,26 @@ export default defineComponent({
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
AlbumForm,
|
AlbumForm,
|
||||||
Plus,
|
|
||||||
ImageMultiple,
|
|
||||||
NcButton,
|
NcButton,
|
||||||
NcListItem,
|
NcListItem,
|
||||||
|
|
||||||
|
PlusIcon,
|
||||||
|
ImageMultipleIcon,
|
||||||
|
CheckIcon,
|
||||||
},
|
},
|
||||||
|
|
||||||
data: () => ({
|
data: () => ({
|
||||||
showAlbumCreationForm: false,
|
showAlbumCreationForm: false,
|
||||||
albums: [] as IAlbum[],
|
|
||||||
loadingAlbums: true,
|
loadingAlbums: true,
|
||||||
photoId: -1,
|
/** List of all albums */
|
||||||
checkmarkIcon,
|
albums: [] as IAlbum[],
|
||||||
selectedAlbums: new Set<IAlbum>(),
|
/** All selected albums */
|
||||||
unselectedAlbums: new Set<IAlbum>(),
|
selection: new Set<IAlbum>(),
|
||||||
selectedCount: 0,
|
/** Deselected albums that were previously selected */
|
||||||
unselectedCount: 0,
|
deselection: new Set<IAlbum>(),
|
||||||
}),
|
}),
|
||||||
|
|
||||||
mounted() {
|
mounted() {
|
||||||
if (this.photos.length === 1) {
|
|
||||||
// this only makes sense when we try to add single photo to albums
|
|
||||||
this.photoId = this.photos[0].fileid;
|
|
||||||
}
|
|
||||||
this.loadAlbums();
|
this.loadAlbums();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -176,11 +164,14 @@ export default defineComponent({
|
||||||
|
|
||||||
async loadAlbums() {
|
async loadAlbums() {
|
||||||
try {
|
try {
|
||||||
const res = await axios.get<IAlbum[]>(API.ALBUM_LIST(3, this.photoId));
|
// this only makes sense when we try to add single photo to albums
|
||||||
|
const photoId = this.photos.length === 1 ? this.photos[0].fileid : -1;
|
||||||
|
|
||||||
|
// get albums, possibly for one photo
|
||||||
|
const res = await axios.get<IAlbum[]>(API.ALBUM_LIST(3, photoId));
|
||||||
this.albums = res.data;
|
this.albums = res.data;
|
||||||
this.selectedAlbums = new Set(this.albums.filter(album => album.has_file));
|
this.selection = new Set(this.albums.filter((album) => album.has_file));
|
||||||
this.unselectedAlbums = new Set();
|
this.deselection = new Set();
|
||||||
this.unselectedCount = 0;
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(e);
|
console.error(e);
|
||||||
} finally {
|
} finally {
|
||||||
|
@ -189,32 +180,24 @@ export default defineComponent({
|
||||||
},
|
},
|
||||||
|
|
||||||
toggleAlbumSelection(album: IAlbum) {
|
toggleAlbumSelection(album: IAlbum) {
|
||||||
if (this.selectedAlbums.has(album)) {
|
if (this.selection.has(album)) {
|
||||||
this.selectedAlbums.delete(album);
|
this.selection.delete(album);
|
||||||
this.unselectedAlbums.add(album)
|
|
||||||
} else if (this.unselectedAlbums.has(album)) {
|
// deselection only if originally selected
|
||||||
this.selectedAlbums.add(album)
|
if (album.has_file) {
|
||||||
this.unselectedAlbums.delete(album);
|
this.deselection.add(album);
|
||||||
} else {
|
|
||||||
this.selectedAlbums.add(album)
|
|
||||||
}
|
|
||||||
|
|
||||||
this.unselectedCount = this.albums.reduce((acc, album) => {
|
|
||||||
if (album.has_file && this.unselectedAlbums.has(album)) {
|
|
||||||
acc += 1;
|
|
||||||
}
|
}
|
||||||
return acc;
|
} else {
|
||||||
}, 0); this.selectedAlbums.size;
|
this.selection.add(album);
|
||||||
this.selectedCount = this.selectedAlbums.size;
|
this.deselection.delete(album);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.$forceUpdate(); // sets do not trigger reactivity
|
||||||
},
|
},
|
||||||
|
|
||||||
pickAlbum(album: IAlbum) {
|
|
||||||
this.$emit('select', [album], []);
|
|
||||||
},
|
|
||||||
|
|
||||||
submit() {
|
submit() {
|
||||||
this.$emit('select', Array.from(this.selectedAlbums), Array.from(this.unselectedAlbums));
|
this.$emit('select', Array.from(this.selection), Array.from(this.deselection));
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
@ -276,17 +259,18 @@ export default defineComponent({
|
||||||
|
|
||||||
.check-circle-icon {
|
.check-circle-icon {
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
border: 1px solid rgba(0, 255, 0, 0.1882352941);
|
border: 1px solid rgba($color: black, $alpha: 0.1);
|
||||||
background-color: rgba(0, 255, 0, 0.1882352941);
|
background-color: transparent;
|
||||||
height: 34px;
|
height: 34px;
|
||||||
width: 34px;
|
width: 34px;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
|
||||||
&--inactive {
|
&--active {
|
||||||
border: 1px solid rgba($color: black, $alpha: 0.1);
|
border: 1px solid var(--color-primary);
|
||||||
background-color: transparent;
|
background-color: var(--color-primary-default);
|
||||||
|
color: var(--color-primary-text);
|
||||||
}
|
}
|
||||||
|
|
||||||
& img {
|
& img {
|
||||||
|
|
Loading…
Reference in New Issue