Merge pull request #44255 from nextcloud/fix/apps-search

fix: Correctly add search event listener to make searching the app list work again
pull/44275/head
Ferdinand Thiessen 2 months ago committed by GitHub
commit eeb6649f9d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -266,14 +266,14 @@ export default {
unsubscribe('nextcloud:unified-search.reset', this.resetSearch)
},
beforeCreate() {
mounted() {
subscribe('nextcloud:unified-search.search', this.setSearch)
subscribe('nextcloud:unified-search.reset', this.resetSearch)
},
methods: {
setSearch(value) {
this.search = value
setSearch({ query }) {
this.search = query
},
resetSearch() {
this.search = ''

@ -1,411 +0,0 @@
<!--
- @copyright Copyright (c) 2018 Julius Härtl <jus@bitgrid.net>
-
- @author Julius Härtl <jus@bitgrid.net>
-
- @license GNU AGPL version 3 or any later version
-
- 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>
<NcContent app-name="settings"
:class="{ 'with-app-sidebar': app}">
<!-- Categories & filters -->
<NcAppNavigation :class="{ 'icon-loading': loading }"
:aria-label="t('settings', 'Apps')">
<template #list>
<NcAppNavigationItem id="app-category-your-apps"
:to="{ name: 'apps' }"
:exact="true"
icon="icon-category-installed"
:name="$options.APPS_SECTION_ENUM.installed" />
<NcAppNavigationItem id="app-category-enabled"
:to="{ name: 'apps-category', params: { category: 'enabled' } }"
icon="icon-category-enabled"
:name="$options.APPS_SECTION_ENUM.enabled" />
<NcAppNavigationItem id="app-category-disabled"
:to="{ name: 'apps-category', params: { category: 'disabled' } }"
icon="icon-category-disabled"
:name="$options.APPS_SECTION_ENUM.disabled" />
<NcAppNavigationItem v-if="updateCount > 0"
id="app-category-updates"
:to="{ name: 'apps-category', params: { category: 'updates' } }"
icon="icon-download"
:name="$options.APPS_SECTION_ENUM.updates">
<template #counter>
<NcCounterBubble>{{ updateCount }}</NcCounterBubble>
</template>
</NcAppNavigationItem>
<NcAppNavigationItem v-if="isSubscribed"
id="app-category-supported"
:to="{ name: 'apps-category', params: { category: 'supported' } }"
:name="$options.APPS_SECTION_ENUM.supported">
<template #icon>
<IconStarShooting :size="20" />
</template>
</NcAppNavigationItem>
<NcAppNavigationItem id="app-category-your-bundles"
:to="{ name: 'apps-category', params: { category: 'app-bundles' } }"
icon="icon-category-app-bundles"
:name="$options.APPS_SECTION_ENUM['app-bundles']" />
<NcAppNavigationSpacer />
<!-- App store categories -->
<template v-if="appstoreEnabled">
<NcAppNavigationItem id="app-category-featured"
:to="{ name: 'apps-category', params: { category: 'featured' } }"
icon="icon-favorite"
:name="$options.APPS_SECTION_ENUM.featured" />
<NcAppNavigationItem v-for="cat in categories"
:key="'icon-category-' + cat.id"
:icon="'icon-category-' + cat.id"
:to="{
name: 'apps-category',
params: { category: cat.id },
}"
:name="cat.displayName" />
</template>
<NcAppNavigationItem id="app-developer-docs"
:name="t('settings', 'Developer documentation') + ' ↗'"
@click="openDeveloperDocumentation" />
</template>
</NcAppNavigation>
<!-- Apps list -->
<NcAppContent class="app-settings-content"
:class="{ 'icon-loading': loadingList }"
:page-heading="pageHeading">
<AppList :category="category" :app="app" :search="searchQuery" />
</NcAppContent>
<!-- Selected app details -->
<NcAppSidebar v-if="id && app"
v-bind="appSidebar"
:class="{'app-sidebar--without-background': !appSidebar.background}"
@close="hideAppDetails">
<template v-if="!appSidebar.background" #header>
<div class="app-sidebar-header__figure--default-app-icon icon-settings-dark" />
</template>
<template #description>
<!-- Featured/Supported badges -->
<AppLevelBadge :level="app.level" />
<AppScore v-if="hasRating" :score="app.appstoreData.ratingOverall" />
<div class="app-version">
<p>{{ app.version }}</p>
</div>
</template>
<!-- Tab content -->
<NcAppSidebarTab id="desc"
icon="icon-category-office"
:name="t('settings', 'Details')"
:order="0">
<AppDetails :app="app" />
</NcAppSidebarTab>
<NcAppSidebarTab v-if="app.appstoreData && app.releases[0].translations.en.changelog"
id="desca"
icon="icon-category-organization"
:name="t('settings', 'Changelog')"
:order="1">
<div v-for="release in app.releases" :key="release.version" class="app-sidebar-tabs__release">
<h2>{{ release.version }}</h2>
<Markdown v-if="changelog(release)" :min-heading="3" :text="changelog(release)" />
</div>
</NcAppSidebarTab>
</NcAppSidebar>
</NcContent>
</template>
<script>
import { subscribe, unsubscribe } from '@nextcloud/event-bus'
import Vue from 'vue'
import VueLocalStorage from 'vue-localstorage'
import NcAppContent from '@nextcloud/vue/dist/Components/NcAppContent.js'
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 NcAppSidebar from '@nextcloud/vue/dist/Components/NcAppSidebar.js'
import NcAppSidebarTab from '@nextcloud/vue/dist/Components/NcAppSidebarTab.js'
import NcCounterBubble from '@nextcloud/vue/dist/Components/NcCounterBubble.js'
import NcContent from '@nextcloud/vue/dist/Components/NcContent.js'
import IconStarShooting from 'vue-material-design-icons/StarShooting.vue'
import AppList from '../components/AppList.vue'
import AppDetails from '../components/AppDetails.vue'
import AppManagement from '../mixins/AppManagement.js'
import AppLevelBadge from '../components/AppList/AppLevelBadge.vue'
import AppScore from '../components/AppList/AppScore.vue'
import Markdown from '../components/Markdown.vue'
import { APPS_SECTION_ENUM } from './../constants/AppsConstants.js'
import { loadState } from '@nextcloud/initial-state'
Vue.use(VueLocalStorage)
const appstoreEnabled = loadState('settings', 'appstoreEnabled')
const developerDocumentation = loadState('settings', 'appstoreDeveloperDocs')
export default {
name: 'Apps',
APPS_SECTION_ENUM,
components: {
NcAppContent,
AppDetails,
AppList,
AppLevelBadge,
IconStarShooting,
NcAppNavigation,
NcAppNavigationItem,
NcAppNavigationSpacer,
NcCounterBubble,
AppScore,
NcAppSidebar,
NcAppSidebarTab,
NcContent,
Markdown,
},
mixins: [AppManagement],
props: {
category: {
type: String,
default: 'installed',
},
id: {
type: String,
default: '',
},
},
data() {
return {
searchQuery: '',
screenshotLoaded: false,
}
},
computed: {
appstoreEnabled() {
return appstoreEnabled
},
pageHeading() {
if (this.$options.APPS_SECTION_ENUM[this.category]) {
return this.$options.APPS_SECTION_ENUM[this.category]
}
const category = this.$store.getters.getCategoryById(this.category)
return category.displayName
},
loading() {
return this.$store.getters.loading('categories')
},
loadingList() {
return this.$store.getters.loading('list')
},
app() {
return this.apps.find(app => app.id === this.id)
},
categories() {
return this.$store.getters.getCategories
},
apps() {
return this.$store.getters.getAllApps
},
updateCount() {
return this.$store.getters.getUpdateCount
},
hasRating() {
return this.app.appstoreData && this.app.appstoreData.ratingNumOverall > 5
},
// sidebar app binding
appSidebar() {
const authorName = (xmlNode) => {
if (xmlNode['@value']) {
// Complex node (with email or homepage attribute)
return xmlNode['@value']
}
// Simple text node
return xmlNode
}
const author = Array.isArray(this.app.author)
? this.app.author.map(authorName).join(', ')
: authorName(this.app.author)
const license = t('settings', '{license}-licensed', { license: ('' + this.app.licence).toUpperCase() })
const subname = t('settings', 'by {author}\n{license}', { author, license })
return {
background: this.app.screenshot && this.screenshotLoaded
? this.app.screenshot
: this.app.preview,
compact: !(this.app.screenshot && this.screenshotLoaded),
name: this.app.name,
subname,
}
},
changelog() {
return (release) => release.translations.en.changelog
},
/**
* Check if the current instance has a support subscription from the Nextcloud GmbH
*/
isSubscribed() {
// For customers of the Nextcloud GmbH the app level will be set to `300` for apps that are supported in their subscription
return this.apps.some(app => app.level === 300)
},
},
watch: {
category() {
this.searchQuery = ''
},
app() {
this.screenshotLoaded = false
if (this.app?.releases && this.app?.screenshot) {
const image = new Image()
image.onload = () => {
this.screenshotLoaded = true
}
image.src = this.app.screenshot
}
},
},
beforeMount() {
this.$store.dispatch('getCategories', { shouldRefetchCategories: true })
this.$store.dispatch('getAllApps')
this.$store.dispatch('getGroups', { offset: 0, limit: 5 })
},
mounted() {
subscribe('nextcloud:unified-search.search', this.setSearch)
subscribe('nextcloud:unified-search.reset', this.resetSearch)
},
beforeDestroy() {
unsubscribe('nextcloud:unified-search.search', this.setSearch)
unsubscribe('nextcloud:unified-search.reset', this.resetSearch)
},
methods: {
setSearch({ query }) {
this.searchQuery = query
},
resetSearch() {
this.searchQuery = ''
},
hideAppDetails() {
this.$router.push({
name: 'apps-category',
params: { category: this.category },
})
},
openDeveloperDocumentation() {
window.open(developerDocumentation)
},
},
}
</script>
<style lang="scss" scoped>
.app-sidebar::v-deep {
&:not(.app-sidebar--without-background) {
// with full screenshot, let's fill the figure
:not(.app-sidebar-header--compact) .app-sidebar-header__figure {
background-size: cover;
}
// revert sidebar app icon so it is black
.app-sidebar-header--compact .app-sidebar-header__figure {
background-size: 32px;
filter: var(--background-invert-if-bright);
}
}
.app-sidebar-header__description {
.app-version {
padding-left: 10px;
}
}
// default icon slot styling
&.app-sidebar--without-background {
.app-sidebar-header__figure {
display: flex;
align-items: center;
justify-content: center;
&--default-app-icon {
width: 32px;
height: 32px;
background-size: 32px;
}
}
}
// TODO: migrate to components
.app-sidebar-header__desc {
// allow multi line subtitle for the license
.app-sidebar-header__subtitle {
overflow: visible !important;
height: auto;
white-space: normal !important;
line-height: 16px;
}
}
.app-sidebar-header__action {
// align with tab content
margin: 0 20px;
input {
margin: 3px;
}
}
}
// Align the appNavigation toggle with the apps header toolbar
.app-navigation::v-deep button.app-navigation-toggle {
top: 8px;
right: -8px;
}
.app-sidebar-tabs__release {
h2 {
border-bottom: 1px solid var(--color-border);
}
// Overwrite changelog heading styles
::v-deep {
h3 {
font-size: 20px;
}
h4 {
font-size: 17px;
}
}
}
</style>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long
Loading…
Cancel
Save