Update about page and add new /about/pod page
This commit is contained in:
parent
e4b11df1ea
commit
77bffa20ac
|
@ -1,201 +1,139 @@
|
|||
<template>
|
||||
<main class="main pusher page-about" v-title="labels.title">
|
||||
<section :class="['ui', 'head', {'with-background': banner}, 'vertical', 'center', 'aligned', 'stripe', 'segment']" :style="headerStyle">
|
||||
<div class="segment-content">
|
||||
<h1 class="ui center aligned large header">
|
||||
<span
|
||||
v-translate="{podName: podName}"
|
||||
translate-context="Content/Home/Header"
|
||||
:translate-params="{podName: podName}">
|
||||
About %{ podName }
|
||||
</span>
|
||||
<div v-if="shortDescription" class="sub header">
|
||||
{{ shortDescription }}
|
||||
</div>
|
||||
</h1>
|
||||
</div>
|
||||
</section>
|
||||
<section class="ui vertical stripe segment">
|
||||
<div class="ui container">
|
||||
<div class="ui mobile reversed stackable grid">
|
||||
<div class="ten wide column">
|
||||
<div class="ui container">
|
||||
<div class="ui horizontally fitted basic stripe segment">
|
||||
<div class="ui horizontally fitted basic very padded segment">
|
||||
<div class="ui center aligned text container">
|
||||
<div class="ui text container">
|
||||
<h2 class="ui header" id="description">
|
||||
<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/Home/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/Home/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/Home/Paragraph">No terms available.</translate>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="six wide column">
|
||||
<div class="ui raised segment">
|
||||
<h3 class="ui header">
|
||||
<translate translate-context="Content/About/Header">Contents</translate>
|
||||
</h3>
|
||||
<div class="ui list">
|
||||
<div class="ui item">
|
||||
<a href="#description">
|
||||
<translate translate-context="Content/About/Header">About this pod</translate>
|
||||
</a>
|
||||
</div>
|
||||
<div class="ui item">
|
||||
<a href="#rules">
|
||||
<translate translate-context="Content/About/Header">Rules</translate>
|
||||
</a>
|
||||
</div>
|
||||
<div class="ui item">
|
||||
<a href="#terms">
|
||||
<translate translate-context="Content/About/Header">Terms and privacy policy</translate>
|
||||
</a>
|
||||
<div class="ui equal width compact stackable grid">
|
||||
<div class="column"></div>
|
||||
<div class="ten wide column">
|
||||
<div class="ui vertically fitted basic segment">
|
||||
<router-link to="/">
|
||||
<logo-text />
|
||||
</router-link>
|
||||
</div>
|
||||
</div>
|
||||
<div class="column"></div>
|
||||
</div>
|
||||
<template v-if="contactEmail">
|
||||
<h3 class="header">
|
||||
<translate translate-context="Content/Home/Header/Name">Contact</translate>
|
||||
</h3>
|
||||
<a :href="`mailto:${contactEmail}`">{{ contactEmail }}</a>
|
||||
</template>
|
||||
<h3 class="header">
|
||||
<translate translate-context="Content/About/Header/Name">Pod configuration</translate>
|
||||
</h3>
|
||||
<table class="ui very basic table">
|
||||
<tbody>
|
||||
<tr v-if="version">
|
||||
<td>
|
||||
<translate translate-context="*/*/*">Funkwhale version</translate>
|
||||
</td>
|
||||
<td>
|
||||
{{ version }}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<translate translate-context="*/*/*">Registrations</translate>
|
||||
</td>
|
||||
<td v-if="openRegistrations">
|
||||
<i class="check icon"></i>
|
||||
<translate translate-context="*/*/*/State of registrations">Open</translate>
|
||||
</td>
|
||||
<td v-else>
|
||||
<i class="x icon"></i>
|
||||
<translate translate-context="*/*/*/State of registrations">Closed</translate>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<translate translate-context="*/*/*">Upload quota</translate>
|
||||
</td>
|
||||
<td v-if="defaultUploadQuota">
|
||||
{{ defaultUploadQuota * 1000 * 1000 | humanSize }}
|
||||
</td>
|
||||
<td v-else>
|
||||
<translate translate-context="*/*/*">N/A</translate>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<translate translate-context="*/*/*">Federation</translate>
|
||||
</td>
|
||||
<td v-if="federationEnabled">
|
||||
<i class="check icon"></i>
|
||||
<translate translate-context="*/*/*/State of feature">Enabled</translate>
|
||||
</td>
|
||||
<td v-else>
|
||||
<i class="x icon"></i>
|
||||
<translate translate-context="*/*/*/State of feature">Disabled</translate>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<translate translate-context="*/*/*">Anonymous access</translate>
|
||||
</td>
|
||||
<td v-if="anonymousCanListen">
|
||||
<i class="check icon"></i>
|
||||
<translate translate-context="*/*/*/State of feature">Enabled</translate>
|
||||
</td>
|
||||
<td v-else>
|
||||
<i class="x icon"></i>
|
||||
<translate translate-context="*/*/*/State of feature">Disabled</translate>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<translate translate-context="*/*/*">Allow-list</translate>
|
||||
</td>
|
||||
<td v-if="allowListEnabled">
|
||||
<i class="check icon"></i>
|
||||
<translate translate-context="*/*/*/State of feature">Enabled</translate>
|
||||
</td>
|
||||
<td v-else>
|
||||
<i class="x icon"></i>
|
||||
<translate translate-context="*/*/*/State of feature">Disabled</translate>
|
||||
</td>
|
||||
</tr>
|
||||
<tr v-if="allowListDomains">
|
||||
<td>
|
||||
<translate translate-context="*/*/*">Allowed domains</translate>
|
||||
</td>
|
||||
<td>
|
||||
<translate :translate-n="allowListDomains.length" translate-plural="%{ count } allowed domains" :translate-params="{count: allowListDomains.length}" translate-context="*/*/*">%{ count } allowed domains</translate>
|
||||
<br>
|
||||
<a @click.prevent="showAllowedDomains = !showAllowedDomains">
|
||||
<translate v-if="showAllowedDomains" key="1" translate-context="*/*/*/Verb">Hide</translate>
|
||||
<translate v-else key="2" translate-context="*/*/*/Verb">Show</translate>
|
||||
</a>
|
||||
<ul class="ui list" v-if="showAllowedDomains">
|
||||
<li v-for="domain in allowListDomains" :key="domain">
|
||||
<a :href="`https://${domain}`" target="_blank" rel="noopener">{{ domain }}</a>
|
||||
</li>
|
||||
</ul>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<template v-if="stats">
|
||||
<h3 class="header">
|
||||
<translate translate-context="Content/Home/Header">Statistics</translate>
|
||||
</h3>
|
||||
<p>
|
||||
<i class="user really discrete icon"></i><translate translate-context="Content/Home/Stat" :translate-params="{count: stats.users.toLocaleString($store.state.ui.momentLocale) }" :translate-n="stats.users" translate-plural="%{ count } active users">%{ count } active user</translate>
|
||||
</p>
|
||||
<p>
|
||||
<i class="music really discrete icon"></i><translate translate-context="Content/Home/Stat" :translate-params="{count: parseInt(stats.hours).toLocaleString($store.state.ui.momentLocale)}" :translate-n="parseInt(stats.hours)" translate-plural="%{ count } hours of music">%{ count } hour of music</translate>
|
||||
</p>
|
||||
<p v-if="stats.artists">
|
||||
<i class="users really discrete icon"></i><translate translate-context="Content/Home/Stat" :translate-params="{count: stats.artists.toLocaleString($store.state.ui.momentLocale) }" :translate-n="stats.artists" translate-plural="%{ count } artists">%{ count } artist</translate>
|
||||
</p>
|
||||
<p v-if="stats.albums">
|
||||
<i class="headphones really discrete icon"></i><translate translate-context="Content/Home/Stat" :translate-params="{count: stats.albums.toLocaleString($store.state.ui.momentLocale) }" :translate-n="stats.albums" translate-plural="%{ count } albums">%{ count } album</translate>
|
||||
</p>
|
||||
<p v-if="stats.tracks">
|
||||
<i class="file really discrete icon"></i><translate translate-context="Content/Home/Stat" :translate-params="{count: stats.tracks.toLocaleString($store.state.ui.momentLocale) }" :translate-n="stats.tracks" translate-plural="%{ count } tracks">%{ count } track</translate>
|
||||
</p>
|
||||
<p v-if="stats.listenings">
|
||||
<i class="play really discrete icon"></i><translate translate-context="Content/Home/Stat" :translate-params="{count: stats.listenings.toLocaleString($store.state.ui.momentLocale) }" :translate-n="stats.listenings" translate-plural="%{ count } listenings">%{ count } listening</translate>
|
||||
</p>
|
||||
</template>
|
||||
<h2 class="header">
|
||||
<translate translate-context="Content/About/Heading">A social platform to enjoy and share music</translate>
|
||||
</h2>
|
||||
<p>
|
||||
<translate translate-context="Content/About/Paragraph">Funkwhale is a community-driven project that lets you listen and share music and audio within a decentralized, open network.</translate>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ui hidden divider"></div>
|
||||
<div class="ui vertically fitted basic stripe segment">
|
||||
<div class="ui two stackable cards">
|
||||
<div class="ui card">
|
||||
<div class="signup-form content">
|
||||
<h3 class="header">
|
||||
<translate translate-context="*/Signup/Title">Sign up</translate>
|
||||
</h3>
|
||||
<template v-if="openRegistrations">
|
||||
<p>
|
||||
<translate translate-context="Content/About/Paragraph">Sign up now to keep a track of your favorites, create playlists, discover new content and much more!</translate>
|
||||
</p>
|
||||
<p v-if="defaultUploadQuota">
|
||||
<translate translate-context="Content/About/Paragraph" :translate-params="{quota: humanSize(defaultUploadQuota * 1000 * 1000)}">Users on this pod also get %{ quota } of free storage to upload their own content!</translate>
|
||||
</p>
|
||||
<signup-form button-classes="success" :show-login="false"></signup-form>
|
||||
</template>
|
||||
<div v-else>
|
||||
<p translate-context="Content/About/Paragraph">Registrations are closed on this pod. You can signup on another pod using the link below.</p>
|
||||
|
||||
<a target="_blank" rel="noopener" href="https://funkwhale.audio/#get-started">
|
||||
<translate translate-context="Content/About/Link">Find another pod</translate>
|
||||
<i class="external alternate icon margin-left"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ui card">
|
||||
<section :class="['ui', 'head', {'with-background': banner}, 'vertical', 'center', 'aligned', 'stripe', 'segment']" :style="headerStyle">
|
||||
</section>
|
||||
<div class="content padding-top padding-bottom">
|
||||
<h3 class="ui header" id="description">
|
||||
<translate translate-context="Content/About/Header">About this pod</translate>
|
||||
</h3>
|
||||
<div v-if="shortDescription" class="sub header">
|
||||
{{ shortDescription }}
|
||||
</div>
|
||||
<p v-else>
|
||||
<translate translate-context="Content/About/Paragraph">No description available.</translate>
|
||||
</p>
|
||||
|
||||
<template v-if="stats">
|
||||
<div class="statistics-container ui doubling grid">
|
||||
<div class="ui six wide column">
|
||||
<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="ui six wide column">
|
||||
<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>
|
||||
</template>
|
||||
|
||||
<router-link to="/about/pod" class="ui fluid basic secondary button">
|
||||
<translate translate-context="Content/About/Paragraph">Learn More</translate>
|
||||
</router-link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ui three stackable cards">
|
||||
<router-link to="/" class="ui card">
|
||||
<div class="content">
|
||||
<h3 class="ui header" id="description">
|
||||
<translate translate-context="Content/About/Header">Browse public content</translate>
|
||||
</h3>
|
||||
<p>
|
||||
<translate translate-context="Content/About/Paragraph">Listen to public albums and playlists shared on this pod.</translate>
|
||||
</p>
|
||||
</div>
|
||||
</router-link>
|
||||
<a href="https://funkwhale.audio/#get-started" class="ui card">
|
||||
<div class="content">
|
||||
<h3 class="ui header" id="description">
|
||||
<translate translate-context="Content/About/Header">Find another pod</translate>
|
||||
<i class="external alternate icon margin-left"></i>
|
||||
</h3>
|
||||
<p>
|
||||
<translate translate-context="Content/About/Paragraph">Listen to public albums and playlists shared on this pod.</translate>
|
||||
</p>
|
||||
</div>
|
||||
</a>
|
||||
<a href="https://funkwhale.audio/apps" class="ui card">
|
||||
<div class="content">
|
||||
<h3 class="ui header" id="description">
|
||||
<translate translate-context="Content/About/Header">Find an app</translate>
|
||||
<i class="external alternate icon margin-left"></i>
|
||||
</h3>
|
||||
<p>
|
||||
<translate translate-context="Content/About/Paragraph">Use Funkwhale on other devices with our apps.</translate>
|
||||
</p>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
<div class="ui fluid horizontally fitted basic clearing segment container">
|
||||
<router-link to="/about/pod" class="ui right floated basic secondary button">
|
||||
<translate translate-context="Content/About/Paragraph">About this pod</translate>
|
||||
<i class="icon arrow right"></i>
|
||||
</router-link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</main>
|
||||
</template>
|
||||
|
||||
|
@ -204,7 +142,14 @@ import { mapState } from "vuex"
|
|||
import _ from '@/lodash'
|
||||
import showdown from 'showdown'
|
||||
|
||||
import SignupForm from "@/components/auth/SignupForm"
|
||||
import LogoText from "@/components/LogoText"
|
||||
|
||||
export default {
|
||||
components: {
|
||||
SignupForm,
|
||||
LogoText,
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
markdown: new showdown.Converter(),
|
||||
|
@ -290,3 +235,21 @@ export default {
|
|||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.margin-left {
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
.padding-top {
|
||||
padding-top: 20px !important;
|
||||
}
|
||||
|
||||
.padding-bottom {
|
||||
padding-bottom: 20px !important;
|
||||
}
|
||||
h3 i {
|
||||
display: inline !important;
|
||||
font-size: 14px !important;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -0,0 +1,345 @@
|
|||
<template>
|
||||
<main class="main pusher page-about" v-title="labels.title">
|
||||
<div class="ui container">
|
||||
<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">
|
||||
<!-- TODO: Table of contents -->
|
||||
<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">
|
||||
<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">
|
||||
<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>
|
||||
<!-- TODO: Moderators -->
|
||||
<div class="ui"></div>
|
||||
<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) +
|
||||
")"
|
||||
)
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
|
@ -0,0 +1,41 @@
|
|||
<template>
|
||||
<svg viewBox="0 0 271.66678 53.49133" version="1.1">
|
||||
<g transform="translate(34.65295 -109.48195)">
|
||||
<g>
|
||||
<g transform="matrix(.3191 0 0 .3191 -45.91741 93.47184)">
|
||||
<g>
|
||||
<g :fill="primary">
|
||||
<path d="M128 157.1c17.7 0 32.1-14.4 32.1-32.1 0-.9-.8-1.7-1.7-1.7h-12.1c-.9 0-1.7.8-1.7 1.7 0 9.1-7.4 16.6-16.6 16.6-9.1 0-16.6-7.4-16.6-16.6 0-.9-.8-1.7-1.7-1.7H97.6c-.9 0-1.7.8-1.7 1.7 0 17.8 14.4 32.1 32.1 32.1z" />
|
||||
<path d="M128 187.4c34.3 0 62.3-28 62.3-62.3 0-.9-.8-1.7-1.7-1.7h-12.1c-.9 0-1.7.8-1.7 1.7 0 25.9-21 46.9-46.9 46.9S81 151 81 125.1c0-.9-.8-1.7-1.7-1.7H67.4c-.9 0-1.7.8-1.7 1.7-.2 34.3 27.8 62.3 62.3 62.3z" />
|
||||
<path d="M219 123.4h-12.1c-.9 0-1.7.8-1.7 1.7 0 42.6-34.8 77.3-77.3 77.3-42.6 0-77.3-34.6-77.3-77.3 0-.9-.8-1.7-1.7-1.7H37c-.9 0-1.7.8-1.7 1.7 0 51.1 41.6 92.7 92.7 92.7s92.7-41.6 92.7-92.7c0-.9-.8-1.7-1.7-1.7z" />
|
||||
</g>
|
||||
<g :fill="secondary">
|
||||
<path d="M86.3 83.3c6.2 3.2 12.9 3.8 18.9 7.3 3.9 2.3 6.4 4.8 8.8 8.6 3.8 5.7 3.6 12.9 3.6 12.9l.5 7.9s3 7.9 9.7 7.9c7.1 0 9.7-7.9 9.7-7.9l.5-7.9s-.2-7.1 3.6-12.9c2.4-3.8 4.8-6.5 8.8-8.6 6-3.5 12.7-4.1 18.9-7.3 6.2-3.2 12.2-7.3 16.3-13 4.1-5.7 6-13.3 3.8-20-11.8-.6-25.4.8-35.8 6.4-14.5 7.7-23.3 5-25.9 16.5h-.2c-2.6-11.6-11.3-8.8-25.9-16.5-10.4-5.6-24-7-35.8-6.4-2.3 6.7-.3 14.2 3.8 20 4.4 5.8 10.5 9.9 16.7 13z" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<g transform="translate(-.75595 -.75595)" :fill="text" stroke-width=".74383">
|
||||
<path d="M32.84591 132.89252c0-6.69443 2.6034-9.29781 10.41356-9.29781 1.63641 0 3.71912.14876 4.83486.37191.59506.14876 1.11574.59506 1.11574 1.11574v2.00832c0 .59506-.4463 1.11574-1.11574 1.11574h-.66944c-.8182 0-1.48765-.29753-2.529-.29753-4.83487 0-5.80184.96698-5.80184 4.98363v.29753h6.62004c.59506 0 1.11574.4463 1.11574 1.11574v2.15709c0 .66945-.4463 1.11574-1.11574 1.11574h-6.62004v11.30614c0 .59506-.4463 1.11574-1.11574 1.11574h-4.01666c-.59506 0-1.11574-.52068-1.11574-1.11574z" />
|
||||
<path d="M57.02023 141.59528c0 3.04968 1.41327 4.31418 3.49598 4.31418 1.78518 0 3.49598-1.2645 4.83487-2.60339v-12.12435c0-.59506.52068-1.11573 1.11574-1.11573h4.09103c.59506 0 1.11574.52067 1.11574 1.11573v17.70304c0 .59506-.4463 1.11574-1.11574 1.11574h-4.09104c-.59505 0-1.11573-.52068-1.11573-1.11574v-1.19012c-1.7108 1.48765-3.57036 2.67777-6.32252 2.67777-4.83486 0-8.25646-2.529-8.25646-8.70275v-10.41355c0-.59506.4463-1.11574 1.11574-1.11574h4.09104c.59506 0 1.11574.52068 1.11574 1.11574v10.33917z" />
|
||||
<path d="M90.71552 138.47121c0-3.04968-1.41327-4.31419-3.49598-4.31419-1.78518 0-3.57036 1.26451-4.90925 2.60339v12.19874c0 .59506-.4463 1.11573-1.11573 1.11573h-4.09104c-.66945 0-1.11574-.52067-1.11574-1.11573v-17.77743c0-.59506.4463-1.11573 1.11574-1.11573h4.16542c.59506 0 1.11574.52067 1.11574 1.11573v1.19012c1.7108-1.48765 3.57036-2.67777 6.3969-2.67777 4.83486 0 8.25645 2.52901 8.25645 8.70276v10.41355c0 .59506-.4463 1.11574-1.11573 1.11574h-4.09104c-.59506 0-1.11574-.52068-1.11574-1.11574z" />
|
||||
<path d="M107.67473 137.95053c2.1571 0 3.57036-.89259 4.31419-2.45462l1.78518-3.71913c.4463-1.04135 1.56203-1.71079 2.60339-1.71079h3.42159c.96698 0 1.11574.74382.59507 1.71079l-2.38025 4.98363c-.74382 1.63642-2.23147 2.90092-3.86789 3.27283 1.48765.4463 2.75216 1.48765 3.86789 3.27283l3.12407 4.98363c.59506.96698.29753 1.7108-.59506 1.7108h-3.4216c-1.19012 0-2.15709-.74382-2.75215-1.7108l-2.30586-3.71912c-.96697-1.63642-2.67777-2.38024-4.31418-2.38024v6.76881c0 .59506-.4463 1.11573-1.11574 1.11573h-4.09104c-.59506 0-1.11574-.52067-1.11574-1.11573v-23.80241c0-.59506.4463-1.11574 1.11574-1.11574h4.09104c.59506 0 1.11574.52068 1.11574 1.11574v12.79379z" />
|
||||
<path d="M140.1799 130.06599c1.04135 0 1.78518.59506 2.08271 1.56203l2.9753 9.81849 2.9753-9.81849c.29753-1.04136 1.33888-1.56203 2.45462-1.56203h3.34722c.89259 0 1.04135.66944.74382 1.56203l-5.50431 16.73607c-.29753.96697-1.33888 1.56203-2.30585 1.56203h-2.60339c-.89259 0-2.00833-.59506-2.30586-1.56203l-3.49598-10.78547-3.49598 10.85985c-.29753.96697-1.41327 1.56203-2.30586 1.56203h-2.60338c-.96698 0-1.93395-.59506-2.30586-1.56203l-5.50431-16.73607c-.29753-.89259-.0744-1.56203.74383-1.56203h3.34721c1.11574 0 2.08271.59506 2.45462 1.56203l2.9753 9.81849 2.9753-9.81849c.29753-.96697 1.04136-1.56203 2.08272-1.56203h3.27283z" />
|
||||
<path d="M172.09 138.47121c0-3.04968-1.41327-4.31419-3.4216-4.31419-1.78518 0-3.57036 1.26451-4.90924 2.60339v12.19874c0 .59506-.4463 1.11573-1.11574 1.11573h-4.09104c-.59506 0-1.11574-.52067-1.11574-1.11573v-23.80241c0-.59506.52068-1.11574 1.11574-1.11574h4.09104c.59506 0 1.11574.52068 1.11574 1.11574v7.2151c1.71079-1.48765 3.57036-2.67777 6.39689-2.67777 4.83487 0 8.25646 2.52901 8.25646 8.70276v10.41355c0 .59506-.52067 1.11574-1.11573 1.11574h-4.09104c-.59506 0-1.11574-.52068-1.11574-1.11574z" />
|
||||
<path d="M189.04921 135.04961c-.44629.59506-1.19012.96698-2.08271.96698h-2.67777c-.59506 0-1.11573-.4463-1.11573-1.11574 0-3.86789 3.86789-5.20678 9.89287-5.20678 5.35554 0 9.59535 2.23148 9.59535 7.88455v11.23176c0 .59506-.52068 1.11574-1.11574 1.11574h-3.49598c-.59506 0-1.11574-.52068-1.11574-1.11574v-.59506c-1.7108 1.19012-3.71912 2.08271-6.62004 2.08271-4.83487 0-8.55399-2.15709-8.55399-6.39689 0-4.23981 3.71912-6.32252 8.55399-6.32252h6.02498c0-2.90092-1.19012-3.79351-3.71912-3.79351-1.56204.0744-2.9753.52068-3.57037 1.2645zm7.28949 9.52097v-2.82654h-5.57869c-1.78518 0-2.75215.96697-2.75215 2.23148 0 1.2645.96697 2.23147 2.9753 2.23147 2.15709 0 4.01666-.8182 5.35554-1.63641z" />
|
||||
<path d="M208.16552 150.0005c-.59506 0-1.11573-.52068-1.11573-1.11574v-23.8024c0-.59506.52067-1.11574 1.11573-1.11574h4.09104c.59506 0 1.11574.52068 1.11574 1.11574v23.8024c0 .59506-.44629 1.11574-1.11574 1.11574z" />
|
||||
<path d="M223.04203 141.96719c.22315 2.9753 1.56203 4.2398 4.61171 4.2398 1.56204 0 2.97531-.44629 3.57037-1.19012.52067-.59506 1.19012-.96697 2.08271-.96697h2.67777c.59506 0 1.11574.52068 1.11574 1.11574 0 3.86789-3.94228 5.20677-9.89288 5.20677-6.62004 0-10.6367-3.57036-10.6367-10.26478 0-6.69443 4.01666-10.33917 10.6367-10.33917 6.62004 0 10.56232 3.57036 10.56232 10.11602v1.04135c0 .59506-.4463 1.11574-1.11574 1.11574h-13.612zm0-3.86789h8.47961c-.14877-2.75216-1.48765-4.23981-4.23981-4.23981-2.67777 0-4.09104 1.48765-4.2398 4.23981z" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
primary: {type: String, default: '#009fe3'},
|
||||
secondary: {type: String, default: 'var(--text-color)'},
|
||||
text: {type: String, default: 'var(--text-color)'},
|
||||
}
|
||||
}
|
||||
</script>
|
|
@ -71,6 +71,12 @@ export default new Router({
|
|||
component: () =>
|
||||
import(/* webpackChunkName: "about" */ '@/components/About')
|
||||
},
|
||||
{
|
||||
path: '/about/pod',
|
||||
name: 'about-pod',
|
||||
component: () =>
|
||||
import(/* webpackChunkName: "about" */ '@/components/AboutPod')
|
||||
},
|
||||
{
|
||||
path: '/login',
|
||||
name: 'login',
|
||||
|
|
|
@ -123,3 +123,7 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
.ui.cards a.card:hover, .ui.link.cards .card:not(.icon):hover, a.ui.card:hover, .ui.link.card:hover {
|
||||
background: var(--light-background-color);
|
||||
}
|
||||
|
|
|
@ -36,3 +36,9 @@
|
|||
td.align.right {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
|
||||
|
||||
.ui.basic.table > tbody > tr {
|
||||
border-bottom: var(--table-border);
|
||||
}
|
||||
|
|
|
@ -3,6 +3,24 @@
|
|||
padding: 0;
|
||||
}
|
||||
|
||||
.ui.basic.segment {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
section.ui.segment.head {
|
||||
border-radius: .5em;
|
||||
}
|
||||
|
||||
table.ui.very.basic {
|
||||
border-radius: 0;
|
||||
border-top: var(--table-border);
|
||||
border-bottom: var(--table-border);
|
||||
|
||||
tr:last-child {
|
||||
border-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
h1.header, h1 .sub.header {
|
||||
text-shadow: 0 2px 0 rgba(0,0,0,.8);
|
||||
color: #fff !important;
|
||||
|
@ -28,4 +46,125 @@
|
|||
display: block;
|
||||
}
|
||||
|
||||
.signup-form {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.about-pod-info-container {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
flex-direction: column;
|
||||
|
||||
margin-top: 2em;
|
||||
|
||||
.about-pod-info-toc {
|
||||
margin-bottom: 2em;
|
||||
|
||||
.ui.secondary.pointing.menu {
|
||||
&.vertical {
|
||||
border-right-width: 0;
|
||||
border-right-style: none;
|
||||
border-left: var(--table-border);
|
||||
border-left-width: 2px;
|
||||
|
||||
.item {
|
||||
border-right-style: none;
|
||||
border-right-width: 0;
|
||||
border-left-color: transparent;
|
||||
border-left-style: solid;
|
||||
border-left-width: 2px;
|
||||
margin: 0 0 0 -2px;
|
||||
|
||||
transition: all .2s ease-in-out;
|
||||
|
||||
padding-top: .5em;
|
||||
padding-bottom: .5em;
|
||||
|
||||
&.active {
|
||||
border-left-color: currentColor;
|
||||
|
||||
&:not(.router-link-exact-active) {
|
||||
border-left: 4px solid currentColor;
|
||||
margin-left: -3px;
|
||||
margin-right: -1px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.active.item {
|
||||
color: var(--vibrant-color);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.statistics-container {
|
||||
padding-top: .5rem;
|
||||
padding-bottom: 1rem;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
|
||||
.statistics-statistic {
|
||||
padding-top: .5rem;
|
||||
padding-bottom: .5rem;
|
||||
display: inline-flex;
|
||||
flex-basis: 25%;
|
||||
|
||||
.statistics-figure {
|
||||
color: var(--really-discrete-text-color);
|
||||
padding-bottom: 1rem;
|
||||
|
||||
span {
|
||||
display: inline-block;
|
||||
padding-bottom: .25rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.features-container {
|
||||
padding-top: .5rem;
|
||||
padding-bottom: 1rem;
|
||||
|
||||
.features-status {
|
||||
color: var(--really-discrete-text-color);
|
||||
}
|
||||
}
|
||||
|
||||
@include media('>desktop') {
|
||||
.about-pod-info-container {
|
||||
flex-direction: row-reverse;
|
||||
|
||||
.about-pod-info-toc {
|
||||
width: 25%;
|
||||
}
|
||||
|
||||
.about-pod-info {
|
||||
width: 75%;
|
||||
padding-right: 2em;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@include media('<tablet') {
|
||||
.statistics-container {
|
||||
.statistics-statistic {
|
||||
flex-basis: 50%;
|
||||
}
|
||||
}
|
||||
|
||||
.features-container {
|
||||
.column {
|
||||
padding: 0 !important;
|
||||
|
||||
& + .column table {
|
||||
border-top: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue