forked from DebaucheryLibrarian/traxxx
Added generic entity page.
This commit is contained in:
185
assets/components/entities/entity.vue
Normal file
185
assets/components/entities/entity.vue
Normal file
@@ -0,0 +1,185 @@
|
||||
<template>
|
||||
<div
|
||||
v-if="entity"
|
||||
class="entity content"
|
||||
>
|
||||
<div class="info">
|
||||
<img
|
||||
v-if="$route.name === 'network'"
|
||||
class="logo"
|
||||
:src="`/img/logos/${entity.slug}/thumbs/network.png`"
|
||||
>
|
||||
|
||||
<img
|
||||
v-else
|
||||
class="logo"
|
||||
:src="`/img/logos/${entity.parent.slug}/thumbs/${entity.slug}.png`"
|
||||
>
|
||||
|
||||
<router-link
|
||||
v-if="entity.parent"
|
||||
:to="{ name: `${entity.parent.type}Base`, params: { entitySlug: entity.parent.slug } }"
|
||||
>
|
||||
<img
|
||||
class="logo"
|
||||
:src="`/img/logos/${entity.parent.slug}/thumbs/network.png`"
|
||||
>
|
||||
</router-link>
|
||||
</div>
|
||||
|
||||
<div class="content-inner">
|
||||
<div
|
||||
v-if="entity.children.length > 0"
|
||||
class="children"
|
||||
:class="{ expanded }"
|
||||
>
|
||||
<EntityTile
|
||||
v-for="child in entity.children"
|
||||
:key="`child-${child.id}`"
|
||||
:entity="child"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div
|
||||
v-if="entity.children.length > 1"
|
||||
class="expand noselect"
|
||||
@click="expanded = !expanded"
|
||||
>
|
||||
<Icon
|
||||
v-show="expanded"
|
||||
icon="arrow-up3"
|
||||
/>
|
||||
|
||||
<Icon
|
||||
v-show="!expanded"
|
||||
icon="arrow-down3"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<FilterBar
|
||||
:fetch-releases="fetchEntity"
|
||||
:items-total="totalCount"
|
||||
:items-per-page="limit"
|
||||
/>
|
||||
|
||||
<div class="releases">
|
||||
<Releases :releases="entity.releases" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import EntityTile from './tile.vue';
|
||||
import FilterBar from '../header/filter-bar.vue';
|
||||
import Releases from '../releases/releases.vue';
|
||||
|
||||
async function fetchEntity() {
|
||||
const { entity, totalCount } = await this.$store.dispatch('fetchEntityBySlugAndType', {
|
||||
entitySlug: this.$route.params.entitySlug,
|
||||
entityType: this.$route.name,
|
||||
limit: this.limit,
|
||||
range: this.$route.params.range,
|
||||
pageNumber: Number(this.$route.params.pageNumber),
|
||||
});
|
||||
|
||||
this.entity = entity;
|
||||
this.totalCount = totalCount;
|
||||
|
||||
this.pageTitle = entity.name;
|
||||
}
|
||||
|
||||
async function mounted() {
|
||||
await this.fetchEntity();
|
||||
}
|
||||
|
||||
async function route() {
|
||||
this.expanded = false;
|
||||
await this.fetchEntity();
|
||||
}
|
||||
|
||||
export default {
|
||||
components: {
|
||||
EntityTile,
|
||||
FilterBar,
|
||||
Releases,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
entity: null,
|
||||
totalCount: null,
|
||||
limit: 10,
|
||||
expanded: false,
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
$route: route,
|
||||
},
|
||||
mounted,
|
||||
methods: {
|
||||
fetchEntity,
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.info {
|
||||
height: 2.5rem;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding: 1rem;
|
||||
background: var(--profile);
|
||||
border-bottom: solid 1px var(--lighten-hint);
|
||||
}
|
||||
|
||||
.logo {
|
||||
height: 100%;
|
||||
max-width: 20rem;
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
.children {
|
||||
display: flex;
|
||||
box-sizing: border-box;
|
||||
overflow-x: auto;
|
||||
padding: 1rem;
|
||||
border-bottom: solid 1px var(--darken-hint);
|
||||
background: var(--profile);
|
||||
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 {
|
||||
background: var(--profile);
|
||||
|
||||
.icon {
|
||||
fill: var(--lighten-weak);
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background: var(--darken-strong);
|
||||
|
||||
.icon {
|
||||
fill: var(--lighten-weak);
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
74
assets/components/entities/tile.vue
Normal file
74
assets/components/entities/tile.vue
Normal file
@@ -0,0 +1,74 @@
|
||||
<template>
|
||||
<router-link
|
||||
:to="{ name: entity.type, params: { entitySlug: entity.slug } }"
|
||||
:title="entity.name"
|
||||
class="tile"
|
||||
>
|
||||
<img
|
||||
v-if="entity.type === 'channel'"
|
||||
:src="`/img/logos/${entity.parent.slug}/thumbs/${entity.slug}.png`"
|
||||
:alt="entity.name"
|
||||
class="logo"
|
||||
>
|
||||
|
||||
<img
|
||||
v-else
|
||||
:src="`/img/logos/${entity.slug}/thumbs/network.png`"
|
||||
:alt="entity.name"
|
||||
class="logo"
|
||||
>
|
||||
</router-link>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
entity: {
|
||||
type: Object,
|
||||
default: null,
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import 'theme';
|
||||
|
||||
.tile {
|
||||
height: 6rem;
|
||||
background: $tile;
|
||||
display: flex;
|
||||
flex-shrink: 0;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
box-sizing: border-box;
|
||||
padding: .5rem 1rem;
|
||||
border-radius: .25rem;
|
||||
box-shadow: 0 0 3px rgba(0, 0, 0, .25);
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.link {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.logo {
|
||||
max-width: 100%;
|
||||
max-height: 100%;
|
||||
color: $text-contrast;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 1rem;
|
||||
font-weight: bold;
|
||||
filter: $logo-highlight;
|
||||
}
|
||||
|
||||
.title {
|
||||
color: $text;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin: 0;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user