Using query instead of parameters for tag filter URI. Added generic scrolling component, using for actor photos and entity children. Removed pagination from filter bar.

This commit is contained in:
ThePendulum 2020-06-29 03:55:10 +02:00
parent 98c19b560f
commit 8f9eb91b13
13 changed files with 536 additions and 321 deletions

View File

@ -283,10 +283,19 @@
</div> </div>
<div class="actor-content"> <div class="actor-content">
<Photos <Scroll
v-if="actor.avatar || (actor.photos && actor.photos.length > 0)" v-if="actor.avatar || (actor.photos && actor.photos.length > 0)"
:actor="actor" class="scroll-light"
/> >
<Photos :actor="actor" />
<template v-slot:expanded>
<Photos
class="expanded"
:actor="actor"
/>
</template>
</Scroll>
<FilterBar <FilterBar
:fetch-releases="fetchActor" :fetch-releases="fetchActor"
@ -307,10 +316,11 @@
</template> </template>
<script> <script>
import Photos from './photos.vue';
import Pagination from '../pagination/pagination.vue'; import Pagination from '../pagination/pagination.vue';
import FilterBar from '../header/filter-bar.vue'; import FilterBar from '../header/filter-bar.vue';
import Releases from '../releases/releases.vue'; import Releases from '../releases/releases.vue';
import Photos from './photos.vue';
import Scroll from '../scroll/scroll.vue';
import Gender from './gender.vue'; import Gender from './gender.vue';
import Social from './social.vue'; import Social from './social.vue';
@ -348,6 +358,7 @@ export default {
FilterBar, FilterBar,
Pagination, Pagination,
Photos, Photos,
Scroll,
Releases, Releases,
Gender, Gender,
Social, Social,
@ -637,9 +648,62 @@ export default {
display: none; display: none;
} }
.expand, .expand {
.collapse-header {
display: none; display: none;
justify-content: center;
align-items: center;
padding: .5rem .25rem;
font-weight: bold;
font-size: .9rem;
cursor: pointer;
.icon {
fill: $shadow;
}
&:hover {
background: $shadow-hint;
.icon {
fill: $shadow-strong;
}
}
}
.expand-sidebar:hover {
background: $shadow-hint;
}
.expand-header {
display: none;
&:hover {
background: $shadow-hint;
}
}
.collapse-header {
display: none;
width: 100%;
justify-content: center;
align-items: center;
padding: 0;
background: $profile;
.icon {
width: 100%;
fill: $highlight;
padding: .5rem 0;
}
&:hover .icon {
background: $highlight-hint;
fill: $text-contrast;
}
}
.scroll {
border-bottom: solid 1px var(--shadow-hint);
} }
@media(max-width: $breakpoint4) { @media(max-width: $breakpoint4) {

View File

@ -5,17 +5,17 @@
:class="{ :class="{
avatar: !!actor.avatar, avatar: !!actor.avatar,
empty: actor.photos.length === 0, empty: actor.photos.length === 0,
wide: actor.photos.length > 2
}" }"
> >
<a <a
v-if="actor.avatar" v-show="actor.avatar"
:href="`/media/${actor.avatar.path}`" :href="`/media/${actor.avatar.path}`"
target="_blank" target="_blank"
rel="noopener noreferrer" rel="noopener noreferrer"
class="avatar-link photo-link" class="avatar-link photo-link"
> >
<img <img
:src="sfw ? `/img/${actor.avatar.sfw.thumbnail}` : `/media/${actor.avatar.thumbnail}`"
:data-src="sfw ? `/img/${actor.avatar.sfw.thumbnail}` : `/media/${actor.avatar.thumbnail}`" :data-src="sfw ? `/img/${actor.avatar.sfw.thumbnail}` : `/media/${actor.avatar.thumbnail}`"
:data-loading="sfw ? `/img/${actor.avatar.sfw.lazy}` : `/media/${actor.avatar.lazy}`" :data-loading="sfw ? `/img/${actor.avatar.sfw.lazy}` : `/media/${actor.avatar.lazy}`"
:title="actor.avatar.copyright && `© ${actor.avatar.copyright}`" :title="actor.avatar.copyright && `© ${actor.avatar.copyright}`"
@ -32,9 +32,10 @@
class="photo-link" class="photo-link"
> >
<img <img
:src="sfw ? `/img/${photo.sfw.thumbnail}` : `/media/${photo.thumbnail}`"
:data-src="sfw ? `/img/${photo.sfw.thumbnail}` : `/media/${photo.thumbnail}`" :data-src="sfw ? `/img/${photo.sfw.thumbnail}` : `/media/${photo.thumbnail}`"
:data-loading="sfw ? `/img/${photo.sfw.lazy}` : `/media/${photo.lazy}`" :data-loading="sfw ? `/img/${photo.sfw.lazy}` : `/media/${photo.lazy}`"
:title="photo.copyright && `© ${photo.copyright}`" :title="`© ${photo.copyright || photo.entity.name}`"
class="photo" class="photo"
> >
</a> </a>
@ -63,15 +64,29 @@ export default {
@import 'theme'; @import 'theme';
.photos { .photos {
width: 100%;
display: flex; display: flex;
box-sizing: border-box; box-sizing: border-box;
padding: 1rem; padding: .5rem 1rem;
border-bottom: solid 1px var(--darken-hint);
font-size: 0; font-size: 0;
overflow-x: scroll; overflow-x: scroll;
scroll-behavior: smooth;
scrollbar-width: none; scrollbar-width: none;
&.expanded {
display: grid;
grid-gap: .5rem;
grid-template-columns: repeat(auto-fill, minmax(13rem, 1fr));
.photo-link {
margin: 0;
}
.photo {
width: 100%;
height: 100%;
}
}
&.empty { &.empty {
display: none; display: none;
} }
@ -86,14 +101,18 @@ export default {
} }
.photo-link { .photo-link {
height: 16rem;
flex-shrink: 0;
margin: 0 .5rem 0 0; margin: 0 .5rem 0 0;
} }
.photo { .photo {
height: 100%; width: 10rem;
height: 15rem;
box-shadow: 0 0 3px $shadow-weak; box-shadow: 0 0 3px $shadow-weak;
object-fit: cover;
}
.expand {
border-bottom: solid 1px var(--darken-hint);
} }
@media(max-width: $breakpoint3) { @media(max-width: $breakpoint3) {
@ -105,6 +124,16 @@ export default {
.avatar-link { .avatar-link {
display: inline-block; display: inline-block;
} }
&.expanded {
grid-template-columns: repeat(auto-fill, minmax(10rem, 1fr));
}
}
}
@media(max-width: $breakpoint0) {
.photos.expanded {
grid-template-columns: repeat(auto-fill, minmax(8rem, 1fr));
} }
} }
</style> </style>

View File

@ -0,0 +1,56 @@
<template>
<div class="children">
<EntityTile
v-for="child in entity.children"
:key="`child-${child.id}`"
:entity="child"
/>
</div>
</template>
<script>
import EntityTile from './tile.vue';
export default {
components: {
EntityTile,
},
props: {
entity: {
type: Object,
default: null,
},
},
};
</script>
<style lang="scss" scoped>
.children {
display: flex;
box-sizing: border-box;
padding: 1rem;
border-bottom: solid 1px var(--darken-hint);
overflow-x: auto;
scroll-behavior: smooth;
scrollbar-width: none;
.tile {
width: 15rem;
margin: 0 1rem 0 0;
}
&.expanded {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr));
grid-gap: 1rem;
.tile {
width: 100%;
}
}
&::-webkit-scrollbar {
display: none;
}
}
</style>

View File

@ -47,73 +47,20 @@
</router-link> </router-link>
</div> </div>
<div class="content-inner"> <div
<div ref="content"
v-if="entity.children.length > 0" class="content-inner"
class="children-container" >
> <Scroll class="scroll-dark">
<div <Children :entity="entity" />
v-if="expanded"
class="expand noselect" <template v-slot:expanded>
@click="expanded = !expanded" <Children
> class="expanded"
<Icon :entity="entity"
v-show="expanded"
icon="arrow-up3"
/> />
</template>
<Icon </Scroll>
v-show="!expanded"
icon="arrow-down3"
/>
</div>
<div
class="scroll-container"
:class="{ expanded }"
>
<div
class="scroll scroll-left noselect"
:class="{ 'scroll-start': scrollAtStart }"
@click="scroll('left')"
><Icon icon="arrow-left3" /></div>
<div
ref="children"
class="children"
:class="{ expanded }"
@scroll="updateScroll"
>
<EntityTile
v-for="child in entity.children"
:key="`child-${child.id}`"
:entity="child"
/>
</div>
<div
class="scroll scroll-right noselect"
:class="{ 'scroll-end': scrollAtEnd }"
@click="scroll('right')"
><Icon icon="arrow-right3" /></div>
</div>
<div
v-if="scrollable || expanded"
class="expand noselect"
@click="expanded = !expanded"
>
<Icon
v-show="expanded"
icon="arrow-up3"
/>
<Icon
v-show="!expanded"
icon="arrow-down3"
/>
</div>
</div>
<FilterBar <FilterBar
:fetch-releases="fetchEntity" :fetch-releases="fetchEntity"
@ -123,15 +70,25 @@
<div class="releases"> <div class="releases">
<Releases :releases="entity.releases" /> <Releases :releases="entity.releases" />
<Pagination
:items-total="totalCount"
:items-per-page="limit"
class="pagination-top"
/>
</div> </div>
</div> </div>
</div> </div>
</template> </template>
<script> <script>
import EntityTile from './tile.vue'; import Vue from 'vue';
import FilterBar from '../header/filter-bar.vue'; import FilterBar from '../header/filter-bar.vue';
import Pagination from '../pagination/pagination.vue';
import Releases from '../releases/releases.vue'; import Releases from '../releases/releases.vue';
import Children from './children.vue';
import Scroll from '../scroll/scroll.vue';
async function fetchEntity() { async function fetchEntity() {
const { entity, totalCount } = await this.$store.dispatch('fetchEntityBySlugAndType', { const { entity, totalCount } = await this.$store.dispatch('fetchEntityBySlugAndType', {
@ -146,68 +103,41 @@ async function fetchEntity() {
this.totalCount = totalCount; this.totalCount = totalCount;
this.pageTitle = entity.name; this.pageTitle = entity.name;
}
function updateScroll() { Vue.nextTick(() => {
this.scrollable = this.$refs.children.scrollWidth > this.$refs.children.clientWidth; this.$refs.content.scrollTop = 0;
this.scrollAtStart = this.$refs.children.scrollLeft === 0; });
this.scrollAtEnd = this.$refs.children.scrollWidth - this.$refs.children.clientWidth === this.$refs.children.scrollLeft;
}
function scroll(direction) {
if (direction === 'right') {
this.$refs.children.scrollLeft = this.$refs.children.scrollLeft + this.$refs.children.clientWidth - 100;
}
if (direction === 'left') {
this.$refs.children.scrollLeft = this.$refs.children.scrollLeft - this.$refs.children.clientWidth + 100;
}
} }
async function mounted() { async function mounted() {
await this.fetchEntity(); await this.fetchEntity();
this.updateScroll();
window.addEventListener('resize', this.updateScroll);
}
function beforeDestroy() {
window.removeEventListener('resize', this.updateScroll);
} }
async function route() { async function route() {
await this.fetchEntity(); await this.fetchEntity();
this.expanded = false;
this.updateScroll();
} }
export default { export default {
components: { components: {
EntityTile,
FilterBar, FilterBar,
Pagination,
Children,
Releases, Releases,
Scroll,
}, },
data() { data() {
return { return {
entity: null, entity: null,
totalCount: null, totalCount: null,
limit: 10, limit: 20,
expanded: false,
scrollable: true,
scrollAtStart: true,
scrollAtEnd: false,
}; };
}, },
watch: { watch: {
$route: route, $route: route,
}, },
mounted, mounted,
beforeDestroy,
methods: { methods: {
fetchEntity, fetchEntity,
updateScroll,
scroll,
}, },
}; };
</script> </script>
@ -250,117 +180,4 @@ export default {
.logo-parent { .logo-parent {
object-position: 100% 50%; object-position: 100% 50%;
} }
.children-container {
background: var(--profile);
}
.children {
display: flex;
box-sizing: border-box;
padding: 1rem;
border-bottom: solid 1px var(--darken-hint);
overflow-x: auto;
scroll-behavior: smooth;
scrollbar-width: none;
.tile {
width: 15rem;
margin: 0 1rem 0 0;
}
&.expanded {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr));
grid-gap: 1rem;
.tile {
width: 100%;
}
}
&::-webkit-scrollbar {
display: none;
}
}
.expand {
.icon {
fill: var(--lighten);
}
&:hover {
background: var(--lighten-hint);
.icon {
fill: var(--text-light);
}
}
}
.scroll-container {
position: relative;
padding: 0 1rem 0 0;
&.expanded {
padding: 0;
.scroll {
display: none;
}
}
}
.scroll {
height: 100%;
display: flex;
align-items: center;
box-sizing: border-box;
position: absolute;
top: 0;
bottom: 0;
&.scroll-start ,
&.scroll-end {
/* use over v-show so button stays visible while still hovered */
display: none;
.icon {
fill: var(--lighten-weak);
}
}
.icon {
fill: var(--lighten);
}
&:hover {
display: flex;
cursor: pointer;
&:not(.scroll-start):not(.scroll-end) {
.icon {
fill: var(--text-light);
}
}
}
}
.scroll-left {
left: 0;
padding: 1rem 2rem 1rem 1rem;
background: linear-gradient(to right, var(--profile) 50%, transparent);
}
.scroll-right {
right: 0;
padding: 1rem 1rem 1rem 2rem;
background: linear-gradient(to left, var(--profile) 50%, transparent);
}
@media(max-width: $breakpoint) {
.scroll {
display: none;
}
}
</style> </style>

View File

@ -0,0 +1,63 @@
<template>
<div>
<div
v-show="expanded"
class="expand expanded"
@click="$emit('expand', false)"
><Icon icon="arrow-up3" /></div>
<div
v-show="!expanded"
class="expand"
@click="$emit('expand', true)"
><Icon icon="arrow-down3" /></div>
</div>
</template>
<script>
export default {
props: {
expanded: {
type: Boolean,
default: false,
},
},
};
</script>
<style lang="scss" scoped>
.expand {
width: 100%;
display: flex;
align-items: center;
justify-content: center;
padding: .5rem;
.icon {
fill: var(--shadow);
}
&:hover {
cursor: pointer;
background: var(--shadow-hint);
.icon {
fill: var(--text);
}
}
}
.expand-dark {
.icon {
fill: var(--lighten);
}
&:hover {
background: var(--lighten-hint);
.icon {
fill: var(--text-light);
}
}
}
</style>

View File

@ -20,11 +20,6 @@
>New</router-link> >New</router-link>
</span> </span>
<Pagination
:items-total="itemsTotal"
:items-per-page="itemsPerPage"
/>
<span class="tags"> <span class="tags">
<Filters <Filters
class="filters-block" class="filters-block"
@ -50,7 +45,6 @@
<script> <script>
import { mapState } from 'vuex'; import { mapState } from 'vuex';
import Filters from './filters.vue'; import Filters from './filters.vue';
import Pagination from '../pagination/pagination.vue';
function filter(state) { function filter(state) {
return state.ui.filter; return state.ui.filter;
@ -85,7 +79,6 @@ async function setBatch(newBatch) {
export default { export default {
components: { components: {
Filters, Filters,
Pagination,
}, },
props: { props: {
fetchReleases: { fetchReleases: {
@ -141,7 +134,6 @@ export default {
.sort { .sort {
display: flex; display: flex;
align-items: center; align-items: center;
margin: 0 0 -1px 0;
} }
.filters-block { .filters-block {
@ -160,6 +152,7 @@ export default {
display: inline-block; display: inline-block;
padding: .75rem 1rem 1rem 1rem; padding: .75rem 1rem 1rem 1rem;
border: none; border: none;
position: relative;
font-size: .8rem; font-size: .8rem;
font-weight: bold; font-weight: bold;
text-decoration: none; text-decoration: none;
@ -175,6 +168,17 @@ export default {
color: var(--primary); color: var(--primary);
background: var(--background-soft); background: var(--background-soft);
border-color: var(--crease); border-color: var(--crease);
&::after {
/* hide grey border for tab effect, negative margin shows grey crease on mobile */
content: '';
width: 100%;
height: 2px;
background: var(--background-soft);
position: absolute;
left: 0;
bottom: -1px;
}
} }
} }

View File

@ -1,17 +1,17 @@
<template> <template>
<v-popover class="filters-container"> <v-popover class="filters-container">
<div class="filters"> <div class="filters">
<Icon icon="filter" />
<div <div
v-if="selectedTags.length > 0" v-if="selectedTags.length > 0"
class="applied" class="applied"
>{{ selectedTags.join(', ') }}</div> >{{ selectedTags.length }} selected</div>
<div <div
v-else v-else
class="applied empty" class="applied empty"
>Filter by tags</div> >Filter by tags</div>
<Icon icon="filter" />
</div> </div>
<div slot="popover"> <div slot="popover">
@ -22,7 +22,7 @@
class="tag" class="tag"
:class="{ selected: selectedTags.includes(tag) }" :class="{ selected: selectedTags.includes(tag) }"
> >
<router-link :to="{ params: { tags: getNewRange(tag) } }"> <router-link :to="{ query: { ...getNewRange(tag) } }">
<Icon <Icon
icon="checkmark" icon="checkmark"
class="include" class="include"
@ -30,7 +30,7 @@
</router-link> </router-link>
<router-link <router-link
:to="{ params: { tags: selectedTags.length === 1 && selectedTags.includes(tag) ? 'all' : tag } }" :to="{ query: { ...(selectedTags.length === 1 && selectedTags.includes(tag) ? null : { tags: tag }) } }"
class="name" class="name"
>{{ tag }}</router-link> >{{ tag }}</router-link>
</li> </li>
@ -55,18 +55,18 @@ const tags = [
function getNewRange(tag) { function getNewRange(tag) {
if (this.selectedTags.includes(tag)) { if (this.selectedTags.includes(tag)) {
if (this.selectedTags.length === 1) { if (this.selectedTags.length > 1) {
return 'all'; return { tags: this.selectedTags.filter(selectedTag => selectedTag !== tag).join(',') };
} }
return this.selectedTags.filter(selectedTag => selectedTag !== tag).join('+'); return {};
} }
return this.selectedTags.concat(tag).join('+'); return { tags: this.selectedTags.concat(tag).join(',') };
} }
function selectedTags() { function selectedTags() {
return this.$route.params.tags.split('+').filter(selectedTag => selectedTag !== 'all'); return this.$route.query.tags ? this.$route.query.tags.split(',') : [];
} }
export default { export default {
@ -108,14 +108,13 @@ export default {
} }
.applied { .applied {
width: 12rem; flex-grow: 1;
background: var(--background); padding: .75rem .5rem;
padding: .5rem;
border: solid 1px var(--shadow-hint);
font-size: 1rem; font-size: 1rem;
white-space: nowrap; white-space: nowrap;
overflow-x: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
text-align: right;
&.empty { &.empty {
color: var(--shadow); color: var(--shadow);

View File

@ -1,11 +1,15 @@
<template> <template>
<div class="content"> <div class="content">
<div class="content-inner"> <div
ref="content"
class="content-inner"
>
<FilterBar <FilterBar
:fetch-releases="fetchReleases" :fetch-releases="fetchReleases"
:is-home="true" :is-home="true"
:items-total="totalCount" :items-total="totalCount"
:items-per-page="limit" :items-per-page="limit"
:content="$refs.content"
/> />
<Releases :releases="releases" /> <Releases :releases="releases" />
@ -34,6 +38,8 @@ async function fetchReleases() {
this.totalCount = totalCount; this.totalCount = totalCount;
this.releases = releases; this.releases = releases;
this.$refs.content.scrollTop = 0;
} }
async function route() { async function route() {
@ -57,7 +63,7 @@ export default {
releases: [], releases: [],
networks: [], networks: [],
pageTitle: null, pageTitle: null,
limit: 15, limit: 20,
totalCount: 0, totalCount: 0,
from: null, from: null,
}; };

View File

@ -89,7 +89,6 @@ export default {
<style lang="scss" scoped> <style lang="scss" scoped>
.pagination { .pagination {
width: 100%;
display: flex; display: flex;
justify-content: center; justify-content: center;
} }
@ -99,7 +98,7 @@ export default {
} }
.pagination-bottom { .pagination-bottom {
margin: 1rem 0 0 0; margin: .5rem 0 1rem 0;
} }
.pagination-button { .pagination-button {

View File

@ -0,0 +1,236 @@
<template>
<div class="scroll">
<Expand
v-if="expanded"
:expanded="expanded"
class="expand-dark"
@expand="(state) => expanded = state"
/>
<Expand
v-if="expanded"
:expanded="expanded"
class="expand-light"
@expand="(state) => expanded = state"
/>
<div
v-show="enabled && !expanded"
class="scroll-button scroll-left noselect"
:class="{ 'scroll-start': scrollAtStart }"
@click="scroll('left')"
><Icon icon="arrow-left3" /></div>
<slot v-if="!expanded" />
<slot
v-if="expanded"
name="expanded"
/>
<div
v-show="enabled && !expanded"
class="scroll-button scroll-right noselect"
:class="{ 'scroll-end': scrollAtEnd }"
@click="scroll('right')"
><Icon icon="arrow-right3" /></div>
<Expand
v-if="expandable && scrollable"
:expanded="expanded"
class="expand-dark"
@expand="(state) => expanded = state"
/>
<Expand
v-if="expandable && scrollable"
:expanded="expanded"
class="expand-light"
@expand="(state) => expanded = state"
/>
</div>
</template>
<script>
import Expand from '../expand/expand.vue';
function updateScroll() {
this.scrollable = this.target.scrollWidth > this.target.clientWidth;
this.scrollAtStart = this.target.scrollLeft === 0;
this.scrollAtEnd = this.target.scrollWidth - this.target.clientWidth === this.target.scrollLeft;
}
function scroll(direction) {
if (direction === 'right') {
this.target.scrollLeft = this.target.scrollLeft + this.target.clientWidth - 100;
}
if (direction === 'left') {
this.target.scrollLeft = this.target.scrollLeft - this.target.clientWidth + 100;
}
}
function mounted() {
this.target = this.$slots.default[0].elm;
this.target.addEventListener('scroll', () => {
this.updateScroll();
});
window.addEventListener('resize', this.updateScroll);
this.updateScroll();
}
function beforeDestroy() {
this.target.removeEventListener('scroll', this.updateScroll);
window.removeEventListener('resize', this.updateScroll);
}
export default {
components: {
Expand,
},
props: {
enabled: {
type: Boolean,
default: true,
},
expandable: {
type: Boolean,
default: true,
},
},
data() {
return {
target: null,
scrollable: true,
scrollAtStart: true,
scrollAtEnd: false,
expanded: false,
};
},
mounted,
beforeDestroy,
methods: {
scroll,
updateScroll,
},
};
</script>
<style lang="scss" scoped>
@import 'theme';
.scroll {
background: var(--profile);
position: relative;
padding: 0 1rem 0 0;
&.expanded {
padding: 0;
.scroll {
display: none;
}
}
}
.scroll-light {
background: var(--background-dim);
.scroll-button {
.icon {
fill: var(--darken);
}
&.scroll-start .icon,
&.scroll-end .icon {
fill: var(--darken-weak);
}
&:hover:not(.scroll-start):not(.scroll-end) .icon {
fill: var(--text-dark);
}
}
.scroll-left {
background: linear-gradient(to right, var(--background-dim) 50%, transparent);
}
.scroll-right {
background: linear-gradient(to left, var(--background-dim) 50%, transparent);
}
.expand-dark {
display: none;
}
}
.scroll-dark {
background: var(--profile);
.scroll-button {
.icon {
fill: var(--lighten);
}
&.scroll-start .icon,
&.scroll-end .icon {
fill: var(--darken-weak);
}
&:hover:not(.scroll-start):not(.scroll-end) .icon {
fill: var(--text-light);
}
}
.scroll-left {
background: linear-gradient(to right, var(--profile) 50%, transparent);
}
.scroll-right {
background: linear-gradient(to left, var(--profile) 50%, transparent);
}
.expand-light {
display: none;
}
}
.scroll-button {
height: 100%;
display: flex;
align-items: center;
box-sizing: border-box;
position: absolute;
top: 0;
bottom: 0;
&.scroll-start,
&.scroll-end {
/* use over v-show so button stays visible while still hovered */
display: none;
}
&:hover {
display: flex;
cursor: pointer;
}
}
.scroll-left {
left: 0;
padding: 1rem 2rem 1rem 1rem;
}
.scroll-right {
right: 0;
padding: 1rem 1rem 1rem 2rem;
}
@media(max-width: $breakpoint) {
.scroll-button {
display: none;
}
}
</style>

View File

@ -37,56 +37,3 @@ body {
fill: $primary; fill: $primary;
} }
} }
.expand {
display: flex;
justify-content: center;
align-items: center;
padding: .5rem .25rem;
font-weight: bold;
font-size: .9rem;
cursor: pointer;
.icon {
fill: $shadow;
}
&:hover {
background: $shadow-hint;
.icon {
fill: $shadow-strong;
}
}
}
.expand-sidebar:hover {
background: $shadow-hint;
}
.expand-header {
display: none;
&:hover {
background: $shadow-hint;
}
}
.collapse-header {
width: 100%;
justify-content: center;
align-items: center;
padding: 0;
background: $profile;
.icon {
width: 100%;
fill: $highlight;
padding: .5rem 0;
}
&:hover .icon {
background: $highlight-hint;
fill: $text-contrast;
}
}

View File

@ -31,8 +31,8 @@ function curateActor(actor, release) {
if (actor.profiles && actor.profiles.length > 0) { if (actor.profiles && actor.profiles.length > 0) {
const photos = actor.profiles const photos = actor.profiles
.map(profile => profile.avatar) .map(profile => ({ entity: profile.entity, ...profile.avatar }))
.filter(avatar => avatar && (!curatedActor.avatar || avatar.hash !== curatedActor.avatar.hash)); .filter(avatar => avatar.id && (!curatedActor.avatar || avatar.hash !== curatedActor.avatar.hash));
const descriptions = actor.profiles.reduce((acc, profile) => ({ const descriptions = actor.profiles.reduce((acc, profile) => ({
...acc, ...acc,

View File

@ -33,13 +33,12 @@ const routes = [
name: 'updates', name: 'updates',
params: { params: {
range: 'latest', range: 'latest',
tags: 'all',
pageNumber: 1, pageNumber: 1,
}, },
}, },
}, },
{ {
path: '/updates/:tags/:range/:pageNumber', path: '/updates/:range/:pageNumber',
component: Home, component: Home,
name: 'updates', name: 'updates',
}, },
@ -61,13 +60,12 @@ const routes = [
params: { params: {
...from.params, ...from.params,
range: 'latest', range: 'latest',
tags: 'all',
pageNumber: 1, pageNumber: 1,
}, },
}), }),
}, },
{ {
path: '/actor/:actorId/:actorSlug/:tags/:range/:pageNumber', path: '/actor/:actorId/:actorSlug/:range/:pageNumber',
component: Actor, component: Actor,
name: 'actorRange', name: 'actorRange',
}, },
@ -79,13 +77,12 @@ const routes = [
params: { params: {
...from.params, ...from.params,
range: 'latest', range: 'latest',
tags: 'all',
pageNumber: 1, pageNumber: 1,
}, },
}), }),
}, },
{ {
path: '/channel/:entitySlug/:tags/:range/:pageNumber', path: '/channel/:entitySlug/:range/:pageNumber',
component: Entity, component: Entity,
name: 'channel', name: 'channel',
}, },
@ -96,13 +93,12 @@ const routes = [
params: { params: {
...from.params, ...from.params,
range: 'latest', range: 'latest',
tags: 'all',
pageNumber: 1, pageNumber: 1,
}, },
}), }),
}, },
{ {
path: '/network/:entitySlug/:tags/:range/:pageNumber', path: '/network/:entitySlug/:range/:pageNumber',
component: Entity, component: Entity,
name: 'network', name: 'network',
}, },
@ -113,12 +109,11 @@ const routes = [
params: { params: {
...from.params, ...from.params,
range: 'latest', range: 'latest',
tags: 'all',
}, },
}), }),
}, },
{ {
path: '/tag/:tagSlug/:tags/:range', path: '/tag/:tagSlug:range',
component: Tag, component: Tag,
name: 'tag', name: 'tag',
}, },