Redesigned homepage.

This commit is contained in:
2019-11-14 01:18:19 +01:00
parent 4497cc41b6
commit 4fa13bb163
10 changed files with 352 additions and 178 deletions

View File

@@ -19,7 +19,10 @@ export default {
</script>
<style lang="scss">
@import 'theme';
.container {
background: $background-dim;
height: 100%;
display: flex;
flex-direction: column;
@@ -30,7 +33,7 @@ export default {
display: flex;
flex-direction: column;
flex-grow: 1;
overflow: hidden;
overflow-y: auto;
}
.content-inner {

View File

@@ -13,9 +13,10 @@
@import 'theme';
.header {
color: $text-contrast;
background: $primary;
background: $background;
color: $primary;
padding: .5rem 1rem;
border-bottom: solid 1px $shadow-hint;
}
.logo-link {

View File

@@ -0,0 +1,76 @@
<template>
<div class="filter-bar noselect">
<Icon icon="filter" />
<Filters
class="filters-container"
:filter="filter"
@set-filter="filter => $emit('set-filter', filter)"
/>
<v-popover class="filters-compact">
<div>Filters</div>
<div slot="popover">
<Filters
:compact="true"
:filter="filter"
@set-filter="filter => $emit('set-filter', filter)"
/>
</div>
</v-popover>
</div>
</template>
<script>
import Filters from './filters.vue';
export default {
components: {
Filters,
},
props: {
filter: {
type: Array,
default: () => [],
},
},
};
</script>
<style lang="scss" scoped>
@import 'theme';
.filter-bar {
background: $background;
display: block;
padding: .5rem 1rem;
font-size: 0;
box-shadow: 0 0 3px $shadow;
.icon {
fill: $shadow;
}
}
.filters-container {
display: inline-block;
}
.filters-compact {
font-size: 1rem;
font-weight: bold;
display: none;
margin: 0 0 0 .5rem;
}
@media(max-width: $breakpoint) {
.filters-container {
display: none;
}
.filters-compact {
display: inline-block;
}
}
</style>

View File

@@ -1,7 +1,5 @@
<template>
<div class="filters-bar noselect">
<Icon icon="filter" />
<div :class="{ compact }">
<ul class="filters">
<li
v-tooltip.bottom="'Not yet available'"
@@ -111,6 +109,10 @@ export default {
type: Array,
default: () => [],
},
compact: {
type: Boolean,
default: false,
},
},
data() {
return {
@@ -123,17 +125,6 @@ export default {
<style lang="scss" scoped>
@import 'theme';
.filters-bar {
display: block;
background: $shadow-hint;
padding: .5rem 1rem;
font-size: 0;
.icon {
fill: $shadow;
}
}
.filters {
display: inline-block;
list-style: none;
@@ -141,7 +132,7 @@ export default {
margin: 0;
&:not(:last-child) {
border-right: solid 1px $shadow-weak;
border-right: solid 1px $shadow-hint;
}
}
@@ -149,12 +140,23 @@ export default {
display: inline-block;
}
.compact {
.filters {
padding: 0;
border: none;
}
.filter {
margin: 0 0 1.5rem 0;
}
}
.toggle {
color: $shadow;
background: $shadow-hint;
color: $shadow-weak;
box-sizing: border-box;
padding: .5rem;
margin: 0 .25rem;
border: solid 1px transparent;
border-radius: .5rem;
font-size: .9rem;
font-weight: bold;
@@ -164,9 +166,13 @@ export default {
display: none;
}
&:hover {
color: $shadow;
}
&.active {
color: $text-contrast;
background: $primary;
color: $primary;
box-shadow: 0 0 2px $shadow-weak;
}
}
</style>

View File

@@ -20,7 +20,7 @@
</template>
<script>
import FilterBar from './filter.vue';
import FilterBar from './filter-bar.vue';
import ReleaseTile from '../tile/release.vue';
async function fetchReleases() {

View File

@@ -0,0 +1,103 @@
<template>
<div
class="banner"
@wheel.prevent="scrollBanner"
>
<div class="trailer">
<video
v-if="release.trailer"
:src="`/media/${release.trailer.path}`"
:poster="`/media/${(release.poster && release.poster.thumbnail) || (release.photos.length && release.photos[Math.floor(Math.random() * release.photos.length)].path)}`"
:alt="release.title"
class="item trailer-video"
controls
>Sorry, the tailer cannot be played in your browser</video>
</div>
<a
v-for="photo in photos"
:key="`banner-${photo.index}`"
:href="`/media/${photo.path}`"
target="_blank"
rel="noopener noreferrer"
>
<img
:src="`/media/${photo.thumbnail}`"
:alt="`Photo ${photo.index + 1}`"
class="item"
>
</a>
</div>
</template>
<script>
function photos() {
if (this.release.photos.length) {
const set = this.release.photos.sort(({ index: indexA }, { index: indexB }) => indexA - indexB);
if (this.release.trailer) {
return set;
}
return [this.release.poster].concat(set);
}
if (this.release.poster && !this.release.trailer) {
return [this.release.poster];
}
return [];
}
function scrollBanner(event) {
event.currentTarget.scrollLeft += event.deltaY; // eslint-disable-line no-param-reassign
}
export default {
props: {
release: {
type: Object,
default: null,
},
},
computed: {
photos,
},
methods: {
scrollBanner,
},
};
</script>
<style lang="scss" scoped>
@import 'theme';
.banner {
background: $empty;
flex-shrink: 0;
white-space: nowrap;
overflow-x: auto;
margin: 0 0 1rem 0;
scrollbar-width: none;
box-shadow: 0 0 3px $shadow;
font-size: 0;
&::-webkit-scrollbar {
display: none;
}
}
.trailer {
display: inline-block;
max-width: 100vw;
}
.trailer-video {
max-width: 100%;
}
.item {
max-height: 18rem;
vertical-align: middle;
}
</style>

View File

@@ -1,34 +1,9 @@
<template>
<div v-if="release">
<div
class="banner"
@wheel.prevent="scrollBanner"
>
<div class="banner-trailer">
<video
v-if="release.trailer"
:src="`/media/${release.trailer.path}`"
:poster="`/media/${(release.poster && release.poster.thumbnail) || (release.photos.length && release.photos[Math.floor(Math.random() * release.photos.length)].path)}`"
:alt="release.title"
class="banner-item"
controls
>Sorry, the tailer cannot be played in your browser</video>
</div>
<a
v-for="photo in photos"
:key="`banner-${photo.index}`"
:href="`/media/${photo.path}`"
target="_blank"
rel="noopener noreferrer"
>
<img
:src="`/media/${photo.thumbnail}`"
:alt="`Photo ${photo.index + 1}`"
class="banner-item"
>
</a>
</div>
<div
v-if="release"
class="content"
>
<Banner :release="release" />
<h2 class="row title">{{ release.title }}</h2>
@@ -141,37 +116,20 @@
</template>
<script>
import Banner from './banner.vue';
function pageTitle() {
return this.release && this.release.title;
}
function scrollBanner(event) {
event.currentTarget.scrollLeft += event.deltaY; // eslint-disable-line no-param-reassign
}
function photos() {
if (this.release.photos.length) {
const set = this.release.photos.sort(({ index: indexA }, { index: indexB }) => indexA - indexB);
if (this.release.trailer) {
return set;
}
return [this.release.poster].concat(set);
}
if (this.release.poster && !this.release.trailer) {
return [this.release.poster];
}
return [];
}
async function mounted() {
[this.release] = await this.$store.dispatch('fetchReleases', { id: this.$route.params.releaseId });
}
export default {
components: {
Banner,
},
data() {
return {
release: null,
@@ -179,41 +137,13 @@ export default {
},
computed: {
pageTitle,
photos,
},
mounted,
methods: {
scrollBanner,
},
};
</script>
<style lang="scss" scoped>
@import 'theme';
.banner {
background: $empty;
white-space: nowrap;
overflow-x: auto;
margin: 0 0 1rem 0;
scrollbar-width: none;
box-shadow: 0 0 3px $shadow;
font-size: 0;
&::-webkit-scrollbar {
display: none;
}
}
.banner-trailer {
display: inline-block;
}
.banner-item {
height: 20rem;
vertical-align: middle;
}
.row {
display: block;
padding: 0 1rem;

View File

@@ -3,13 +3,16 @@
<span class="banner">
<span class="details">
<a
:href="`/site/${release.site.slug}`"
v-tooltip.bottom="`Part of ${release.network.name}`"
:title="`Part of ${release.network.name}`"
:href="`/site/${release.site.slug}`"
class="site site-link"
>{{ release.site.name }}</a>
<a
v-if="release.date"
v-tooltip.bottom="`View scene on ${release.site.name}`"
:title="`View scene on ${release.site.name}`"
:href="release.url"
target="_blank"
rel="noopener noreferrer"
@@ -78,23 +81,21 @@
</ul>
</span>
<span
<ul
:title="release.tags.map(tag => tag.name).join(', ')"
class="row"
class="tags nolist"
>
<ul class="tags nolist">
<li
v-for="tag in release.tags"
:key="`tag-${tag.slug}`"
class="tag"
>
<a
:href="`/tag/${tag.slug}`"
class="tag-link"
>{{ tag.name }}</a>
</li>
</ul>
</span>
<li
v-for="tag in release.tags"
:key="`tag-${tag.slug}`"
class="tag"
>
<a
:href="`/tag/${tag.slug}`"
class="tag-link"
>{{ tag.name }}</a>
</li>
</ul>
</div>
</div>
</template>
@@ -114,6 +115,7 @@ export default {
@import 'theme';
.tile {
background: $background;
display: flex;
flex-direction: column;
box-sizing: border-box;
@@ -149,7 +151,7 @@ export default {
align-items: center;
box-sizing: border-box;
padding: 0 .5rem;
margin: 0 0 .25rem 0;
margin: 0 0 .5rem 0;
}
.details {
@@ -179,6 +181,8 @@ export default {
}
.info {
display: flex;
flex-direction: column;
flex-grow: 1;
}
@@ -210,32 +214,26 @@ export default {
}
.tags {
word-wrap: break-word;
overflow: hidden;
max-height: 2.5rem;
padding: .25rem .5rem 1rem .5rem;
line-height: 1.25rem;
}
.actor,
.tag {
margin: 0 .25rem 0 0;
word-wrap: break-word;
overflow-y: hidden;
}
.actor {
font-size: .9rem;
margin: 0 .25rem 0 0;
}
.tag {
font-size: .75rem;
margin: 0 .25rem .5rem 0;
}
.actor:not(:last-of-type)::after,
.tag:not(:last-child):after {
.actor:not(:last-of-type)::after {
content: ",";
}
.actor-link,
.tag-link {
.actor-link {
text-decoration: none;
&:hover {
@@ -248,6 +246,16 @@ export default {
}
.tag-link {
color: $shadow-strong;
color: $shadow;
padding: .25rem;
border-radius: .25rem;
box-shadow: 0 0 2px $shadow-weak;
font-size: .75rem;
font-weight: bold;
text-decoration: none;
&:hover {
color: $primary;
}
}
</style>