fix(settings): use proper component structure to make navigation work

`NcAppNavigation` is only allowed in `NcContent` but we were not using
it because the content was rendered by the server as templates.
This is now fixed by moving the content inside the `NcContent` once
mounted.

Signed-off-by: Ferdinand Thiessen <opensource@fthiessen.de>
This commit is contained in:
Ferdinand Thiessen 2026-05-08 13:28:17 +02:00
parent f16c6c95c4
commit 60f4b4c159
No known key found for this signature in database
GPG key ID: 7E849AE05218500F
7 changed files with 58 additions and 27 deletions

View file

@ -5,9 +5,9 @@
import { getCSPNonce } from '@nextcloud/auth'
import Vue from 'vue'
import SettingsNavigation from './views/SettingsNavigation.vue'
import SettingsApp from './views/SettingsApp.vue'
__webpack_nonce__ = getCSPNonce()
const app = new Vue(SettingsNavigation)
app.$mount('#app-navigation')
const app = new Vue(SettingsApp)
app.$mount('#settings-app')

View file

@ -12,7 +12,7 @@ import VTooltipPlugin from 'v-tooltip'
import Vue from 'vue'
import Vuex from 'vuex'
import { sync } from 'vuex-router-sync'
import SettingsApp from './views/SettingsApp.vue'
import UserManagement from './views/UserManagement.vue'
import router from './router/index.ts'
import { useStore } from './store/index.js'
@ -37,10 +37,10 @@ const pinia = createPinia()
// Migrate legacy local storage settings to the database
store.dispatch('migrateLocalStorage')
export default new Vue({
const App = Vue.extend(UserManagement)
const app = new App({
router,
store,
pinia,
render: (h) => h(SettingsApp),
el: '#content',
})
app.$mount('#content')

View file

@ -1,21 +1,14 @@
/**
/*
* SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
import type { RouteConfig } from 'vue-router'
const UserManagement = () => import(/* webpackChunkName: 'settings-users' */'../views/UserManagement.vue')
const UserManagementNavigation = () => import(/* webpackChunkName: 'settings-users' */'../views/UserManagementNavigation.vue')
const routes: RouteConfig[] = [
{
name: 'users',
path: '/:index(index.php/)?settings/users',
components: {
default: UserManagement,
navigation: UserManagementNavigation,
},
props: true,
children: [
{

View file

@ -4,13 +4,22 @@
-->
<template>
<NcContent app-name="settings">
<router-view name="navigation" />
<router-view />
<router-view name="sidebar" />
<NcContent :class="$style.settingsApp" appName="settings">
<SettingsNavigation />
<SettingsContentWrapper />
</NcContent>
</template>
<script setup lang="ts">
import NcContent from '@nextcloud/vue/components/NcContent'
import SettingsContentWrapper from './SettingsContentWrapper.vue'
import SettingsNavigation from './SettingsNavigation.vue'
</script>
<style module>
:global(#content):has(.settingsApp) {
margin: 0;
width: 100%;
height: 100%;
}
</style>

View file

@ -0,0 +1,22 @@
<!--
- SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors
- SPDX-License-Identifier: AGPL-3.0-or-later
-->
<template>
<NcAppContent>
<div ref="contentMain" />
</NcAppContent>
</template>
<script setup lang="ts">
import { NcAppContent } from '@nextcloud/vue'
import { onMounted, ref } from 'vue'
const contentMain = ref<HTMLDivElement>()
onMounted(() => {
const realElement = document.getElementById('original-settings-content')!
contentMain.value!.replaceChildren(...realElement.childNodes)
realElement.parentNode!.removeChild(realElement)
})
</script>

View file

@ -4,11 +4,14 @@
-->
<template>
<NcAppContent :page-heading="pageHeading">
<UserList
:selected-group="selectedGroupDecoded"
:external-actions="externalActions" />
</NcAppContent>
<NcContent app-name="settings">
<UserManagementNavigation />
<NcAppContent :page-heading="pageHeading">
<UserList
:selected-group="selectedGroupDecoded"
:external-actions="externalActions" />
</NcAppContent>
</NcContent>
</template>
<script>
@ -16,14 +19,18 @@ import { emit } from '@nextcloud/event-bus'
import { translate as t } from '@nextcloud/l10n'
import { defineComponent } from 'vue'
import NcAppContent from '@nextcloud/vue/components/NcAppContent'
import NcContent from '@nextcloud/vue/components/NcContent'
import UserList from '../components/UserList.vue'
import UserManagementNavigation from './UserManagementNavigation.vue'
export default defineComponent({
name: 'UserManagement',
components: {
NcContent,
NcAppContent,
UserList,
UserManagementNavigation,
},
data() {

View file

@ -7,7 +7,7 @@
style('settings', 'settings');
?>
<div id="app-navigation"></div>
<main id="app-content" <?php if (!empty($_['activeSectionId'])) { ?> data-active-section-id="<?php print_unescaped($_['activeSectionId']) ?>" <?php } if (!empty($_['activeSectionType'])) { ?> data-active-section-type="<?php print_unescaped($_['activeSectionType']) ?>" <?php } ?>>
<div id="settings-app"></div>
<div class="hidden-visually" id="original-settings-content" <?php if (!empty($_['activeSectionId'])) { ?> data-active-section-id="<?php print_unescaped($_['activeSectionId']) ?>" <?php } if (!empty($_['activeSectionType'])) { ?> data-active-section-type="<?php print_unescaped($_['activeSectionType']) ?>" <?php } ?>>
<?php print_unescaped($_['content']); ?>
</main>
</div>