From 6688587eb6bdf118687c630378d40e36a3700a52 Mon Sep 17 00:00:00 2001
From: Zephyrrus <krisztian1997@gmail.com>
Date: Thu, 2 Jul 2020 02:48:21 +0300
Subject: feat: move toolbar into a level and add slot for pagination on grid

---
 src/site/components/grid/Grid.vue | 57 ++++++++++++++++++++-------------------
 1 file changed, 30 insertions(+), 27 deletions(-)

(limited to 'src/site/components/grid/Grid.vue')

diff --git a/src/site/components/grid/Grid.vue b/src/site/components/grid/Grid.vue
index b6615be..279472c 100644
--- a/src/site/components/grid/Grid.vue
+++ b/src/site/components/grid/Grid.vue
@@ -1,37 +1,40 @@
 <template>
 	<div>
-		<div v-if="enableToolbar"
-			class="toolbar">
-			<div class="block">
-				<b-radio v-model="showList"
-					name="name"
-					:native-value="true">
-					List
-				</b-radio>
-				<b-radio v-model="showList"
-					name="name"
-					:native-value="false">
-					Grid
-				</b-radio>
+		<nav class="level">
+			<div class="level-left">
+				<div class="level-item">
+					<slot name="pagination" />
+				</div>
 			</div>
-		</div>
+			<div v-if="enableToolbar"
+				class="level-right toolbar">
+				<div class="level-item">
+					<div class="block">
+						<b-radio v-model="showList"
+							name="name"
+							:native-value="true">
+							List
+						</b-radio>
+						<b-radio v-model="showList"
+							name="name"
+							:native-value="false">
+							Grid
+						</b-radio>
+					</div>
+				</div>
+			</div>
+		</nav>
 
 		<template v-if="!showList">
 			<Waterfall v-if="showWaterfall"
 				:gutterWidth="10"
 				:gutterHeight="4">
-				<!--
-					TODO: Implement search based on originalName, albumName and tags
-					<input v-if="enableSearch"
-						v-model="searchTerm"
-						type="text"
-						placeholder="Search..."
-						@input="search()"
-						@keyup.enter="search()">
-				-->
-
-				<!-- TODO: Implement pagination -->
-
+				<input v-if="enableSearch"
+					v-model="searchTerm"
+					type="text"
+					placeholder="Search..."
+					@input="search()"
+					@keyup.enter="search()">	
 				<WaterfallItem v-for="(item, index) in gridFiles"
 					:key="item.id"
 					:width="width"
@@ -289,7 +292,7 @@ export default {
 		isAlbumSelected(id) {
 			if (!this.showingModalForFile) return;
 			const found = this.showingModalForFile.albums.find(el => el.id === id);
-			return found ? found.id ? true : false : false;
+			return found && found.id ? true : false;
 		},
 		async openAlbumModal(file) {
 			this.showingModalForFile = file;
-- 
cgit v1.2.3


From c2dbbe6396540ee9d76991a00f5028b49d221d0c Mon Sep 17 00:00:00 2001
From: Zephyrrus <krisztian1997@gmail.com>
Date: Thu, 2 Jul 2020 23:42:02 +0300
Subject: feat: refactor account to use vuex, fix small presentational
 components

---
 src/site/components/grid/Grid.vue | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

(limited to 'src/site/components/grid/Grid.vue')

diff --git a/src/site/components/grid/Grid.vue b/src/site/components/grid/Grid.vue
index 279472c..a06eabf 100644
--- a/src/site/components/grid/Grid.vue
+++ b/src/site/components/grid/Grid.vue
@@ -198,6 +198,8 @@
 </template>
 
 <script>
+import { mapState } from 'vuex';
+
 import Waterfall from './waterfall/Waterfall.vue';
 import WaterfallItem from './waterfall/WaterfallItem.vue';
 
@@ -246,9 +248,9 @@ export default {
 		};
 	},
 	computed: {
-		user() {
-			return this.$store.state.user;
-		},
+		...mapState({
+			user: state => state.auth.user
+		}),
 		blank() {
 			return require('@/assets/images/blank.png');
 		},
-- 
cgit v1.2.3


From 92be4504ccb8f6d918013e5c33870858cd22376a Mon Sep 17 00:00:00 2001
From: Zephyrrus <krisztian1997@gmail.com>
Date: Sat, 4 Jul 2020 03:26:35 +0300
Subject: feat: refactor most of the album components to use store for
 presentation and actions

---
 src/site/components/grid/Grid.vue | 12 +++++-------
 1 file changed, 5 insertions(+), 7 deletions(-)

(limited to 'src/site/components/grid/Grid.vue')

diff --git a/src/site/components/grid/Grid.vue b/src/site/components/grid/Grid.vue
index a06eabf..956dd28 100644
--- a/src/site/components/grid/Grid.vue
+++ b/src/site/components/grid/Grid.vue
@@ -29,12 +29,6 @@
 			<Waterfall v-if="showWaterfall"
 				:gutterWidth="10"
 				:gutterHeight="4">
-				<input v-if="enableSearch"
-					v-model="searchTerm"
-					type="text"
-					placeholder="Search..."
-					@input="search()"
-					@keyup.enter="search()">	
 				<WaterfallItem v-for="(item, index) in gridFiles"
 					:key="item.id"
 					:width="width"
@@ -167,7 +161,7 @@
 				</template>
 				<template slot="footer">
 					<div class="has-text-right has-text-default">
-						{{ files.length }} files
+						Showing {{ files.length }} files ({{ total }} total)
 					</div>
 				</template>
 			</b-table>
@@ -213,6 +207,10 @@ export default {
 			type: Array,
 			default: () => []
 		},
+		total: {
+			type: Number,
+			default: 0
+		},
 		fixed: {
 			type: Boolean,
 			default: false
-- 
cgit v1.2.3


From 1e1f3fbb27976a34f53a4e8d250da34dad4e6c20 Mon Sep 17 00:00:00 2001
From: Zephyrrus <krisztian1997@gmail.com>
Date: Sat, 4 Jul 2020 23:18:51 +0300
Subject: feat: experimental videos in grid

---
 src/site/components/grid/Grid.vue | 32 ++++++++++++++++++++++----------
 1 file changed, 22 insertions(+), 10 deletions(-)

(limited to 'src/site/components/grid/Grid.vue')

diff --git a/src/site/components/grid/Grid.vue b/src/site/components/grid/Grid.vue
index 956dd28..0fff307 100644
--- a/src/site/components/grid/Grid.vue
+++ b/src/site/components/grid/Grid.vue
@@ -32,6 +32,7 @@
 				<WaterfallItem v-for="(item, index) in gridFiles"
 					:key="item.id"
 					:width="width"
+					:video="!!item.preview"
 					move-class="item-move">
 					<template v-if="isPublic">
 						<a :href="`${item.url}`"
@@ -42,7 +43,11 @@
 						</a>
 					</template>
 					<template v-else>
-						<img :src="item.thumb ? item.thumb : blank">
+						<img v-if="!item.preview" :class="{'hidden': item.preview}" 
+							:src="item.thumb ? item.thumb : blank">
+						<video v-if="item.preview" autoplay loop>
+  							<source :src="item.preview" type="video/mp4" />
+						</video>
 						<span v-if="!item.thumb && item.name"
 							class="extension">{{ item.name.split('.').pop() }}</span>
 						<div v-if="!isPublic"
@@ -56,21 +61,20 @@
 									<i class="icon-web-code" />
 								</a>
 							</b-tooltip>
-							<b-tooltip label="Albums"
+							<b-tooltip label="Tags"
 								position="is-top">
 								<a class="btn"
-									@click="openAlbumModal(item)">
-									<i class="icon-interface-window" />
+									@click="manageTags(item)">
+									<i class="icon-ecommerce-tag-c" />
 								</a>
 							</b-tooltip>
-							<!--
-							<b-tooltip label="Tags"
+							<b-tooltip label="Albums"
 								position="is-top">
-								<a @click="manageTags(item)">
-									<i class="icon-ecommerce-tag-c" />
+								<a class="btn"
+									@click="openAlbumModal(item)">
+									<i class="icon-interface-window" />
 								</a>
-							</b-tooltip>
-							-->
+							</b-tooltip>							
 							<b-tooltip label="Delete"
 								position="is-top">
 								<a class="btn"
@@ -318,6 +322,9 @@ export default {
 			const response = await this.$axios.$get(`albums/dropdown`);
 			this.albums = response.albums;
 			this.$forceUpdate();
+		},
+		mouseOverTest() {
+			console.log('aaaaaa');
 		}
 	}
 };
@@ -385,6 +392,7 @@ export default {
 			&:nth-child(1), &:nth-child(3) {
 				justify-content: flex-end;
 			}
+
 			a {
 				width: 30px;
 				height: 30px;
@@ -429,6 +437,10 @@ export default {
 			text-align: left;
 		}
 	}
+
+	img.hidden {
+		display: none;
+	}
 </style>
 
 <style lang="scss">
-- 
cgit v1.2.3


From 766e74cc51138b32482f65f0f2647eb9d943103e Mon Sep 17 00:00:00 2001
From: Zephyrrus <krisztian1997@gmail.com>
Date: Sun, 5 Jul 2020 04:18:08 +0300
Subject: feat: add video preview on hover to dashboard and apply new linter
 rules to some of the files

---
 src/site/components/grid/Grid.vue | 435 ++++++++++++++++++++------------------
 1 file changed, 225 insertions(+), 210 deletions(-)

(limited to 'src/site/components/grid/Grid.vue')

diff --git a/src/site/components/grid/Grid.vue b/src/site/components/grid/Grid.vue
index 0fff307..d4fe067 100644
--- a/src/site/components/grid/Grid.vue
+++ b/src/site/components/grid/Grid.vue
@@ -6,18 +6,13 @@
 					<slot name="pagination" />
 				</div>
 			</div>
-			<div v-if="enableToolbar"
-				class="level-right toolbar">
+			<div v-if="enableToolbar" class="level-right toolbar">
 				<div class="level-item">
 					<div class="block">
-						<b-radio v-model="showList"
-							name="name"
-							:native-value="true">
+						<b-radio v-model="showList" name="name" :native-value="true">
 							List
 						</b-radio>
-						<b-radio v-model="showList"
-							name="name"
-							:native-value="false">
+						<b-radio v-model="showList" name="name" :native-value="false">
 							Grid
 						</b-radio>
 					</div>
@@ -26,66 +21,71 @@
 		</nav>
 
 		<template v-if="!showList">
-			<Waterfall v-if="showWaterfall"
+			<Waterfall
+				v-if="showWaterfall"
 				:gutterWidth="10"
 				:gutterHeight="4">
-				<WaterfallItem v-for="(item, index) in gridFiles"
+				<WaterfallItem
+					v-for="(item, index) in gridFiles"
 					:key="item.id"
 					:width="width"
-					:video="!!item.preview"
 					move-class="item-move">
 					<template v-if="isPublic">
-						<a :href="`${item.url}`"
-							target="_blank">
+						<a
+							:href="`${item.url}`"
+							class="preview-container"
+							target="_blank"
+							@mouseenter.self.stop.prevent="item.preview && mouseOver(item.id)"
+							@mouseleave.self.stop.prevent="item.preview && mouseOut(item.id)">
+
 							<img :src="item.thumb ? item.thumb : blank">
-							<span v-if="!item.thumb && item.name"
-								class="extension">{{ item.name.split('.').pop() }}</span>
+							<div v-if="item.preview && isHovered(item.id)" class="preview">
+								<video ref="video" class="preview" autoplay loop muted>
+									<source :src="item.preview" type="video/mp4">
+								</video>
+							</div>
+
+							<span v-if="!item.thumb && item.name" class="extension">{{
+								item.name.split('.').pop()
+							}}</span>
 						</a>
 					</template>
 					<template v-else>
-						<img v-if="!item.preview" :class="{'hidden': item.preview}" 
-							:src="item.thumb ? item.thumb : blank">
-						<video v-if="item.preview" autoplay loop>
-  							<source :src="item.preview" type="video/mp4" />
-						</video>
-						<span v-if="!item.thumb && item.name"
-							class="extension">{{ item.name.split('.').pop() }}</span>
-						<div v-if="!isPublic"
+						<img :src="item.thumb ? item.thumb : blank">
+						<div v-if="item.preview && isHovered(item.id)" class="preview">
+							<video ref="video" class="preview" autoplay loop muted>
+								<source :src="item.preview" type="video/mp4">
+							</video>
+						</div>
+
+						<span v-if="!item.thumb && item.name" class="extension">{{ item.name.split('.').pop() }}</span>
+						<div
+							v-if="!isPublic"
 							:class="{ fixed }"
-							class="actions">
-							<b-tooltip label="Link"
-								position="is-top">
-								<a :href="`${item.url}`"
-									target="_blank"
-									class="btn">
+							class="actions"
+							@mouseenter.self.stop.prevent="item.preview && mouseOver(item.id)"
+							@mouseleave.self.stop.prevent="item.preview && mouseOut(item.id)">
+							<b-tooltip label="Link" position="is-top">
+								<a :href="`${item.url}`" target="_blank" class="btn">
 									<i class="icon-web-code" />
 								</a>
 							</b-tooltip>
-							<b-tooltip label="Tags"
-								position="is-top">
-								<a class="btn"
-									@click="manageTags(item)">
+							<b-tooltip label="Tags" position="is-top">
+								<a class="btn" @click="manageTags(item)">
 									<i class="icon-ecommerce-tag-c" />
 								</a>
 							</b-tooltip>
-							<b-tooltip label="Albums"
-								position="is-top">
-								<a class="btn"
-									@click="openAlbumModal(item)">
+							<b-tooltip label="Albums" position="is-top">
+								<a class="btn" @click="openAlbumModal(item)">
 									<i class="icon-interface-window" />
 								</a>
-							</b-tooltip>							
-							<b-tooltip label="Delete"
-								position="is-top">
-								<a class="btn"
-									@click="deleteFile(item, index)">
+							</b-tooltip>
+							<b-tooltip label="Delete" position="is-top">
+								<a class="btn" @click="deleteFile(item, index)">
 									<i class="icon-editorial-trash-a-l" />
 								</a>
 							</b-tooltip>
-							<b-tooltip v-if="user && user.isAdmin"
-								label="More info"
-								position="is-top"
-								class="more">
+							<b-tooltip v-if="user && user.isAdmin" label="More info" position="is-top" class="more">
 								<nuxt-link :to="`/dashboard/admin/file/${item.id}`">
 									<i class="icon-interface-more" />
 								</nuxt-link>
@@ -96,58 +96,42 @@
 			</Waterfall>
 		</template>
 		<div v-else>
-			<b-table
-				:data="gridFiles || []"
-				:mobile-cards="true">
+			<b-table :data="gridFiles || []" :mobile-cards="true">
 				<template slot-scope="props">
 					<template v-if="!props.row.hideFromList">
-						<b-table-column field="url"
-							label="URL">
-							<a :href="props.row.url"
-								target="_blank">{{ props.row.url }}</a>
+						<b-table-column field="url" label="URL">
+							<a :href="props.row.url" target="_blank">{{ props.row.url }}</a>
 						</b-table-column>
 
-						<b-table-column field="albums"
-							label="Albums"
-							centered>
+						<b-table-column field="albums" label="Albums" centered>
 							<template v-for="(album, index) in props.row.albums">
-								<nuxt-link :key="index"
-									:to="`/dashboard/albums/${album.id}`">
+								<nuxt-link :key="index" :to="`/dashboard/albums/${album.id}`">
 									{{ album.name }}
 								</nuxt-link>
-								<template v-if="index < props.row.albums.length - 1">, </template>
+								<template v-if="index < props.row.albums.length - 1">
+									,
+								</template>
 							</template>
 
 							{{ props.row.username }}
 						</b-table-column>
 
-						<b-table-column field="uploaded"
-							label="Uploaded"
-							centered>
+						<b-table-column field="uploaded" label="Uploaded" centered>
 							<span><timeago :since="props.row.createdAt" /></span>
 						</b-table-column>
 
-						<b-table-column field="purge"
-							centered>
-							<b-tooltip label="Albums"
-								position="is-top">
-								<a class="btn"
-									@click="openAlbumModal(props.row)">
+						<b-table-column field="purge" centered>
+							<b-tooltip label="Albums" position="is-top">
+								<a class="btn" @click="openAlbumModal(props.row)">
 									<i class="icon-interface-window" />
 								</a>
 							</b-tooltip>
-							<b-tooltip label="Delete"
-								position="is-top"
-								class="is-danger">
-								<a class="is-danger"
-									@click="deleteFile(props.row)">
+							<b-tooltip label="Delete" position="is-top" class="is-danger">
+								<a class="is-danger" @click="deleteFile(props.row)">
 									<i class="icon-editorial-trash-a-l" />
 								</a>
 							</b-tooltip>
-							<b-tooltip v-if="user && user.isAdmin"
-								label="More info"
-								position="is-top"
-								class="more">
+							<b-tooltip v-if="user && user.isAdmin" label="More info" position="is-top" class="more">
 								<nuxt-link :to="`/dashboard/admin/file/${props.row.id}`">
 									<i class="icon-interface-more" />
 								</nuxt-link>
@@ -170,21 +154,23 @@
 				</template>
 			</b-table>
 		</div>
-		<b-modal :active.sync="isAlbumsModalActive"
-			:width="640"
-			scroll="keep">
+		<b-modal :active.sync="isAlbumsModalActive" :width="640" scroll="keep">
 			<div class="card albumsModal">
 				<div class="card-content">
 					<div class="content">
-						<h3 class="subtitle">Select the albums this file should be a part of</h3>
+						<h3 class="subtitle">
+							Select the albums this file should be a part of
+						</h3>
 						<hr>
+
 						<div class="albums-container">
-							<div v-for="(album, index) in albums"
-								:key="index"
-								class="album">
+							<div v-for="(album, index) in albums" :key="index" class="album">
 								<div class="field">
-									<b-checkbox :value="isAlbumSelected(album.id)"
-										@input="albumCheckboxClicked($event, album.id)">{{ album.name }}</b-checkbox>
+									<b-checkbox
+										:value="isAlbumSelected(album.id)"
+										@input="albumCheckboxClicked($event, album.id)">
+										{{ album.name }}
+									</b-checkbox>
 								</div>
 							</div>
 						</div>
@@ -204,37 +190,37 @@ import WaterfallItem from './waterfall/WaterfallItem.vue';
 export default {
 	components: {
 		Waterfall,
-		WaterfallItem
+		WaterfallItem,
 	},
 	props: {
 		files: {
 			type: Array,
-			default: () => []
+			default: () => [],
 		},
 		total: {
 			type: Number,
-			default: 0
+			default: 0,
 		},
 		fixed: {
 			type: Boolean,
-			default: false
+			default: false,
 		},
 		isPublic: {
 			type: Boolean,
-			default: false
+			default: false,
 		},
 		width: {
 			type: Number,
-			default: 150
+			default: 150,
 		},
 		enableSearch: {
 			type: Boolean,
-			default: true
+			default: true,
 		},
 		enableToolbar: {
 			type: Boolean,
-			default: true
-		}
+			default: true,
+		},
 	},
 	data() {
 		return {
@@ -242,18 +228,20 @@ export default {
 			searchTerm: null,
 			showList: false,
 			albums: [],
+			hoveredItems: [],
 			isAlbumsModalActive: false,
 			showingModalForFile: null,
 			filesOffsetWaterfall: 0,
 			filesOffsetEndWaterfall: 50,
-			filesPerPageWaterfall: 50
+			filesPerPageWaterfall: 50,
 		};
 	},
 	computed: {
 		...mapState({
-			user: state => state.auth.user
+			user: (state) => state.auth.user,
 		}),
 		blank() {
+			// eslint-disable-next-line global-require, import/no-unresolved
 			return require('@/assets/images/blank.png');
 		},
 		gridFiles() {
@@ -262,12 +250,7 @@ export default {
 	},
 	methods: {
 		async search() {
-			const data = await this.$search.do(this.searchTerm, [
-				'name',
-				'original',
-				'type',
-				'albums:name'
-			]);
+			const data = await this.$search.do(this.searchTerm, ['name', 'original', 'type', 'albums:name']);
 			console.log('> Search result data', data);
 		},
 		deleteFile(file, index) {
@@ -290,13 +273,13 @@ export default {
 						});
 					}
 					return this.$buefy.toast.open(response.message);
-				}
+				},
 			});
 		},
 		isAlbumSelected(id) {
-			if (!this.showingModalForFile) return;
-			const found = this.showingModalForFile.albums.find(el => el.id === id);
-			return found && found.id ? true : false;
+			if (!this.showingModalForFile) return false;
+			const found = this.showingModalForFile.albums.find((el) => el.id === id);
+			return !!(found && found.id);
 		},
 		async openAlbumModal(file) {
 			this.showingModalForFile = file;
@@ -311,7 +294,7 @@ export default {
 		async albumCheckboxClicked(value, id) {
 			const response = await this.$axios.$post(`file/album/${value ? 'add' : 'del'}`, {
 				albumId: id,
-				fileId: this.showingModalForFile.id
+				fileId: this.showingModalForFile.id,
 			});
 			this.$buefy.toast.open(response.message);
 
@@ -319,134 +302,166 @@ export default {
 			this.$parent.getFiles();
 		},
 		async getAlbums() {
-			const response = await this.$axios.$get(`albums/dropdown`);
+			const response = await this.$axios.$get('albums/dropdown');
 			this.albums = response.albums;
 			this.$forceUpdate();
 		},
-		mouseOverTest() {
-			console.log('aaaaaa');
-		}
-	}
+		mouseOver(id) {
+			console.log('in', id);
+			const foundIndex = this.hoveredItems.indexOf(id);
+			if (foundIndex > -1) return;
+			this.hoveredItems.push(id);
+			/// XXX: THIS IS NOT OK!
+			this.$nextTick(() => {
+				this.$refs.video.forEach((e) => e.play().catch(() => {}));
+			});
+		},
+		mouseOut(id) {
+			console.log('out', id);
+			const foundIndex = this.hoveredItems.indexOf(id);
+			if (foundIndex > -1) this.hoveredItems.splice(foundIndex, 1);
+		},
+		isHovered(id) {
+			return this.hoveredItems.includes(id);
+		},
+	},
 };
 </script>
 
 <style lang="scss" scoped>
-	@import '~/assets/styles/_colors.scss';
-	.item-move {
-		transition: all .25s cubic-bezier(.55,0,.1,1);
-	}
+@import '~/assets/styles/_colors.scss';
+.item-move {
+	transition: all 0.25s cubic-bezier(0.55, 0, 0.1, 1);
+}
 
-	div.toolbar {
-		padding: 1rem;
+div.toolbar {
+	padding: 1rem;
 
-		.block {
-			text-align: right;
-		}
+	.block {
+		text-align: right;
 	}
+}
 
-	span.extension {
-		position: absolute;
-		width: 100%;
-		height: 100%;
-		z-index: 0;
-		top: 0;
-		left: 0;
-		display: flex;
-		align-items: center;
-		justify-content: center;
-		font-size: 2rem;
-		pointer-events: none;
-		opacity: .75;
-		max-width: 150px;
-	}
+span.extension {
+	position: absolute;
+	width: 100%;
+	height: 100%;
+	z-index: 0;
+	top: 0;
+	left: 0;
+	display: flex;
+	align-items: center;
+	justify-content: center;
+	font-size: 2rem;
+	pointer-events: none;
+	opacity: 0.75;
+	max-width: 150px;
+}
 
-	div.actions {
-		opacity: 0;
-		-webkit-transition: opacity 0.1s linear;
-		-moz-transition: opacity 0.1s linear;
-		-ms-transition: opacity 0.1s linear;
-		-o-transition: opacity 0.1s linear;
-		transition: opacity 0.1s linear;
-		position: absolute;
-		top: 0px;
-		left: 0px;
-		width: 100%;
-		height: calc(100% - 6px);
-		background: rgba(0, 0, 0, 0.5);
-		display: flex;
-		justify-content: center;
-		align-items: center;
-
-		span {
-			padding: 3px;
-			&.more {
-				position: absolute;
-				top: 0;
-				right: 0;
-			}
+div.preview {
+	position: absolute;
+	top: 0px;
+	left: 0px;
+	width: 100%;
+	height: calc(100% - 6px);
+	overflow: hidden;
+}
 
-			&:nth-child(1), &:nth-child(2) {
-				align-items: flex-end;
-			}
+.preview-container {
+	display: inline-block;
+}
 
-			&:nth-child(1), &:nth-child(3) {
-				justify-content: flex-end;
-			}
+div.actions {
+	opacity: 0;
+	-webkit-transition: opacity 0.1s linear;
+	-moz-transition: opacity 0.1s linear;
+	-ms-transition: opacity 0.1s linear;
+	-o-transition: opacity 0.1s linear;
+	transition: opacity 0.1s linear;
+	position: absolute;
+	top: 0px;
+	left: 0px;
+	width: 100%;
+	height: calc(100% - 6px);
+	// background: rgba(0, 0, 0, 0.5);
+	background: linear-gradient(to top, rgba(0, 0, 0, 0.5) 0px, rgba(0, 0, 0, 0) 60px),
+		linear-gradient(to bottom, rgba(0, 0, 0, 0.5) 0px, rgba(0, 0, 0, 0) 45px);
+	display: flex;
+	justify-content: center;
+	align-items: flex-end;
+
+	span {
+		padding: 3px;
+
+		&.more {
+			position: absolute;
+			top: 0;
+			right: 0;
+		}
+
+		&:nth-child(1),
+		&:nth-child(2) {
+			align-items: flex-end;
+			padding-bottom: 10px;
+		}
+
+		&:nth-child(3),
+		&:nth-child(4) {
+			justify-content: flex-end;
+			padding-bottom: 10px;
+		}
 
-			a {
+		a {
+			width: 30px;
+			height: 30px;
+			color: white;
+			justify-content: center;
+			align-items: center;
+			display: flex;
+			&.btn:before {
+				content: '';
 				width: 30px;
 				height: 30px;
-				color: white;
-				justify-content: center;
-				align-items: center;
-				display: flex;
-				&.btn:before {
-					content: '';
-					width: 30px;
-					height: 30px;
-					border: 1px solid white;
-					border-radius: 50%;
-					position: absolute;
-				}
+				border: 1px solid white;
+				border-radius: 50%;
+				position: absolute;
 			}
 		}
+	}
 
-		&.fixed {
-			position: relative;
-			opacity: 1;
-			background: none;
-
-			a {
-				width: auto;
-				height: auto;
-				color: $defaultTextColor;
-				&:before {
-					display: none;
-				}
-			}
+	&.fixed {
+		position: relative;
+		opacity: 1;
+		background: none;
 
+		a {
+			width: auto;
+			height: auto;
+			color: $defaultTextColor;
+			&:before {
+				display: none;
+			}
 		}
 	}
+}
 
-	.albums-container {
-		display: flex;
-		flex-direction: row;
-		flex-wrap: wrap;
-		.album {
-			flex-basis: 33%;
-			text-align: left;
-		}
+.albums-container {
+	display: flex;
+	flex-direction: row;
+	flex-wrap: wrap;
+	.album {
+		flex-basis: 33%;
+		text-align: left;
 	}
+}
 
-	img.hidden {
-		display: none;
-	}
-</style>
+.hidden {
+	display: none;
+}
 
-<style lang="scss">
-	.waterfall-item:hover {
-		div.actions {
-			opacity: 1
-		}
+.waterfall-item:hover {
+	div.actions {
+		opacity: 1;
 	}
+}
 </style>
-- 
cgit v1.2.3


From fb0bc57542a44dcc94149f393d8a4ff0c2e7902b Mon Sep 17 00:00:00 2001
From: Zephyrrus <krisztian1997@gmail.com>
Date: Tue, 7 Jul 2020 02:02:59 +0300
Subject: feat: try fixing THE SHITTY WATERFALL

---
 src/site/components/grid/Grid.vue | 28 ++++++++++------------------
 1 file changed, 10 insertions(+), 18 deletions(-)

(limited to 'src/site/components/grid/Grid.vue')

diff --git a/src/site/components/grid/Grid.vue b/src/site/components/grid/Grid.vue
index d4fe067..e6a8c64 100644
--- a/src/site/components/grid/Grid.vue
+++ b/src/site/components/grid/Grid.vue
@@ -24,12 +24,10 @@
 			<Waterfall
 				v-if="showWaterfall"
 				:gutterWidth="10"
-				:gutterHeight="4">
-				<WaterfallItem
-					v-for="(item, index) in gridFiles"
-					:key="item.id"
-					:width="width"
-					move-class="item-move">
+				:gutterHeight="4"
+				:itemWidth="width"
+				:items="gridFiles">
+				<template v-slot="{item}">
 					<template v-if="isPublic">
 						<a
 							:href="`${item.url}`"
@@ -81,7 +79,7 @@
 								</a>
 							</b-tooltip>
 							<b-tooltip label="Delete" position="is-top">
-								<a class="btn" @click="deleteFile(item, index)">
+								<a class="btn" @click="deleteFile(item)">
 									<i class="icon-editorial-trash-a-l" />
 								</a>
 							</b-tooltip>
@@ -92,7 +90,7 @@
 							</b-tooltip>
 						</div>
 					</template>
-				</WaterfallItem>
+				</template>
 			</Waterfall>
 		</template>
 		<div v-else>
@@ -185,12 +183,10 @@
 import { mapState } from 'vuex';
 
 import Waterfall from './waterfall/Waterfall.vue';
-import WaterfallItem from './waterfall/WaterfallItem.vue';
 
 export default {
 	components: {
 		Waterfall,
-		WaterfallItem,
 	},
 	props: {
 		files: {
@@ -253,13 +249,13 @@ export default {
 			const data = await this.$search.do(this.searchTerm, ['name', 'original', 'type', 'albums:name']);
 			console.log('> Search result data', data);
 		},
-		deleteFile(file, index) {
-			this.$buefy.dialog.confirm({
+		deleteFile(file) {
+			this.$emit('delete', file);
+			/* this.$buefy.dialog.confirm({
 				title: 'Deleting file',
 				message: 'Are you sure you want to <b>delete</b> this file?',
 				confirmText: 'Delete File',
 				type: 'is-danger',
-				hasIcon: true,
 				onConfirm: async () => {
 					const response = await this.$axios.$delete(`file/${file.id}`);
 					if (this.showList) {
@@ -274,7 +270,7 @@ export default {
 					}
 					return this.$buefy.toast.open(response.message);
 				},
-			});
+			}); */
 		},
 		isAlbumSelected(id) {
 			if (!this.showingModalForFile) return false;
@@ -311,10 +307,6 @@ export default {
 			const foundIndex = this.hoveredItems.indexOf(id);
 			if (foundIndex > -1) return;
 			this.hoveredItems.push(id);
-			/// XXX: THIS IS NOT OK!
-			this.$nextTick(() => {
-				this.$refs.video.forEach((e) => e.play().catch(() => {}));
-			});
 		},
 		mouseOut(id) {
 			console.log('out', id);
-- 
cgit v1.2.3


From 5d61b4d000a114857e4519be25c5834f510d450f Mon Sep 17 00:00:00 2001
From: Zephyrrus <krisztian1997@gmail.com>
Date: Tue, 7 Jul 2020 02:50:03 +0300
Subject: feat: refactor waterfall to be more efficient

---
 src/site/components/grid/Grid.vue | 5 +++++
 1 file changed, 5 insertions(+)

(limited to 'src/site/components/grid/Grid.vue')

diff --git a/src/site/components/grid/Grid.vue b/src/site/components/grid/Grid.vue
index e6a8c64..f98108e 100644
--- a/src/site/components/grid/Grid.vue
+++ b/src/site/components/grid/Grid.vue
@@ -25,6 +25,7 @@
 				v-if="showWaterfall"
 				:gutterWidth="10"
 				:gutterHeight="4"
+				:options="{fitWidth: true}"
 				:itemWidth="width"
 				:items="gridFiles">
 				<template v-slot="{item}">
@@ -451,6 +452,10 @@ div.actions {
 	display: none;
 }
 
+.waterfall {
+	margin: 0 auto;
+}
+
 .waterfall-item:hover {
 	div.actions {
 		opacity: 1;
-- 
cgit v1.2.3


From b519b6ccb469e874c783b995ddf0ab6fabdb5a0e Mon Sep 17 00:00:00 2001
From: Zephyrrus <krisztian1997@gmail.com>
Date: Wed, 8 Jul 2020 03:37:50 +0300
Subject: refactor: refactor grid to use vuex for every action

---
 src/site/components/grid/Grid.vue | 83 ++++++++++++++++++++++-----------------
 1 file changed, 48 insertions(+), 35 deletions(-)

(limited to 'src/site/components/grid/Grid.vue')

diff --git a/src/site/components/grid/Grid.vue b/src/site/components/grid/Grid.vue
index f98108e..42dcc6b 100644
--- a/src/site/components/grid/Grid.vue
+++ b/src/site/components/grid/Grid.vue
@@ -70,7 +70,7 @@
 								</a>
 							</b-tooltip>
 							<b-tooltip label="Tags" position="is-top">
-								<a class="btn" @click="manageTags(item)">
+								<a class="btn" @click="false && manageTags(item)">
 									<i class="icon-ecommerce-tag-c" />
 								</a>
 							</b-tooltip>
@@ -163,7 +163,7 @@
 						<hr>
 
 						<div class="albums-container">
-							<div v-for="(album, index) in albums" :key="index" class="album">
+							<div v-for="(album, index) in albums" :key="album.id" class="album">
 								<div class="field">
 									<b-checkbox
 										:value="isAlbumSelected(album.id)"
@@ -224,7 +224,6 @@ export default {
 			showWaterfall: true,
 			searchTerm: null,
 			showList: false,
-			albums: [],
 			hoveredItems: [],
 			isAlbumsModalActive: false,
 			showingModalForFile: null,
@@ -236,6 +235,8 @@ export default {
 	computed: {
 		...mapState({
 			user: (state) => state.auth.user,
+			albums: (state) => state.albums.tinyDetails,
+			images: (state) => state.images,
 		}),
 		blank() {
 			// eslint-disable-next-line global-require, import/no-unresolved
@@ -245,33 +246,31 @@ export default {
 			return this.files;
 		},
 	},
+	created() {
+		this.getAlbums();
+	},
 	methods: {
 		async search() {
 			const data = await this.$search.do(this.searchTerm, ['name', 'original', 'type', 'albums:name']);
 			console.log('> Search result data', data);
 		},
 		deleteFile(file) {
-			this.$emit('delete', file);
-			/* this.$buefy.dialog.confirm({
+			// this.$emit('delete', file);
+			this.$buefy.dialog.confirm({
 				title: 'Deleting file',
 				message: 'Are you sure you want to <b>delete</b> this file?',
 				confirmText: 'Delete File',
 				type: 'is-danger',
 				onConfirm: async () => {
-					const response = await this.$axios.$delete(`file/${file.id}`);
-					if (this.showList) {
-						file.hideFromList = true;
-						this.$forceUpdate();
-					} else {
-						this.showWaterfall = false;
-						this.files.splice(index, 1);
-						this.$nextTick(() => {
-							this.showWaterfall = true;
-						});
+					try {
+						const response = await this.$store.dispatch('images/deleteFile', file.id);
+
+						this.$buefy.toast.open(response.message);
+					} catch (e) {
+						this.$store.dispatch('alert/set', { text: e.message, error: true }, { root: true });
 					}
-					return this.$buefy.toast.open(response.message);
 				},
-			}); */
+			});
 		},
 		isAlbumSelected(id) {
 			if (!this.showingModalForFile) return false;
@@ -279,38 +278,52 @@ export default {
 			return !!(found && found.id);
 		},
 		async openAlbumModal(file) {
+			const { id } = file;
 			this.showingModalForFile = file;
 			this.showingModalForFile.albums = [];
-			this.isAlbumsModalActive = true;
 
-			const response = await this.$axios.$get(`file/${file.id}/albums`);
-			this.showingModalForFile.albums = response.albums;
+			try {
+				await this.$store.dispatch('images/getFileAlbums', id);
+			} catch (e) {
+				this.$store.dispatch('alert/set', { text: e.message, error: true }, { root: true });
+			}
+			this.showingModalForFile.albums = this.images.filesAlbums[id];
 
-			this.getAlbums();
+			this.isAlbumsModalActive = true;
 		},
-		async albumCheckboxClicked(value, id) {
-			const response = await this.$axios.$post(`file/album/${value ? 'add' : 'del'}`, {
-				albumId: id,
-				fileId: this.showingModalForFile.id,
-			});
-			this.$buefy.toast.open(response.message);
-
-			// Not the prettiest solution to refetch on each click but it'll do for now
-			this.$parent.getFiles();
+		async albumCheckboxClicked(add, id) {
+			try {
+				let response;
+				if (add) {
+					response = await this.$store.dispatch('images/addToAlbum', {
+						albumId: id,
+						fileId: this.showingModalForFile.id,
+					});
+				} else {
+					response = await this.$store.dispatch('images/removeFromAlbum', {
+						albumId: id,
+						fileId: this.showingModalForFile.id,
+					});
+				}
+
+				this.$buefy.toast.open(response.message);
+			} catch (e) {
+				this.$store.dispatch('alert/set', { text: e.message, error: true }, { root: true });
+			}
 		},
 		async getAlbums() {
-			const response = await this.$axios.$get('albums/dropdown');
-			this.albums = response.albums;
-			this.$forceUpdate();
+			try {
+				await this.$store.dispatch('albums/getTinyDetails');
+			} catch (e) {
+				this.$store.dispatch('alert/set', { text: e.message, error: true }, { root: true });
+			}
 		},
 		mouseOver(id) {
-			console.log('in', id);
 			const foundIndex = this.hoveredItems.indexOf(id);
 			if (foundIndex > -1) return;
 			this.hoveredItems.push(id);
 		},
 		mouseOut(id) {
-			console.log('out', id);
 			const foundIndex = this.hoveredItems.indexOf(id);
 			if (foundIndex > -1) this.hoveredItems.splice(foundIndex, 1);
 		},
-- 
cgit v1.2.3


From ad852de51a0d2dd5d29c08838d5a430c58849e74 Mon Sep 17 00:00:00 2001
From: Zephyrrus <krisztian1997@gmail.com>
Date: Wed, 8 Jul 2020 04:00:12 +0300
Subject: chore: linter the entire project using the new rules

---
 src/site/components/grid/Grid.vue | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

(limited to 'src/site/components/grid/Grid.vue')

diff --git a/src/site/components/grid/Grid.vue b/src/site/components/grid/Grid.vue
index 42dcc6b..84c0b11 100644
--- a/src/site/components/grid/Grid.vue
+++ b/src/site/components/grid/Grid.vue
@@ -163,7 +163,7 @@
 						<hr>
 
 						<div class="albums-container">
-							<div v-for="(album, index) in albums" :key="album.id" class="album">
+							<div v-for="album in albums" :key="album.id" class="album">
 								<div class="field">
 									<b-checkbox
 										:value="isAlbumSelected(album.id)"
@@ -252,7 +252,7 @@ export default {
 	methods: {
 		async search() {
 			const data = await this.$search.do(this.searchTerm, ['name', 'original', 'type', 'albums:name']);
-			console.log('> Search result data', data);
+			console.log('> Search result data', data); // eslint-disable-line no-console
 		},
 		deleteFile(file) {
 			// this.$emit('delete', file);
-- 
cgit v1.2.3


From 0f66d807035d3e32a66c7dc9bf55fb3be99aedac Mon Sep 17 00:00:00 2001
From: Zephyrrus <krisztian1997@gmail.com>
Date: Fri, 10 Jul 2020 01:13:51 +0300
Subject: refactor: finish refactoring all the components to use vuex

---
 src/site/components/grid/Grid.vue | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'src/site/components/grid/Grid.vue')

diff --git a/src/site/components/grid/Grid.vue b/src/site/components/grid/Grid.vue
index 84c0b11..90c196b 100644
--- a/src/site/components/grid/Grid.vue
+++ b/src/site/components/grid/Grid.vue
@@ -287,7 +287,7 @@ export default {
 			} catch (e) {
 				this.$store.dispatch('alert/set', { text: e.message, error: true }, { root: true });
 			}
-			this.showingModalForFile.albums = this.images.filesAlbums[id];
+			this.showingModalForFile.albums = this.images.fileAlbumsMap[id];
 
 			this.isAlbumsModalActive = true;
 		},
-- 
cgit v1.2.3

