Skip to content

Commit 6a86839

Browse files
authored
Refactoring: DRY page type/icon handling (#4119)
Signed-off-by: Jimmy Tanagra <jcode@tanagra.id.au>
1 parent 48f187c commit 6a86839

6 files changed

Lines changed: 67 additions & 84 deletions

File tree

bundles/org.openhab.ui/web/src/App.vue

Lines changed: 3 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
view=".view-main"
3535
panel-close>
3636
<template #media>
37-
<oh-icon :icon="pageIcon(page)" height="18" width="18" />
37+
<oh-icon :icon="getPageIcon(page)" height="18" width="18" />
3838
</template>
3939
</f7-list-item>
4040
</f7-list>
@@ -484,6 +484,7 @@ import buildInfo from '@/assets/build-info'
484484
485485
import routes from '@/js/routes.js'
486486
import PanelRight from '@/pages/panel-right.vue'
487+
import { getPageIcon } from '@/pages/page-type'
487488
import EmptyStatePlaceholder from '@/components/empty-state-placeholder.vue'
488489
489490
import { useRuntimeStore } from '@/js/stores/useRuntimeStore'
@@ -820,23 +821,7 @@ export default {
820821
if (page.config.visibleTo.indexOf('user:' + user.name) >= 0) return true
821822
return false
822823
},
823-
pageIcon(page) {
824-
if (page.config && page.config.icon) return page.config.icon
825-
switch (page.component) {
826-
case 'oh-layout-page':
827-
return 'f7:rectangle_grid_2x2'
828-
case 'oh-tabs-page':
829-
return 'f7:squares_below_rectangle'
830-
case 'oh-map-page':
831-
return 'f7:map'
832-
case 'oh-plan-page':
833-
return 'f7:square_stack_3d_up'
834-
case 'oh-chart-page':
835-
return 'f7:graph_square'
836-
default:
837-
return 'f7:tv'
838-
}
839-
},
824+
getPageIcon,
840825
updateThemeOptions() {
841826
if (useUIOptionsStore().visibleBreakpointDisabled) {
842827
nextTick(() => {

bundles/org.openhab.ui/web/src/components/developer/developer-sidebar.vue

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -636,6 +636,7 @@ import SearchResults from './search-results.vue'
636636
import ExpressionTester from './expression-tester.vue'
637637
import ClipboardIcon from '@/components/util/clipboard-icon.vue'
638638
639+
import { getPageType } from '@/pages/page-type'
639640
import RuleStatus from '@/components/rule/rule-status-mixin'
640641
import ThingStatus from '@/components/thing/thing-status-mixin'
641642
import cloneDeep from 'lodash/cloneDeep'
@@ -687,15 +688,6 @@ export default {
687688
newCollectionName: '',
688689
sseEvents: [],
689690
openedItem: null,
690-
pageTypes: [
691-
{ type: 'sitemap', label: 'Sitemap', componentType: 'Sitemap', icon: 'menu' },
692-
{ type: 'layout', label: 'Layout', componentType: 'oh-layout-page', icon: 'rectangle_grid_2x2' },
693-
{ type: 'home', label: 'Home', componentType: 'oh-home-page', icon: 'house' },
694-
{ type: 'tabs', label: 'Tabbed', componentType: 'oh-tabs-page', icon: 'squares_below_rectangle' },
695-
{ type: 'map', label: 'Map', componentType: 'oh-map-page', icon: 'map' },
696-
{ type: 'plan', label: 'Floor plan', componentType: 'oh-plan-page', icon: 'square_stack_3d_up' },
697-
{ type: 'chart', label: 'Chart', componentType: 'oh-chart-page', icon: 'graph_square' }
698-
],
699691
testExpression: '',
700692
addThingAutocomplete: null,
701693
theme
@@ -1023,9 +1015,7 @@ export default {
10231015
load()
10241016
}
10251017
},
1026-
getPageType(page) {
1027-
return this.pageTypes.find((t) => t.componentType === page.component)
1028-
},
1018+
getPageType,
10291019
showItem(evt, item) {
10301020
evt.cancelBubble = true
10311021
if (this.$$(evt.target).closest('.itemlist-actions').length) return

bundles/org.openhab.ui/web/src/components/developer/search-results.vue

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -388,6 +388,7 @@
388388

389389
<script>
390390
import ClipboardIcon from '@/components/util/clipboard-icon.vue'
391+
import { getPageType } from '@/pages/page-type'
391392
392393
export default {
393394
components: {
@@ -408,16 +409,7 @@ export default {
408409
rules: 'wand_stars',
409410
pages: 'tv'
410411
},
411-
expandedTypes: {},
412-
pageTypes: [
413-
{ type: 'sitemap', label: 'Sitemap', componentType: 'Sitemap', icon: 'menu' },
414-
{ type: 'layout', label: 'Layout', componentType: 'oh-layout-page', icon: 'rectangle_grid_2x2' },
415-
{ type: 'home', label: 'Home', componentType: 'oh-home-page', icon: 'house' },
416-
{ type: 'tabs', label: 'Tabbed', componentType: 'oh-tabs-page', icon: 'squares_below_rectangle' },
417-
{ type: 'map', label: 'Map', componentType: 'oh-map-page', icon: 'map' },
418-
{ type: 'plan', label: 'Floor plan', componentType: 'oh-plan-page', icon: 'square_stack_3d_up' },
419-
{ type: 'chart', label: 'Chart', componentType: 'oh-chart-page', icon: 'graph_square' }
420-
]
412+
expandedTypes: {}
421413
}
422414
},
423415
computed: {
@@ -482,9 +474,7 @@ export default {
482474
showingAll(type) {
483475
return this.expandedTypes[type] || this.searchResults[type].length <= 5
484476
},
485-
getPageType(page) {
486-
return this.pageTypes.find((t) => t.componentType === page.component)
487-
},
477+
getPageType,
488478
togglePin(evt, type, obj, keyName) {
489479
evt.cancelBubble = true
490480
if (evt.target.tagName.toLowerCase() === 'i') return
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import type * as api from '@/api'
2+
import type { DeepReadonly } from 'vue'
3+
4+
type PageType = {
5+
type: string
6+
label: string
7+
icon: string
8+
}
9+
10+
const pageTypes: Record<string, PageType> = {
11+
Sitemap: { type: 'sitemap', label: 'Sitemap', icon: 'f7:menu' },
12+
'oh-layout-page': { type: 'layout', label: 'Layout', icon: 'f7:rectangle_grid_2x2' },
13+
'oh-home-page': { type: 'home', label: 'Home', icon: 'f7:house' },
14+
'oh-tabs-page': { type: 'tabs', label: 'Tabbed', icon: 'f7:squares_below_rectangle' },
15+
'oh-map-page': { type: 'map', label: 'Map', icon: 'f7:map' },
16+
'oh-plan-page': { type: 'plan', label: 'Floor plan', icon: 'f7:square_stack_3d_up' },
17+
'oh-chart-page': { type: 'chart', label: 'Chart', icon: 'f7:graph_square' }
18+
}
19+
20+
const unknownPageType: PageType = { type: 'unknown', label: 'Unknown Page Type!', icon: 'f7:question_circle' }
21+
22+
/**
23+
* Returns the PageType for the given page, or a default "unknown" PageType if the page type is unknown.
24+
* The page type is determined by matching the page's component type against the known page types.
25+
* @param page
26+
* @returns The PageType for the given page, or a default "unknown" PageType if the page type is unknown.
27+
*/
28+
export function getPageType(page?: api.RootUiComponent | DeepReadonly<api.RootUiComponent> | null): PageType {
29+
if (!page) return unknownPageType
30+
return pageTypes[page.component] || unknownPageType
31+
}
32+
33+
/**
34+
* Returns the icon for the given page, or a default icon if the page type is unknown.
35+
* The page type is determined by matching the page's component type against the known page types.
36+
*
37+
* Special cases:
38+
* - If the page is null or undefined, it is considered an unknown page type and gets a question mark icon.
39+
* - If the page has a uid of "overview", it is considered the overview page and gets a house icon.
40+
* - If the page has a config with an icon, that icon is used.
41+
*
42+
* @param page
43+
* @returns The icon for the given page, or a default icon if the page type is unknown.
44+
*/
45+
export function getPageIcon(page?: api.RootUiComponent | DeepReadonly<api.RootUiComponent> | null): string {
46+
if (!page) return unknownPageType.icon
47+
if (page.uid === 'overview') return 'f7:house'
48+
if (page.config && page.config.icon) return page.config.icon as string
49+
return getPageType(page).icon
50+
}

bundles/org.openhab.ui/web/src/pages/page/page-view.vue

Lines changed: 3 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ import { useWidgetExpression } from '@/components/widgets/useWidgetExpression.ts
9898
import { useViewArea } from '@/js/composables/useViewArea.ts'
9999
100100
import * as api from '@/api'
101+
import { getPageType } from '@/pages/page-type'
101102
102103
import OhLayoutPage from '@/components/widgets/layout/oh-layout-page.vue'
103104
import EmptyStatePlaceholder from '@/components/empty-state-placeholder.vue'
@@ -170,7 +171,7 @@ const context = computed(() => ({
170171
vars: Object.assign(vars.value, page.value?.config?.defineVars ?? {}, props.defineVars ?? {}),
171172
store: statesStore.trackedItems
172173
}))
173-
const pageType = computed(() => (page.value ? getPageType(page.value) : null))
174+
const pageType = computed(() => getPageType(page.value).type)
174175
const pageLabel = computed(() => page.value?.config?.label)
175176
const editable = computed(() => page.value && userStore.isAdmin())
176177
const fullscreenIcon = computed(() => {
@@ -199,24 +200,6 @@ const onTabChange = (idx: number) => {
199200
// @ts-expect-error - url is not typed as part of the router
200201
props.f7router.url = url
201202
}
202-
const getPageType = (page: api.RootUiComponent | DeepReadonly<api.RootUiComponent>) => {
203-
if (!page) return null
204-
switch (page.component) {
205-
case 'oh-layout-page':
206-
return 'layout'
207-
case 'oh-map-page':
208-
return 'map'
209-
case 'oh-tabs-page':
210-
return 'tabs'
211-
case 'oh-plan-page':
212-
return 'plan'
213-
case 'oh-chart-page':
214-
return 'chart'
215-
default:
216-
console.warn('Unknown page type!')
217-
return 'unknown'
218-
}
219-
}
220203
const tabContext = (tab: api.UiComponent) => {
221204
const tabPage: DeepReadonly<api.RootUiComponent> | string = tab.config.page
222205
? componentStore.page((tab.config.page as string).replace('page:', ''))!
@@ -291,7 +274,7 @@ const editPage = () => {
291274
onClick: () => {
292275
const tabPageUid = (page.value!.slots.default![currentTab.value]!.config.page as string).replace('page:', '')
293276
const tabPage = componentStore.page(tabPageUid)!
294-
const tabPageType = getPageType(tabPage)
277+
const tabPageType = getPageType(tabPage).type
295278
props.f7router.navigate('/settings/pages/' + tabPageType + '/' + tabPageUid)
296279
}
297280
}

bundles/org.openhab.ui/web/src/pages/settings/pages/pages-list.vue

Lines changed: 6 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,7 @@ import { f7, theme } from 'framework7-vue'
171171
172172
import { useLastSearchQueryStore } from '@/js/stores/useLastSearchQueryStore'
173173
import { showToast } from '@/js/dialog-promises'
174+
import { getPageType, getPageIcon } from '@/pages/page-type'
174175
175176
export default {
176177
props: {
@@ -187,16 +188,7 @@ export default {
187188
pages: [],
188189
selectedItems: [],
189190
groupBy: 'alphabetical',
190-
showCheckboxes: false,
191-
pageTypes: [
192-
{ type: 'sitemap', label: 'Sitemap', componentType: 'Sitemap', icon: 'f7:menu' },
193-
{ type: 'layout', label: 'Layout', componentType: 'oh-layout-page', icon: 'f7:rectangle_grid_2x2' },
194-
{ type: 'home', label: 'Home', componentType: 'oh-home-page', icon: 'f7:house' },
195-
{ type: 'tabs', label: 'Tabbed', componentType: 'oh-tabs-page', icon: 'f7:squares_below_rectangle' },
196-
{ type: 'map', label: 'Map', componentType: 'oh-map-page', icon: 'f7:map' },
197-
{ type: 'plan', label: 'Floor plan', componentType: 'oh-plan-page', icon: 'f7:square_stack_3d_up' },
198-
{ type: 'chart', label: 'Chart', componentType: 'oh-chart-page', icon: 'f7:graph_square' }
199-
]
191+
showCheckboxes: false
200192
}
201193
},
202194
computed: {
@@ -214,7 +206,7 @@ export default {
214206
}, {})
215207
} else {
216208
const typeGroups = this.pages.reduce((prev, page, i, things) => {
217-
const type = this.getPageType(page).label
209+
const type = getPageType(page).label
218210
if (!prev[type]) {
219211
prev[type] = []
220212
}
@@ -292,7 +284,7 @@ export default {
292284
if (this.showCheckboxes) {
293285
this.toggleItemCheck(event, item.uid, item)
294286
} else {
295-
this.f7router.navigate(this.getPageType(item).type + '/' + item.uid)
287+
this.f7router.navigate(getPageType(item).type + '/' + item.uid)
296288
}
297289
},
298290
ctrlClick(event, item) {
@@ -308,15 +300,8 @@ export default {
308300
this.selectedItems.push(itemName)
309301
}
310302
},
311-
getPageType(page) {
312-
return this.pageTypes.find((t) => t.componentType === page.component)
313-
},
314-
getPageIcon(page) {
315-
if (page.uid === 'overview') return 'f7:house'
316-
if (page.config && page.config.icon) return page.config.icon
317-
const pageType = this.pageTypes.find((t) => t.componentType === page.component)
318-
return pageType ? pageType.icon : 'f7:tv'
319-
},
303+
getPageType,
304+
getPageIcon,
320305
removeSelected() {
321306
const vm = this
322307

0 commit comments

Comments
 (0)