Skip to content

Commit abd6b12

Browse files
committed
fixp
1 parent 8ad8280 commit abd6b12

7 files changed

Lines changed: 184 additions & 19 deletions

File tree

apps/settings/img/a.webp

11.9 KB
Loading
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
<template>
2+
<div class="app-discover">
3+
<NcEmptyContent v-if="layoutList.length === 0"
4+
:name="t('settings', 'Nothing to show')"
5+
:description="t('settings', 'Could not load section content from app store.')">
6+
<template #icon>
7+
<NcIconSvgWrapper :path="mdiEyeOff" :size="64" />
8+
</template>
9+
</NcEmptyContent>
10+
<template v-for="entry, index in layoutList" v-else>
11+
<component :is="getComponent(entry.type)"
12+
:key="entry.id ?? index"
13+
v-bind="entry" />
14+
</template>
15+
</div>
16+
</template>
17+
18+
<script setup>
19+
import { mdiEyeOff } from '@mdi/js'
20+
import { translate as t } from '@nextcloud/l10n'
21+
import { defineAsyncComponent, defineComponent } from 'vue'
22+
23+
import NcEmptyContent from '@nextcloud/vue/dist/Components/NcEmptyContent.js'
24+
import NcIconSvgWrapper from '@nextcloud/vue/dist/Components/NcIconSvgWrapper.js'
25+
import { generateFilePath, imagePath } from '@nextcloud/router'
26+
27+
const PostType = defineAsyncComponent(() => import('./PostType.vue'))
28+
29+
const getComponent = (type) => {
30+
console.warn(type)
31+
if (type === 'post') {
32+
return PostType
33+
}
34+
return defineComponent({
35+
mounted: () => console.error('Unknown component requested ', type),
36+
render: (h) => h('div'),
37+
})
38+
}
39+
const layoutList = [{
40+
type: 'post',
41+
headline: {
42+
en: 'Amazing wallpapers',
43+
de: 'Bezaubernde Hintergründe',
44+
},
45+
text: {
46+
en: 'This are the most amazing wallpaers that you can possible have. Get them now!',
47+
de: 'Die wohl beeindruckensten Hintergründe die man haben kann. Hol sie dir jetzt!',
48+
},
49+
link: 'https://example.com/wallpapers',
50+
media: {
51+
alignment: 'end',
52+
content: {
53+
en: {
54+
src: generateFilePath('settings', 'img', 'a.webp'),
55+
alt: 'Amazing wallpaper',
56+
},
57+
},
58+
},
59+
}]
60+
</script>
61+
62+
<style scoped>
63+
.app-discover {
64+
margin-inline: 54px;
65+
max-width: 900px;
66+
}
67+
</style>
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
<template>
2+
<article class="app-discover-post"
3+
:class="{ 'app-discover-post--reverse': media && media.alignment === 'start' }">
4+
<div v-if="headline || text" class="app-discover-post__text">
5+
<h3>{{ translatedHeadline }}</h3>
6+
<p>{{ translatedText }}</p>
7+
</div>
8+
<div v-if="media">
9+
<img class="app-discover-post__media" :alt="mediaAlt" :src="mediaSource">
10+
</div>
11+
</article>
12+
</template>
13+
14+
<script setup lang="ts">
15+
import { getLanguage } from '@nextcloud/l10n'
16+
import { computed } from 'vue'
17+
18+
type ILocalizedValue<T> = Record<string, T | undefined> & { en: T }
19+
20+
const props = defineProps<{
21+
type: string
22+
23+
headline: ILocalizedValue<string>
24+
text: ILocalizedValue<string>
25+
link?: string
26+
media: {
27+
alignment: 'start'|'end'
28+
content: ILocalizedValue<{ src: string, alt: string}>
29+
}
30+
}>()
31+
32+
const language = getLanguage()
33+
34+
const getLocalizedValue = <T, >(dict: ILocalizedValue<T>) => dict[language] ?? dict[language.split('_')[0]] ?? dict.en
35+
36+
const translatedText = computed(() => getLocalizedValue(props.text))
37+
const translatedHeadline = computed(() => getLocalizedValue(props.headline))
38+
39+
const localizedMedia = computed(() => getLocalizedValue(props.media.content))
40+
41+
const mediaSource = computed(() => localizedMedia.value?.src)
42+
const mediaAlt = ''
43+
</script>
44+
45+
<style scoped lang="scss">
46+
.app-discover-post {
47+
width: 100%;
48+
background-color: var(--color-primary-element-light);
49+
border-radius: var(--border-radius-rounded);
50+
51+
display: flex;
52+
flex-direction: row;
53+
&--reverse {
54+
flex-direction: row-reverse;
55+
}
56+
57+
h3 {
58+
font-size: 24px;
59+
font-weight: 600;
60+
margin-block: 0 1em;
61+
}
62+
63+
&__text {
64+
padding: var(--border-radius-rounded);
65+
}
66+
67+
&__media {
68+
max-height: 300px;
69+
max-width: 450px;
70+
border-radius: var(--border-radius-rounded);
71+
border-end-start-radius: 0;
72+
border-start-start-radius: 0;
73+
}
74+
75+
&--reverse &__media {
76+
border-radius: var(--border-radius-rounded);
77+
border-end-end-radius: 0;
78+
border-start-end-radius: 0;
79+
}
80+
}
81+
</style>

apps/settings/src/constants/AppsConstants.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import { translate as t } from '@nextcloud/l10n'
2424

2525
/** Enum of verification constants, according to Apps */
2626
export const APPS_SECTION_ENUM = Object.freeze({
27+
discover: t('settings', 'Discover'),
2728
installed: t('settings', 'Your apps'),
2829
enabled: t('settings', 'Active apps'),
2930
disabled: t('settings', 'Disabled apps'),

apps/settings/src/constants/AppstoreCategoryIcons.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ import {
3939
mdiOpenInApp,
4040
mdiSecurity,
4141
mdiStar,
42+
mdiStarCircleOutline,
4243
mdiStarShooting,
4344
mdiTools,
4445
mdiViewDashboard,
@@ -49,6 +50,7 @@ import {
4950
*/
5051
export default Object.freeze({
5152
// system special categories
53+
discover: mdiStarCircleOutline,
5254
installed: mdiAccount,
5355
enabled: mdiCheck,
5456
disabled: mdiClose,

apps/settings/src/views/AppStore.vue

Lines changed: 24 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,11 @@
2424
<template>
2525
<!-- Apps list -->
2626
<NcAppContent class="app-settings-content"
27-
:page-heading="pageHeading">
28-
<NcEmptyContent v-if="isLoading"
27+
:page-heading="appStoreLabel">
28+
<h2 class="app-settings-content__label" v-text="viewLabel" />
29+
30+
<AppStoreDiscoverSection v-if="currentCategory === 'discover'" />
31+
<NcEmptyContent v-else-if="isLoading"
2932
class="empty-content__loading"
3033
:name="t('settings', 'Loading app list')">
3134
<template #icon>
@@ -38,36 +41,31 @@
3841

3942
<script setup lang="ts">
4043
import { translate as t } from '@nextcloud/l10n'
41-
import { computed, getCurrentInstance, onBeforeMount, watch } from 'vue'
44+
import { computed, getCurrentInstance, onBeforeMount, watchEffect } from 'vue'
4245
import { useRoute } from 'vue-router/composables'
43-
import { APPS_SECTION_ENUM } from '../constants/AppsConstants.js'
46+
4447
import { useAppsStore } from '../store/apps-store'
48+
import { APPS_SECTION_ENUM } from '../constants/AppsConstants'
4549
4650
import NcAppContent from '@nextcloud/vue/dist/Components/NcAppContent.js'
4751
import NcEmptyContent from '@nextcloud/vue/dist/Components/NcEmptyContent.js'
4852
import NcLoadingIcon from '@nextcloud/vue/dist/Components/NcLoadingIcon.js'
4953
import AppList from '../components/AppList.vue'
54+
import AppStoreDiscoverSection from '../components/AppStoreDiscover/AppStoreDiscoverSection.vue'
5055
5156
const route = useRoute()
5257
const store = useAppsStore()
5358
5459
/**
55-
* ID of the current active category, default is `installed`
60+
* ID of the current active category, default is `discover`
5661
*/
57-
const currentCategory = computed(() => route.params?.category ?? 'installed')
62+
const currentCategory = computed(() => route.params?.category ?? 'discover')
5863
59-
/**
60-
* The H1 to be used on the website
61-
*/
62-
const pageHeading = computed(() => {
63-
if (currentCategory.value in APPS_SECTION_ENUM) {
64-
return APPS_SECTION_ENUM[currentCategory.value]
65-
}
66-
const category = store.getCategoryById(currentCategory.value)
67-
return category?.displayName ?? t('settings', 'Apps')
68-
})
69-
watch([pageHeading], () => {
70-
window.document.title = `${pageHeading.value} - Apps - Nextcloud`
64+
const appStoreLabel = t('settings', 'App Store')
65+
const viewLabel = computed(() => APPS_SECTION_ENUM[currentCategory.value] ?? store.getCategoryById(currentCategory.value)?.displayName ?? appStoreLabel)
66+
67+
watchEffect(() => {
68+
window.document.title = `${viewLabel.value} - ${appStoreLabel} - Nextcloud`
7169
})
7270
7371
// TODO this part should be migrated to pinia
@@ -87,4 +85,12 @@ onBeforeMount(() => {
8785
.empty-content__loading {
8886
height: 100%;
8987
}
88+
89+
.app-settings-content__label {
90+
margin-block-start: var(--app-navigation-padding);
91+
margin-inline-start: calc(var(--default-clickable-area) + var(--app-navigation-padding) * 2);
92+
min-height: var(--default-clickable-area);
93+
line-height: var(--default-clickable-area);
94+
vertical-align: center;
95+
}
9096
</style>

apps/settings/src/views/AppStoreNavigation.vue

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,17 @@
22
<!-- Categories & filters -->
33
<NcAppNavigation :aria-label="t('settings', 'Apps')">
44
<template #list>
5-
<NcAppNavigationItem id="app-category-your-apps"
5+
<NcAppNavigationItem id="app-category-discover"
66
:to="{ name: 'apps' }"
77
:exact="true"
8+
:name="APPS_SECTION_ENUM.discover">
9+
<template #icon>
10+
<NcIconSvgWrapper :path="APPSTORE_CATEGORY_ICONS.discover" />
11+
</template>
12+
</NcAppNavigationItem>
13+
<NcAppNavigationItem id="app-category-installed"
14+
:to="{ name: 'apps-category', params: { category: 'installed'} }"
15+
:exact="true"
816
:name="APPS_SECTION_ENUM.installed">
917
<template #icon>
1018
<NcIconSvgWrapper :path="APPSTORE_CATEGORY_ICONS.installed" />

0 commit comments

Comments
 (0)