mirror of
https://github.com/IT4Change/Ocelot-Social.git
synced 2025-12-13 07:45:56 +00:00
Merge pull request #4468 from Ocelot-Social-Community/4464-flexible-footer-links
feat: 🍰 Flexible Footer Links
This commit is contained in:
commit
a99b9ed052
@ -1,7 +1,13 @@
|
||||
// this file is duplicated in `backend/src/config/links.js` and `webapp/constants/links.js` and replaced on rebranding
|
||||
export default {
|
||||
ORGANIZATION: 'https://ocelot.social',
|
||||
DONATE: 'https://ocelot-social.herokuapp.com/donations',
|
||||
FAQ: 'https://ocelot.social',
|
||||
SUPPORT: 'https://ocelot.social',
|
||||
|
||||
// on null or empty strings internal imprint is used, see 'webapp/locales/html/'
|
||||
DONATE: 'https://ocelot-social.herokuapp.com/donations', // we use 'ocelot-social.herokuapp.com' at the moment, because redirections of 'ocelot.social' subpages are not working correctly
|
||||
IMPRINT: 'https://ocelot-social.herokuapp.com/imprint', // we use 'ocelot-social.herokuapp.com' at the moment, because redirections of 'ocelot.social' subpages are not working correctly
|
||||
TERMS_AND_CONDITIONS: null,
|
||||
CODE_OF_CONDUCT: null,
|
||||
DATA_PRIVACY: null,
|
||||
FAQ: 'https://ocelot.social',
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { config, mount } from '@vue/test-utils'
|
||||
import PageFooter from './PageFooter.vue'
|
||||
import links from '~/constants/links.js'
|
||||
import linksDefault from '~/constants/links.js'
|
||||
|
||||
const localVue = global.localVue
|
||||
|
||||
@ -8,6 +8,7 @@ config.stubs['nuxt-link'] = '<span class="nuxt-link"><slot /></span>'
|
||||
|
||||
describe('PageFooter.vue', () => {
|
||||
let mocks
|
||||
let wrapper
|
||||
|
||||
beforeEach(() => {
|
||||
mocks = {
|
||||
@ -15,30 +16,118 @@ describe('PageFooter.vue', () => {
|
||||
$env: {
|
||||
VERSION: 'v1.0.0',
|
||||
},
|
||||
links,
|
||||
}
|
||||
})
|
||||
|
||||
describe('mount', () => {
|
||||
let wrapper
|
||||
const Wrapper = () => {
|
||||
return mount(PageFooter, { mocks, localVue })
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
wrapper = Wrapper()
|
||||
describe('links.js', () => {
|
||||
beforeEach(() => {
|
||||
wrapper = Wrapper()
|
||||
})
|
||||
|
||||
it('renders four links', () => {
|
||||
expect(wrapper.findAll('a')).toHaveLength(4)
|
||||
})
|
||||
|
||||
it('renders three nuxt-links', () => {
|
||||
expect(wrapper.findAll('.nuxt-link')).toHaveLength(3)
|
||||
})
|
||||
|
||||
it('renders version', () => {
|
||||
expect(wrapper.find('.ds-footer').text()).toContain('v1.0.0')
|
||||
})
|
||||
})
|
||||
|
||||
it('renders three links', () => {
|
||||
expect(wrapper.findAll('a')).toHaveLength(3)
|
||||
describe('inflexible links', () => {
|
||||
beforeEach(() => {
|
||||
wrapper = Wrapper()
|
||||
})
|
||||
|
||||
it('renders ORGANIZATION', () => {
|
||||
expect(wrapper.find('a[data-test="organization-link"]').exists()).toBe(true)
|
||||
})
|
||||
|
||||
it('renders version', () => {
|
||||
expect(wrapper.find('a[data-test="version-link"]').exists()).toBe(true)
|
||||
})
|
||||
})
|
||||
|
||||
it('renders four nuxt-links', () => {
|
||||
expect(wrapper.findAll('.nuxt-link')).toHaveLength(4)
|
||||
describe('flexible links not set', () => {
|
||||
beforeEach(async () => {
|
||||
const links = {
|
||||
...linksDefault,
|
||||
IMPRINT: null,
|
||||
TERMS_AND_CONDITIONS: null,
|
||||
CODE_OF_CONDUCT: null,
|
||||
DATA_PRIVACY: null,
|
||||
FAQ: null,
|
||||
}
|
||||
wrapper = Wrapper()
|
||||
wrapper.setData({ links })
|
||||
await wrapper.vm.$nextTick()
|
||||
})
|
||||
|
||||
it('renders IMPRINT as nuxt-link', () => {
|
||||
expect(wrapper.find('span[data-test="imprint-nuxt-link"]').exists()).toBe(true)
|
||||
})
|
||||
|
||||
it('renders TERMS_AND_CONDITIONS as nuxt-link', () => {
|
||||
expect(wrapper.find('span[data-test="terms-nuxt-link"]').exists()).toBe(true)
|
||||
})
|
||||
|
||||
it('renders CODE_OF_CONDUCT as nuxt-link', () => {
|
||||
expect(wrapper.find('span[data-test="code-nuxt-link"]').exists()).toBe(true)
|
||||
})
|
||||
|
||||
it('renders DATA_PRIVACY as nuxt-link', () => {
|
||||
expect(wrapper.find('span[data-test="data-nuxt-link"]').exists()).toBe(true)
|
||||
})
|
||||
|
||||
it('renders FAQ as nuxt-link', () => {
|
||||
expect(wrapper.find('span[data-test="faq-nuxt-link"]').exists()).toBe(true)
|
||||
})
|
||||
})
|
||||
|
||||
it('renders version', () => {
|
||||
expect(wrapper.find('.ds-footer').text()).toContain('v1.0.0')
|
||||
describe('flexible links set', () => {
|
||||
beforeEach(async () => {
|
||||
const links = {
|
||||
...linksDefault,
|
||||
IMPRINT: 'https://ocelot.social/IMPRINT',
|
||||
TERMS_AND_CONDITIONS: 'https://ocelot.social/TERMS_AND_CONDITIONS',
|
||||
CODE_OF_CONDUCT: 'https://ocelot.social/CODE_OF_CONDUCT',
|
||||
DATA_PRIVACY: 'https://ocelot.social/DATA_PRIVACY',
|
||||
FAQ: 'https://ocelot.social/FAQ',
|
||||
}
|
||||
wrapper = Wrapper()
|
||||
wrapper.setData({ links })
|
||||
await wrapper.vm.$nextTick()
|
||||
})
|
||||
|
||||
it('renders IMPRINT as "a" tag link', () => {
|
||||
expect(wrapper.find(`a[href="https://ocelot.social/IMPRINT"]`).exists()).toBe(true)
|
||||
})
|
||||
|
||||
it('renders TERMS_AND_CONDITIONS as "a" tag link', () => {
|
||||
expect(wrapper.find(`a[href="https://ocelot.social/TERMS_AND_CONDITIONS"]`).exists()).toBe(
|
||||
true,
|
||||
)
|
||||
})
|
||||
|
||||
it('renders CODE_OF_CONDUCT as "a" tag link', () => {
|
||||
expect(wrapper.find(`a[href="https://ocelot.social/CODE_OF_CONDUCT"]`).exists()).toBe(true)
|
||||
})
|
||||
|
||||
it('renders DATA_PRIVACY as "a" tag link', () => {
|
||||
expect(wrapper.find(`a[href="https://ocelot.social/DATA_PRIVACY"]`).exists()).toBe(true)
|
||||
})
|
||||
|
||||
it('renders FAQ as "a" tag link', () => {
|
||||
expect(wrapper.find(`a[href="https://ocelot.social/FAQ"]`).exists()).toBe(true)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@ -1,26 +1,67 @@
|
||||
<template>
|
||||
<div id="footer" class="ds-footer">
|
||||
<a :href="links.ORGANIZATION" target="_blank" v-html="$t('site.made')"></a>
|
||||
<!-- made with ❤️ -->
|
||||
<a :href="links.ORGANIZATION" target="_blank" data-test="organization-link">
|
||||
{{ $t('site.made') }}
|
||||
</a>
|
||||
<span>-</span>
|
||||
<nuxt-link to="/imprint">
|
||||
<!-- imprint -->
|
||||
<nuxt-link v-if="noLinkDefined(links.IMPRINT)" to="/imprint" data-test="imprint-nuxt-link">
|
||||
{{ $t('site.imprint') }}
|
||||
</nuxt-link>
|
||||
<a v-else :href="links.IMPRINT" target="_blank">
|
||||
{{ $t('site.imprint') }}
|
||||
</a>
|
||||
<span>-</span>
|
||||
<nuxt-link to="/terms-and-conditions">{{ $t('site.termsAndConditions') }}</nuxt-link>
|
||||
<!-- terms and conditions -->
|
||||
<nuxt-link
|
||||
v-if="noLinkDefined(links.TERMS_AND_CONDITIONS)"
|
||||
to="/terms-and-conditions"
|
||||
data-test="terms-nuxt-link"
|
||||
>
|
||||
{{ $t('site.termsAndConditions') }}
|
||||
</nuxt-link>
|
||||
<a v-else :href="links.TERMS_AND_CONDITIONS" target="_blank">
|
||||
{{ $t('site.termsAndConditions') }}
|
||||
</a>
|
||||
<span>-</span>
|
||||
<nuxt-link to="/code-of-conduct">{{ $t('site.code-of-conduct') }}</nuxt-link>
|
||||
<!-- code of conduct -->
|
||||
<nuxt-link
|
||||
v-if="noLinkDefined(links.CODE_OF_CONDUCT)"
|
||||
to="/code-of-conduct"
|
||||
data-test="code-nuxt-link"
|
||||
>
|
||||
{{ $t('site.code-of-conduct') }}
|
||||
</nuxt-link>
|
||||
<a v-else :href="links.CODE_OF_CONDUCT" target="_blank">
|
||||
{{ $t('site.code-of-conduct') }}
|
||||
</a>
|
||||
<span>-</span>
|
||||
<nuxt-link to="/data-privacy">
|
||||
<!-- data privacy -->
|
||||
<nuxt-link
|
||||
v-if="noLinkDefined(links.DATA_PRIVACY)"
|
||||
to="/data-privacy"
|
||||
data-test="data-nuxt-link"
|
||||
>
|
||||
{{ $t('site.data-privacy') }}
|
||||
</nuxt-link>
|
||||
<a v-else :href="links.DATA_PRIVACY" target="_blank">
|
||||
{{ $t('site.data-privacy') }}
|
||||
</a>
|
||||
<span>-</span>
|
||||
<a :href="links.FAQ" target="_blank">
|
||||
<!-- faq -->
|
||||
<nuxt-link v-if="noLinkDefined(links.FAQ)" to="/faq" data-test="faq-nuxt-link">
|
||||
{{ $t('site.faq') }}
|
||||
</nuxt-link>
|
||||
<a v-else :href="links.FAQ" target="_blank">
|
||||
{{ $t('site.faq') }}
|
||||
</a>
|
||||
<span>-</span>
|
||||
<!-- version -->
|
||||
<a
|
||||
href="https://github.com/Ocelot-Social-Community/Ocelot-Social/blob/master/CHANGELOG.md"
|
||||
target="_blank"
|
||||
data-test="version-link"
|
||||
>
|
||||
{{ version }}
|
||||
</a>
|
||||
@ -29,10 +70,16 @@
|
||||
|
||||
<script>
|
||||
import links from '~/constants/links.js'
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return { links, version: `v${this.$env.VERSION}` }
|
||||
},
|
||||
methods: {
|
||||
noLinkDefined(link) {
|
||||
return !link || link.length === 0
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
@ -1,7 +1,13 @@
|
||||
// this file is duplicated in `backend/src/config/links.js` and `webapp/constants/links.js` and replaced on rebranding
|
||||
export default {
|
||||
ORGANIZATION: 'https://ocelot.social',
|
||||
DONATE: 'https://ocelot-social.herokuapp.com/donations',
|
||||
FAQ: 'https://ocelot.social',
|
||||
SUPPORT: 'https://ocelot.social',
|
||||
|
||||
// on null or empty strings internal imprint is used, see 'webapp/locales/html/'
|
||||
DONATE: 'https://ocelot-social.herokuapp.com/donations', // we use 'ocelot-social.herokuapp.com' at the moment, because redirections of 'ocelot.social' subpages are not working correctly
|
||||
IMPRINT: 'https://ocelot-social.herokuapp.com/imprint', // we use 'ocelot-social.herokuapp.com' at the moment, because redirections of 'ocelot.social' subpages are not working correctly
|
||||
TERMS_AND_CONDITIONS: null,
|
||||
CODE_OF_CONDUCT: null,
|
||||
DATA_PRIVACY: null,
|
||||
FAQ: 'https://ocelot.social',
|
||||
}
|
||||
|
||||
@ -771,7 +771,7 @@
|
||||
"faq": "FAQ",
|
||||
"germany": "Deutschland",
|
||||
"imprint": "Impressum",
|
||||
"made": "Mit ❤ gemacht",
|
||||
"made": "Mit ❤️ gemacht",
|
||||
"register": "Registernummer",
|
||||
"responsible": "Verantwortlich für Inhalte dieser Seite (§ 55 Abs. 2 RStV)",
|
||||
"taxident": "Umsatzsteuer-Identifikationsnummer gemäß § 27 a Umsatzsteuergesetz (Deutschland)",
|
||||
|
||||
@ -771,7 +771,7 @@
|
||||
"faq": "FAQ",
|
||||
"germany": "Germany",
|
||||
"imprint": "Imprint",
|
||||
"made": "Made with ❤",
|
||||
"made": "Made with ❤️",
|
||||
"register": "Registry number",
|
||||
"responsible": "responsible for contents of this page (§ 55 Abs. 2 RStV)",
|
||||
"taxident": "USt-ID. according to §27a of the German Sales Tax Law:",
|
||||
|
||||
@ -694,7 +694,7 @@
|
||||
"faq": "Preguntas más frecuentes",
|
||||
"germany": "Alemania",
|
||||
"imprint": "Pie de imprenta",
|
||||
"made": "Hecho con ❤",
|
||||
"made": "Hecho con ❤️",
|
||||
"register": "Número de registro",
|
||||
"responsible": "Responsable según § 55 Abs. 2 RStV (Alemania)",
|
||||
"taxident": "Número de identificación del impuesto sobre el valor añadido según el § 27 a de la Ley del Impuesto sobre el Valor Añadido (Alemania)",
|
||||
|
||||
@ -662,7 +662,7 @@
|
||||
"faq": "FAQ",
|
||||
"germany": "Allemagne",
|
||||
"imprint": "Mentions légales",
|
||||
"made": "Fabriqué avec ❤",
|
||||
"made": "Fabriqué avec ❤️",
|
||||
"register": "Numéro de registre",
|
||||
"responsible": "Responsable selon § 55 Abs. 2 RStV (Allemagne)",
|
||||
"taxident": "Numéro d'identification à la taxe sur la valeur ajoutée selon § 27 a de la loi sur la taxe sur la valeur ajoutée (Allemagne)",
|
||||
|
||||
@ -1 +1,3 @@
|
||||
<!-- this file is replaced on rebranding -->
|
||||
|
||||
<p>Ich bin der Inhalt vom Verhaltenskodex</p>
|
||||
|
||||
@ -1 +1,3 @@
|
||||
<!-- this file is replaced on rebranding -->
|
||||
|
||||
<p>Das hier wäre der Inhalt der Datenschutzbestimmungen</p>
|
||||
|
||||
3
webapp/locales/html/de/faq.html
Normal file
3
webapp/locales/html/de/faq.html
Normal file
@ -0,0 +1,3 @@
|
||||
<!-- this file is replaced on rebranding -->
|
||||
|
||||
<p>Hier stehen die FAQs</p>
|
||||
@ -1 +1,3 @@
|
||||
<!-- this file is replaced on rebranding -->
|
||||
|
||||
<p>Ich bin das Impressum</p>
|
||||
|
||||
@ -1,11 +1,13 @@
|
||||
import termsAndConditions from './terms-and-conditions.html'
|
||||
import codeOfConduct from './code-of-conduct.html'
|
||||
import dataPrivacy from './data-privacy.html'
|
||||
import faq from './faq.html'
|
||||
import imprint from './imprint.html'
|
||||
|
||||
export default {
|
||||
termsAndConditions,
|
||||
codeOfConduct,
|
||||
dataPrivacy,
|
||||
faq,
|
||||
imprint,
|
||||
}
|
||||
|
||||
@ -1 +1,3 @@
|
||||
<!-- this file is replaced on rebranding -->
|
||||
|
||||
<p>Ich bin der Inhalt der Seite "Nutzungsbedingungen"</p>
|
||||
|
||||
@ -1 +1,3 @@
|
||||
<!-- this file is replaced on rebranding -->
|
||||
|
||||
<p>I am the content of the code of conduct</p>
|
||||
|
||||
@ -1 +1,3 @@
|
||||
<!-- this file is replaced on rebranding -->
|
||||
|
||||
<p>This would be our data privacy section</p>
|
||||
|
||||
3
webapp/locales/html/en/faq.html
Normal file
3
webapp/locales/html/en/faq.html
Normal file
@ -0,0 +1,3 @@
|
||||
<!-- this file is replaced on rebranding -->
|
||||
|
||||
<p>Here are the FAQs</p>
|
||||
@ -1 +1,3 @@
|
||||
<!-- this file is replaced on rebranding -->
|
||||
|
||||
<p>I am the imprint</p>
|
||||
|
||||
@ -1,11 +1,13 @@
|
||||
import termsAndConditions from './terms-and-conditions.html'
|
||||
import codeOfConduct from './code-of-conduct.html'
|
||||
import dataPrivacy from './data-privacy.html'
|
||||
import faq from './faq.html'
|
||||
import imprint from './imprint.html'
|
||||
|
||||
export default {
|
||||
termsAndConditions,
|
||||
codeOfConduct,
|
||||
dataPrivacy,
|
||||
faq,
|
||||
imprint,
|
||||
}
|
||||
|
||||
@ -1 +1,3 @@
|
||||
<!-- this file is replaced on rebranding -->
|
||||
|
||||
<p>I am the content of the page "terms and conditions"<p>
|
||||
|
||||
@ -612,7 +612,7 @@
|
||||
"faq": null,
|
||||
"germany": "Germania",
|
||||
"imprint": "Impressum",
|
||||
"made": "Con ❤ fatto",
|
||||
"made": "Con ❤️ fatto",
|
||||
"register": "numero di registro",
|
||||
"responsible": "Responsabile ai sensi del § 55 Abs. 2 RStV (Germania)",
|
||||
"taxident": "Numero di identificazione dell'imposta sul valore aggiunto ai sensi del § 27 a Legge sull'imposta sul valore aggiunto (Germania)",
|
||||
|
||||
@ -165,7 +165,7 @@
|
||||
"director": "Directeur",
|
||||
"germany": "Duitsland",
|
||||
"imprint": "Afdruk",
|
||||
"made": "Met ❤ gemaakt",
|
||||
"made": "Met ❤️ gemaakt",
|
||||
"register": "inschrijfnummer",
|
||||
"responsible": "Verantwoordelijk volgens § 55 Abs. 2 RStV (Duitsland).",
|
||||
"taxident": "Identificatienummer voor de belasting over de toegevoegde waarde overeenkomstig § 27 a Wet op de belasting over de toegevoegde waarde (Duitsland).",
|
||||
|
||||
@ -350,7 +350,7 @@
|
||||
"director": "Dyrektor zarządzający",
|
||||
"germany": "Niemcy",
|
||||
"imprint": "Nadruk",
|
||||
"made": "Z ❤ zrobiony",
|
||||
"made": "Z ❤️ zrobiony",
|
||||
"register": "numer rejestracyjny",
|
||||
"responsible": "Odpowiedzialny zgodnie z § 55 Abs. 2 RStV (Niemcy)",
|
||||
"taxident": "Numer identyfikacyjny podatku od wartości dodanej zgodnie z § 27 a Ustawa o podatku od wartości dodanej (Niemcy)",
|
||||
|
||||
@ -647,7 +647,7 @@
|
||||
"faq": "FAQ",
|
||||
"germany": "Alemanha",
|
||||
"imprint": "Impressão",
|
||||
"made": "Feito com ❤",
|
||||
"made": "Feito com ❤️",
|
||||
"register": "número de registo",
|
||||
"responsible": "Responsável segundo § 55 Abs. 2 RStV (Alemanha) ",
|
||||
"taxident": "Número de identificação do imposto sobre o valor acrescentado de acordo com o § 27 da Lei do Imposto sobre o Valor Acrescentado (Alemanha)",
|
||||
|
||||
@ -694,7 +694,7 @@
|
||||
"faq": "ЧаВо (FAQ)",
|
||||
"germany": "Германия",
|
||||
"imprint": "Импрессум",
|
||||
"made": "Сделано с ❤",
|
||||
"made": "Сделано с ❤️",
|
||||
"register": "Регистрационный номер",
|
||||
"responsible": "ответственный за содержание этой страницы (§ 55 Abs. 2 RStV)",
|
||||
"taxident": "UST-ID. в соответствии с §27a Закона о налоге с продаж Германии:",
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div>
|
||||
<ds-space>
|
||||
<ds-space margin="small">
|
||||
<ds-heading tag="h2">{{ $t('site.code-of-conduct') }}</ds-heading>
|
||||
</ds-space>
|
||||
<ds-container>
|
||||
|
||||
@ -1,9 +1,8 @@
|
||||
<template>
|
||||
<div>
|
||||
<ds-space>
|
||||
<ds-space margin="small">
|
||||
<ds-heading tag="h2">{{ $t('site.data-privacy') }}</ds-heading>
|
||||
</ds-space>
|
||||
|
||||
<ds-container>
|
||||
<div v-html="$t('html.dataPrivacy')" />
|
||||
</ds-container>
|
||||
|
||||
38
webapp/pages/faq.spec.js
Normal file
38
webapp/pages/faq.spec.js
Normal file
@ -0,0 +1,38 @@
|
||||
import { mount } from '@vue/test-utils'
|
||||
import Faq from './faq.vue'
|
||||
import VueMeta from 'vue-meta'
|
||||
|
||||
const localVue = global.localVue
|
||||
localVue.use(VueMeta, { keyName: 'head' })
|
||||
|
||||
describe('faq.vue', () => {
|
||||
let wrapper
|
||||
let mocks
|
||||
|
||||
beforeEach(() => {
|
||||
mocks = {
|
||||
$t: (t) => t,
|
||||
}
|
||||
})
|
||||
|
||||
describe('mount', () => {
|
||||
const Wrapper = () => {
|
||||
return mount(Faq, {
|
||||
mocks,
|
||||
localVue,
|
||||
})
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
wrapper = Wrapper()
|
||||
})
|
||||
|
||||
it('renders', () => {
|
||||
expect(wrapper.is('div')).toBe(true)
|
||||
})
|
||||
|
||||
it('has correct <head> content', () => {
|
||||
expect(wrapper.vm.$metaInfo.title).toBe('site.faq')
|
||||
})
|
||||
})
|
||||
})
|
||||
21
webapp/pages/faq.vue
Normal file
21
webapp/pages/faq.vue
Normal file
@ -0,0 +1,21 @@
|
||||
<template>
|
||||
<div>
|
||||
<ds-space margin="small">
|
||||
<ds-heading tag="h2">{{ $t('site.faq') }}</ds-heading>
|
||||
</ds-space>
|
||||
<ds-container>
|
||||
<div v-html="$t('html.faq')" />
|
||||
</ds-container>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
layout: 'basic',
|
||||
head() {
|
||||
return {
|
||||
title: this.$t('site.faq'),
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
||||
@ -1,9 +1,8 @@
|
||||
<template>
|
||||
<div>
|
||||
<ds-space>
|
||||
<ds-space margin="small">
|
||||
<ds-heading tag="h2">{{ $t('site.imprint') }}</ds-heading>
|
||||
</ds-space>
|
||||
|
||||
<ds-container>
|
||||
<div v-html="$t('html.imprint')" />
|
||||
</ds-container>
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div>
|
||||
<ds-space>
|
||||
<ds-space margin="small">
|
||||
<ds-heading tag="h2">{{ $t('site.termsAndConditions') }}</ds-heading>
|
||||
</ds-space>
|
||||
<ds-container>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user