Client - init privacy policy and instance description

This commit is contained in:
Sam
2023-02-26 18:25:25 +01:00
parent 8a3f9a5d59
commit 3834e71c95
33 changed files with 359 additions and 26 deletions

View File

@ -46,16 +46,24 @@
{{ weather_provider.name }}
</a>
</div>
<template v-if="appConfig.about">
<p class="about-instance">{{ $t('about.ABOUT_THIS_INSTANCE') }}</p>
<div
v-html="snarkdown(linkifyAndClean(appConfig.about))"
/>
</template>
</div>
</div>
</template>
<script lang="ts" setup>
import snarkdown from 'snarkdown'
import { ComputedRef, computed, capitalize } from 'vue'
import { ROOT_STORE } from '@/store/constants'
import { TAppConfig } from '@/types/application'
import { useStore } from '@/use/useStore'
import { linkifyAndClean } from '@/utils/inputs'
const store = useStore()
const appConfig: ComputedRef<TAppConfig> = computed(
@ -84,11 +92,17 @@
.about-text {
margin-top: 200px;
margin-right: 100px;
@media screen and (max-width: $small-limit) {
margin-top: 0;
margin-right: 0;
}
.fa-padding {
padding-right: $default-padding;
}
.about-instance {
font-weight: bold;
margin-top: $default-margin*3;
}
}
</style>

View File

@ -73,6 +73,42 @@
:disabled="!edition"
/>
</label>
<label class="about-label" for="about">
{{ $t('admin.ABOUT.TEXT') }}:
</label>
<span class="textarea-description">
{{ $t('admin.ABOUT.DESCRIPTION') }}
</span>
<textarea
v-if="edition"
id="about"
name="about"
rows="10"
v-model="appData.about"
/>
<div
v-else
v-html="snarkdown(linkifyAndClean(appData.about ? appData.about : $t('admin.NO_TEXT_ENTERED')))"
class="textarea-content"
/>
<label class="privacy-policy-label" for="privacy_policy">
{{ capitalize($t('privacy_policy.TITLE')) }}:
</label>
<span class="textarea-description">
{{ $t('admin.PRIVACY_POLICY_DESCRIPTION') }}
</span>
<textarea
v-if="edition"
id="privacy_policy"
name="privacy_policy"
rows="20"
v-model="appData.privacy_policy"
/>
<div
v-else
v-html="snarkdown(linkifyAndClean(appData.privacy_policy ? appData.privacy_policy : $t('admin.NO_TEXT_ENTERED')))"
class="textarea-content"
/>
<ErrorMessage :message="errorMessages" v-if="errorMessages" />
<div class="form-buttons" v-if="edition">
<button class="confirm" type="submit">
@ -100,8 +136,10 @@
</template>
<script setup lang="ts">
import snarkdown from 'snarkdown'
import {
ComputedRef,
capitalize,
computed,
reactive,
withDefaults,
@ -114,6 +152,7 @@
import { TAppConfig, TAppConfigForm } from '@/types/application'
import { useStore } from '@/use/useStore'
import { getFileSizeInMB } from '@/utils/files'
import { linkifyAndClean } from '@/utils/inputs'
interface Props {
appConfig: TAppConfig
@ -133,6 +172,8 @@
max_single_file_size: 0,
max_zip_file_size: 0,
gpx_limit_import: 0,
about: '',
privacy_policy: '',
})
const errorMessages: ComputedRef<string | string[] | null> = computed(
() => store.getters[ROOT_STORE.GETTERS.ERROR_MESSAGES]
@ -150,9 +191,15 @@
? // eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
(appData[key] = getFileSizeInMB(appConfig[key]))
: // eslint-disable-next-line @typescript-eslint/ban-ts-comment
: ['about', 'privacy_policy'].includes(key)
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
(appData[key] = appConfig[key])
? appData[key] = appConfig[key]!== null
? appConfig[key]
: ''
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
: (appData[key] = appConfig[key])
})
}
function onCancel() {
@ -171,16 +218,30 @@
<style lang="scss" scoped>
@import '~@/scss/vars.scss';
.user-limit-help {
display: flex;
span {
#admin-app {
.user-limit-help {
display: flex;
span {
font-style: italic;
}
.fa-info-circle {
margin-right: $default-margin;
}
}
.no-contact {
font-style: italic;
}
.fa-info-circle {
margin-right: $default-margin;
textarea {
margin-bottom: $default-padding;
}
}
.no-contact {
font-style: italic;
.textarea-description {
font-style: italic;
}
.textarea-content {
margin-bottom: $default-margin;
padding: $default-padding;
}
}
</style>

View File

@ -17,13 +17,9 @@
</div>
<div class="footer-item bullet"></div>
<div class="footer-item">
<a
href="https://samr1.github.io/FitTrackee/"
target="_blank"
rel="noopener noreferrer"
>
{{ $t('common.DOCUMENTATION') }}
</a>
<router-link to="/privacy-policy">
{{ $t('privacy_policy.TITLE') }}
</router-link>
</div>
</div>
</div>
@ -61,6 +57,7 @@
.footer-items {
display: flex;
flex-wrap: wrap;
align-content: center;
justify-content: center;
@ -76,14 +73,17 @@
@media screen and (max-width: $x-small-limit) {
.footer-items {
border-top: solid 1px var(--footer-border-color);
font-size: 0.85em;
padding: 0 0 2px;
.footer-item {
padding: 5px 5px;
border-top: none;
padding: 1px 5px;
}
.bullet {
padding: 5px 0;
padding: 1px 0;
}
}
}

View File

@ -0,0 +1,91 @@
<template>
<div class="privacy-policy-text">
<h1>
{{ capitalize($t('privacy_policy.TITLE')) }}
</h1>
<p class="last-update">
{{ $t('privacy_policy.LAST_UPDATE')}}: {{ private_policy_date }}
</p>
<template v-if="appConfig.privacy_policy">
<div
v-html="snarkdown(linkifyAndClean(appConfig.privacy_policy))"
/>
</template>
<template v-else>
<template v-for="paragraph in paragraphs" :key="paragraph">
<h2>
{{ $t(`privacy_policy.CONTENT.${paragraph}.TITLE`)}}
</h2>
<p v-html="snarkdown($t(`privacy_policy.CONTENT.${paragraph}.CONTENT`))" />
</template>
</template>
</div>
</template>
<script lang="ts" setup>
import snarkdown from 'snarkdown'
import { ComputedRef, capitalize, computed } from 'vue'
import { AUTH_USER_STORE, ROOT_STORE } from '@/store/constants'
import { TAppConfig } from '@/types/application'
import { IAuthUserProfile } from '@/types/user'
import { useStore } from '@/use/useStore'
import { dateStringFormats, formatDate } from '@/utils/dates'
import { linkifyAndClean } from '@/utils/inputs'
const store = useStore()
const fittrackee_private_policy_date = 'Sun, 26 Feb 2023 17:00:00 GMT'
const appConfig: ComputedRef<TAppConfig> = computed(
() => store.getters[ROOT_STORE.GETTERS.APP_CONFIG]
)
const language: ComputedRef<string> = computed(
() => store.getters[ROOT_STORE.GETTERS.LANGUAGE]
)
const authUser: ComputedRef<IAuthUserProfile> = computed(
() => store.getters[AUTH_USER_STORE.GETTERS.AUTH_USER_PROFILE]
)
const dateFormat = computed(() => getDateFormat())
const timezone = computed(() => getTimezone())
const private_policy_date = computed(() => getPolicyDate())
const paragraphs = [
'DATA_COLLECTED', 'INFORMATION_USAGE', 'INFORMATION_PROTECTION',
'INFORMATION_DISCLOSURE', 'SITE_USAGE_BY_CHILDREN','ACCOUNT_DELETION',
'YOUR_CONSENT', 'CHANGES_TO_OUR_PRIVACY_POLICY'
]
function getTimezone() {
return authUser.value.timezone
? authUser.value.timezone
: Intl.DateTimeFormat().resolvedOptions().timeZone
? Intl.DateTimeFormat().resolvedOptions().timeZone
: 'Europe/Paris'
}
function getDateFormat() {
return dateStringFormats[language.value]
}
function getPolicyDate() {
return formatDate(
appConfig.value.privacy_policy && appConfig.value.privacy_policy_date
? `${appConfig.value.privacy_policy_date}`
: fittrackee_private_policy_date,
timezone.value,
dateFormat.value,
false,
)
}
</script>
<style lang="scss" scoped>
@import '~@/scss/base.scss';
.privacy-policy-text {
margin: 10px 50px 20px;
padding: $default-padding;
width: 100%;
@media screen and (max-width: $small-limit) {
margin: 0;
}
}
</style>

View File

@ -98,6 +98,27 @@
@updatePassword="updatePassword"
@passwordError="invalidateForm"
/>
<label
v-if="action === 'register'"
for="accepted_policy"
class="accepted_policy"
>
<input
type="checkbox"
id="accepted_policy"
:disabled="registration_disabled"
required
@invalid="invalidateForm"
v-model="formData.accepted_policy"
/>
<span>
<i18n-t keypath="user.READ_AND_ACCEPT_PRIVACY_POLICY">
<router-link to="/privacy-policy">
{{ $t('privacy_policy.TITLE') }}
</router-link>
</i18n-t>
</span>
</label>
</div>
<button
type="submit"
@ -176,6 +197,7 @@
username: '',
email: '',
password: '',
accepted_policy: false
})
const buttonText: ComputedRef<string> = computed(() =>
getButtonText(props.action)
@ -261,6 +283,7 @@
formData.username = ''
formData.email = ''
formData.password = ''
formData.accepted_policy = false
}
onUnmounted(() => store.commit(ROOT_STORE.MUTATIONS.EMPTY_ERROR_MESSAGES))
@ -310,6 +333,12 @@
.success-message {
margin: $default-margin;
}
.accepted_policy {
display: flex;
align-items: center;
font-size: .85em;
font-weight: normal;
}
}
@media screen and (max-width: $medium-limit) {