Skip to content

Commit 951863c

Browse files
authored
ui: add an infinite scroll select component (#10840)
Signed-off-by: Abhishek Kumar <[email protected]>
1 parent 112dfdd commit 951863c

File tree

4 files changed

+370
-170
lines changed

4 files changed

+370
-170
lines changed

ui/public/locales/en.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1925,6 +1925,7 @@
19251925
"label.sharedrouteripv6": "IPv6 address for the VR in this shared Network.",
19261926
"label.sharewith": "Share with",
19271927
"label.showing": "Showing",
1928+
"label.showing.results.for": "Showing results for \"%x\"",
19281929
"label.shrinkok": "Shrink OK",
19291930
"label.shutdown": "Shutdown",
19301931
"label.shutdown.provider": "Shutdown provider",

ui/src/components/header/ProjectMenu.vue

Lines changed: 40 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -17,112 +17,75 @@
1717

1818
<template>
1919
<span class="header-notice-opener">
20-
<a-select
21-
v-if="!isDisabled()"
20+
<infinite-scroll-select
21+
v-if="!isDisabled"
22+
v-model:value="selectedProjectId"
2223
class="project-select"
23-
:loading="loading"
24-
v-model:value="projectSelected"
25-
:filterOption="filterProject"
26-
@change="changeProject"
27-
@focus="fetchData"
28-
showSearch>
29-
30-
<a-select-option
31-
v-for="(project, index) in projects"
32-
:key="index"
33-
:label="project.displaytext || project.name">
34-
<span>
35-
<resource-icon v-if="project.icon && project.icon.base64image" :image="project.icon.base64image" size="1x" style="margin-right: 5px"/>
36-
<project-outlined v-else style="margin-right: 5px" />
37-
{{ project.displaytext || project.name }}
38-
</span>
39-
</a-select-option>
40-
</a-select>
24+
api="listProjects"
25+
:apiParams="projectsApiParams"
26+
resourceType="project"
27+
:defaultOption="defaultOption"
28+
defaultIcon="project-outlined"
29+
:pageSize="100"
30+
@change-option="changeProject" />
4131
</span>
4232
</template>
4333

4434
<script>
45-
import store from '@/store'
46-
import { api } from '@/api'
47-
import _ from 'lodash'
48-
import ResourceIcon from '@/components/view/ResourceIcon'
35+
import InfiniteScrollSelect from '@/components/widgets/InfiniteScrollSelect'
4936
5037
export default {
5138
name: 'ProjectMenu',
5239
components: {
53-
ResourceIcon
40+
InfiniteScrollSelect
5441
},
5542
data () {
5643
return {
57-
projects: [],
44+
selectedProjectId: null,
5845
loading: false
5946
}
6047
},
6148
created () {
62-
this.fetchData()
49+
this.selectedProjectId = this.$store.getters?.project?.id || this.defaultOption.id
50+
this.$store.dispatch('ToggleTheme', this.selectedProjectId ? 'dark' : 'light')
6351
},
6452
computed: {
65-
projectSelected () {
66-
let projectIndex = 0
67-
if (this.$store.getters?.project?.id) {
68-
projectIndex = this.projects.findIndex(project => project.id === this.$store.getters.project.id)
69-
this.$store.dispatch('ToggleTheme', projectIndex === undefined ? 'light' : 'dark')
53+
isDisabled () {
54+
return !('listProjects' in this.$store.getters.apis)
55+
},
56+
defaultOption () {
57+
return { id: 0, name: this.$t('label.default.view') }
58+
},
59+
projectsApiParams () {
60+
return {
61+
details: 'min',
62+
listall: true
7063
}
71-
72-
return projectIndex
7364
}
7465
},
75-
methods: {
76-
fetchData () {
77-
if (this.isDisabled()) {
78-
return
79-
}
80-
var page = 1
81-
const projects = []
82-
const getNextPage = () => {
83-
this.loading = true
84-
api('listProjects', { listAll: true, page: page, pageSize: 500, details: 'min', showIcon: true }).then(json => {
85-
if (json?.listprojectsresponse?.project) {
86-
projects.push(...json.listprojectsresponse.project)
87-
}
88-
if (projects.length < json.listprojectsresponse.count) {
89-
page++
90-
getNextPage()
91-
}
92-
}).finally(() => {
93-
this.loading = false
94-
this.$store.commit('RELOAD_ALL_PROJECTS', projects)
95-
})
66+
mounted () {
67+
this.unwatchProject = this.$store.watch(
68+
(state, getters) => getters.project?.id,
69+
(newId) => {
70+
this.selectedProjectId = newId
9671
}
97-
getNextPage()
98-
},
99-
isDisabled () {
100-
return !Object.prototype.hasOwnProperty.call(store.getters.apis, 'listProjects')
101-
},
102-
changeProject (index) {
103-
const project = this.projects[index]
72+
)
73+
},
74+
beforeUnmount () {
75+
if (this.unwatchProject) {
76+
this.unwatchProject()
77+
}
78+
},
79+
methods: {
80+
changeProject (project) {
10481
this.$store.dispatch('ProjectView', project.id)
10582
this.$store.dispatch('SetProject', project)
106-
this.$store.dispatch('ToggleTheme', project.id === undefined ? 'light' : 'dark')
83+
this.$store.dispatch('ToggleTheme', project.id ? 'dark' : 'light')
10784
this.$message.success(`${this.$t('message.switch.to')} "${project.displaytext || project.name}"`)
10885
if (this.$route.name !== 'dashboard') {
10986
this.$router.push({ name: 'dashboard' })
11087
}
111-
},
112-
filterProject (input, option) {
113-
return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0
11488
}
115-
},
116-
mounted () {
117-
this.$store.watch(
118-
(state, getters) => getters.allProjects,
119-
(newValue, oldValue) => {
120-
if (oldValue !== newValue && newValue !== undefined) {
121-
this.projects = _.orderBy(newValue, ['displaytext'], ['asc'])
122-
this.projects.unshift({ name: this.$t('label.default.view') })
123-
}
124-
}
125-
)
12689
}
12790
}
12891
</script>

0 commit comments

Comments
 (0)