Skip to content

Commit

Permalink
Refactor: Move personal user settings page to Vue
Browse files Browse the repository at this point in the history
Signed-off-by: codewithvk <[email protected]>
  • Loading branch information
codewithvk committed Jan 16, 2025
1 parent 705cdf6 commit ca586cb
Show file tree
Hide file tree
Showing 4 changed files with 362 additions and 221 deletions.
78 changes: 78 additions & 0 deletions src/components/DocSigningField.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
<!--
- SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
- SPDX-License-Identifier: AGPL-3.0-or-later
-->

<template>
<p>
<label :for="id">
{{ label }}
</label>
<br>
<textarea :id="id"
v-model="localValue"
:name="name" />
<br>
<button :id="id + 'Save'" @click="onClickSave">
<span :title="saveTooltip" data-toggle="tooltip">
Save
</span>
</button>

<button :id="id + 'Remove'" @click="onClickRemove">
<span class="icon-delete"
:title="removeTooltip"
data-toggle="tooltip" />
</button>
</p>
</template>

<script>
export default {
name: 'DocSigningField',
props: {
id: {
type: String,
required: true,
},
name: {
type: String,
default: '',
},
label: {
type: String,
required: true,
},
value: {
type: String,
default: '',
},
saveTooltip: {
type: String,
default: 'Save',
},
removeTooltip: {
type: String,
default: 'Remove',
},
},
data() {
return {
localValue: this.value,
}
},
watch: {
value(newVal) {
this.localValue = newVal
},
},
methods: {
onClickSave() {
this.$emit('save', this.localValue)
},
onClickRemove() {
this.$emit('remove')
},
},
}
</script>
264 changes: 264 additions & 0 deletions src/components/PersonalSettings.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,264 @@
<!--
- SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
- SPDX-License-Identifier: AGPL-3.0-or-later
-->

<template>
<div id="richdocuments" class="section">
<h2>
{{ t('richdocuments', 'Nextcloud Office') }}
</h2>

<span id="documents-admin-msg" class="msg" />

<!-- Template folder selection -->
<p>
<label for="templateInputField">
{{ t('richdocuments', 'Select a template directory') }}
</label><br>
<input id="templateInputField"
type="text"
name="templateInputField"
:value="templateFolder"
disabled>
<button id="templateSelectButton"
@click="onTemplateSelectButtonClick">
<span class="icon-folder"
:title="t('richdocuments', 'Select a personal template folder')"
data-toggle="tooltip" />
</button>
<button id="templateResetButton"
@click="resetTemplate">
<span class="icon-delete"
:title="t('richdocuments', 'Remove personal template folder')"
data-toggle="tooltip" />
</button>
</p>
<p>
<em>
{{ t('richdocuments', 'Templates inside of this directory will be added to the template selector of Nextcloud Office.') }}
</em>
</p>

<!-- Zotero -->
<p><strong>{{ t('richdocuments', 'Zotero') }}</strong></p>
<template v-if="hasZoteroSupport">
<div class="input-wrapper">
<p>
<label for="zoteroAPIKeyField">
{{ t('richdocuments', 'Enter Zotero API Key') }}
</label><br>
<input id="zoteroAPIKeyField"
v-model="zoteroAPIKey"
type="text"
name="zoteroAPIKeyField">
<button id="zoteroAPIKeySave"
@click="saveZoteroAPIKey">
<span :title="t('richdocuments', 'Save Zotero API key')" data-toggle="tooltip">
Save
</span>
</button>
<button id="zoteroAPIKeyRemove"
@click="resetZoteroAPI">
<span class="icon-delete"
:title="t('richdocuments', 'Remove Zotero API Key')"
data-toggle="tooltip" />
</button>
</p>
<p>
<em>
{{ t('richdocuments', 'To use Zotero specify your API key here. You can create your API key in your') }}
<a href="https://www.zotero.org/settings/keys" target="_blank">
{{ t('richdocuments', 'Zotero account API settings.') }}
</a>
</em>
</p>
</div>
</template>
<p v-else>
<em>
{{ t('richdocuments', 'This instance does not support Zotero, because the feature is missing or disabled. Please contact the administration.') }}
</em>
</p>

<!-- Document signing -->
<p><strong>{{ t('richdocuments', 'Document signing') }}</strong></p>
<template v-if="hasDocumentSigningSupport">
<div class="input-wrapper">
<!-- Cert -->
<DocSigningField id="documentSigningCertField"
name="documentSigningCertField"
:label="t('richdocuments', 'Enter document signing cert (in PEM format)')"
:value="documentSigningCert"
:save-tooltip="t('richdocuments', 'Save document signing cert')"
:remove-tooltip="t('richdocuments', 'Remove document signing cert')"
@save="val => setDocumentSigningCert(val)"
@remove="() => setDocumentSigningCert('')" />

<!-- Key -->
<DocSigningField id="documentSigningKeyField"
name="documentSigningKeyField"
:label="t('richdocuments', 'Enter document signing key')"
:value="documentSigningKey"
:save-tooltip="t('richdocuments', 'Save document signing key')"
:remove-tooltip="t('richdocuments', 'Remove document signing key')"
@save="val => setDocumentSigningKey(val)"
@remove="() => setDocumentSigningKey('')" />

<!-- CA -->
<DocSigningField id="documentSigningCaField"
name="documentSigningCaField"
:label="t('richdocuments', 'Enter document signing CA chain')"
:value="documentSigningCa"
:save-tooltip="t('richdocuments', 'Save document signing CA chain')"
:remove-tooltip="t('richdocuments', 'Remove document signing CA chain')"
@save="val => setDocumentSigningCa(val)"
@remove="() => setDocumentSigningCa('')" />

<p>
<em>
{{ t('richdocuments', 'To use document signing, specify your signing certificate, key and CA chain here.') }}
</em>
</p>
</div>
</template>
<p v-else>
<em>
{{ t('richdocuments', 'This instance does not support document signing, because the feature is missing or disabled. Please contact the administrator.') }}
</em>
</p>
</div>
</template>

<script>
import { generateFilePath } from '@nextcloud/router'
import { showError, showSuccess } from '@nextcloud/dialogs'
import DocSigningField from './DocSigningField.vue'

export default {
name: 'PersonalSettings',
components: {
DocSigningField,
},
props: {
initial: {
type: Object,
required: true,
},
},
data() {
return {
templateFolder: this.initial.templateFolder || '',
hasZoteroSupport: this.initial.hasZoteroSupport || false,
zoteroAPIKey: this.initial.zoteroAPIKey || '',
hasDocumentSigningSupport: this.initial.hasDocumentSigningSupport || false,
documentSigningCert: this.initial.documentSigningCert || '',
documentSigningKey: this.initial.documentSigningKey || '',
documentSigningCa: this.initial.documentSigningCa || '',
}
},
methods: {
onTemplateSelectButtonClick() {
OC.dialogs.filepicker(
this.t('richdocuments', 'Select a personal template folder'),
(datapath) => {
this.updateSetting({ templateFolder: datapath }, () => {
this.templateFolder = datapath
}, () => {})
},
false,
'httpd/unix-directory',
true,
OC.dialogs.FILEPICKER_TYPE_CHOOSE,
)
},
resetTemplate() {
this.updateSetting({ templateFolder: '' }, () => {
this.templateFolder = ''
}, () => {})
},
saveZoteroAPIKey() {
this.updateSetting({ zoteroAPIKeyInput: this.zoteroAPIKey }, () => {
showSuccess(this.t('richdocuments', 'Zotero API key saved'))
}, () => {
showError(this.t('richdocuments', 'Failed to update the Zotero API key'))
})
},
resetZoteroAPI() {
this.updateSetting({ zoteroAPIKeyInput: '' }, () => {
this.zoteroAPIKey = ''
}, () => {
showError(this.t('richdocuments', 'Failed to reset the Zotero API key'))
})
},
setDocumentSigningCert(val) {
this.updateSetting({ documentSigningCertInput: val }, () => {
this.documentSigningCert = val
if (val === '') {
showSuccess(this.t('richdocuments', 'Document signing cert removed'))
} else {
showSuccess(this.t('richdocuments', 'Document signing cert saved'))
}
}, () => {
showError(this.t('richdocuments', 'Failed to update the document signing CA chain'))
})
},
setDocumentSigningKey(val) {
this.updateSetting({ documentSigningKeyInput: val }, () => {
this.documentSigningKey = val
if (val === '') {
showSuccess(this.t('richdocuments', 'Document signing key removed'))
} else {
showSuccess(this.t('richdocuments', 'Document signing key saved'))
}
}, () => {
showError(this.t('richdocuments', 'Failed to update the document signing CA chain'))
})
},
setDocumentSigningCa(val) {
this.updateSetting({ documentSigningCaInput: val }, () => {
this.documentSigningCa = val
if (val === '') {
showSuccess(this.t('richdocuments', 'Document signing CA chain removed'))
} else {
showSuccess(this.t('richdocuments', 'Document signing CA chain saved'))
}
}, () => {
showError(this.t('richdocuments', 'Failed to update the document signing CA chain'))
})
},

updateSetting(data, successCallback, errorCallback) {
OC.msg.startAction('#documents-admin-msg', this.t('richdocuments', 'Saving …'))
const request = new XMLHttpRequest()
request.open('POST', generateFilePath('richdocuments', 'ajax', 'personal.php'), true)
request.setRequestHeader('Content-Type', 'application/json')
request.setRequestHeader('requesttoken', OC.requestToken)
request.onload = function() {
if (request.status >= 200 && request.status < 400) {
const response = JSON.parse(request.response)
OC.msg.finishedAction('#documents-admin-msg', response)
successCallback(response)
} else {
errorCallback(this.response)
}
}
request.onerror = function() {
errorCallback(this.response)
}
request.send(JSON.stringify(data))
},
},
}
</script>

<style scoped>
.personal-settings {
padding: 2rem;
font-family: Arial, sans-serif;
}

.icon-folder::before {
content: "\1F4C1";
}
</style>
Loading

0 comments on commit ca586cb

Please sign in to comment.