forked from nutomic/joinpeertube
Design instance card
This commit is contained in:
parent
1f2d2c4d1b
commit
a7877a865e
10 changed files with 467 additions and 173 deletions
14
.eslintrc.js
14
.eslintrc.js
|
@ -9,8 +9,20 @@ module.exports = {
|
||||||
],
|
],
|
||||||
rules: {
|
rules: {
|
||||||
'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off',
|
'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off',
|
||||||
'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off'
|
'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off',
|
||||||
|
'vue/script-indent': ['error', 2, {
|
||||||
|
baseIndent: 1,
|
||||||
|
switchCase: 1
|
||||||
|
}]
|
||||||
},
|
},
|
||||||
|
overrides: [
|
||||||
|
{
|
||||||
|
files: ['*.vue'],
|
||||||
|
rules: {
|
||||||
|
indent: 'off'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
parserOptions: {
|
parserOptions: {
|
||||||
parser: 'babel-eslint'
|
parser: 'babel-eslint'
|
||||||
}
|
}
|
||||||
|
|
69
README.md
69
README.md
|
@ -1,72 +1,13 @@
|
||||||
|
# JoinPeerTube
|
||||||
|
|
||||||
Architecture de base pour un site statique réactif et internationalisé à l’aide de :
|
## Dev
|
||||||
- Vuejs 2
|
|
||||||
- Vue-i18n + Vue-router pour l’internationnalisation des pages
|
|
||||||
- Import de jQuery, Bootstrap et ForkAwesome
|
|
||||||
- YAML pour les fichiers de langue (plus lisible qu’un JSON mais automatiquement converti)
|
|
||||||
- SASS pour l’habillage
|
|
||||||
- Webpack 4 pour automatiser la construction de l’ensemble
|
|
||||||
|
|
||||||
## En prod
|
|
||||||
Pour construire le site :
|
|
||||||
|
|
||||||
```
|
```
|
||||||
npm install
|
$ npm run serve
|
||||||
npm run prod
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Les fichiers sont placés dans le dossier public.
|
## Build for production
|
||||||
Le site fonctionne uniquement à la racine du domaine.
|
|
||||||
Les pages sont prérendues **avec les traductions dans le code html**
|
|
||||||
|
|
||||||
## En développement
|
|
||||||
Pour voir le site en local
|
|
||||||
|
|
||||||
```
|
```
|
||||||
npm run dev
|
$ npm run build
|
||||||
```
|
|
||||||
|
|
||||||
Les changements s’appliquent en temps réel et se voient sur http://localhost:8080/.
|
|
||||||
|
|
||||||
## En preview
|
|
||||||
On peut forcer la construction du site en local avec la commande :
|
|
||||||
|
|
||||||
```
|
|
||||||
npm run preview
|
|
||||||
```
|
|
||||||
|
|
||||||
Mais l’intérêt consiste surtout à voir le rendu sur les Gitlab Pages.
|
|
||||||
Les fichiers sont placés dans un sous-dossier du dossier public
|
|
||||||
correspondant au nom du dépôt.
|
|
||||||
Les pages sont prérendues **sans les traductions dans le code html** (la `fallbackLocale` est utilisée).
|
|
||||||
Celles-ci sont chargées dynamiquement (important à savoir lorsqu’il faut débugger un script).
|
|
||||||
|
|
||||||
```
|
|
||||||
├── app
|
|
||||||
│ ├── App.vue
|
|
||||||
│ ├── assets
|
|
||||||
│ │ ├── fonts
|
|
||||||
│ │ ├── icons
|
|
||||||
│ │ ├── img
|
|
||||||
│ │ └── scss
|
|
||||||
│ │ └── main.scss # le fichier compilé est minifié dans /public/style.css
|
|
||||||
│ ├── components
|
|
||||||
│ │ ├── pages # exemple de pages (juste le titre change)
|
|
||||||
│ │ │ ├── About.vue
|
|
||||||
│ │ │ ├── Home.vue
|
|
||||||
│ │ │ └── HowItWorks.vue
|
|
||||||
│ │ └── partials
|
|
||||||
│ │ ├── Header.vue # en-tête et menu de navigation
|
|
||||||
│ │ ├── I18n.vue # switch en/fr
|
|
||||||
│ │ └── i18n.js # script de changement de langue
|
|
||||||
│ ├── index.js # gestion de l’i18n + routage des pages + import des assets
|
|
||||||
│ └── locales # traductions
|
|
||||||
│ ├── en.yml
|
|
||||||
│ └── fr.yml
|
|
||||||
├── index.html # le fichier est simplement copié dans /public
|
|
||||||
├── package.json # liste des dépendances + définition de commandes npm run dev|prod
|
|
||||||
├── package-lock.json
|
|
||||||
├── postcss.config.js # juste pour préfixer les css avec -webkit, -moz, -ms
|
|
||||||
├── README.md
|
|
||||||
└── webpack.config.js # config webpack pour la construction du site
|
|
||||||
```
|
```
|
||||||
|
|
|
@ -107,18 +107,6 @@
|
||||||
|
|
||||||
.tags {
|
.tags {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|
||||||
.tag {
|
|
||||||
border: 1px solid $orange;
|
|
||||||
border-radius: 10px;
|
|
||||||
margin-right: 20px;
|
|
||||||
font-size: 14px;
|
|
||||||
min-width: 140px;
|
|
||||||
height: 25px;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
224
src/components/InstanceCard.vue
Normal file
224
src/components/InstanceCard.vue
Normal file
|
@ -0,0 +1,224 @@
|
||||||
|
<template>
|
||||||
|
<div class="root">
|
||||||
|
|
||||||
|
<div class="left">
|
||||||
|
<div class="name-host">
|
||||||
|
<div class="name">{{ instance.name }}</div>
|
||||||
|
<div class="host">{{ instance.host }}</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="description">
|
||||||
|
{{ instance.shortDescription }}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="upload-limits" v-if="isVideoMaker">
|
||||||
|
<div class="quota">
|
||||||
|
<div v-if="instance.userVideoQuota">
|
||||||
|
<div class="icon"></div>
|
||||||
|
{{ bytes(instance.userVideoQuota) }}
|
||||||
|
<translate>per user</translate>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-else v-translate>
|
||||||
|
No video quota per user
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="auto-blacklist" v-if="instance.autoBlacklistUserVideosEnabled">
|
||||||
|
<div class="label">Videos publication</div>
|
||||||
|
<div class="value">After moderation</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="tags">
|
||||||
|
<div class="tag" v-for="category in instance.categories" :key="category">
|
||||||
|
{{ translatedThemes[category] }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="right">
|
||||||
|
<div class="follow">
|
||||||
|
<template v-if="isVideoMaker">
|
||||||
|
<div class="icon">
|
||||||
|
<icon-followers></icon-followers>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<translate :translate-n="instance.totalInstanceFollowers"
|
||||||
|
translate-plural="%{ instance.totalInstanceFollowers } followers instances">
|
||||||
|
%{ instance.totalInstanceFollowers } follower instance
|
||||||
|
</translate>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template v-else>
|
||||||
|
<div class="icon">
|
||||||
|
<icon-following></icon-following>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<translate :translate-n="instance.totalInstanceFollowing"
|
||||||
|
translate-plural="Follows %{ instance.totalInstanceFollowing } instances">
|
||||||
|
Follows %{ instance.totalInstanceFollowing } instance
|
||||||
|
</translate>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="languages" v-if="Array.isArray(instance.languages) && instance.languages.length !== 0">
|
||||||
|
<div class="icon">
|
||||||
|
<icon-languages></icon-languages>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>{{ getLanguages(instance.languages) }}</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="nsfw">
|
||||||
|
<span v-translate class="label">Sensitive content</span>
|
||||||
|
<div v-translate v-if="instance.defaultNSFWPolicy === 'do_not_list'">Hidden</div>
|
||||||
|
<div v-translate v-if="instance.defaultNSFWPolicy === 'blur'">Blurred</div>
|
||||||
|
<div v-translate v-if="instance.defaultNSFWPolicy === 'display'">Displayed</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="link">
|
||||||
|
<a :href="getUrl(instance)" class="bottom-link" target="_blank" rel="noopener noreferrer">
|
||||||
|
<span class="text" v-translate>See the instance</span>
|
||||||
|
<icon-right></icon-right>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
@import '../scss/_variables.scss';
|
||||||
|
|
||||||
|
.root {
|
||||||
|
height: 185px;
|
||||||
|
width: 770px;
|
||||||
|
margin: auto;
|
||||||
|
box-shadow: 0 2px 6px 0 rgba(0, 0, 0, 0.35);
|
||||||
|
border: solid 1px #d9d9d9;
|
||||||
|
padding: 20px 25px;
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.left,
|
||||||
|
.right {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
|
||||||
|
.left {
|
||||||
|
margin-right: 40px;
|
||||||
|
width: 480px;
|
||||||
|
|
||||||
|
.name-host {
|
||||||
|
display: flex;
|
||||||
|
margin-bottom: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.name {
|
||||||
|
font-family: "Proza Libre", sans-serif;
|
||||||
|
font-weight: $font-semibold;
|
||||||
|
margin-right: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.host {
|
||||||
|
color: $grey;
|
||||||
|
}
|
||||||
|
|
||||||
|
.description {
|
||||||
|
margin-bottom: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tags {
|
||||||
|
margin-top: auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.right {
|
||||||
|
.icon,
|
||||||
|
.label {
|
||||||
|
margin-right: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.follow,
|
||||||
|
.languages {
|
||||||
|
margin-bottom: 10px;
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nsfw {
|
||||||
|
display: flex;
|
||||||
|
|
||||||
|
.label {
|
||||||
|
color: $grey;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.link {
|
||||||
|
margin-top: auto;
|
||||||
|
margin-bottom: 2px;
|
||||||
|
align-self: flex-end;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import IconRight from './icons/IconRight'
|
||||||
|
import IconFollowers from './icons/IconFollowers'
|
||||||
|
import IconFollowing from './icons/IconFollowing'
|
||||||
|
import IconLanguages from './icons/IconLanguages'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
components: {
|
||||||
|
IconRight,
|
||||||
|
IconFollowers,
|
||||||
|
IconFollowing,
|
||||||
|
IconLanguages
|
||||||
|
},
|
||||||
|
|
||||||
|
props: {
|
||||||
|
instance: Object,
|
||||||
|
translatedThemes: Object,
|
||||||
|
translatedLanguages: Object,
|
||||||
|
isVideoMaker: Boolean
|
||||||
|
},
|
||||||
|
|
||||||
|
data () {
|
||||||
|
return {}
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
bytes (value) {
|
||||||
|
if (value === -1) return this.$gettext('Unlimited space for users')
|
||||||
|
|
||||||
|
// https://github.com/danrevah/ngx-pipes/blob/master/src/pipes/math/bytes.ts
|
||||||
|
const dictionaryBytes = [
|
||||||
|
{ max: 1024, type: this.$gettext('B') },
|
||||||
|
{ max: 1048576, type: this.$gettext('KB') },
|
||||||
|
{ max: 1073741824, type: this.$gettext('MB') },
|
||||||
|
{ max: 1.0995116e12, type: this.$gettext('GB') }
|
||||||
|
]
|
||||||
|
|
||||||
|
const format = dictionaryBytes.find(function (d) { return value < d.max }) || dictionaryBytes[dictionaryBytes.length - 1]
|
||||||
|
const calc = Math.floor(value / (format.max / 1024)).toString()
|
||||||
|
|
||||||
|
return calc + format.type
|
||||||
|
},
|
||||||
|
|
||||||
|
getLanguages (languages) {
|
||||||
|
return languages.map(l => this.translatedLanguages[l]).join(', ')
|
||||||
|
},
|
||||||
|
|
||||||
|
getUrl (instance) {
|
||||||
|
return `https://${instance.host}`
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
mounted () {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
|
@ -3,7 +3,7 @@
|
||||||
<div class="filters">
|
<div class="filters">
|
||||||
<div v-translate class="title">Filter according to your preferences</div>
|
<div v-translate class="title">Filter according to your preferences</div>
|
||||||
|
|
||||||
<form>
|
<form @change="onFormChange()">
|
||||||
<div class="group">
|
<div class="group">
|
||||||
<label for="profile" v-translate>Your profile</label>
|
<label for="profile" v-translate>Your profile</label>
|
||||||
|
|
||||||
|
@ -47,7 +47,7 @@
|
||||||
<div class="group">
|
<div class="group">
|
||||||
<label for="profile" v-translate>Sensitive videos</label>
|
<label for="profile" v-translate>Sensitive videos</label>
|
||||||
|
|
||||||
<b-form-radio-group id="nsfw" buttons name="nsfw" v-model="wantTo">
|
<b-form-radio-group id="nsfw" buttons name="nsfw" v-model="nsfw">
|
||||||
<b-form-radio value="hide">
|
<b-form-radio value="hide">
|
||||||
<translate>Hide</translate>
|
<translate>Hide</translate>
|
||||||
</b-form-radio>
|
</b-form-radio>
|
||||||
|
@ -78,7 +78,7 @@
|
||||||
></b-form-checkbox-group>
|
></b-form-checkbox-group>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="group">
|
<div class="group" v-if="isVideoMaker() && wantToRegister()">
|
||||||
<label for="quota" v-translate>Allowed video space</label>
|
<label for="quota" v-translate>Allowed video space</label>
|
||||||
|
|
||||||
<b-form-select v-model="quota" id="quota" name="quota">
|
<b-form-select v-model="quota" id="quota" name="quota">
|
||||||
|
@ -102,9 +102,23 @@
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div class="instances-list">
|
||||||
<div v-if="error" id="instances-list-error" class="alert alert-danger">
|
<div v-translate class="title">Instances list</div>
|
||||||
Sorry, but we cannot fetch the instances list. Please retry later.
|
|
||||||
|
<div class="list">
|
||||||
|
<div v-for="instance of instances" class="instance">
|
||||||
|
<instance-card
|
||||||
|
:instance="instance" :isVideoMaker="isVideoMaker()"
|
||||||
|
:translatedLanguages="translatedLanguages" :translatedThemes="translatedThemes"
|
||||||
|
>
|
||||||
|
</instance-card>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<div v-if="error" id="instances-list-error" class="alert alert-danger">
|
||||||
|
Sorry, but we cannot fetch the instances list. Please retry later.
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -113,11 +127,14 @@
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
@import '../scss/_variables.scss';
|
@import '../scss/_variables.scss';
|
||||||
|
|
||||||
|
.title {
|
||||||
|
font-size: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
.filters {
|
.filters {
|
||||||
margin-bottom: 100px;
|
margin-bottom: 100px;
|
||||||
|
|
||||||
.title {
|
.title {
|
||||||
font-size: 24px;
|
|
||||||
margin-bottom: 25px;
|
margin-bottom: 25px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -167,6 +184,10 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.instances-list {
|
||||||
|
margin-bottom: 50px;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
|
@ -190,30 +211,42 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
&:nth-child(4n-1) {
|
&:nth-child(4n-1) {
|
||||||
width: 110px;
|
width: 190px;
|
||||||
}
|
}
|
||||||
|
|
||||||
&:nth-child(4n-2) {
|
&:nth-child(4n-2) {
|
||||||
width: 110px;
|
width: 130px;
|
||||||
}
|
}
|
||||||
|
|
||||||
&:nth-child(4n-3) {
|
&:nth-child(4n-3) {
|
||||||
width: 200px;
|
width: 100px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.instances-list {
|
||||||
|
.title {
|
||||||
|
margin-bottom: 50px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.instance {
|
||||||
|
margin-bottom: 40px;
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { BFormRadio, BFormRadioGroup, BFormCheckboxGroup, BFormSelect } from 'bootstrap-vue'
|
import { BFormCheckboxGroup, BFormRadio, BFormRadioGroup, BFormSelect } from 'bootstrap-vue'
|
||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
|
import InstanceCard from './InstanceCard'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
'b-form-radio-group': BFormRadioGroup,
|
'b-form-radio-group': BFormRadioGroup,
|
||||||
'b-form-radio': BFormRadio,
|
'b-form-radio': BFormRadio,
|
||||||
'b-form-checkbox-group': BFormCheckboxGroup,
|
'b-form-checkbox-group': BFormCheckboxGroup,
|
||||||
'b-form-select': BFormSelect
|
'b-form-select': BFormSelect,
|
||||||
|
InstanceCard
|
||||||
},
|
},
|
||||||
|
|
||||||
data () {
|
data () {
|
||||||
|
@ -221,50 +254,28 @@
|
||||||
error: false,
|
error: false,
|
||||||
|
|
||||||
instances: [],
|
instances: [],
|
||||||
availableThemes: [
|
translatedThemes: {
|
||||||
{ value: '11', text: this.$gettext('News & Politics') },
|
'1': this.$gettext('Music'),
|
||||||
{ value: '1', text: this.$gettext('Music') },
|
'2': this.$gettext('Films'),
|
||||||
{ value: '2', text: this.$gettext('Films') },
|
'3': this.$gettext('Vehicles'),
|
||||||
{ value: '3', text: this.$gettext('Vehicles') },
|
'4': this.$gettext('Art'),
|
||||||
|
'5': this.$gettext('Sports'),
|
||||||
{ value: '10', text: this.$gettext('Entertainment') },
|
'6': this.$gettext('Travels'),
|
||||||
{ value: '4', text: this.$gettext('Art') },
|
'7': this.$gettext('Gaming'),
|
||||||
{ value: '5', text: this.$gettext('Sports') },
|
'8': this.$gettext('People'),
|
||||||
{ value: '6', text: this.$gettext('Travels') },
|
'9': this.$gettext('Comedy'),
|
||||||
|
'10': this.$gettext('Entertainment'),
|
||||||
{ value: '15', text: this.$gettext('Science & Technology') },
|
'11': this.$gettext('News & Politics'),
|
||||||
{ value: '8', text: this.$gettext('People') },
|
'12': this.$gettext('How To'),
|
||||||
{ value: '9', text: this.$gettext('Comedy') },
|
'13': this.$gettext('Education'),
|
||||||
{ value: '12', text: this.$gettext('How To') },
|
'14': this.$gettext('Activism'),
|
||||||
|
'15': this.$gettext('Science & Technology'),
|
||||||
{ value: '7', text: this.$gettext('Gaming') },
|
'16': this.$gettext('Animals'),
|
||||||
{ value: '13', text: this.$gettext('Education') },
|
'17': this.$gettext('Kids'),
|
||||||
{ value: '14', text: this.$gettext('Activism') },
|
'18': this.$gettext('Food')
|
||||||
{ value: '16', text: this.$gettext('Animals') },
|
},
|
||||||
|
translatedLanguages: {
|
||||||
{ value: '17', text: this.$gettext('Kids') },
|
'en': this.$gettext('English'),
|
||||||
{ value: '18', text: this.$gettext('Food') },
|
|
||||||
],
|
|
||||||
|
|
||||||
profile: 'viewer',
|
|
||||||
wantTo: 'create-account',
|
|
||||||
themes: [],
|
|
||||||
nsfw: 'no-opinion',
|
|
||||||
languages: [],
|
|
||||||
quota: '5'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
computed: {
|
|
||||||
availableLanguages: function () {
|
|
||||||
const available = [
|
|
||||||
{
|
|
||||||
value: 'en',
|
|
||||||
text: this.$gettext('English')
|
|
||||||
}
|
|
||||||
]
|
|
||||||
|
|
||||||
const all = {
|
|
||||||
'fr': this.$gettext('Français'),
|
'fr': this.$gettext('Français'),
|
||||||
'ja': this.$gettext('日本語'),
|
'ja': this.$gettext('日本語'),
|
||||||
'eu': this.$gettext('Euskara'),
|
'eu': this.$gettext('Euskara'),
|
||||||
|
@ -284,12 +295,43 @@
|
||||||
'pl': this.$gettext('Polski'),
|
'pl': this.$gettext('Polski'),
|
||||||
'fi': this.$gettext('suomi'),
|
'fi': this.$gettext('suomi'),
|
||||||
'ru': this.$gettext('русский')
|
'ru': this.$gettext('русский')
|
||||||
|
},
|
||||||
|
|
||||||
|
profile: 'viewer',
|
||||||
|
wantTo: 'create-account',
|
||||||
|
themes: [],
|
||||||
|
nsfw: 'no-opinion',
|
||||||
|
languages: [],
|
||||||
|
quota: '5'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
computed: {
|
||||||
|
availableThemes: function () {
|
||||||
|
const result = []
|
||||||
|
|
||||||
|
for (const key of Object.keys(this.translatedThemes)) {
|
||||||
|
result.push({
|
||||||
|
value: key,
|
||||||
|
text: this.translatedThemes[key]
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
},
|
||||||
|
|
||||||
|
availableLanguages: function () {
|
||||||
|
const available = [
|
||||||
|
{
|
||||||
|
value: 'en',
|
||||||
|
text: this.translatedLanguages['en']
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
const navigatorLanguage = window.navigator.userLanguage || window.navigator.language
|
const navigatorLanguage = window.navigator.userLanguage || window.navigator.language
|
||||||
const smallLanguage = navigatorLanguage.split('-')[0]
|
const smallLanguage = navigatorLanguage.split('-')[0]
|
||||||
|
|
||||||
const found = all[smallLanguage]
|
const found = this.translatedLanguages[smallLanguage]
|
||||||
if (found && found !== 'en') {
|
if (found && found !== 'en') {
|
||||||
available.push({
|
available.push({
|
||||||
value: smallLanguage,
|
value: smallLanguage,
|
||||||
|
@ -302,6 +344,18 @@
|
||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
|
isViewer () {
|
||||||
|
return this.profile === 'viewer'
|
||||||
|
},
|
||||||
|
|
||||||
|
isVideoMaker () {
|
||||||
|
return this.profile === 'video-maker'
|
||||||
|
},
|
||||||
|
|
||||||
|
wantToRegister () {
|
||||||
|
return this.wantTo === 'discover-instances'
|
||||||
|
},
|
||||||
|
|
||||||
// Thanks https://stackoverflow.com/a/6274381
|
// Thanks https://stackoverflow.com/a/6274381
|
||||||
shuffle (a) {
|
shuffle (a) {
|
||||||
for (let i = a.length - 1; i > 0; i--) {
|
for (let i = a.length - 1; i > 0; i--) {
|
||||||
|
@ -312,51 +366,36 @@
|
||||||
return a
|
return a
|
||||||
},
|
},
|
||||||
|
|
||||||
bytes (value) {
|
onFormChange () {
|
||||||
// https://github.com/danrevah/ngx-pipes/blob/master/src/pipes/math/bytes.ts
|
this.fetchInstances()
|
||||||
const dictionaryBytes = [
|
},
|
||||||
{max: 1024, type: 'B'},
|
|
||||||
{max: 1048576, type: 'KB'},
|
|
||||||
{max: 1073741824, type: 'MB'},
|
|
||||||
{max: 1.0995116e12, type: 'GB'}
|
|
||||||
]
|
|
||||||
|
|
||||||
if (value === -1) return 'No quota'
|
fetchInstances () {
|
||||||
|
const options = {
|
||||||
|
method: 'GET',
|
||||||
|
params: {
|
||||||
|
start: 0,
|
||||||
|
count: 250,
|
||||||
|
// signup: true,
|
||||||
|
healthy: true,
|
||||||
|
nsfwPolicy: ['do_not_list', 'blur'],
|
||||||
|
search: 'peertube2'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const format = dictionaryBytes.find(function (d) { return value < d.max }) || dictionaryBytes[dictionaryBytes.length - 1]
|
axios('https://instances.joinpeertube.org/api/v1/instances', options)
|
||||||
const calc = Math.floor(value / (format.max / 1024)).toString()
|
.then(response => {
|
||||||
|
this.instances = this.shuffle(response.data.data)
|
||||||
return calc + format.type
|
})
|
||||||
|
.catch(err => {
|
||||||
|
console.error(err)
|
||||||
|
this.error = true
|
||||||
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
mounted () {
|
mounted () {
|
||||||
const options = {
|
this.fetchInstances()
|
||||||
method: 'GET',
|
|
||||||
params: {
|
|
||||||
start: 0,
|
|
||||||
count: 100,
|
|
||||||
signup: true,
|
|
||||||
healthy: true,
|
|
||||||
nsfwPolicy: ['do_not_list', 'blur']
|
|
||||||
}
|
|
||||||
}
|
|
||||||
axios('https://instances.joinpeertube.org/api/v1/instances', options)
|
|
||||||
.then(response => {
|
|
||||||
this.instances = this.shuffle(response.data.data)
|
|
||||||
|
|
||||||
this.instances.forEach(i => {
|
|
||||||
i.url = 'https://' + i.host
|
|
||||||
|
|
||||||
if (i.userVideoQuota) {
|
|
||||||
i.userVideoQuotaBytes = this.bytes(i.userVideoQuota)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
.catch(err => {
|
|
||||||
console.error(err)
|
|
||||||
this.error = true
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
23
src/components/icons/IconFollowers.vue
Normal file
23
src/components/icons/IconFollowers.vue
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
<template>
|
||||||
|
<svg width="23px" height="23px" viewBox="0 0 23 23" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||||
|
<defs>
|
||||||
|
<path d="M16.675,15.1416667 L16.5472222,14.95 C15.2694444,13.5444444 13.4805556,12.7138889 11.5638889,12.7777778 C9.64722222,12.7138889 7.79444444,13.5444444 6.51666667,14.95 L6.38888889,15.1416667 L6.38888889,19.9972222 C6.38888889,20.5722222 6.83611111,21.0833333 7.475,21.0833333 C7.475,21.0833333 7.475,21.0833333 7.475,21.0833333 L15.6527778,21.0833333 C16.2277778,21.0833333 16.7388889,20.5722222 16.7388889,19.9972222 C16.7388889,19.9972222 16.7388889,19.9972222 16.7388889,19.9972222 L16.7388889,15.1416667 L16.675,15.1416667 Z M15.3972222,19.8055556 L7.66666667,19.8055556 L7.66666667,15.5888889 C8.68888889,14.5666667 10.0944444,14.0555556 11.5638889,14.0555556 C12.9694444,13.9916667 14.375,14.5666667 15.3972222,15.5888889 L15.3972222,19.8055556 Z M6.58055556,9.00833333 C6.70833333,9.00833333 6.83611111,9.00833333 6.96388889,8.94444444 C6.96388889,8.81666667 6.96388889,8.68888889 6.96388889,8.56111111 C6.96388889,8.24166667 6.96388889,7.92222222 7.02777778,7.66666667 C6.9,7.73055556 6.70833333,7.73055556 6.58055556,7.73055556 C5.75,7.73055556 5.04722222,7.02777778 5.04722222,6.19722222 C5.04722222,5.36666667 5.75,4.66388889 6.58055556,4.66388889 C7.21944444,4.66388889 7.79444444,5.04722222 8.05,5.62222222 C8.30555556,5.30277778 8.68888889,4.98333333 9.00833333,4.72777778 C8.17777778,3.38611111 6.45277778,2.93888889 5.11111111,3.76944444 C3.76944444,4.6 3.32222222,6.325 4.15277778,7.66666667 C4.66388889,8.49722222 5.55833333,9.00833333 6.58055556,9.00833333 Z M7.66666667,11.1166667 C7.41111111,10.7333333 7.21944444,10.2861111 7.09166667,9.775 C6.9,9.775 6.77222222,9.775 6.58055556,9.775 C4.91944444,9.71111111 3.32222222,10.2861111 2.10833333,11.3083333 L1.91666667,11.5 L1.91666667,16.6111111 L3.19444444,16.6111111 L3.19444444,12.0111111 C4.21666667,11.3083333 5.36666667,10.925 6.58055556,10.9888889 C6.96388889,10.9888889 7.34722222,11.0527778 7.66666667,11.1166667 Z M14.95,5.62222222 C15.2694444,4.85555556 16.1638889,4.47222222 16.9944444,4.79166667 C17.7611111,5.11111111 18.1444444,6.00555556 17.825,6.83611111 C17.5694444,7.41111111 16.9944444,7.79444444 16.4194444,7.79444444 C16.2916667,7.79444444 16.1,7.79444444 15.9722222,7.73055556 C16.0361111,8.05 16.0361111,8.36944444 16.0361111,8.625 C16.0361111,8.75277778 16.0361111,8.88055556 16.0361111,9.00833333 C16.1638889,9.00833333 16.2916667,9.07222222 16.4194444,9.07222222 C18.0166667,9.07222222 19.2944444,7.79444444 19.2944444,6.26111111 C19.2944444,4.66388889 18.0166667,3.38611111 16.4833333,3.38611111 C15.4611111,3.38611111 14.5666667,3.89722222 14.0555556,4.79166667 C14.375,4.98333333 14.6944444,5.23888889 14.95,5.62222222 Z M20.8916667,11.3083333 C19.6777778,10.2222222 18.0805556,9.64722222 16.4194444,9.71111111 C16.2277778,9.71111111 16.1,9.71111111 15.9083333,9.71111111 C15.7805556,10.2222222 15.5888889,10.6694444 15.3333333,11.0527778 C15.7166667,10.9888889 16.0361111,10.9888889 16.4194444,10.9888889 C17.6333333,10.925 18.8472222,11.3083333 19.8055556,12.0111111 L19.8055556,16.6111111 L21.0833333,16.6111111 L21.0833333,11.5 L20.8916667,11.3083333 Z M11.4361111,11.6916667 C13.1611111,11.6916667 14.5027778,10.2861111 14.5027778,8.56111111 C14.5027778,6.83611111 13.0972222,5.49444444 11.3722222,5.49444444 C9.64722222,5.49444444 8.30555556,6.9 8.30555556,8.56111111 C8.30555556,10.2861111 9.71111111,11.6916667 11.4361111,11.6916667 Z M11.3722222,6.77222222 C11.4361111,6.77222222 11.4361111,6.77222222 11.3722222,6.77222222 C12.3944444,6.77222222 13.225,7.60277778 13.225,8.625 C13.225,9.64722222 12.3944444,10.4138889 11.3722222,10.4138889 C10.35,10.4138889 9.58333333,9.58333333 9.58333333,8.625 C9.58333333,7.60277778 10.4138889,6.77222222 11.3722222,6.77222222 Z" id="path-followers"></path>
|
||||||
|
</defs>
|
||||||
|
<g id="icone/abonnements" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||||
|
<mask id="mask-followers" fill="white">
|
||||||
|
<use xlink:href="#path-followers"></use>
|
||||||
|
</mask>
|
||||||
|
<use id="Mask" fill="#000000" fill-rule="nonzero" xlink:href="#path-followers"></use>
|
||||||
|
<g id="color" mask="url(#mask-followers)" fill="#868686">
|
||||||
|
<g transform="translate(-0.000000, 0.000000)" id="Rectangle">
|
||||||
|
<rect x="0" y="0" width="23" height="23"></rect>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {}
|
||||||
|
</script>
|
27
src/components/icons/IconFollowing.vue
Normal file
27
src/components/icons/IconFollowing.vue
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
<template>
|
||||||
|
<svg width="23px" height="23px" viewBox="0 0 23 23" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||||
|
<defs>
|
||||||
|
<path d="M4.62555556,8.59306644 C4.4538821,8.59066881 4.29039398,8.51928667 4.17194444,8.395 L0.268333333,4.47222222 L4.17194444,0.549444444 C4.33286282,0.387384803 4.56801532,0.323484451 4.78882228,0.381814032 C5.00962923,0.440143613 5.18254481,0.611841477 5.24243339,0.832230699 C5.30232196,1.05261992 5.24008504,1.28821814 5.07916667,1.45027778 L2.70888889,3.83333333 L14.1322222,3.83333333 C14.4850708,3.83333333 14.7711111,4.11937363 14.7711111,4.47222222 C14.7711111,4.82507081 14.4850708,5.11111111 14.1322222,5.11111111 L2.70888889,5.11111111 L5.07916667,7.50055556 C5.26346052,7.68333557 5.31885341,7.95944823 5.21932033,8.19916874 C5.11978725,8.43888925 4.8851138,8.59456501 4.62555556,8.59306644 Z M11.1358333,7.55805556 L15.0330556,11.5 L11.1294444,15.4036111 C10.9685261,15.5656708 10.7333736,15.6295711 10.5125666,15.5712415 C10.2917596,15.512912 10.1188441,15.3412141 10.0589555,15.1208249 C9.9990669,14.9004356 10.0613038,14.6648374 10.2222222,14.5027778 L12.5988889,12.1388889 L1.16916667,12.1388889 C0.816318076,12.1388889 0.530277778,11.8528486 0.530277778,11.5 C0.530277778,11.1471514 0.816318076,10.8611111 1.16916667,10.8611111 L12.5988889,10.8611111 L10.2222222,8.45888889 C9.97346398,8.20660215 9.97632438,7.80042493 10.2286111,7.55166668 C10.4808979,7.30290842 10.8870751,7.30576882 11.1358333,7.55805556 Z" id="path-following"></path>
|
||||||
|
</defs>
|
||||||
|
<g stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||||
|
<g transform="translate(3.000000, 3.000000)">
|
||||||
|
<g transform="translate(0.833333, 0.194444)">
|
||||||
|
<mask id="mask-following" fill="white">
|
||||||
|
<use xlink:href="#path-following"></use>
|
||||||
|
</mask>
|
||||||
|
<use id="Mask" fill="#000000" fill-rule="nonzero" xlink:href="#path-following"></use>
|
||||||
|
<g mask="url(#mask-following)" fill="#868686" id="Rectangle">
|
||||||
|
<g transform="translate(-3.833333, -3.194444)">
|
||||||
|
<rect x="0" y="0" width="23" height="23"></rect>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {}
|
||||||
|
</script>
|
26
src/components/icons/IconLanguages.vue
Normal file
26
src/components/icons/IconLanguages.vue
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
<template>
|
||||||
|
<svg width="23px" height="23px" viewBox="0 0 23 23" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||||
|
<defs>
|
||||||
|
<path d="M18.5277778,0 L7.66666667,0 C6.6081209,0 5.75,0.858120896 5.75,1.91666667 L5.75,9.58333333 C5.75,10.6418791 6.6081209,11.5 7.66666667,11.5 L16.3236111,11.5 L19.3775,13.8702778 C19.5623174,14.0069208 19.8062885,14.0337576 20.0163889,13.9405556 C20.2382646,13.8348816 20.3798599,13.6113102 20.3805559,13.3655556 L20.3805559,1.91666667 C20.3811302,0.8825773 19.5612927,0.0344694912 18.5277778,0 Z M19.1666667,12.1005556 L16.9305556,10.3563889 C16.8190376,10.2698401 16.6819955,10.2226617 16.5408333,10.2222222 L7.66666667,10.2222222 C7.31381808,10.2222222 7.02777778,9.93618192 7.02777778,9.58333333 L7.02777778,1.91666667 C7.02777778,1.56381808 7.31381808,1.27777778 7.66666667,1.27777778 L18.5277778,1.27777778 C18.8811722,1.30985178 19.1552157,1.60033787 19.1666667,1.955 L19.1666667,12.1005556 Z M13.4166667,14.0555556 L13.4166667,13.4166667 L14.6944444,13.4166667 L14.6944444,14.1386111 C14.7123355,14.627945 14.526684,15.1028213 14.1816543,15.4502723 C13.8366246,15.7977232 13.3630581,15.986691 12.8736111,15.9722222 L4.28694444,15.9722222 L0.996666667,18.3936111 C0.810649053,18.5281453 0.566752307,18.552535 0.357777778,18.4575 C0.140449868,18.3510235 0.00193934525,18.1308907 0,17.8888889 L0,6.38888889 C0,5.33034312 0.858120896,4.47222222 1.91666667,4.47222222 L4.38277778,4.47222222 L4.38277778,5.75 L1.91666667,5.75 C1.56381808,5.75 1.27777778,6.0360403 1.27777778,6.38888889 L1.27777778,16.6111111 L3.44361111,14.9052778 C3.55861111,14.8222222 3.69277778,14.6944444 3.83333333,14.6944444 L12.7777778,14.6944444 C13.1306264,14.6944444 13.4166667,14.4084041 13.4166667,14.0555556 Z" id="path-language"></path>
|
||||||
|
</defs>
|
||||||
|
<g stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||||
|
<g transform="translate(1.000000, 2.000000)">
|
||||||
|
<g transform="translate(0.277778, 0.555556)">
|
||||||
|
<mask id="mask-languages" fill="white">
|
||||||
|
<use xlink:href="#path-language"></use>
|
||||||
|
</mask>
|
||||||
|
<use id="Mask" fill="#000000" fill-rule="nonzero" xlink:href="#path-language"></use>
|
||||||
|
<g mask="url(#mask-languages)" fill="#868686" id="Rectangle">
|
||||||
|
<g transform="translate(-1.277778, -2.555556)">
|
||||||
|
<rect x="0" y="0" width="23" height="23"></rect>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {}
|
||||||
|
</script>
|
|
@ -1,3 +1,4 @@
|
||||||
$font-semibold: 600;
|
$font-semibold: 600;
|
||||||
|
|
||||||
$orange: #f67e08;
|
$orange: #f67e08;
|
||||||
|
$grey: #5e5e5e;
|
||||||
|
|
|
@ -203,3 +203,16 @@ main {
|
||||||
width: 200px;
|
width: 200px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.tag {
|
||||||
|
border: 1px solid $orange;
|
||||||
|
border-radius: 10px;
|
||||||
|
margin-right: 20px;
|
||||||
|
font-size: 14px;
|
||||||
|
min-width: 140px;
|
||||||
|
height: 25px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
width: fit-content;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue