mirror of
https://github.com/nextcloud/server.git
synced 2026-06-09 08:44:07 -04:00
feat(Settings): Add section to select preset
Signed-off-by: Louis Chemineau <louis@chmn.me>
This commit is contained in:
parent
9e9f3b9d16
commit
ed02d0df05
15 changed files with 512 additions and 4 deletions
File diff suppressed because one or more lines are too long
|
|
@ -29,6 +29,7 @@
|
|||
<settings>
|
||||
<admin>OCA\Settings\Settings\Admin\Mail</admin>
|
||||
<admin>OCA\Settings\Settings\Admin\Overview</admin>
|
||||
<admin>OCA\Settings\Settings\Admin\Presets</admin>
|
||||
<admin>OCA\Settings\Settings\Admin\ArtificialIntelligence</admin>
|
||||
<admin>OCA\Settings\Settings\Admin\Server</admin>
|
||||
<admin>OCA\Settings\Settings\Admin\Sharing</admin>
|
||||
|
|
@ -39,6 +40,7 @@
|
|||
<admin-section>OCA\Settings\Sections\Admin\Delegation</admin-section>
|
||||
<admin-section>OCA\Settings\Sections\Admin\Groupware</admin-section>
|
||||
<admin-section>OCA\Settings\Sections\Admin\Overview</admin-section>
|
||||
<admin-section>OCA\Settings\Sections\Admin\Presets</admin-section>
|
||||
<admin-section>OCA\Settings\Sections\Admin\ArtificialIntelligence</admin-section>
|
||||
<admin-section>OCA\Settings\Sections\Admin\Security</admin-section>
|
||||
<admin-section>OCA\Settings\Sections\Admin\Server</admin-section>
|
||||
|
|
|
|||
|
|
@ -55,6 +55,7 @@ return array(
|
|||
'OCA\\Settings\\Sections\\Admin\\Delegation' => $baseDir . '/../lib/Sections/Admin/Delegation.php',
|
||||
'OCA\\Settings\\Sections\\Admin\\Groupware' => $baseDir . '/../lib/Sections/Admin/Groupware.php',
|
||||
'OCA\\Settings\\Sections\\Admin\\Overview' => $baseDir . '/../lib/Sections/Admin/Overview.php',
|
||||
'OCA\\Settings\\Sections\\Admin\\Presets' => $baseDir . '/../lib/Sections/Admin/Presets.php',
|
||||
'OCA\\Settings\\Sections\\Admin\\Security' => $baseDir . '/../lib/Sections/Admin/Security.php',
|
||||
'OCA\\Settings\\Sections\\Admin\\Server' => $baseDir . '/../lib/Sections/Admin/Server.php',
|
||||
'OCA\\Settings\\Sections\\Admin\\Sharing' => $baseDir . '/../lib/Sections/Admin/Sharing.php',
|
||||
|
|
@ -71,6 +72,7 @@ return array(
|
|||
'OCA\\Settings\\Settings\\Admin\\Mail' => $baseDir . '/../lib/Settings/Admin/Mail.php',
|
||||
'OCA\\Settings\\Settings\\Admin\\MailProvider' => $baseDir . '/../lib/Settings/Admin/MailProvider.php',
|
||||
'OCA\\Settings\\Settings\\Admin\\Overview' => $baseDir . '/../lib/Settings/Admin/Overview.php',
|
||||
'OCA\\Settings\\Settings\\Admin\\Presets' => $baseDir . '/../lib/Settings/Admin/Presets.php',
|
||||
'OCA\\Settings\\Settings\\Admin\\Security' => $baseDir . '/../lib/Settings/Admin/Security.php',
|
||||
'OCA\\Settings\\Settings\\Admin\\Server' => $baseDir . '/../lib/Settings/Admin/Server.php',
|
||||
'OCA\\Settings\\Settings\\Admin\\Sharing' => $baseDir . '/../lib/Settings/Admin/Sharing.php',
|
||||
|
|
|
|||
|
|
@ -70,6 +70,7 @@ class ComposerStaticInitSettings
|
|||
'OCA\\Settings\\Sections\\Admin\\Delegation' => __DIR__ . '/..' . '/../lib/Sections/Admin/Delegation.php',
|
||||
'OCA\\Settings\\Sections\\Admin\\Groupware' => __DIR__ . '/..' . '/../lib/Sections/Admin/Groupware.php',
|
||||
'OCA\\Settings\\Sections\\Admin\\Overview' => __DIR__ . '/..' . '/../lib/Sections/Admin/Overview.php',
|
||||
'OCA\\Settings\\Sections\\Admin\\Presets' => __DIR__ . '/..' . '/../lib/Sections/Admin/Presets.php',
|
||||
'OCA\\Settings\\Sections\\Admin\\Security' => __DIR__ . '/..' . '/../lib/Sections/Admin/Security.php',
|
||||
'OCA\\Settings\\Sections\\Admin\\Server' => __DIR__ . '/..' . '/../lib/Sections/Admin/Server.php',
|
||||
'OCA\\Settings\\Sections\\Admin\\Sharing' => __DIR__ . '/..' . '/../lib/Sections/Admin/Sharing.php',
|
||||
|
|
@ -86,6 +87,7 @@ class ComposerStaticInitSettings
|
|||
'OCA\\Settings\\Settings\\Admin\\Mail' => __DIR__ . '/..' . '/../lib/Settings/Admin/Mail.php',
|
||||
'OCA\\Settings\\Settings\\Admin\\MailProvider' => __DIR__ . '/..' . '/../lib/Settings/Admin/MailProvider.php',
|
||||
'OCA\\Settings\\Settings\\Admin\\Overview' => __DIR__ . '/..' . '/../lib/Settings/Admin/Overview.php',
|
||||
'OCA\\Settings\\Settings\\Admin\\Presets' => __DIR__ . '/..' . '/../lib/Settings/Admin/Presets.php',
|
||||
'OCA\\Settings\\Settings\\Admin\\Security' => __DIR__ . '/..' . '/../lib/Settings/Admin/Security.php',
|
||||
'OCA\\Settings\\Settings\\Admin\\Server' => __DIR__ . '/..' . '/../lib/Settings/Admin/Server.php',
|
||||
'OCA\\Settings\\Settings\\Admin\\Sharing' => __DIR__ . '/..' . '/../lib/Settings/Admin/Sharing.php',
|
||||
|
|
|
|||
1
apps/settings/img/library_add_check.svg
Normal file
1
apps/settings/img/library_add_check.svg
Normal file
|
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="#5f6368\"><path d="m508-398 226-226-56-58-170 170-86-84-56 56 142 142ZM320-240q-33 0-56.5-23.5T240-320v-480q0-33 23.5-56.5T320-880h480q33 0 56.5 23.5T880-800v480q0 33-23.5 56.5T800-240H320Zm0-80h480v-480H320v480ZM160-80q-33 0-56.5-23.5T80-160v-560h80v560h560v80H160Zm160-720v480-480Z"/></svg>
|
||||
|
After Width: | Height: | Size: 390 B |
38
apps/settings/lib/Sections/Admin/Presets.php
Normal file
38
apps/settings/lib/Sections/Admin/Presets.php
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
namespace OCA\Settings\Sections\Admin;
|
||||
|
||||
use OCP\IL10N;
|
||||
use OCP\IURLGenerator;
|
||||
use OCP\Settings\IIconSection;
|
||||
|
||||
class Presets implements IIconSection {
|
||||
|
||||
public function __construct(
|
||||
private IL10N $l,
|
||||
private IURLGenerator $urlGenerator,
|
||||
) {
|
||||
}
|
||||
|
||||
public function getIcon(): string {
|
||||
return $this->urlGenerator->imagePath('settings', 'library_add_check.svg');
|
||||
}
|
||||
|
||||
public function getID(): string {
|
||||
return 'presets';
|
||||
}
|
||||
|
||||
public function getName(): string {
|
||||
return $this->l->t('Settings presets');
|
||||
}
|
||||
|
||||
public function getPriority(): int {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
54
apps/settings/lib/Settings/Admin/Presets.php
Normal file
54
apps/settings/lib/Settings/Admin/Presets.php
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
namespace OCA\Settings\Settings\Admin;
|
||||
|
||||
use OC\Config\PresetManager;
|
||||
use OCP\AppFramework\Http\TemplateResponse;
|
||||
use OCP\AppFramework\Services\IInitialState;
|
||||
use OCP\IConfig;
|
||||
use OCP\IL10N;
|
||||
use OCP\ServerVersion;
|
||||
use OCP\Settings\ISettings;
|
||||
|
||||
class Presets implements ISettings {
|
||||
public function __construct(
|
||||
private ServerVersion $serverVersion,
|
||||
private IConfig $config,
|
||||
private IL10N $l,
|
||||
private readonly PresetManager $presetManager,
|
||||
private IInitialState $initialState,
|
||||
) {
|
||||
}
|
||||
|
||||
public function getForm() {
|
||||
$presets = $this->presetManager->retrieveLexiconPreset();
|
||||
$selectedPreset = $this->presetManager->getLexiconPreset();
|
||||
$presetsApps = $this->presetManager->retrieveLexiconPresetApps();
|
||||
|
||||
$this->initialState->provideInitialState('settings-selected-preset', $selectedPreset->name);
|
||||
$this->initialState->provideInitialState('settings-presets', $presets);
|
||||
$this->initialState->provideInitialState('settings-presets-apps', $presetsApps);
|
||||
|
||||
return new TemplateResponse('settings', 'settings/admin/presets', [], '');
|
||||
}
|
||||
|
||||
public function getSection() {
|
||||
return 'presets';
|
||||
}
|
||||
|
||||
public function getPriority() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public function getName(): ?string {
|
||||
return $this->l->t('Settings presets');
|
||||
}
|
||||
|
||||
public function getAuthorizedAppConfig(): array {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,160 @@
|
|||
<!--
|
||||
- SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
|
||||
- SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
-->
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue'
|
||||
|
||||
import { t } from '@nextcloud/l10n'
|
||||
import { loadState } from '@nextcloud/initial-state'
|
||||
import NcCheckboxRadioSwitch from '@nextcloud/vue/components/NcCheckboxRadioSwitch'
|
||||
|
||||
import type { PresetAppConfig, PresetAppConfigs, PresetAppsStates, PresetIds } from './models.ts'
|
||||
|
||||
const applicationsStates = loadState('settings', 'settings-presets-apps', {}) as PresetAppsStates
|
||||
|
||||
const props = defineProps({
|
||||
presets: {
|
||||
type: Object as () => PresetAppConfigs,
|
||||
required: true,
|
||||
},
|
||||
selectedPreset: {
|
||||
type: String as () => PresetIds,
|
||||
default: 'NONE',
|
||||
},
|
||||
})
|
||||
|
||||
const appsConfigPresets = Object.entries(props.presets)
|
||||
.map(([appId, presets]) => [appId, presets.filter(configPreset => configPreset.config === 'app')])
|
||||
.filter(([, presets]) => presets.length > 0) as [string, PresetAppConfig[]][]
|
||||
const userConfigPresets = Object.entries(props.presets)
|
||||
.map(([appId, presets]) => [appId, presets.filter(configPreset => configPreset.config === 'user')])
|
||||
.filter(([, presets]) => presets.length > 0) as [string, PresetAppConfig[]][]
|
||||
|
||||
const hasApplicationsPreset = computed(() => applicationsStates[props.selectedPreset].enabled.length > 0 || applicationsStates[props.selectedPreset].disabled.length > 0)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="presets">
|
||||
<h3 class="presets__title">
|
||||
{{ t('settings', 'Default config values') }}
|
||||
</h3>
|
||||
|
||||
<div v-if="appsConfigPresets.length > 0" class="presets__config-list">
|
||||
<h4 class="presets__config-list__subtitle">
|
||||
{{ t('settings', 'Applications config') }}
|
||||
</h4>
|
||||
<template v-for="[appId, appConfigPresets] in appsConfigPresets">
|
||||
<div v-for="configPreset in appConfigPresets"
|
||||
:key="appId + '-' + configPreset.entry.key"
|
||||
class="presets__config-list__item">
|
||||
<span>
|
||||
<div>{{ configPreset.entry.definition }}</div>
|
||||
<code class="presets__config-list__item__key">{{ configPreset.entry.key }}</code>
|
||||
</span>
|
||||
<span>
|
||||
<NcCheckboxRadioSwitch v-if="configPreset.entry.type === 'BOOL'"
|
||||
:model-value="configPreset.defaults[selectedPreset] === '1'"
|
||||
:disabled="true" />
|
||||
<code v-else>{{ configPreset.defaults[selectedPreset] }}</code>
|
||||
</span>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
|
||||
<div v-if="userConfigPresets.length > 0" class="presets__config-list">
|
||||
<h4 class="presets__config-list__subtitle">
|
||||
{{ t('settings', 'User config') }}
|
||||
</h4>
|
||||
<template v-for="[appId, userPresets] in userConfigPresets">
|
||||
<div v-for="configPreset in userPresets"
|
||||
:key="appId + '-' + configPreset.entry.key"
|
||||
class="presets__config-list__item">
|
||||
<span>
|
||||
<div>{{ configPreset.entry.definition }}</div>
|
||||
<code class="presets__config-list__item__key">{{ configPreset.entry.key }}</code>
|
||||
</span>
|
||||
<span>
|
||||
<NcCheckboxRadioSwitch v-if="configPreset.entry.type === 'BOOL'"
|
||||
:model-value="configPreset.defaults[selectedPreset] === '1'"
|
||||
:disabled="true" />
|
||||
<code v-else>{{ configPreset.defaults[selectedPreset] }}</code>
|
||||
</span>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
|
||||
<template v-if="hasApplicationsPreset">
|
||||
<h3 class="presets__title">
|
||||
{{ t('settings', 'Bundled applications') }}
|
||||
</h3>
|
||||
|
||||
<div class="presets__app-list">
|
||||
<div class="presets__app-list__enabled">
|
||||
<h4 class="presets__app-list__title">
|
||||
{{ t('settings', 'Enabled applications') }}
|
||||
</h4>
|
||||
<ul>
|
||||
<li v-for="applicationId in applicationsStates[selectedPreset].enabled"
|
||||
:key="applicationId">
|
||||
{{ applicationId }}
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="presets__app-list__disabled">
|
||||
<h4 class="presets__app-list__title">
|
||||
{{ t('settings', 'Disabled applications') }}
|
||||
</h4>
|
||||
<ul>
|
||||
<li v-for="applicationId in applicationsStates[selectedPreset].disabled"
|
||||
:key="applicationId">
|
||||
{{ applicationId }}
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.presets {
|
||||
margin-top: 16px;
|
||||
|
||||
&__title {
|
||||
font-size: 16px;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
&__config-list {
|
||||
margin-top: 8px;
|
||||
width: 55%;
|
||||
|
||||
&__subtitle {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
&__item {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 2px 0;
|
||||
|
||||
&__key {
|
||||
font-size: 12px;
|
||||
color: var(--color-text-maxcontrast);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&__app-list {
|
||||
display: flex;
|
||||
gap: 32px;
|
||||
|
||||
&__title {
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,118 @@
|
|||
<!--
|
||||
- SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
|
||||
- SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
-->
|
||||
|
||||
<script setup lang="ts">
|
||||
import Domain from 'vue-material-design-icons/Domain.vue'
|
||||
import CloudCircleOutline from 'vue-material-design-icons/CloudCircleOutline.vue'
|
||||
import SchoolOutline from 'vue-material-design-icons/SchoolOutline.vue'
|
||||
import Crowd from 'vue-material-design-icons/Crowd.vue'
|
||||
import AccountGroupOutline from 'vue-material-design-icons/AccountGroupOutline.vue'
|
||||
import AccountOutline from 'vue-material-design-icons/AccountOutline.vue'
|
||||
import MinusCircleOutline from 'vue-material-design-icons/MinusCircleOutline.vue'
|
||||
|
||||
import { t } from '@nextcloud/l10n'
|
||||
import NcCheckboxRadioSwitch from '@nextcloud/vue/components/NcCheckboxRadioSwitch'
|
||||
|
||||
import { type PresetAppConfigs, type PresetIds } from './models.ts'
|
||||
|
||||
const PresetNames = {
|
||||
LARGE: t('settings', 'Large organization'),
|
||||
MEDIUM: t('settings', 'Big organization'),
|
||||
SMALL: t('settings', 'Small organization'),
|
||||
SHARED: t('settings', 'Hosting company'),
|
||||
UNIVERSITY: t('settings', 'University'),
|
||||
SCHOOL: t('settings', 'School'),
|
||||
CLUB: t('settings', 'Club or association'),
|
||||
FAMILY: t('settings', 'Family'),
|
||||
PRIVATE: t('settings', 'Personal use'),
|
||||
NONE: t('settings', 'Default'),
|
||||
}
|
||||
|
||||
const PresetsIcons = {
|
||||
LARGE: Domain,
|
||||
MEDIUM: Domain,
|
||||
SMALL: Domain,
|
||||
SHARED: CloudCircleOutline,
|
||||
UNIVERSITY: SchoolOutline,
|
||||
SCHOOL: SchoolOutline,
|
||||
CLUB: AccountGroupOutline,
|
||||
FAMILY: Crowd,
|
||||
PRIVATE: AccountOutline,
|
||||
NONE: MinusCircleOutline,
|
||||
}
|
||||
|
||||
defineProps({
|
||||
presets: {
|
||||
type: Object as () => PresetAppConfigs,
|
||||
required: true,
|
||||
},
|
||||
value: {
|
||||
type: String as () => PresetIds,
|
||||
default: '',
|
||||
},
|
||||
})
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'input', option: string): void
|
||||
}>()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<form class="presets-form">
|
||||
<label v-for="(presetName, presetId) in PresetNames"
|
||||
:key="presetId"
|
||||
class="presets-form__option">
|
||||
|
||||
<components :is="PresetsIcons[presetId]" :size="32" />
|
||||
|
||||
<NcCheckboxRadioSwitch type="radio"
|
||||
:model-value="value"
|
||||
:value="presetId"
|
||||
name="preset"
|
||||
@update:modelValue="emit('input', presetId)" />
|
||||
|
||||
<span class="presets-form__option__name">{{ presetName }}</span>
|
||||
</label>
|
||||
</form>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.presets-form {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 24px;
|
||||
margin-top: 32px;
|
||||
|
||||
&__option {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-between;
|
||||
width: 250px;
|
||||
min-height: 100px;
|
||||
padding: 16px;
|
||||
border-radius: var(--border-radius-large);
|
||||
background-color: var(--color-background-dark);
|
||||
font-size: 20px;
|
||||
|
||||
&:hover {
|
||||
background-color: var(--color-background-darker);
|
||||
}
|
||||
|
||||
&:has(input[type=radio]:checked) {
|
||||
border: 2px solid var(--color-main-text);
|
||||
padding: 14px;
|
||||
}
|
||||
|
||||
&__name {
|
||||
flex-basis: 250px;
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
&__name, .material-design-icon {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
31
apps/settings/src/components/SettingsPresets/models.ts
Normal file
31
apps/settings/src/components/SettingsPresets/models.ts
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
/**
|
||||
* SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
type PresetAppConfigEntry = {
|
||||
key: string
|
||||
type: 'ARRAY' | 'BOOL' | 'FLOAT' | 'INT' | 'MIXED' | 'STRING'
|
||||
definition: string
|
||||
note: string
|
||||
lazy: boolean
|
||||
deprecated: boolean
|
||||
}
|
||||
|
||||
export type PresetIds = 'LARGE' | 'MEDIUM' | 'SMALL' | 'SHARED' | 'UNIVERSITY' | 'SCHOOL' | 'CLUB' | 'FAMILY' | 'PRIVATE' | 'NONE'
|
||||
|
||||
export type PresetAppConfig = {
|
||||
config: 'app' | 'user'
|
||||
entry: PresetAppConfigEntry
|
||||
defaults: Record<PresetIds, string>
|
||||
value?: unknown
|
||||
}
|
||||
|
||||
export type PresetAppConfigs = Record<string, PresetAppConfig[]>
|
||||
|
||||
type PresetAppsState = {
|
||||
enabled: string[]
|
||||
disabled: string[]
|
||||
}
|
||||
|
||||
export type PresetAppsStates = Record<PresetIds, PresetAppsState>
|
||||
19
apps/settings/src/main-admin-settings-presets.ts
Normal file
19
apps/settings/src/main-admin-settings-presets.ts
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
/**
|
||||
* SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
import Vue from 'vue'
|
||||
|
||||
import SettingsPresets from './views/SettingsPresets.vue'
|
||||
import { getCSPNonce } from '@nextcloud/auth'
|
||||
|
||||
// CSP config for webpack dynamic chunk loading
|
||||
// eslint-disable-next-line camelcase
|
||||
__webpack_nonce__ = getCSPNonce()
|
||||
|
||||
export default new Vue({
|
||||
render: h => h(SettingsPresets),
|
||||
el: '#settings-presets',
|
||||
name: 'SettingsPresets',
|
||||
})
|
||||
68
apps/settings/src/views/SettingsPresets.vue
Normal file
68
apps/settings/src/views/SettingsPresets.vue
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
<!--
|
||||
- SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
|
||||
- SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
-->
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue'
|
||||
import { t } from '@nextcloud/l10n'
|
||||
import { generateUrl } from '@nextcloud/router'
|
||||
import axios from '@nextcloud/axios'
|
||||
import NcSettingsSection from '@nextcloud/vue/components/NcSettingsSection'
|
||||
import NcButton from '@nextcloud/vue/components/NcButton'
|
||||
import NcLoadingIcon from '@nextcloud/vue/components/NcLoadingIcon'
|
||||
import { loadState } from '@nextcloud/initial-state'
|
||||
import { showError } from '@nextcloud/dialogs'
|
||||
|
||||
import PresetsSelectionForm from '../components/SettingsPresets/PresetsSelectionForm.vue'
|
||||
import PresetVisualisation from '../components/SettingsPresets/PresetVisualisation.vue'
|
||||
import type { PresetAppConfigs, PresetIds } from '../components/SettingsPresets/models'
|
||||
import logger from '../logger'
|
||||
|
||||
const presets = loadState('settings', 'settings-presets', {}) as PresetAppConfigs
|
||||
const currentPreset = ref(loadState('settings', 'settings-selected-preset', 'NONE') as PresetIds)
|
||||
const selectedPreset = ref(currentPreset.value)
|
||||
const savingPreset = ref(false)
|
||||
|
||||
async function saveSelectedPreset() {
|
||||
try {
|
||||
savingPreset.value = true
|
||||
await axios.post(generateUrl('/settings/preset/current'), {
|
||||
presetName: selectedPreset.value,
|
||||
})
|
||||
currentPreset.value = selectedPreset.value
|
||||
} catch (error) {
|
||||
showError(t('settings', 'Failed to save selected preset.'))
|
||||
logger.error('Error saving selected preset:', { error })
|
||||
selectedPreset.value = currentPreset.value
|
||||
} finally {
|
||||
savingPreset.value = false
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<NcSettingsSection :name="t('settings', 'Settings presets')"
|
||||
:description="t('settings', 'Select a configuration preset for easy setup.')">
|
||||
<PresetsSelectionForm v-model="selectedPreset" :presets="presets" />
|
||||
|
||||
<PresetVisualisation :presets="presets" :selected-preset="selectedPreset" />
|
||||
|
||||
<NcButton class="save-button"
|
||||
variant="primary"
|
||||
:disabled="selectedPreset === currentPreset || savingPreset"
|
||||
@click="saveSelectedPreset()">
|
||||
{{ t('settings', 'Apply') }}
|
||||
|
||||
<template v-if="savingPreset" #icon>
|
||||
<NcLoadingIcon />
|
||||
</template>
|
||||
</NcButton>
|
||||
</NcSettingsSection>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.save-button {
|
||||
margin-top: 16px;
|
||||
}
|
||||
</style>
|
||||
12
apps/settings/templates/settings/admin/presets.php
Normal file
12
apps/settings/templates/settings/admin/presets.php
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
<?php
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
\OCP\Util::addScript('settings', 'vue-settings-admin-settings-presets');
|
||||
|
||||
?>
|
||||
|
||||
<div id="settings-presets">
|
||||
</div>
|
||||
|
|
@ -53,7 +53,7 @@ class ConfigLexicon implements ILexicon {
|
|||
Preset::FAMILY, Preset::PRIVATE => true,
|
||||
default => false,
|
||||
},
|
||||
definition: 'Allow users to set custom share link tokens',
|
||||
definition: 'Allow users to customize share URL',
|
||||
lazy: true,
|
||||
note: 'Shares with guessable tokens may be accessed easily. Shares with custom tokens will continue to be accessible after this setting has been disabled.',
|
||||
),
|
||||
|
|
@ -65,7 +65,7 @@ class ConfigLexicon implements ILexicon {
|
|||
Preset::SCHOOL, Preset::UNIVERSITY, Preset::SHARED, Preset::SMALL, Preset::MEDIUM, Preset::LARGE => true,
|
||||
default => false,
|
||||
},
|
||||
definition: 'Enforce password protection when sharing document'
|
||||
definition: 'Enforce password protection for shared documents'
|
||||
),
|
||||
new Entry(
|
||||
key: self::SHARE_LINK_EXPIRE_DATE_DEFAULT,
|
||||
|
|
@ -74,7 +74,7 @@ class ConfigLexicon implements ILexicon {
|
|||
Preset::SHARED, Preset::SMALL, Preset::MEDIUM, Preset::LARGE => true,
|
||||
default => false,
|
||||
},
|
||||
definition: 'Set default expiration date for shares via link or mail'
|
||||
definition: 'Default expiration date for shares via link or mail'
|
||||
),
|
||||
new Entry(
|
||||
key: self::SHARE_LINK_EXPIRE_DATE_ENFORCED,
|
||||
|
|
|
|||
|
|
@ -87,6 +87,7 @@ module.exports = {
|
|||
'vue-settings-admin-ai': path.join(__dirname, 'apps/settings/src', 'main-admin-ai.js'),
|
||||
'vue-settings-admin-delegation': path.join(__dirname, 'apps/settings/src', 'main-admin-delegation.js'),
|
||||
'vue-settings-admin-security': path.join(__dirname, 'apps/settings/src', 'main-admin-security.js'),
|
||||
'vue-settings-admin-settings-presets': path.join(__dirname, 'apps/settings/src', 'main-admin-settings-presets.js'),
|
||||
'vue-settings-admin-sharing': path.join(__dirname, 'apps/settings/src', 'admin-settings-sharing.ts'),
|
||||
'vue-settings-apps-users-management': path.join(__dirname, 'apps/settings/src', 'main-apps-users-management.ts'),
|
||||
'vue-settings-nextcloud-pdf': path.join(__dirname, 'apps/settings/src', 'main-nextcloud-pdf.js'),
|
||||
|
|
|
|||
Loading…
Reference in a new issue