@@ -1,17 +1,15 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="hero intro is-medium is-primary">
|
||||
<div class="hero intro is-small is-primary">
|
||||
<div class="hero-body">
|
||||
<div class="container">
|
||||
<h1 class="title">{{ $t("About Mobilizon") }}</h1>
|
||||
<p class="subtitle">
|
||||
<span>
|
||||
{{
|
||||
$t(
|
||||
"A user-friendly, emancipatory and ethical tool for gathering, organising, and mobilising."
|
||||
)
|
||||
}}
|
||||
</span>
|
||||
<p>
|
||||
{{
|
||||
$t(
|
||||
"A user-friendly, emancipatory and ethical tool for gathering, organising, and mobilising."
|
||||
)
|
||||
}}
|
||||
</p>
|
||||
<b-button
|
||||
icon-left="open-in-new"
|
||||
@@ -24,165 +22,56 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="container">
|
||||
<section>
|
||||
<div class="columns">
|
||||
<div class="column has-text-left-desktop">
|
||||
<h2 class="title">{{ $t("Gather ⋅ Organize ⋅ Mobilize") }}</h2>
|
||||
<p
|
||||
class="content"
|
||||
v-html="
|
||||
$t(
|
||||
'From a birthday party with friends and family to a march for climate change, right now, our gatherings are <b>trapped inside the tech giants’ platforms</b>. How can we organize, how can we click “Attend,” without <b>providing private data</b> to Facebook or <b>locking ourselves up</b> inside MeetUp?'
|
||||
)
|
||||
"
|
||||
/>
|
||||
<p
|
||||
v-html="
|
||||
$t(
|
||||
'Mobilizon is a free/libre software that will allow communities to create <b>their own spaces</b> to publish events in order to better emancipate themselves from tech giants.'
|
||||
)
|
||||
"
|
||||
/>
|
||||
</div>
|
||||
<div class="column has-text-right-desktop has-text-centered-mobile">
|
||||
<img
|
||||
src="img/about/action-mobilizon.png"
|
||||
width="300"
|
||||
:alt="$t('Organize and take action, freely')"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<section>
|
||||
<div class="columns">
|
||||
<div class="column has-text-right-desktop">
|
||||
<h2 class="title">{{ $t("Let's create a new common") }}</h2>
|
||||
<p
|
||||
v-html="
|
||||
$t(
|
||||
'We want to develop a <b>digital common</b>, that everyone can make their own, which respects <b>privacy and activism by design</b>.'
|
||||
)
|
||||
"
|
||||
/>
|
||||
<p>
|
||||
<span
|
||||
v-html="
|
||||
$t(
|
||||
'Installing Mobilizon will allow communities to free themselves from the services of tech giants by creating <b>their own event platform</b>.'
|
||||
)
|
||||
"
|
||||
/>
|
||||
<i18n
|
||||
tag="span"
|
||||
path="This installation (called “instance“) can easily {interconnect}, thanks to {protocol}."
|
||||
>
|
||||
<b slot="interconnect">{{ $t("interconnect with others like it") }}</b>
|
||||
<a slot="protocol" href="https://en.wikipedia.org/wiki/ActivityPub">{{
|
||||
$t("a decentralised federation protocol")
|
||||
}}</a>
|
||||
</i18n>
|
||||
<main class="container">
|
||||
<div class="columns">
|
||||
<div class="column is-one-quarter-desktop">
|
||||
<aside class="menu">
|
||||
<p class="menu-label">
|
||||
{{ $t("About") }}
|
||||
</p>
|
||||
</div>
|
||||
<div class="column has-text-left-desktop has-text-centered-mobile">
|
||||
<img
|
||||
src="img/about/common-mobilizon.png"
|
||||
width="300"
|
||||
:alt="$t('Let\'s create a new common')"
|
||||
/>
|
||||
</div>
|
||||
<ul class="menu-list">
|
||||
<li>
|
||||
<router-link :to="{ name: RouteName.ABOUT_INSTANCE }">{{
|
||||
$t("About this instance")
|
||||
}}</router-link>
|
||||
</li>
|
||||
<li>
|
||||
<router-link :to="{ name: RouteName.ABOUT_MOBILIZON }">{{
|
||||
$t("About Mobilizon")
|
||||
}}</router-link>
|
||||
</li>
|
||||
</ul>
|
||||
<p class="menu-label">
|
||||
{{ $t("Legal") }}
|
||||
</p>
|
||||
<ul class="menu-list">
|
||||
<li>
|
||||
<router-link :to="{ name: RouteName.TERMS }">{{
|
||||
$t("Terms of service")
|
||||
}}</router-link>
|
||||
</li>
|
||||
<li>
|
||||
<router-link :to="{ name: RouteName.PRIVACY }">{{
|
||||
$t("Privacy policy")
|
||||
}}</router-link>
|
||||
</li>
|
||||
<li>
|
||||
<router-link :to="{ name: RouteName.RULES }">{{
|
||||
$t("Instance rules")
|
||||
}}</router-link>
|
||||
</li>
|
||||
<li>
|
||||
<router-link :to="{ name: RouteName.GLOSSARY }">{{ $t("Glossary") }}</router-link>
|
||||
</li>
|
||||
</ul>
|
||||
</aside>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
<div class="hero quote is-secondary">
|
||||
<div class="hero-body">
|
||||
<div class="container">
|
||||
<h2 class="title">{{ $t("To change the world, change the software") }}</h2>
|
||||
<blockquote>
|
||||
{{
|
||||
$t(
|
||||
"We won’t change the world from Facebook. The tool we dream of, surveillance capitalism corporations won’t develop it, as they couldn’t profit from it. This is an opportunity to build something better, by taking another approach."
|
||||
)
|
||||
}}
|
||||
</blockquote>
|
||||
<footer class="blockquote-footer">
|
||||
<a
|
||||
href="https://framablog.org/2019/05/14/mobilizon-lets-finance-a-software-to-free-our-events-from-facebook/"
|
||||
>{{ $t("Read Framasoft’s statement of intent on the Framablog") }}</a
|
||||
>
|
||||
</footer>
|
||||
<div class="column router">
|
||||
<router-view />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="container">
|
||||
<section>
|
||||
<div class="columns">
|
||||
<div class="column">
|
||||
<h2 class="title">{{ $t("Software to the people") }}</h2>
|
||||
<i18n
|
||||
tag="p"
|
||||
path="{license} guarantees {respect} of the people who will use it. Since {source}, anyone can audit it, which guarantees its transparency."
|
||||
>
|
||||
<a slot="license" href="https://choosealicense.com/licenses/agpl-3.0/">{{
|
||||
$t("Mobilizon’s licence")
|
||||
}}</a>
|
||||
<b slot="respect">{{ $t("respect of the fundamental freedoms") }}</b>
|
||||
<a slot="source" href="https://framagit.org/framasoft/mobilizon">{{
|
||||
$t("its source code is public")
|
||||
}}</a>
|
||||
</i18n>
|
||||
<p>
|
||||
{{
|
||||
$t(
|
||||
"If the direction given by the development team does not suit you, you have the legal right to create your own version of the software, with your own governance choices."
|
||||
)
|
||||
}}
|
||||
</p>
|
||||
<i18n
|
||||
tag="p"
|
||||
path="Mobilizon is not developed by a secretive start-up, but by a group of friends who strive to {change_world}. So while we do work slower, we remain attentive and in touch with our users."
|
||||
>
|
||||
<a slot="change_world" href="https://framasoft.org">{{
|
||||
$t("change the world, one byte at a time")
|
||||
}}</a>
|
||||
</i18n>
|
||||
</div>
|
||||
<div class="column has-text-right-desktop has-text-centered-mobile">
|
||||
<img
|
||||
src="img/about/software-to-the-people-mobilizon.png"
|
||||
width="300"
|
||||
:alt="('Software to the people')"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<section>
|
||||
<div class="columns">
|
||||
<div class="column has-text-right-desktop">
|
||||
<h2 class="title">{{ $t("Concieved with care for humans") }}</h2>
|
||||
<i18n
|
||||
tag="p"
|
||||
path="We asked professional designers to help us develop our vision for Mobilizon. We took time to study the {digital_habits} in order to understand the features they need to gather, organize, and mobilize."
|
||||
>
|
||||
<b slot="digital_habits">{{ $t("digital habits of activists") }}</b>
|
||||
</i18n>
|
||||
<i18n
|
||||
tag="p"
|
||||
path="So that, right from its conception, Mobilizon would {fit_needs_uses_people} who are going to use it."
|
||||
>
|
||||
<b slot="fit_needs_uses_people">{{ $t("fit the needs and uses of the people") }}</b>
|
||||
</i18n>
|
||||
</div>
|
||||
<div class="column has-text-left-desktop has-text-centered-mobile">
|
||||
<img
|
||||
src="img/about/concieved-mobilizon.png"
|
||||
width="300"
|
||||
:alt="$t('Concieved with care for humans')"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<!-- We hide the "Find an instance button until https://joinmobilizon.org gets a instance picker -->
|
||||
<div class="hero register is-primary is-medium" v-if="config && config.registrationsOpen">
|
||||
<div class="hero-body">
|
||||
@@ -234,13 +123,13 @@ export default class About extends Vue {
|
||||
|
||||
.hero.is-primary {
|
||||
background: $background-color;
|
||||
.subtitle {
|
||||
padding: 1rem;
|
||||
display: block;
|
||||
|
||||
span {
|
||||
color: lighten($background-color, 10%);
|
||||
}
|
||||
.title {
|
||||
margin: 30px auto 1rem auto;
|
||||
}
|
||||
|
||||
p {
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -248,49 +137,17 @@ export default class About extends Vue {
|
||||
background: lighten($background-color, 20%);
|
||||
}
|
||||
|
||||
section {
|
||||
padding: 3rem 0;
|
||||
|
||||
&:not(:last-child) {
|
||||
border-bottom: 0.1rem dotted #777;
|
||||
}
|
||||
|
||||
p {
|
||||
margin-top: 1.5rem;
|
||||
}
|
||||
|
||||
&:nth-child(odd) .columns {
|
||||
flex-direction: row-reverse;
|
||||
}
|
||||
aside.menu {
|
||||
position: sticky;
|
||||
top: 2rem;
|
||||
margin-top: 2rem;
|
||||
}
|
||||
|
||||
.hero.quote {
|
||||
background: lighten($secondary, 20%);
|
||||
h2 {
|
||||
background: initial;
|
||||
}
|
||||
.router.column {
|
||||
background: $white;
|
||||
}
|
||||
|
||||
blockquote {
|
||||
border-left: 0.2em solid #333;
|
||||
display: block;
|
||||
padding-left: 1em;
|
||||
|
||||
&:before {
|
||||
content: "« ";
|
||||
}
|
||||
|
||||
&:after {
|
||||
content: " »";
|
||||
}
|
||||
}
|
||||
|
||||
.blockquote-footer a {
|
||||
color: #6c757d;
|
||||
background: initial;
|
||||
|
||||
&:before {
|
||||
content: "\2014\00A0";
|
||||
}
|
||||
}
|
||||
ul.menu-list > li > a {
|
||||
text-decoration: none;
|
||||
}
|
||||
</style>
|
||||
|
||||
163
js/src/views/About/AboutInstance.vue
Normal file
163
js/src/views/About/AboutInstance.vue
Normal file
@@ -0,0 +1,163 @@
|
||||
<template>
|
||||
<div v-if="config">
|
||||
<section class="hero is-primary">
|
||||
<div class="hero-body">
|
||||
<div class="container">
|
||||
<h2 class="title">{{ config.name }}</h2>
|
||||
<p>{{ config.description }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<section class="columns contact-statistics" v-if="statistics">
|
||||
<div class="column is-three-quarters-desktop statistics">
|
||||
<i18n tag="p" path="Home to {number} users">
|
||||
<strong slot="number">{{ statistics.numberOfUsers }}</strong>
|
||||
</i18n>
|
||||
<i18n tag="p" path="Who published {number} events">
|
||||
<strong slot="number">{{ statistics.numberOfEvents }}</strong>
|
||||
</i18n>
|
||||
<i18n tag="p" path="And {number} comments">
|
||||
<strong slot="number">{{ statistics.numberOfComments }}</strong>
|
||||
</i18n>
|
||||
</div>
|
||||
<div class="column contact">
|
||||
<h4>{{ $t("Contact") }}</h4>
|
||||
<p>
|
||||
<a :title="config.contact" v-if="generateConfigLink()" :href="generateConfigLink().uri">{{
|
||||
generateConfigLink().text
|
||||
}}</a>
|
||||
<span v-else-if="config.contact">{{ config.contact }}</span>
|
||||
<span v-else>{{ $t("contact uninformed") }}</span>
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
<hr />
|
||||
<section class="long-description">
|
||||
<div v-html="config.longDescription" />
|
||||
</section>
|
||||
<hr />
|
||||
<section class="config">
|
||||
<h3 class="subtitle">{{ $t("Instance configuration") }}</h3>
|
||||
<table class="table is-fullwidth">
|
||||
<tr>
|
||||
<td>{{ $t("Mobilizon version") }}</td>
|
||||
<td>{{ config.version }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{{ $t("Registrations") }}</td>
|
||||
<td v-if="config.registrationsOpen && config.registrationsWhitelist">
|
||||
{{ $t("Restricted") }}
|
||||
</td>
|
||||
<td v-if="config.registrationsOpen && !config.registrationsWhitelist">
|
||||
{{ $t("Open") }}
|
||||
</td>
|
||||
<td v-else>{{ $t("Closed") }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{{ $t("Federation") }}</td>
|
||||
<td v-if="config.federating">{{ $t("Enabled") }}</td>
|
||||
<td v-else>{{ $t("Disabled") }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{{ $t("Anonymous participations") }}</td>
|
||||
<td v-if="config.anonymous.participation.allowed">{{ $t("If allowed by organizer") }}</td>
|
||||
<td v-else>{{ $t("Disabled") }}</td>
|
||||
</tr>
|
||||
</table>
|
||||
</section>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { Component, Vue } from "vue-property-decorator";
|
||||
import { ABOUT } from "../../graphql/config";
|
||||
import { STATISTICS } from "../../graphql/statistics";
|
||||
import { IConfig } from "../../types/config.model";
|
||||
import { IStatistics } from "../../types/statistics.model";
|
||||
|
||||
@Component({
|
||||
apollo: {
|
||||
config: ABOUT,
|
||||
statistics: STATISTICS,
|
||||
},
|
||||
})
|
||||
export default class AboutInstance extends Vue {
|
||||
config!: IConfig;
|
||||
statistics!: IStatistics;
|
||||
|
||||
get isContactEmail(): boolean {
|
||||
return this.config && this.config.contact.includes("@");
|
||||
}
|
||||
|
||||
get isContactURL(): boolean {
|
||||
return this.config && this.config.contact.match(/^https?:\/\//g) !== null;
|
||||
}
|
||||
|
||||
generateConfigLink(): { uri: string; text: string } | null {
|
||||
if (!this.config.contact) return null;
|
||||
if (this.isContactEmail) {
|
||||
return { uri: `mailto:${this.config.contact}`, text: this.config.contact };
|
||||
} else if (this.isContactURL) {
|
||||
return {
|
||||
uri: this.config.contact,
|
||||
text: this.urlToHostname(this.config.contact) || (this.$t("Contact") as string),
|
||||
};
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
urlToHostname(url: string): string | null {
|
||||
try {
|
||||
return new URL(url).hostname;
|
||||
} catch (e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import "../../variables.scss";
|
||||
|
||||
section {
|
||||
&:not(:first-child) {
|
||||
margin: 2rem auto;
|
||||
}
|
||||
|
||||
&.hero {
|
||||
h2.title {
|
||||
margin: auto;
|
||||
}
|
||||
}
|
||||
|
||||
&.contact-statistics {
|
||||
margin: 2px auto;
|
||||
.statistics {
|
||||
display: flex;
|
||||
p {
|
||||
text-align: right;
|
||||
flex: 1;
|
||||
padding: 0 15px;
|
||||
|
||||
& > * {
|
||||
display: block;
|
||||
}
|
||||
|
||||
strong {
|
||||
font-weight: 500;
|
||||
font-size: 32px;
|
||||
line-height: 48px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.contact {
|
||||
p {
|
||||
width: 200px;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
236
js/src/views/About/AboutMobilizon.vue
Normal file
236
js/src/views/About/AboutMobilizon.vue
Normal file
@@ -0,0 +1,236 @@
|
||||
<template>
|
||||
<div class="container">
|
||||
<div class="container">
|
||||
<section>
|
||||
<div class="columns">
|
||||
<div class="column has-text-left-desktop">
|
||||
<h2 class="title">{{ $t("Gather ⋅ Organize ⋅ Mobilize") }}</h2>
|
||||
<p
|
||||
class="content"
|
||||
v-html="
|
||||
$t(
|
||||
'From a birthday party with friends and family to a march for climate change, right now, our gatherings are <b>trapped inside the tech giants’ platforms</b>. How can we organize, how can we click “Attend,” without <b>providing private data</b> to Facebook or <b>locking ourselves up</b> inside MeetUp?'
|
||||
)
|
||||
"
|
||||
/>
|
||||
<p
|
||||
v-html="
|
||||
$t(
|
||||
'Mobilizon is a free/libre software that will allow communities to create <b>their own spaces</b> to publish events in order to better emancipate themselves from tech giants.'
|
||||
)
|
||||
"
|
||||
/>
|
||||
</div>
|
||||
<div class="column has-text-right-desktop has-text-centered-mobile">
|
||||
<img
|
||||
src="/img/about/action-mobilizon.png"
|
||||
width="300"
|
||||
:alt="$t('Organize and take action, freely')"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<section>
|
||||
<div class="columns">
|
||||
<div class="column has-text-right-desktop">
|
||||
<h2 class="title">{{ $t("Let's create a new common") }}</h2>
|
||||
<p
|
||||
v-html="
|
||||
$t(
|
||||
'We want to develop a <b>digital common</b>, that everyone can make their own, which respects <b>privacy and activism by design</b>.'
|
||||
)
|
||||
"
|
||||
/>
|
||||
<p>
|
||||
<span
|
||||
v-html="
|
||||
$t(
|
||||
'Installing Mobilizon will allow communities to free themselves from the services of tech giants by creating <b>their own event platform</b>.'
|
||||
)
|
||||
"
|
||||
/>
|
||||
<i18n
|
||||
tag="span"
|
||||
path="This installation (called “instance“) can easily {interconnect}, thanks to {protocol}."
|
||||
>
|
||||
<b slot="interconnect">{{ $t("interconnect with others like it") }}</b>
|
||||
<a slot="protocol" href="https://en.wikipedia.org/wiki/ActivityPub">{{
|
||||
$t("a decentralised federation protocol")
|
||||
}}</a>
|
||||
</i18n>
|
||||
</p>
|
||||
</div>
|
||||
<div class="column has-text-left-desktop has-text-centered-mobile">
|
||||
<img
|
||||
src="/img/about/common-mobilizon.png"
|
||||
width="300"
|
||||
:alt="$t('Let\'s create a new common')"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
<div class="hero quote is-secondary">
|
||||
<div class="hero-body">
|
||||
<div class="container">
|
||||
<h2 class="title">{{ $t("To change the world, change the software") }}</h2>
|
||||
<blockquote>
|
||||
{{
|
||||
$t(
|
||||
"We won’t change the world from Facebook. The tool we dream of, surveillance capitalism corporations won’t develop it, as they couldn’t profit from it. This is an opportunity to build something better, by taking another approach."
|
||||
)
|
||||
}}
|
||||
</blockquote>
|
||||
<footer class="blockquote-footer">
|
||||
<a
|
||||
href="https://framablog.org/2019/05/14/mobilizon-lets-finance-a-software-to-free-our-events-from-facebook/"
|
||||
>{{ $t("Read Framasoft’s statement of intent on the Framablog") }}</a
|
||||
>
|
||||
</footer>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="container">
|
||||
<section>
|
||||
<div class="columns">
|
||||
<div class="column">
|
||||
<h2 class="title">{{ $t("Software to the people") }}</h2>
|
||||
<i18n
|
||||
tag="p"
|
||||
path="{license} guarantees {respect} of the people who will use it. Since {source}, anyone can audit it, which guarantees its transparency."
|
||||
>
|
||||
<a slot="license" href="https://choosealicense.com/licenses/agpl-3.0/">{{
|
||||
$t("Mobilizon’s licence")
|
||||
}}</a>
|
||||
<b slot="respect">{{ $t("respect of the fundamental freedoms") }}</b>
|
||||
<a slot="source" href="https://framagit.org/framasoft/mobilizon">{{
|
||||
$t("its source code is public")
|
||||
}}</a>
|
||||
</i18n>
|
||||
<p>
|
||||
{{
|
||||
$t(
|
||||
"If the direction given by the development team does not suit you, you have the legal right to create your own version of the software, with your own governance choices."
|
||||
)
|
||||
}}
|
||||
</p>
|
||||
<i18n
|
||||
tag="p"
|
||||
path="Mobilizon is not developed by a secretive start-up, but by a group of friends who strive to {change_world}. So while we do work slower, we remain attentive and in touch with our users."
|
||||
>
|
||||
<a slot="change_world" href="https://framasoft.org">{{
|
||||
$t("change the world, one byte at a time")
|
||||
}}</a>
|
||||
</i18n>
|
||||
</div>
|
||||
<div class="column has-text-right-desktop has-text-centered-mobile">
|
||||
<img
|
||||
src="/img/about/software-to-the-people-mobilizon.png"
|
||||
width="300"
|
||||
:alt="('Software to the people')"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<section>
|
||||
<div class="columns">
|
||||
<div class="column has-text-right-desktop">
|
||||
<h2 class="title">{{ $t("Concieved with care for humans") }}</h2>
|
||||
<i18n
|
||||
tag="p"
|
||||
path="We asked professional designers to help us develop our vision for Mobilizon. We took time to study the {digital_habits} in order to understand the features they need to gather, organize, and mobilize."
|
||||
>
|
||||
<b slot="digital_habits">{{ $t("digital habits of activists") }}</b>
|
||||
</i18n>
|
||||
<i18n
|
||||
tag="p"
|
||||
path="So that, right from its conception, Mobilizon would {fit_needs_uses_people} who are going to use it."
|
||||
>
|
||||
<b slot="fit_needs_uses_people">{{ $t("fit the needs and uses of the people") }}</b>
|
||||
</i18n>
|
||||
</div>
|
||||
<div class="column has-text-left-desktop has-text-centered-mobile">
|
||||
<img
|
||||
src="/img/about/concieved-mobilizon.png"
|
||||
width="300"
|
||||
:alt="$t('Concieved with care for humans')"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { Component, Vue } from "vue-property-decorator";
|
||||
|
||||
@Component
|
||||
export default class AboutMobilizon extends Vue {}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import "../../variables.scss";
|
||||
|
||||
.hero.is-primary {
|
||||
background: $background-color;
|
||||
.subtitle {
|
||||
padding: 1rem;
|
||||
display: block;
|
||||
|
||||
span {
|
||||
color: lighten($background-color, 10%);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.hero.register {
|
||||
background: lighten($background-color, 20%);
|
||||
}
|
||||
|
||||
section {
|
||||
padding: 3rem 0;
|
||||
|
||||
&:not(:last-child) {
|
||||
border-bottom: 0.1rem dotted #777;
|
||||
}
|
||||
|
||||
p {
|
||||
margin-top: 1.5rem;
|
||||
}
|
||||
|
||||
&:nth-child(odd) .columns {
|
||||
flex-direction: row-reverse;
|
||||
}
|
||||
}
|
||||
|
||||
.hero.quote {
|
||||
background: lighten($secondary, 20%);
|
||||
h2 {
|
||||
background: initial;
|
||||
}
|
||||
|
||||
blockquote {
|
||||
border-left: 0.2em solid #333;
|
||||
display: block;
|
||||
padding-left: 1em;
|
||||
|
||||
&:before {
|
||||
content: "« ";
|
||||
}
|
||||
|
||||
&:after {
|
||||
content: " »";
|
||||
}
|
||||
}
|
||||
|
||||
.blockquote-footer a {
|
||||
color: #6c757d;
|
||||
background: initial;
|
||||
|
||||
&:before {
|
||||
content: "\2014\00A0";
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
86
js/src/views/About/Glossary.vue
Normal file
86
js/src/views/About/Glossary.vue
Normal file
@@ -0,0 +1,86 @@
|
||||
<template>
|
||||
<div class="container section">
|
||||
<h2 class="title">{{ $t("Glossary") }}</h2>
|
||||
<div class="content" v-if="config">
|
||||
<p>
|
||||
{{
|
||||
$t(
|
||||
"Some terms, technical or otherwise, used in the text below may cover concepts that are difficult to grasp. We have provided a glossary here to help you understand them better:"
|
||||
)
|
||||
}}
|
||||
</p>
|
||||
<dl>
|
||||
<dt>{{ $t("Instance") }}</dt>
|
||||
<i18n
|
||||
tag="dd"
|
||||
path="An instance is an installed version of the Mobilizon software running on a server. An instance can be run by anyone using the {mobilizon_software} or other federated apps, aka the “fediverse”. This instance's name is {instance_name}. Mobilizon is a federated network of multiple instances (just like email servers), users registered on different instances may communicate even though they didn't register on the same instance."
|
||||
>
|
||||
<a slot="mobilizon_software" href="https://joinmobilizon.org">{{
|
||||
$t("Mobilizon software")
|
||||
}}</a>
|
||||
<b slot="instance_name">{{ config.name }}</b>
|
||||
</i18n>
|
||||
<dt>{{ $t("Instance administrator") }}</dt>
|
||||
<dd>
|
||||
{{
|
||||
$t(
|
||||
"The instance administrator is the person or entity that runs this Mobilizon instance."
|
||||
)
|
||||
}}
|
||||
</dd>
|
||||
<dt>{{ $t("Application") }}</dt>
|
||||
<dd>
|
||||
{{
|
||||
$t(
|
||||
"In the following context, an application is a software, either provided by the Mobilizon team or by a 3rd-party, used to interact with your instance."
|
||||
)
|
||||
}}
|
||||
</dd>
|
||||
<dt>{{ $t("API") }}</dt>
|
||||
<dd>
|
||||
{{
|
||||
$t(
|
||||
"An “application programming interface” or “API” is a communication protocol that allows software components to communicate with each other. The Mobilizon API, for example, can allow third-party software tools to communicate with Mobilizon instances to carry out certain actions, such as posting events on your behalf, automatically and remotely."
|
||||
)
|
||||
}}
|
||||
</dd>
|
||||
<dt>{{ $t("SSL/TLS") }}</dt>
|
||||
<i18n
|
||||
tag="dd"
|
||||
path="SSL and it's successor TLS are encryption technologies to secure data communications when using the service. You can recognize an encrypted connection in your browser's address line when the URL begins with {https} and the lock icon is displayed in your browser's address bar."
|
||||
>
|
||||
<code slot="https">https://</code>
|
||||
</i18n>
|
||||
<dt>{{ $t("Cookies and Local storage") }}</dt>
|
||||
<dd>
|
||||
{{
|
||||
$t(
|
||||
"A cookie is a small file containing informations that is sent to your computer when you visit a website. When you visit the site again, the cookie allows that site to recognize your browser. Cookies may store user preferences and other information. You can configure your browser to refuse all cookies. However, this may result in some website features or services partially working. Local storage works the same way but allows to store more data."
|
||||
)
|
||||
}}
|
||||
</dd>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { Component, Vue } from "vue-property-decorator";
|
||||
import { ABOUT } from "../../graphql/config";
|
||||
import { IConfig } from "../../types/config.model";
|
||||
|
||||
@Component({
|
||||
apollo: {
|
||||
config: ABOUT,
|
||||
},
|
||||
})
|
||||
export default class Glossary extends Vue {
|
||||
config!: IConfig;
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
/deep/ dt {
|
||||
font-weight: bold;
|
||||
}
|
||||
</style>
|
||||
66
js/src/views/About/Privacy.vue
Normal file
66
js/src/views/About/Privacy.vue
Normal file
@@ -0,0 +1,66 @@
|
||||
<template>
|
||||
<div class="container section">
|
||||
<h2 class="title">{{ $t("Privacy Policy") }}</h2>
|
||||
<div class="content" v-html="config.privacy.bodyHtml" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { Component, Vue, Watch } from "vue-property-decorator";
|
||||
import { PRIVACY } from "@/graphql/config";
|
||||
import { IConfig } from "@/types/config.model";
|
||||
import { InstancePrivacyType } from "@/types/admin.model";
|
||||
|
||||
@Component({
|
||||
apollo: {
|
||||
config: {
|
||||
query: PRIVACY,
|
||||
variables() {
|
||||
return {
|
||||
locale: this.locale,
|
||||
};
|
||||
},
|
||||
skip() {
|
||||
return !this.locale;
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
export default class Privacy extends Vue {
|
||||
config!: IConfig;
|
||||
|
||||
locale: string | null = null;
|
||||
|
||||
created() {
|
||||
this.locale = this.$i18n.locale;
|
||||
}
|
||||
|
||||
@Watch("config", { deep: true })
|
||||
watchConfig(config: IConfig) {
|
||||
if (config.privacy.type) {
|
||||
console.log(this.config.privacy);
|
||||
this.redirectToUrl();
|
||||
}
|
||||
}
|
||||
|
||||
redirectToUrl() {
|
||||
if (this.config.privacy.type === InstancePrivacyType.URL) {
|
||||
window.location.replace(this.config.privacy.url);
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
@import "@/variables.scss";
|
||||
|
||||
main > .container {
|
||||
background: $white;
|
||||
|
||||
/deep/ dt {
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
.content /deep/ li {
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
</style>
|
||||
@@ -11,7 +11,7 @@ import { Component, Vue, Watch } from "vue-property-decorator";
|
||||
import { RULES } from "@/graphql/config";
|
||||
import { IConfig } from "@/types/config.model";
|
||||
import { InstanceTermsType } from "@/types/admin.model";
|
||||
import RouteName from "../router/name";
|
||||
import RouteName from "../../router/name";
|
||||
|
||||
@Component({
|
||||
apollo: {
|
||||
@@ -32,4 +32,7 @@ export default class Rules extends Vue {
|
||||
main > .container {
|
||||
background: $white;
|
||||
}
|
||||
.content /deep/ li {
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
</style>
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div class="container section">
|
||||
<h2 class="title">{{ $t("Privacy Policy") }}</h2>
|
||||
<h2 class="title">{{ $t("Terms") }}</h2>
|
||||
<div class="content" v-html="config.terms.bodyHtml" />
|
||||
</div>
|
||||
</template>
|
||||
@@ -10,7 +10,6 @@ import { Component, Vue, Watch } from "vue-property-decorator";
|
||||
import { TERMS } from "@/graphql/config";
|
||||
import { IConfig } from "@/types/config.model";
|
||||
import { InstanceTermsType } from "@/types/admin.model";
|
||||
import RouteName from "../router/name";
|
||||
|
||||
@Component({
|
||||
apollo: {
|
||||
@@ -49,14 +48,10 @@ export default class Terms extends Vue {
|
||||
window.location.replace(this.config.terms.url);
|
||||
}
|
||||
}
|
||||
|
||||
RouteName = RouteName;
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
@import "@/variables.scss";
|
||||
|
||||
main > .container {
|
||||
background: $white;
|
||||
.content /deep/ li {
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
</style>
|
||||
@@ -23,7 +23,10 @@
|
||||
size="is-small"
|
||||
/>
|
||||
</template>
|
||||
<router-link :to="{ name: RouteName.ADMIN_PROFILE, params: { id: props.row.id } }">
|
||||
<router-link
|
||||
class="profile"
|
||||
:to="{ name: RouteName.ADMIN_PROFILE, params: { id: props.row.id } }"
|
||||
>
|
||||
<article class="media">
|
||||
<figure class="media-left" v-if="props.row.avatar">
|
||||
<p class="image is-48x48">
|
||||
@@ -136,3 +139,8 @@ export default class Profiles extends Vue {
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
a.profile {
|
||||
text-decoration: none;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -4,9 +4,24 @@
|
||||
<b-field :label="$t('Instance Name')">
|
||||
<b-input v-model="adminSettings.instanceName" />
|
||||
</b-field>
|
||||
<b-field :label="$t('Instance Description')">
|
||||
<b-input type="textarea" v-model="adminSettings.instanceDescription" />
|
||||
</b-field>
|
||||
<div class="field">
|
||||
<label class="label has-help">{{ $t("Instance Short Description") }}</label>
|
||||
<small>
|
||||
{{
|
||||
$t(
|
||||
"Displayed on homepage and meta tags. Describe what Mobilizon is and what makes this instance special in a single paragraph."
|
||||
)
|
||||
}}
|
||||
</small>
|
||||
<b-input type="textarea" v-model="adminSettings.instanceDescription" rows="2" />
|
||||
</div>
|
||||
<div class="field">
|
||||
<label class="label has-help">{{ $t("Contact") }}</label>
|
||||
<small>
|
||||
{{ $t("Can be an email or a link, or just plain text.") }}
|
||||
</small>
|
||||
<b-input v-model="adminSettings.contact" />
|
||||
</div>
|
||||
<b-field :label="$t('Allow registrations')">
|
||||
<b-switch v-model="adminSettings.registrationsOpen">
|
||||
<p class="content" v-if="adminSettings.registrationsOpen">
|
||||
@@ -15,9 +30,24 @@
|
||||
<p class="content" v-else>{{ $t("Registration is closed.") }}</p>
|
||||
</b-switch>
|
||||
</b-field>
|
||||
<b-field :label="$t('Instance Rules')">
|
||||
<div class="field">
|
||||
<label class="label has-help">{{ $t("Instance Long Description") }}</label>
|
||||
<small>
|
||||
{{
|
||||
$t(
|
||||
"A place to explain who you are and the things that set your instance apart. You can use HTML tags."
|
||||
)
|
||||
}}
|
||||
</small>
|
||||
<b-input type="textarea" v-model="adminSettings.instanceLongDescription" rows="4" />
|
||||
</div>
|
||||
<div class="field">
|
||||
<label class="label has-help">{{ $t("Instance Rules") }}</label>
|
||||
<small>
|
||||
{{ $t("A place for your code of conduct, rules or guidelines. You can use HTML tags.") }}
|
||||
</small>
|
||||
<b-input type="textarea" v-model="adminSettings.instanceRules" />
|
||||
</b-field>
|
||||
</div>
|
||||
<b-field :label="$t('Instance Terms Source')">
|
||||
<div class="columns">
|
||||
<div class="column is-one-third-desktop">
|
||||
@@ -26,7 +56,7 @@
|
||||
v-model="adminSettings.instanceTermsType"
|
||||
name="instanceTermsType"
|
||||
:native-value="InstanceTermsType.DEFAULT"
|
||||
>{{ $t("Default Mobilizon.org terms") }}</b-radio
|
||||
>{{ $t("Default Mobilizon terms") }}</b-radio
|
||||
>
|
||||
</b-field>
|
||||
<b-field>
|
||||
@@ -65,6 +95,11 @@
|
||||
>{{ $t("default Mobilizon terms") }}</a
|
||||
>
|
||||
</i18n>
|
||||
<b>{{
|
||||
$t(
|
||||
"NOTE! The default terms have not been checked over by a lawyer and thus are unlikely to provide full legal protection for all situations for an instance admin using them. They are also not specific to all countries and jurisdictions. If you are unsure, please check with a lawyer."
|
||||
)
|
||||
}}</b>
|
||||
</div>
|
||||
<div
|
||||
class="notification"
|
||||
@@ -78,13 +113,20 @@
|
||||
v-if="adminSettings.instanceTermsType === InstanceTermsType.CUSTOM"
|
||||
>
|
||||
<b>{{ $t("Custom") }}</b>
|
||||
<p class="content">
|
||||
{{
|
||||
$t(
|
||||
"Enter your own terms. HTML tags allowed. Mobilizon.org's terms are provided as template."
|
||||
)
|
||||
}}
|
||||
</p>
|
||||
<i18n
|
||||
tag="p"
|
||||
class="content"
|
||||
path="Enter your own terms. HTML tags allowed. The {mobilizon_terms} are provided as template."
|
||||
>
|
||||
<a
|
||||
slot="mobilizon_terms"
|
||||
href="https://mobilizon.org/terms"
|
||||
target="_blank"
|
||||
rel="noopener"
|
||||
>
|
||||
{{ $t("default Mobilizon terms") }}</a
|
||||
>
|
||||
</i18n>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -99,7 +141,97 @@
|
||||
:label="$t('Instance Terms')"
|
||||
v-if="adminSettings.instanceTermsType === InstanceTermsType.CUSTOM"
|
||||
>
|
||||
<b-input type="textarea" v-model="adminSettings.instanceTerms" />
|
||||
<b-input type="textarea" v-model="adminSettings.instancePrivacyPolicy" />
|
||||
</b-field>
|
||||
<b-field :label="$t('Instance Privacy Policy Source')">
|
||||
<div class="columns">
|
||||
<div class="column is-one-third-desktop">
|
||||
<b-field>
|
||||
<b-radio
|
||||
v-model="adminSettings.instancePrivacyPolicyType"
|
||||
name="instancePrivacyType"
|
||||
:native-value="InstancePrivacyType.DEFAULT"
|
||||
>{{ $t("Default Mobilizon privacy policy") }}</b-radio
|
||||
>
|
||||
</b-field>
|
||||
<b-field>
|
||||
<b-radio
|
||||
v-model="adminSettings.instancePrivacyPolicyType"
|
||||
name="instancePrivacyType"
|
||||
:native-value="InstancePrivacyType.URL"
|
||||
>{{ $t("Custom URL") }}</b-radio
|
||||
>
|
||||
</b-field>
|
||||
<b-field>
|
||||
<b-radio
|
||||
v-model="adminSettings.instancePrivacyPolicyType"
|
||||
name="instancePrivacyType"
|
||||
:native-value="InstancePrivacyType.CUSTOM"
|
||||
>{{ $t("Custom text") }}</b-radio
|
||||
>
|
||||
</b-field>
|
||||
</div>
|
||||
<div class="column">
|
||||
<div
|
||||
class="notification"
|
||||
v-if="adminSettings.instancePrivacyPolicyType === InstancePrivacyType.DEFAULT"
|
||||
>
|
||||
<b>{{ $t("Default") }}</b>
|
||||
<i18n
|
||||
tag="p"
|
||||
class="content"
|
||||
path="The {default_privacy_policy} will be used. They will be translated in the user's language."
|
||||
>
|
||||
<a
|
||||
slot="default_privacy_policy"
|
||||
href="https://mobilizon.org/terms"
|
||||
target="_blank"
|
||||
rel="noopener"
|
||||
>{{ $t("default Mobilizon privacy policy") }}</a
|
||||
>
|
||||
</i18n>
|
||||
</div>
|
||||
<div
|
||||
class="notification"
|
||||
v-if="adminSettings.instancePrivacyPolicyType === InstancePrivacyType.URL"
|
||||
>
|
||||
<b>{{ $t("URL") }}</b>
|
||||
<p class="content">{{ $t("Set an URL to a page with your own privacy policy.") }}</p>
|
||||
</div>
|
||||
<div
|
||||
class="notification"
|
||||
v-if="adminSettings.instancePrivacyPolicyType === InstancePrivacyType.CUSTOM"
|
||||
>
|
||||
<b>{{ $t("Custom") }}</b>
|
||||
<i18n
|
||||
tag="p"
|
||||
class="content"
|
||||
path="Enter your own privacy policy. HTML tags allowed. The {mobilizon_privacy_policy} is provided as template."
|
||||
>
|
||||
<a
|
||||
slot="mobilizon_privacy_policy"
|
||||
href="https://mobilizon.org/privacy"
|
||||
target="_blank"
|
||||
rel="noopener"
|
||||
>
|
||||
{{ $t("default Mobilizon privacy policy") }}</a
|
||||
>
|
||||
</i18n>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</b-field>
|
||||
<b-field
|
||||
:label="$t('Instance Privacy Policy URL')"
|
||||
v-if="adminSettings.instancePrivacyPolicyType === InstancePrivacyType.URL"
|
||||
>
|
||||
<b-input type="URL" v-model="adminSettings.instancePrivacyPolicyUrl" />
|
||||
</b-field>
|
||||
<b-field
|
||||
:label="$t('Instance Privacy Policy')"
|
||||
v-if="adminSettings.instancePrivacyPolicyType === InstancePrivacyType.CUSTOM"
|
||||
>
|
||||
<b-input type="textarea" v-model="adminSettings.instancePrivacyPolicy" />
|
||||
</b-field>
|
||||
<b-button native-type="submit" type="is-primary">{{ $t("Save") }}</b-button>
|
||||
</form>
|
||||
@@ -108,7 +240,7 @@
|
||||
<script lang="ts">
|
||||
import { Component, Vue } from "vue-property-decorator";
|
||||
import { ADMIN_SETTINGS, SAVE_ADMIN_SETTINGS } from "@/graphql/admin";
|
||||
import { IAdminSettings, InstanceTermsType } from "../../types/admin.model";
|
||||
import { IAdminSettings, InstanceTermsType, InstancePrivacyType } from "../../types/admin.model";
|
||||
import RouteName from "../../router/name";
|
||||
|
||||
@Component({
|
||||
@@ -120,6 +252,7 @@ export default class Settings extends Vue {
|
||||
adminSettings!: IAdminSettings;
|
||||
|
||||
InstanceTermsType = InstanceTermsType;
|
||||
InstancePrivacyType = InstancePrivacyType;
|
||||
|
||||
RouteName = RouteName;
|
||||
|
||||
@@ -148,4 +281,8 @@ export default class Settings extends Vue {
|
||||
text-decoration-color: #fea72b !important;
|
||||
text-decoration-thickness: 2px !important;
|
||||
}
|
||||
|
||||
label.label.has-help {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
/>
|
||||
</template>
|
||||
<router-link
|
||||
class="user-profile"
|
||||
:to="{ name: RouteName.ADMIN_USER_PROFILE, params: { id: props.row.id } }"
|
||||
:class="{ disabled: props.row.disabled }"
|
||||
>
|
||||
@@ -49,6 +50,7 @@
|
||||
|
||||
<template slot="detail" slot-scope="props">
|
||||
<router-link
|
||||
class="profile"
|
||||
v-for="actor in props.row.actors"
|
||||
:key="actor.id"
|
||||
:to="{ name: RouteName.ADMIN_PROFILE, params: { id: actor.id } }"
|
||||
@@ -130,6 +132,10 @@ export default class Users extends Vue {
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import "../../variables.scss";
|
||||
a.profile,
|
||||
a.user-profile {
|
||||
text-decoration: none;
|
||||
}
|
||||
a.disabled {
|
||||
color: $danger;
|
||||
text-decoration: line-through;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<aside class="section container">
|
||||
<div class="section container">
|
||||
<h1 class="title">{{ $t("Settings") }}</h1>
|
||||
<div class="columns">
|
||||
<SettingsMenu class="column is-one-quarter-desktop" :menu="menu" />
|
||||
@@ -18,7 +18,7 @@
|
||||
<router-view />
|
||||
</div>
|
||||
</div>
|
||||
</aside>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { Component, Vue, Watch } from "vue-property-decorator";
|
||||
|
||||
Reference in New Issue
Block a user