Signed-off-by: Ferdinand Thiessen <opensource@fthiessen.de>pull/44092/head
parent
14bdc11dee
commit
e678b77031
@ -0,0 +1,75 @@ |
||||
<!-- |
||||
- @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> |
||||
<NcAppSidebarTab v-if="hasChangelog" |
||||
id="desca" |
||||
:name="t('settings', 'Changelog')" |
||||
:order="1"> |
||||
<template #icon> |
||||
<NcIconSvgWrapper :path="mdiClockFast" :size="24" /> |
||||
</template> |
||||
<div v-for="release in app.releases" :key="release.version" class="app-sidebar-tabs__release"> |
||||
<h2>{{ release.version }}</h2> |
||||
<Markdown class="app-sidebar-tabs__release-text" :text="createChangelogFromRelease(release)" /> |
||||
</div> |
||||
</NcAppSidebarTab> |
||||
</template> |
||||
|
||||
<script setup lang="ts"> |
||||
import type { IAppstoreApp, IAppstoreAppRelease } from '../../app-types.ts' |
||||
|
||||
import { mdiClockFast } from '@mdi/js' |
||||
import { getLanguage, translate as t } from '@nextcloud/l10n' |
||||
|
||||
import NcAppSidebarTab from '@nextcloud/vue/dist/Components/NcAppSidebarTab.js' |
||||
import NcIconSvgWrapper from '@nextcloud/vue/dist/Components/NcIconSvgWrapper.js' |
||||
import Markdown from '../Markdown.vue' |
||||
import { computed, watch } from 'vue' |
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars |
||||
const props = defineProps<{ app: IAppstoreApp }>() |
||||
|
||||
watch([props], () => console.warn(props.app.releases)) |
||||
const hasChangelog = computed(() => Object.values(props.app.releases[0]?.translations ?? {}).some(({ changelog }) => !!changelog)) |
||||
|
||||
const createChangelogFromRelease = (release: IAppstoreAppRelease) => release.translations?.[getLanguage()]?.changelog ?? release.translations?.en?.changelog ?? '' |
||||
</script> |
||||
|
||||
<style scoped lang="scss"> |
||||
.app-sidebar-tabs__release { |
||||
h2 { |
||||
border-bottom: 1px solid var(--color-border); |
||||
font-size: 24px; |
||||
} |
||||
|
||||
&-text { |
||||
// Overwrite changelog heading styles |
||||
:deep(h3) { |
||||
font-size: 20px; |
||||
} |
||||
:deep(h4) { |
||||
font-size: 17px; |
||||
} |
||||
} |
||||
} |
||||
</style> |
@ -0,0 +1,76 @@ |
||||
/** |
||||
* @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/>. |
||||
* |
||||
*/ |
||||
import { |
||||
mdiAccount, |
||||
mdiAccountMultiple, |
||||
mdiArchive, |
||||
mdiCheck, |
||||
mdiClipboardFlow, |
||||
mdiClose, |
||||
mdiCog, |
||||
mdiControllerClassic, |
||||
mdiDownload, |
||||
mdiFileDocumentEdit, |
||||
mdiFolder, |
||||
mdiKey, |
||||
mdiMagnify, |
||||
mdiMonitorEye, |
||||
mdiMultimedia, |
||||
mdiOfficeBuilding, |
||||
mdiOpenInApp, |
||||
mdiSecurity, |
||||
mdiStar, |
||||
mdiStarShooting, |
||||
mdiTools, |
||||
mdiViewDashboard, |
||||
} from '@mdi/js' |
||||
|
||||
/** |
||||
* SVG paths used for appstore category icons |
||||
*/ |
||||
export default Object.freeze({ |
||||
// system special categories
|
||||
installed: mdiAccount, |
||||
enabled: mdiCheck, |
||||
disabled: mdiClose, |
||||
bundles: mdiArchive, |
||||
supported: mdiStarShooting, |
||||
featured: mdiStar, |
||||
updates: mdiDownload, |
||||
|
||||
// generic categories
|
||||
auth: mdiKey, |
||||
customization: mdiCog, |
||||
dashboard: mdiViewDashboard, |
||||
files: mdiFolder, |
||||
games: mdiControllerClassic, |
||||
integration: mdiOpenInApp, |
||||
monitoring: mdiMonitorEye, |
||||
multimedia: mdiMultimedia, |
||||
office: mdiFileDocumentEdit, |
||||
organization: mdiOfficeBuilding, |
||||
search: mdiMagnify, |
||||
security: mdiSecurity, |
||||
social: mdiAccountMultiple, |
||||
tools: mdiTools, |
||||
workflow: mdiClipboardFlow, |
||||
}) |
@ -0,0 +1,63 @@ |
||||
<!-- |
||||
- @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" /> |
||||
</NcAppContent> |
||||
</template> |
||||
|
||||
<script setup lang="ts"> |
||||
import { translate as t } from '@nextcloud/l10n' |
||||
import { computed, 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 AppList from '../components/AppList.vue' |
||||
|
||||
const route = useRoute() |
||||
const store = useAppsStore() |
||||
|
||||
/** |
||||
* ID of the current active category, default is `installed` |
||||
*/ |
||||
const currentCategory = computed(() => route.params?.category ?? 'installed') |
||||
|
||||
/** |
||||
* The H1 to be used on the website |
||||
*/ |
||||
const pageHeading = computed(() => { |
||||
if (currentCategory.value in APPS_SECTION_ENUM) { |
||||
return APPS_SECTION_ENUM[currentCategory.value] |
||||
} |
||||
const category = store.getCategoryById(currentCategory.value) |
||||
return category?.displayName ?? t('settings', 'Apps') |
||||
}) |
||||
watch([pageHeading], () => { |
||||
window.document.title = `${pageHeading.value} - Apps - Nextcloud` |
||||
}) |
||||
</script> |
@ -0,0 +1,136 @@ |
||||
<template> |
||||
<!-- Categories & filters --> |
||||
<NcAppNavigation :aria-label="t('settings', 'Apps')"> |
||||
<template #list> |
||||
<NcAppNavigationItem id="app-category-your-apps" |
||||
:to="{ name: 'apps' }" |
||||
:exact="true" |
||||
:name="APPS_SECTION_ENUM.installed"> |
||||
<template #icon> |
||||
<NcIconSvgWrapper :path="APPSTORE_CATEGORY_ICONS.installed" /> |
||||
</template> |
||||
</NcAppNavigationItem> |
||||
<NcAppNavigationItem id="app-category-enabled" |
||||
:to="{ name: 'apps-category', params: { category: 'enabled' } }" |
||||
:name="APPS_SECTION_ENUM.enabled"> |
||||
<template #icon> |
||||
<NcIconSvgWrapper :path="APPSTORE_CATEGORY_ICONS.enabled" /> |
||||
</template> |
||||
</NcAppNavigationItem> |
||||
<NcAppNavigationItem id="app-category-disabled" |
||||
:to="{ name: 'apps-category', params: { category: 'disabled' } }" |
||||
:name="APPS_SECTION_ENUM.disabled"> |
||||
<template #icon> |
||||
<NcIconSvgWrapper :path="APPSTORE_CATEGORY_ICONS.disabled" /> |
||||
</template> |
||||
</NcAppNavigationItem> |
||||
<NcAppNavigationItem v-if="updateCount > 0" |
||||
id="app-category-updates" |
||||
:to="{ name: 'apps-category', params: { category: 'updates' } }" |
||||
:name="APPS_SECTION_ENUM.updates"> |
||||
<template #counter> |
||||
<NcCounterBubble>{{ updateCount }}</NcCounterBubble> |
||||
</template> |
||||
<template #icon> |
||||
<NcIconSvgWrapper :path="APPSTORE_CATEGORY_ICONS.updates" /> |
||||
</template> |
||||
</NcAppNavigationItem> |
||||
<NcAppNavigationItem id="app-category-your-bundles" |
||||
:to="{ name: 'apps-category', params: { category: 'app-bundles' } }" |
||||
:name="APPS_SECTION_ENUM['app-bundles']"> |
||||
<template #icon> |
||||
<NcIconSvgWrapper :path="APPSTORE_CATEGORY_ICONS.bundles" /> |
||||
</template> |
||||
</NcAppNavigationItem> |
||||
|
||||
<NcAppNavigationSpacer /> |
||||
|
||||
<!-- App store categories --> |
||||
<li v-if="appstoreEnabled && categoriesLoading" class="categories--loading"> |
||||
<NcLoadingIcon :size="20" :aria-label="t('settings', 'Loading categories')" /> |
||||
</li> |
||||
<template v-else-if="appstoreEnabled && !categoriesLoading"> |
||||
<NcAppNavigationItem v-if="isSubscribed" |
||||
id="app-category-supported" |
||||
:to="{ name: 'apps-category', params: { category: 'supported' } }" |
||||
:name="APPS_SECTION_ENUM.supported"> |
||||
<template #icon> |
||||
<NcIconSvgWrapper :path="APPSTORE_CATEGORY_ICONS.supported" /> |
||||
</template> |
||||
</NcAppNavigationItem> |
||||
<NcAppNavigationItem id="app-category-featured" |
||||
:to="{ name: 'apps-category', params: { category: 'featured' } }" |
||||
:name="APPS_SECTION_ENUM.featured"> |
||||
<template #icon> |
||||
<NcIconSvgWrapper :path="APPSTORE_CATEGORY_ICONS.featured" /> |
||||
</template> |
||||
</NcAppNavigationItem> |
||||
|
||||
<NcAppNavigationItem v-for="category in categories" |
||||
:id="`app-category-${category.id}`" |
||||
:key="category.id" |
||||
:name="category.displayName" |
||||
:to="{ |
||||
name: 'apps-category', |
||||
params: { category: category.id }, |
||||
}"> |
||||
<template #icon> |
||||
<NcIconSvgWrapper :path="category.icon" /> |
||||
</template> |
||||
</NcAppNavigationItem> |
||||
</template> |
||||
|
||||
<NcAppNavigationItem id="app-developer-docs" |
||||
:name="t('settings', 'Developer documentation ↗')" |
||||
:href="developerDocsUrl" /> |
||||
</template> |
||||
</NcAppNavigation> |
||||
</template> |
||||
|
||||
<script setup lang="ts"> |
||||
import { loadState } from '@nextcloud/initial-state' |
||||
import { translate as t } from '@nextcloud/l10n' |
||||
import { computed, onBeforeMount } from 'vue' |
||||
import { APPS_SECTION_ENUM } from '../constants/AppsConstants' |
||||
import { useAppsStore } from '../store/apps-store' |
||||
|
||||
import NcAppNavigation from '@nextcloud/vue/dist/Components/NcAppNavigation.js' |
||||
import NcAppNavigationItem from '@nextcloud/vue/dist/Components/NcAppNavigationItem.js' |
||||
import NcAppNavigationSpacer from '@nextcloud/vue/dist/Components/NcAppNavigationSpacer.js' |
||||
import NcCounterBubble from '@nextcloud/vue/dist/Components/NcCounterBubble.js' |
||||
import NcIconSvgWrapper from '@nextcloud/vue/dist/Components/NcIconSvgWrapper.js' |
||||
import NcLoadingIcon from '@nextcloud/vue/dist/Components/NcLoadingIcon.js' |
||||
|
||||
import APPSTORE_CATEGORY_ICONS from '../constants/AppstoreCategoryIcons.ts' |
||||
|
||||
const updateCount = loadState<number>('settings', 'appstoreUpdateCount', 0) |
||||
const appstoreEnabled = loadState<boolean>('settings', 'appstoreEnabled', true) |
||||
const developerDocsUrl = loadState<string>('settings', 'appstoreDeveloperDocs', '') |
||||
|
||||
const store = useAppsStore() |
||||
const categories = computed(() => store.categories) |
||||
const categoriesLoading = computed(() => store.loading.categories) |
||||
|
||||
/** |
||||
* Check if the current instance has a support subscription from the Nextcloud GmbH |
||||
* |
||||
* For customers of the Nextcloud GmbH the app level will be set to `300` for apps that are supported in their subscription |
||||
*/ |
||||
const isSubscribed = computed(() => store.apps.find(({ level }) => level === 300) !== undefined) |
||||
|
||||
// load categories when component is mounted |
||||
onBeforeMount(() => { |
||||
store.loadCategories() |
||||
store.loadApps() |
||||
}) |
||||
</script> |
||||
|
||||
<style scoped> |
||||
/* The categories-loading indicator */ |
||||
.categories--loading { |
||||
flex: 1; |
||||
display: flex; |
||||
align-items: center; |
||||
justify-content: center; |
||||
} |
||||
</style> |
Loading…
Reference in new issue