Skip to content

Commit

Permalink
fixup! Force the user to scroll text to accept the TOS
Browse files Browse the repository at this point in the history
Signed-off-by: greta <[email protected]>
  • Loading branch information
GretaD committed Jul 16, 2024
1 parent 5ddf5db commit b1d2856
Show file tree
Hide file tree
Showing 2 changed files with 232 additions and 220 deletions.
224 changes: 120 additions & 104 deletions src/UserApp.vue
Original file line number Diff line number Diff line change
@@ -1,136 +1,152 @@

<!--
- SPDX-FileCopyrightText: 2021 Nextcloud GmbH and Nextcloud contributors
- SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
- SPDX-License-Identifier: AGPL-3.0-or-later
-->

<template>
<div id="terms_of_service_content"
class="modal-content"
aria-live="polite">
<div class="modal-content__header">
<slot name="header" />
</div>

<!-- Scrollable terms of service -->
<div ref="termsContent" class="terms-content">
<slot />
</div>

<NcButton ref="acceptButton"
class="modal-content__button"
type="primary"
:wide="true"
autofocus
:title="t('terms_of_service', 'I acknowledge that I have read and agree to the above terms of service')"
:disabled="!isScrollComplete"
@click.prevent.stop="handleClick"
@keydown.enter="handleClick">
{{ t('terms_of_service', 'I acknowledge that I have read and agree to the above terms of service') }}
</NcButton>
<div id="terms_of_service_confirm">
<NcModal v-if="showModal"
:can-close="hasSigned"
@close="handleCloseModal">
<ModalContent :is-scroll-complete="hasScrolledToBottom" @click="acceptTerms">
<template #header>
<h3>{{ t('terms_of_service', 'Terms of service') }}</h3>
<select v-if="terms.length > 1" v-model="selectedLanguage">
<option v-for="(language, index) in languages" :key="index" :value="index">
{{ language }}
</option>
</select>
</template>

<!-- eslint-disable-next-line vue/no-v-html -->
<div ref="termsContent"
class="text-content"
@scroll="checkScroll"
v-html="termsBody" />

Check warning on line 25 in src/UserApp.vue

View workflow job for this annotation

GitHub Actions / NPM lint

'v-html' directive can lead to XSS attack
</ModalContent>
</NcModal>
</div>
</template>

<script>
import NcButton from '@nextcloud/vue/dist/Components/NcButton.js'
import axios from '@nextcloud/axios'
import { generateUrl } from '@nextcloud/router'
import NcModal from '@nextcloud/vue/dist/Components/NcModal.js'
import ModalContent from './components/ModalContent.vue'

export default {
name: 'ModalContent',
name: 'UserApp',

components: {
NcButton,
NcModal,
ModalContent,
},

data() {
return {
showModal: false,
hasSigned: false,
terms: {},
languages: [],
selectedLanguage: 0,
termsId: 0,
termsBody: '',
publicContent: null,
hasScrolledToBottom: false,
}
},

props: {
isScrollComplete: {
type: Boolean,
default: false,
watch: {
selectedLanguage(newLanguage) {
this.selectTerms(newLanguage)
},
},

mounted() {
this.$nextTick(() => {
this.$refs.acceptButton.$el.focus()
})
this.loadTerms()
},

methods: {
handleClick() {
if (this.isScrollComplete) {
this.$emit('click')
async loadTerms() {
try {
const response = await axios.get(generateUrl('/apps/terms_of_service/terms'))
this.hasSigned = response.data.hasSigned
this.terms = response.data.terms

const language = OC.getLanguage().split('-')[0]

if (!this.terms.length || this.hasSigned) {
return
}

this.publicContent = document.getElementById('files-public-content')
if (this.publicContent !== null) {
this.publicContent.style.visibility = 'hidden'
}

this.selectTerms(0)
if (this.terms.length > 1) {
Object.keys(this.terms).forEach((index) => {
if (language === this.terms[index].languageCode) {
this.selectedLanguage = index
}

this.languages.push(response.data.languages[this.terms[index].languageCode])
})
}

this.showTerms()
} catch (error) {
console.error('Error loading terms:', error)
}
},
},
}
</script>

<style lang="scss" scoped>
#terms_of_service_content.modal-content,
.modal-content {
padding: 0 12px;
height: 100%;
display: flex;
flex-direction: column;
color: var(--color-main-text);

&__header {
padding-top: 12px;
}

h3 {
float: left;
font-weight: 800;
}

&__button {
margin: 8px 0 12px 0;
}

.terms-content {
height: 100%;
overflow-y: auto;
flex: 1;
}

select {
float: right;
padding: 0 12px;

color: var(--color-main-text);
border: 1px solid var(--color-border-dark);
border-radius: var(--border-radius);
&:hover {
border-color: var(--color-primary-element);
}
}
selectTerms(index) {
this.termsBody = this.terms[index].renderedBody
this.termsId = this.terms[index].id
},

:deep div.text-content {
height: 100%;
overflow: auto;
text-align: left;
showTerms() {
this.showModal = true
this.$nextTick(() => {
this.checkScroll()
})
},

h3 {
font-weight: 800;
}
acceptTerms() {
this.hasSigned = true
this.showModal = false

p {
padding-top: 5px;
padding-bottom: 5px;
}
let url = '/apps/terms_of_service/sign'
if (this.$root.source === 'public') {
url = '/apps/terms_of_service/sign_public'
}

ol {
padding-left: 12px;
}
axios.post(
generateUrl(url),
{ termId: this.termsId },
).then(() => {
window.location.reload()
})
},

ul {
list-style-type: disc;
padding-left: 25px;
}
handleCloseModal() {
this.showModal = false
},

a {
text-decoration: underline;
color: var(--color-main-text) !important;
}
}
checkScroll() {
const termsContent = this.$refs.termsContent
const isScrollable = termsContent.scrollHeight > termsContent.clientHeight

this.hasScrolledToBottom = !isScrollable || (termsContent.scrollHeight - termsContent.scrollTop <= termsContent.clientHeight + 1)
},
},
}
</style>
</script>

<style lang="scss" scoped>
:deep .modal-container {
display: flex;
height: 100%;
}
</style>
Loading

0 comments on commit b1d2856

Please sign in to comment.