diff options
author | Ferdinand Thiessen <opensource@fthiessen.de> | 2024-02-22 16:45:42 +0100 |
---|---|---|
committer | Ferdinand Thiessen <opensource@fthiessen.de> | 2024-03-11 16:02:34 +0100 |
commit | 1100e908b79ddecd1198c682ac3dcc41f2871122 (patch) | |
tree | 3f7e61648adcccaec1a5b6c7f67ab1c3b6c59b65 /apps | |
parent | 2b794b41ad0eb9610674fc44543006a9da9d624e (diff) | |
download | nextcloud-server-1100e908b79ddecd1198c682ac3dcc41f2871122.tar.gz nextcloud-server-1100e908b79ddecd1198c682ac3dcc41f2871122.zip |
feat(settings): Split account management and app store views into chunks
Signed-off-by: Ferdinand Thiessen <opensource@fthiessen.de>
Diffstat (limited to 'apps')
-rw-r--r-- | apps/settings/src/app-types.ts | 70 | ||||
-rw-r--r-- | apps/settings/src/components/AppList.vue | 32 | ||||
-rw-r--r-- | apps/settings/src/store/apps.js | 1 | ||||
-rw-r--r-- | apps/settings/src/views/AppStore.vue | 73 | ||||
-rw-r--r-- | apps/settings/src/views/UserManagement.vue (renamed from apps/settings/src/views/Users.vue) | 210 | ||||
-rw-r--r-- | apps/settings/src/views/UserManagementNavigation.vue | 5 |
6 files changed, 258 insertions, 133 deletions
diff --git a/apps/settings/src/app-types.ts b/apps/settings/src/app-types.ts new file mode 100644 index 00000000000..99f0c1ef679 --- /dev/null +++ b/apps/settings/src/app-types.ts @@ -0,0 +1,70 @@ +/** + * @copyright Copyright (c) 2024 Ferdinand Thiessen <opensource@fthiessen.de> + * + * @author Ferdinand Thiessen <opensource@fthiessen.de> + * + * @license AGPL-3.0-or-later + * + * 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/>. + */ + +export interface IAppstoreCategory { + /** + * The category ID + */ + id: string + /** + * The display name (can be localized) + */ + displayName: string + /** + * Inline SVG path + */ + icon: string +} + +export interface IAppstoreAppRelease { + version: string + translations: { + [key: string]: { + changelog: string + } + } +} + +export interface IAppstoreApp { + id: string + name: string + summary: string + description: string + licence: string + author: string[] | Record<string, string> + level: number + version: string + category: string|string[] + + preview?: string + screenshot?: string + + active: boolean + internal: boolean + removeable: boolean + installed: boolean + canInstall: boolean + canUninstall: boolean + isCompatible: boolean + + appstoreData: Record<string, never> + releases: IAppstoreAppRelease[] +} diff --git a/apps/settings/src/components/AppList.vue b/apps/settings/src/components/AppList.vue index 324fa6b0537..320d6a60e95 100644 --- a/apps/settings/src/components/AppList.vue +++ b/apps/settings/src/components/AppList.vue @@ -139,6 +139,7 @@ </template> <script> +import { subscribe, unsubscribe } from '@nextcloud/event-bus' import AppItem from './AppList/AppItem.vue' import pLimit from 'p-limit' import NcButton from '@nextcloud/vue/dist/Components/NcButton.js' @@ -149,7 +150,19 @@ export default { AppItem, NcButton, }, - props: ['category'], + + props: { + category: { + type: String, + required: true, + }, + }, + + data() { + return { + search: '', + } + }, computed: { counter() { return this.apps.filter(app => app.update).length @@ -247,7 +260,24 @@ export default { } }, }, + + beforeDestroy() { + unsubscribe('nextcloud:unified-search.search', this.setSearch) + unsubscribe('nextcloud:unified-search.reset', this.resetSearch) + }, + + beforeCreate() { + subscribe('nextcloud:unified-search.search', this.setSearch) + subscribe('nextcloud:unified-search.reset', this.resetSearch) + }, + methods: { + setSearch(value) { + this.search = value + }, + resetSearch() { + this.search = '' + }, toggleBundle(id) { if (this.allBundlesEnabled(id)) { return this.disableBundle(id) diff --git a/apps/settings/src/store/apps.js b/apps/settings/src/store/apps.js index b6cf640fcb9..b8528f58412 100644 --- a/apps/settings/src/store/apps.js +++ b/apps/settings/src/store/apps.js @@ -34,7 +34,6 @@ const state = { categories: [], updateCount: loadState('settings', 'appstoreUpdateCount', 0), loading: {}, - loadingList: false, gettingCategoriesPromise: null, } diff --git a/apps/settings/src/views/AppStore.vue b/apps/settings/src/views/AppStore.vue index 06c47611238..3c3c53d4330 100644 --- a/apps/settings/src/views/AppStore.vue +++ b/apps/settings/src/views/AppStore.vue @@ -1,42 +1,51 @@ <!-- - - @copyright Copyright (c) 2018 Julius Härtl <jus@bitgrid.net> - - - - @author Julius Härtl <jus@bitgrid.net> - - @author Ferdinand Thiessen <opensource@fthiessen.de> - - - - @license AGPL-3.0-or-later - - - - 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/>. - - - --> + - @copyright Copyright (c) 2018 Julius Härtl <jus@bitgrid.net> + - + - @author Julius Härtl <jus@bitgrid.net> + - @author Ferdinand Thiessen <opensource@fthiessen.de> + - + - @license AGPL-3.0-or-later + - + - 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/>. + - + --> <template> <!-- Apps list --> <NcAppContent class="app-settings-content" :page-heading="pageHeading"> - <AppList :category="currentCategory" /> + <NcEmptyContent v-if="isLoading" + class="empty-content__loading" + :name="t('settings', 'Loading app list')"> + <template #icon> + <NcLoadingIcon :size="64" /> + </template> + </NcEmptyContent> + <AppList v-else :category="currentCategory" /> </NcAppContent> </template> <script setup lang="ts"> import { translate as t } from '@nextcloud/l10n' -import { computed, watch } from 'vue' +import { computed, getCurrentInstance, onBeforeMount, watch } from 'vue' import { useRoute } from 'vue-router/composables' import { APPS_SECTION_ENUM } from '../constants/AppsConstants.js' import { useAppsStore } from '../store/apps-store' import NcAppContent from '@nextcloud/vue/dist/Components/NcAppContent.js' +import NcEmptyContent from '@nextcloud/vue/dist/Components/NcEmptyContent.js' +import NcLoadingIcon from '@nextcloud/vue/dist/Components/NcLoadingIcon.js' import AppList from '../components/AppList.vue' const route = useRoute() @@ -60,4 +69,22 @@ const pageHeading = computed(() => { watch([pageHeading], () => { window.document.title = `${pageHeading.value} - Apps - Nextcloud` }) + +// TODO this part should be migrated to pinia +const instance = getCurrentInstance() +/** Is the app list loading */ +// eslint-disable-next-line @typescript-eslint/no-explicit-any +const isLoading = computed(() => (instance?.proxy as any).$store.getters.loading('list')) +onBeforeMount(() => { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + (instance?.proxy as any).$store.dispatch('getCategories', { shouldRefetchCategories: true }); + // eslint-disable-next-line @typescript-eslint/no-explicit-any + (instance?.proxy as any).$store.dispatch('getAllApps') +}) </script> + +<style scoped> +.empty-content__loading { + height: 100%; +} +</style> diff --git a/apps/settings/src/views/Users.vue b/apps/settings/src/views/UserManagement.vue index d44fa7c8416..d25071e63ed 100644 --- a/apps/settings/src/views/Users.vue +++ b/apps/settings/src/views/UserManagement.vue @@ -22,119 +22,117 @@ <template> <Fragment> - <NcContent app-name="settings"> - <NcAppNavigation :aria-label="t('settings', 'Account management')"> - <NcAppNavigationNew button-id="new-user-button" - :text="t('settings','New account')" - @click="showNewUserMenu" - @keyup.enter="showNewUserMenu" - @keyup.space="showNewUserMenu"> + <NcAppNavigation :aria-label="t('settings', 'Account management')"> + <NcAppNavigationNew button-id="new-user-button" + :text="t('settings','New account')" + @click="showNewUserMenu" + @keyup.enter="showNewUserMenu" + @keyup.space="showNewUserMenu"> + <template #icon> + <Plus :size="20" /> + </template> + </NcAppNavigationNew> + + <NcAppNavigationList data-cy-users-settings-navigation-groups="system"> + <NcAppNavigationItem id="everyone" + :exact="true" + :name="t('settings', 'Active accounts')" + :to="{ name: 'users' }"> <template #icon> - <Plus :size="20" /> + <AccountGroup :size="20" /> + </template> + <template #counter> + <NcCounterBubble v-if="userCount" :type="!selectedGroupDecoded ? 'highlighted' : undefined"> + {{ userCount }} + </NcCounterBubble> </template> - </NcAppNavigationNew> + </NcAppNavigationItem> - <NcAppNavigationList data-cy-users-settings-navigation-groups="system"> - <NcAppNavigationItem id="everyone" - :exact="true" - :name="t('settings', 'Active accounts')" - :to="{ name: 'users' }"> + <NcAppNavigationItem v-if="settings.isAdmin" + id="admin" + :exact="true" + :name="t('settings', 'Admins')" + :to="{ name: 'group', params: { selectedGroup: 'admin' } }"> + <template #icon> + <ShieldAccount :size="20" /> + </template> + <template v-if="adminGroupMenu.count > 0" #counter> + <NcCounterBubble :type="selectedGroupDecoded === 'admin' ? 'highlighted' : undefined"> + {{ adminGroupMenu.count }} + </NcCounterBubble> + </template> + </NcAppNavigationItem> + + <!-- Hide the disabled if none, if we don't have the data (-1) show it --> + <NcAppNavigationItem v-if="disabledGroupMenu.usercount > 0 || disabledGroupMenu.usercount === -1" + id="disabled" + :exact="true" + :name="t('settings', 'Disabled users')" + :to="{ name: 'group', params: { selectedGroup: 'disabled' } }"> + <template #icon> + <AccountOff :size="20" /> + </template> + <template v-if="disabledGroupMenu.usercount > 0" #counter> + <NcCounterBubble :type="selectedGroupDecoded === 'disabled' ? 'highlighted' : undefined"> + {{ disabledGroupMenu.usercount }} + </NcCounterBubble> + </template> + </NcAppNavigationItem> + </NcAppNavigationList> + + <NcAppNavigationCaption :name="t('settings', 'Groups')" + :disabled="loadingAddGroup" + :aria-label="loadingAddGroup ? t('settings', 'Creating group …') : t('settings', 'Create group')" + force-menu + is-heading + :open.sync="isAddGroupOpen"> + <template #actionsTriggerIcon> + <NcLoadingIcon v-if="loadingAddGroup" /> + <Plus v-else :size="20" /> + </template> + <template #actions> + <NcActionText> <template #icon> <AccountGroup :size="20" /> </template> - <template #counter> - <NcCounterBubble v-if="userCount" :type="!selectedGroupDecoded ? 'highlighted' : undefined"> - {{ userCount }} - </NcCounterBubble> - </template> - </NcAppNavigationItem> - - <NcAppNavigationItem v-if="settings.isAdmin" - id="admin" - :exact="true" - :name="t('settings', 'Admins')" - :to="{ name: 'group', params: { selectedGroup: 'admin' } }"> - <template #icon> - <ShieldAccount :size="20" /> - </template> - <template v-if="adminGroupMenu.count > 0" #counter> - <NcCounterBubble :type="selectedGroupDecoded === 'admin' ? 'highlighted' : undefined"> - {{ adminGroupMenu.count }} - </NcCounterBubble> - </template> - </NcAppNavigationItem> - - <!-- Hide the disabled if none, if we don't have the data (-1) show it --> - <NcAppNavigationItem v-if="disabledGroupMenu.usercount > 0 || disabledGroupMenu.usercount === -1" - id="disabled" - :exact="true" - :name="t('settings', 'Disabled users')" - :to="{ name: 'group', params: { selectedGroup: 'disabled' } }"> + {{ t('settings', 'Create group') }} + </NcActionText> + <NcActionInput :label="t('settings', 'Group name')" + data-cy-users-settings-new-group-name + :label-outside="false" + :disabled="loadingAddGroup" + :value.sync="newGroupName" + :error="hasAddGroupError" + :helper-text="hasAddGroupError ? t('settings', 'Please enter a valid group name') : ''" + @submit="createGroup" /> + </template> + </NcAppNavigationCaption> + + <NcAppNavigationList data-cy-users-settings-navigation-groups="custom"> + <GroupListItem v-for="group in groupList" + :id="group.id" + :key="group.id" + :active="selectedGroupDecoded === group.id" + :name="group.title" + :count="group.count" /> + </NcAppNavigationList> + + <template #footer> + <ul class="app-navigation-entry__settings"> + <NcAppNavigationItem :name="t('settings', 'Account management settings')" + @click="isDialogOpen = true"> <template #icon> - <AccountOff :size="20" /> - </template> - <template v-if="disabledGroupMenu.usercount > 0" #counter> - <NcCounterBubble :type="selectedGroupDecoded === 'disabled' ? 'highlighted' : undefined"> - {{ disabledGroupMenu.usercount }} - </NcCounterBubble> + <Cog :size="20" /> </template> </NcAppNavigationItem> - </NcAppNavigationList> - - <NcAppNavigationCaption :name="t('settings', 'Groups')" - :disabled="loadingAddGroup" - :aria-label="loadingAddGroup ? t('settings', 'Creating group …') : t('settings', 'Create group')" - force-menu - is-heading - :open.sync="isAddGroupOpen"> - <template #actionsTriggerIcon> - <NcLoadingIcon v-if="loadingAddGroup" /> - <Plus v-else :size="20" /> - </template> - <template #actions> - <NcActionText> - <template #icon> - <AccountGroup :size="20" /> - </template> - {{ t('settings', 'Create group') }} - </NcActionText> - <NcActionInput :label="t('settings', 'Group name')" - data-cy-users-settings-new-group-name - :label-outside="false" - :disabled="loadingAddGroup" - :value.sync="newGroupName" - :error="hasAddGroupError" - :helper-text="hasAddGroupError ? t('settings', 'Please enter a valid group name') : ''" - @submit="createGroup" /> - </template> - </NcAppNavigationCaption> - - <NcAppNavigationList data-cy-users-settings-navigation-groups="custom"> - <GroupListItem v-for="group in groupList" - :id="group.id" - :key="group.id" - :active="selectedGroupDecoded === group.id" - :name="group.title" - :count="group.count" /> - </NcAppNavigationList> - - <template #footer> - <ul class="app-navigation-entry__settings"> - <NcAppNavigationItem :name="t('settings', 'Account management settings')" - @click="isDialogOpen = true"> - <template #icon> - <Cog :size="20" /> - </template> - </NcAppNavigationItem> - </ul> - </template> - </NcAppNavigation> + </ul> + </template> + </NcAppNavigation> - <NcAppContent :page-heading="pageHeading"> - <UserList :selected-group="selectedGroupDecoded" - :external-actions="externalActions" /> - </NcAppContent> - </NcContent> + <NcAppContent :page-heading="pageHeading"> + <UserList :selected-group="selectedGroupDecoded" + :external-actions="externalActions" /> + </NcAppContent> <UserSettingsDialog :open.sync="isDialogOpen" /> </Fragment> @@ -155,7 +153,6 @@ import NcAppNavigationCaption from '@nextcloud/vue/dist/Components/NcAppNavigati import NcAppNavigationItem from '@nextcloud/vue/dist/Components/NcAppNavigationItem.js' import NcAppNavigationList from '@nextcloud/vue/dist/Components/NcAppNavigationList.js' import NcAppNavigationNew from '@nextcloud/vue/dist/Components/NcAppNavigationNew.js' -import NcContent from '@nextcloud/vue/dist/Components/NcContent.js' import NcCounterBubble from '@nextcloud/vue/dist/Components/NcCounterBubble.js' import NcLoadingIcon from '@nextcloud/vue/dist/Components/NcLoadingIcon.js' @@ -163,7 +160,6 @@ import AccountGroup from 'vue-material-design-icons/AccountGroup.vue' import AccountOff from 'vue-material-design-icons/AccountOff.vue' import Cog from 'vue-material-design-icons/Cog.vue' import Plus from 'vue-material-design-icons/Plus.vue' -import ShieldAccount from 'vue-material-design-icons/ShieldAccount.vue' import GroupListItem from '../components/GroupListItem.vue' import UserList from '../components/UserList.vue' @@ -172,7 +168,7 @@ import UserSettingsDialog from '../components/Users/UserSettingsDialog.vue' Vue.use(VueLocalStorage) export default { - name: 'Users', + name: 'UserManagement', components: { AccountGroup, @@ -188,11 +184,9 @@ export default { NcAppNavigationItem, NcAppNavigationList, NcAppNavigationNew, - NcContent, NcCounterBubble, NcLoadingIcon, Plus, - ShieldAccount, UserList, UserSettingsDialog, }, diff --git a/apps/settings/src/views/UserManagementNavigation.vue b/apps/settings/src/views/UserManagementNavigation.vue new file mode 100644 index 00000000000..a32313f8edf --- /dev/null +++ b/apps/settings/src/views/UserManagementNavigation.vue @@ -0,0 +1,5 @@ +<template> + <div>...</div> +</template> +<script setup> +</script> |