funkwhale/front/src/components/AboutPod.vue

350 lines
16 KiB
Vue

<template>
<main
v-title="labels.title"
class="main pusher page-about"
>
<div class="ui" :class="{ container: onDesktop}">
<div class="ui horizontally fitted stripe basic segment">
<div class="ui basic vertically fitted stripe segment content">
<section :class="['ui', 'head', {'with-background': banner}, 'vertical', 'center', 'aligned', 'stripe', 'segment']" :style="headerStyle">
</section>
</div>
<div class="ui basic vertically fitted stripe segment content">
<!-- See layout in _about.scss -->
<div class="about-pod-info-container">
<div class="about-pod-info-toc">
<div class="ui vertical pointing secondary menu">
<router-link to="/about/pod" class="item">
<translate translate-context="Content/About/Header">About this pod</translate>
</router-link>
<router-link to="/about/pod#rules" class="item">
<translate translate-context="Content/About/Header">Rules</translate>
</router-link>
<router-link to="/about/pod#terms" class="item">
<translate translate-context="Content/About/Header">Terms and privacy policy</translate>
</router-link>
<router-link to="/about/pod#features" class="item">
<translate translate-context="Content/About/Header">Features</translate>
</router-link>
<router-link v-if="stats" to="/about/pod#statistics" class="item">
<translate translate-context="Content/About/Header">Statistics</translate>
</router-link>
</div>
</div>
<div class="about-pod-info">
<h2 class="ui header" id="description about-this-pod">
<translate translate-context="Content/About/Header">About this pod</translate>
</h2>
<div v-html="markdown.makeHtml(longDescription)" v-if="longDescription"></div>
<p v-else>
<translate translate-context="Content/About/Paragraph">No description available.</translate>
</p>
<h3 class="ui header" id="rules">
<translate translate-context="Content/About/Header">Rules</translate>
</h3>
<div v-html="markdown.makeHtml(rules)" v-if="rules"></div>
<p v-else>
<translate translate-context="Content/About/Paragraph">No rules available.</translate>
</p>
<h3 class="ui header" id="terms">
<translate translate-context="Content/About/Header">Terms and privacy policy</translate>
</h3>
<div v-html="markdown.makeHtml(terms)" v-if="terms"></div>
<p v-else>
<translate translate-context="Content/About/Paragraph">No terms available.</translate>
</p>
<h3 class="header" id="features">
<translate translate-context="Content/About/Header/Name">Features</translate>
</h3>
<div class="features-container ui two column stackable grid">
<div class="column">
<table class="ui very basic table unstackable">
<tbody>
<tr>
<td>
<translate translate-context="*/*/*">Funkwhale version</translate>
</td>
<td v-if="version" class="right aligned">
<span class="features-status ui text">
{{ version }}
</span>
</td>
<td v-else class="right aligned">
<span class="features-status ui text">
<translate translate-context="*/*/*">N/A</translate>
</span>
</td>
</tr>
<tr>
<td>
<translate translate-context="*/*/*">Federation</translate>
</td>
<td v-if="federationEnabled" class="right aligned">
<span class="features-status ui text">
<i class="check icon"></i>
<translate translate-context="*/*/*/State of feature">Enabled</translate>
</span>
</td>
<td v-else class="right aligned">
<span class="features-status ui text">
<i class="x icon"></i>
<translate translate-context="*/*/*/State of feature">Disabled</translate>
</span>
</td>
</tr>
<tr>
<td>
<translate translate-context="*/*/*">Allow-list</translate>
</td>
<td v-if="allowListEnabled" class="right aligned">
<span class="features-status ui text">
<i class="check icon"></i>
<translate translate-context="*/*/*/State of feature">Enabled</translate>
</span>
</td>
<td v-else class="right aligned">
<span class="features-status ui text">
<i class="x icon"></i>
<translate translate-context="*/*/*/State of feature">Disabled</translate>
</span>
</td>
</tr>
</tbody>
</table>
</div>
<div class="column">
<table class="ui very basic table unstackable">
<tbody>
<tr>
<td>
<translate translate-context="*/*/*">Anonymous access</translate>
</td>
<td v-if="anonymousCanListen" class="right aligned">
<span class="features-status ui text">
<i class="check icon"></i>
<translate translate-context="*/*/*/State of feature">Enabled</translate>
</span>
</td>
<td v-else class="right aligned">
<span class="features-status ui text">
<i class="x icon"></i>
<translate translate-context="*/*/*/State of feature">Disabled</translate>
</span>
</td>
</tr>
<tr>
<td>
<translate translate-context="*/*/*">Registrations</translate>
</td>
<td v-if="openRegistrations" class="right aligned">
<span class="features-status ui text">
<i class="check icon"></i>
<translate translate-context="*/*/*/State of registrations">Open</translate>
</span>
</td>
<td v-else class="right aligned">
<span class="features-status ui text">
<i class="x icon"></i>
<translate translate-context="*/*/*/State of registrations">Closed</translate>
</span>
</td>
</tr>
<tr>
<td>
<translate translate-context="*/*/*">Upload quota</translate>
</td>
<td v-if="defaultUploadQuota" class="right aligned">
<span class="features-status ui text">
{{ defaultUploadQuota * 1000 * 1000 | humanSize }}
</span>
</td>
<td v-else class="right aligned">
<span class="features-status ui text">
<translate translate-context="*/*/*">N/A</translate>
</span>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<template v-if="stats">
<h3 class="header" id="statistics">
<translate translate-context="Content/About/Header">Statistics</translate>
</h3>
<div class="statistics-container">
<div class="statistics-statistic" v-if="stats.hours">
<span class="statistics-figure ui text">
<span class="ui big text"><strong>{{ parseInt(stats.hours).toLocaleString($store.state.ui.momentLocale) }}</strong></span>
<br />
<translate translate-context="Content/About/*" :translate-n="parseInt(stats.hours)" translate-plural="hours of music">hour of music</translate>
</span>
</div>
<div class="statistics-statistic" v-if="stats.artists">
<span class="statistics-figure ui text">
<span class="ui big text"><strong>{{ stats.artists.toLocaleString($store.state.ui.momentLocale) }}</strong></span>
<br />
<translate translate-context="Content/About/*" :translate-n="stats.artists" translate-plural="artists">artist</translate>
</span>
</div>
<div class="statistics-statistic" v-if="stats.albums">
<span class="statistics-figure ui text">
<span class="ui big text"><strong>{{ stats.albums.toLocaleString($store.state.ui.momentLocale) }}</strong></span>
<br />
<translate translate-context="Content/About/*" :translate-n="stats.albums" translate-plural="albums">album</translate>
</span>
</div>
<div class="statistics-statistic" v-if="stats.tracks">
<span class="statistics-figure ui text">
<span class="ui big text"><strong>{{ stats.tracks.toLocaleString($store.state.ui.momentLocale) }}</strong></span>
<br />
<translate translate-context="Content/About/*" :translate-n="stats.tracks" translate-plural="tracks">track</translate>
</span>
</div>
<div class="statistics-statistic" v-if="stats.users">
<span class="statistics-figure ui text">
<span class="ui big text"><strong>{{ stats.users.toLocaleString($store.state.ui.momentLocale) }}</strong></span>
<br />
<translate translate-context="Content/About/*" :translate-n="stats.users" translate-plural="active users">active user</translate>
</span>
</div>
<div class="statistics-statistic" v-if="stats.listenings">
<span class="statistics-figure ui text">
<span class="ui big text"><strong>{{ stats.listenings.toLocaleString($store.state.ui.momentLocale) }}</strong></span>
<br />
<translate translate-context="Content/About/*" :translate-n="stats.listenings" translate-plural="listenings">listening</translate>
</span>
</div>
</div>
</template>
<template v-if="contactEmail">
<h3 class="ui header" id="contact">
<translate translate-context="Content/About/Header">Contact</translate>
</h3>
<a v-if="contactEmail" :href="`mailto:${contactEmail}`">
<translate translate-context="Content/About/Email" :translate-params="{ email: contactEmail }">Send us an email: {{ contactEmail }}</translate>
</a>
</template>
<div class="ui hidden divider"></div>
<div class="ui fluid horizontally fitted basic clearing segment container">
<router-link to="/about" class="ui left floated basic secondary button">
<i class="icon arrow left"></i>
<translate translate-context="Content/About/Paragraph">Introduction</translate>
</router-link>
</div>
</div>
</div>
</div>
</div>
</div>
</main>
</template>
<script>
import { mapState } from "vuex"
import _ from '@/lodash'
import showdown from 'showdown'
import SignupForm from "@/components/auth/SignupForm"
export default {
components: {
SignupForm,
},
data () {
return {
markdown: new showdown.Converter(),
showAllowedDomains: false,
}
},
computed: {
...mapState({
nodeinfo: state => state.instance.nodeinfo,
}),
labels() {
return {
title: this.$pgettext('Head/About/Title', "About")
}
},
podName() {
return _.get(this.nodeinfo, 'metadata.nodeName') || "Funkwhale"
},
banner () {
return _.get(this.nodeinfo, 'metadata.banner')
},
shortDescription () {
return _.get(this.nodeinfo, 'metadata.shortDescription')
},
longDescription () {
return _.get(this.nodeinfo, 'metadata.longDescription')
},
rules () {
return _.get(this.nodeinfo, 'metadata.rules')
},
terms () {
return _.get(this.nodeinfo, 'metadata.terms')
},
stats () {
let data = {
users: _.get(this.nodeinfo, 'usage.users.activeMonth', null),
hours: _.get(this.nodeinfo, 'metadata.library.music.hours', null),
artists: _.get(this.nodeinfo, 'metadata.library.artists.total', null),
albums: _.get(this.nodeinfo, 'metadata.library.albums.total', null),
tracks: _.get(this.nodeinfo, 'metadata.library.tracks.total', null),
listenings: _.get(this.nodeinfo, 'metadata.usage.listenings.total', null),
}
if (data.users === null || data.artists === null) {
return
}
return data
},
contactEmail () {
return _.get(this.nodeinfo, 'metadata.contactEmail')
},
anonymousCanListen () {
return _.get(this.nodeinfo, 'metadata.library.anonymousCanListen')
},
allowListEnabled () {
return _.get(this.nodeinfo, 'metadata.allowList.enabled')
},
allowListDomains () {
return _.get(this.nodeinfo, 'metadata.allowList.domains')
},
version () {
return _.get(this.nodeinfo, 'software.version')
},
openRegistrations () {
return _.get(this.nodeinfo, 'openRegistrations')
},
defaultUploadQuota () {
return _.get(this.nodeinfo, 'metadata.defaultUploadQuota')
},
federationEnabled () {
return _.get(this.nodeinfo, 'metadata.library.federationEnabled')
},
headerStyle() {
if (!this.banner) {
return ""
}
return (
"background-image: url(" +
this.$store.getters["instance/absoluteUrl"](this.banner) +
")"
)
},
onDesktop () {
if(window.innerWidth > 800) return true;
return false;
}
}
}
</script>