diff options
Diffstat (limited to 'apps/settings/src/components/BasicSettings')
-rw-r--r-- | apps/settings/src/components/BasicSettings/BackgroundJob.vue | 201 | ||||
-rw-r--r-- | apps/settings/src/components/BasicSettings/ProfileSettings.vue | 41 |
2 files changed, 212 insertions, 30 deletions
diff --git a/apps/settings/src/components/BasicSettings/BackgroundJob.vue b/apps/settings/src/components/BasicSettings/BackgroundJob.vue new file mode 100644 index 00000000000..a9a3cbb9cef --- /dev/null +++ b/apps/settings/src/components/BasicSettings/BackgroundJob.vue @@ -0,0 +1,201 @@ +<!-- + - SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors + - SPDX-License-Identifier: AGPL-3.0-or-later +--> + +<template> + <NcSettingsSection :name="t('settings', 'Background jobs')" + :description="t('settings', 'For the server to work properly, it\'s important to configure background jobs correctly. Cron is the recommended setting. Please see the documentation for more information.')" + :doc-url="backgroundJobsDocUrl"> + <template v-if="lastCron !== 0"> + <NcNoteCard v-if="oldExecution" type="error"> + {{ t('settings', 'Last job execution ran {time}. Something seems wrong.', {time: relativeTime}) }} + </NcNoteCard> + + <NcNoteCard v-else-if="longExecutionCron" type="warning"> + {{ t('settings', "Some jobs have not been executed since {maxAgeRelativeTime}. Please consider increasing the execution frequency.", {maxAgeRelativeTime}) }} + </NcNoteCard> + + <NcNoteCard v-else-if="longExecutionNotCron" type="warning"> + {{ t('settings', "Some jobs have not been executed since {maxAgeRelativeTime}. Please consider switching to system cron.", {maxAgeRelativeTime}) }} + </NcNoteCard> + + <NcNoteCard v-else type="success"> + {{ t('settings', 'Last job ran {relativeTime}.', {relativeTime}) }} + </NcNoteCard> + </template> + + <NcNoteCard v-else type="error"> + {{ t('settings', 'Background job did not run yet!') }} + </NcNoteCard> + + <NcCheckboxRadioSwitch type="radio" + :checked.sync="backgroundJobsMode" + name="backgroundJobsMode" + value="ajax" + class="ajaxSwitch" + @update:checked="onBackgroundJobModeChanged"> + {{ t('settings', 'AJAX') }} + </NcCheckboxRadioSwitch> + <em>{{ t('settings', 'Execute one task with each page loaded. Use case: Single account instance.') }}</em> + + <NcCheckboxRadioSwitch type="radio" + :checked.sync="backgroundJobsMode" + name="backgroundJobsMode" + value="webcron" + @update:checked="onBackgroundJobModeChanged"> + {{ t('settings', 'Webcron') }} + </NcCheckboxRadioSwitch> + <em>{{ t('settings', 'cron.php is registered at a webcron service to call cron.php every 5 minutes over HTTP. Use case: Very small instance (1–5 accounts depending on the usage).') }}</em> + + <NcCheckboxRadioSwitch type="radio" + :disabled="!cliBasedCronPossible" + :checked.sync="backgroundJobsMode" + value="cron" + name="backgroundJobsMode" + @update:checked="onBackgroundJobModeChanged"> + {{ t('settings', 'Cron (Recommended)') }} + </NcCheckboxRadioSwitch> + <!-- eslint-disable-next-line vue/no-v-html The translation is sanitized--> + <em v-html="cronLabel" /> + </NcSettingsSection> +</template> + +<script> +import { loadState } from '@nextcloud/initial-state' +import { showError } from '@nextcloud/dialogs' +import { generateOcsUrl } from '@nextcloud/router' +import { confirmPassword } from '@nextcloud/password-confirmation' +import axios from '@nextcloud/axios' +import moment from '@nextcloud/moment' + +import NcCheckboxRadioSwitch from '@nextcloud/vue/components/NcCheckboxRadioSwitch' +import NcSettingsSection from '@nextcloud/vue/components/NcSettingsSection' +import NcNoteCard from '@nextcloud/vue/components/NcNoteCard' + +import '@nextcloud/password-confirmation/dist/style.css' + +const lastCron = loadState('settings', 'lastCron') +const cronMaxAge = loadState('settings', 'cronMaxAge', '') +const backgroundJobsMode = loadState('settings', 'backgroundJobsMode', 'cron') +const cliBasedCronPossible = loadState('settings', 'cliBasedCronPossible', true) +const cliBasedCronUser = loadState('settings', 'cliBasedCronUser', 'www-data') +const backgroundJobsDocUrl = loadState('settings', 'backgroundJobsDocUrl') + +export default { + name: 'BackgroundJob', + + components: { + NcCheckboxRadioSwitch, + NcSettingsSection, + NcNoteCard, + }, + + data() { + return { + lastCron, + cronMaxAge, + backgroundJobsMode, + cliBasedCronPossible, + cliBasedCronUser, + backgroundJobsDocUrl, + relativeTime: moment(lastCron * 1000).fromNow(), + maxAgeRelativeTime: moment(cronMaxAge * 1000).fromNow(), + } + }, + computed: { + cronLabel() { + let desc = t('settings', 'Use system cron service to call the cron.php file every 5 minutes.') + if (this.cliBasedCronPossible) { + desc += '<br>' + t('settings', 'The cron.php needs to be executed by the system account "{user}".', { user: this.cliBasedCronUser }) + } else { + desc += '<br>' + t('settings', 'The PHP POSIX extension is required. See {linkstart}PHP documentation{linkend} for more details.', { + linkstart: '<a target="_blank" rel="noreferrer nofollow" class="external" href="https://www.php.net/manual/en/book.posix.php">', + linkend: '</a>', + }, undefined, { escape: false }) + } + return desc + }, + oldExecution() { + return Date.now() / 1000 - this.lastCron > 600 + }, + longExecutionNotCron() { + return Date.now() / 1000 - this.cronMaxAge > 12 * 3600 && this.backgroundJobsMode !== 'cron' + }, + longExecutionCron() { + return Date.now() / 1000 - this.cronMaxAge > 24 * 3600 && this.backgroundJobsMode === 'cron' + }, + }, + methods: { + async onBackgroundJobModeChanged(backgroundJobsMode) { + const url = generateOcsUrl('/apps/provisioning_api/api/v1/config/apps/{appId}/{key}', { + appId: 'core', + key: 'backgroundjobs_mode', + }) + + await confirmPassword() + + try { + const { data } = await axios.post(url, { + value: backgroundJobsMode, + }) + this.handleResponse({ + status: data.ocs?.meta?.status, + }) + } catch (e) { + this.handleResponse({ + errorMessage: t('settings', 'Unable to update background job mode'), + error: e, + }) + } + }, + async handleResponse({ status, errorMessage, error }) { + if (status === 'ok') { + await this.deleteError() + } else { + showError(errorMessage) + console.error(errorMessage, error) + } + }, + async deleteError() { + // clear cron errors on background job mode change + const url = generateOcsUrl('/apps/provisioning_api/api/v1/config/apps/{appId}/{key}', { + appId: 'core', + key: 'cronErrors', + }) + + await confirmPassword() + + try { + await axios.delete(url) + } catch (error) { + console.error(error) + } + }, + }, +} +</script> + +<style lang="scss" scoped> +.error { + margin-top: 8px; + padding: 5px; + border-radius: var(--border-radius); + color: var(--color-primary-element-text); + background-color: var(--color-error); + width: initial; +} + +.warning { + margin-top: 8px; + padding: 5px; + border-radius: var(--border-radius); + color: var(--color-primary-element-text); + background-color: var(--color-warning); + width: initial; +} + +.ajaxSwitch { + margin-top: 1rem; +} +</style> diff --git a/apps/settings/src/components/BasicSettings/ProfileSettings.vue b/apps/settings/src/components/BasicSettings/ProfileSettings.vue index 9abce3d787c..276448cd97b 100644 --- a/apps/settings/src/components/BasicSettings/ProfileSettings.vue +++ b/apps/settings/src/components/BasicSettings/ProfileSettings.vue @@ -1,23 +1,6 @@ <!-- - - @copyright 2022 Christopher Ng <chrng8@gmail.com> - - - - @author Christopher Ng <chrng8@gmail.com> - - - - @license GNU AGPL version 3 or any later version - - - - This program is free software: you can redistribute it and/or modify - - it under the terms of the GNU Affero General Public License as - - published by the Free Software Foundation, either version 3 of the - - License, or (at your option) any later version. - - - - This program is distributed in the hope that it will be useful, - - but WITHOUT ANY WARRANTY; without even the implied warranty of - - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - - GNU Affero General Public License for more details. - - - - You should have received a copy of the GNU Affero General Public License - - along with this program. If not, see <http://www.gnu.org/licenses/>. - - + - SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors + - SPDX-License-Identifier: AGPL-3.0-or-later --> <template> @@ -28,14 +11,14 @@ </h2> <p class="settings-hint"> - {{ t('settings', 'Enable or disable profile by default for new users.') }} + {{ t('settings', 'Enable or disable profile by default for new accounts.') }} </p> - <CheckboxRadioSwitch type="switch" + <NcCheckboxRadioSwitch type="switch" :checked.sync="initialProfileEnabledByDefault" @update:checked="onProfileDefaultChange"> {{ t('settings', 'Enable') }} - </CheckboxRadioSwitch> + </NcCheckboxRadioSwitch> </div> </template> @@ -43,10 +26,11 @@ import { loadState } from '@nextcloud/initial-state' import { showError } from '@nextcloud/dialogs' -import { saveProfileDefault } from '../../service/ProfileService' -import { validateBoolean } from '../../utils/validate' +import { saveProfileDefault } from '../../service/ProfileService.js' +import { validateBoolean } from '../../utils/validate.js' +import logger from '../../logger.ts' -import CheckboxRadioSwitch from '@nextcloud/vue/dist/Components/CheckboxRadioSwitch' +import NcCheckboxRadioSwitch from '@nextcloud/vue/components/NcCheckboxRadioSwitch' const profileEnabledByDefault = loadState('settings', 'profileEnabledByDefault', true) @@ -54,7 +38,7 @@ export default { name: 'ProfileSettings', components: { - CheckboxRadioSwitch, + NcCheckboxRadioSwitch, }, data() { @@ -90,12 +74,9 @@ export default { this.initialProfileEnabledByDefault = isEnabled } else { showError(errorMessage) - this.logger.error(errorMessage, error) + logger.error(errorMessage, error) } }, }, } </script> - -<style lang="scss" scoped> -</style> |