Skip to content

Commit e776cdf

Browse files
committed
add suggestions for invalid page component
Signed-off-by: Jimmy Tanagra <jcode@tanagra.id.au>
1 parent d428fec commit e776cdf

File tree

2 files changed

+63
-1
lines changed

2 files changed

+63
-1
lines changed

bundles/org.openhab.ui/web/src/pages/page-type-mixin.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,13 +49,23 @@ export function getPageIcon(page?: api.RootUiComponent | DeepReadonly<api.RootUi
4949
return getPageType(page).icon
5050
}
5151

52+
/**
53+
* Return the list of known page component type keys.
54+
*/
55+
export function getPageComponentTypes(): string[] {
56+
return Object.keys(pageTypes)
57+
}
58+
5259
const PageType = {
5360
methods: {
5461
getPageType(page: api.RootUiComponent | DeepReadonly<api.RootUiComponent> | null) {
5562
return getPageType(page)
5663
},
5764
getPageIcon(page: api.RootUiComponent | DeepReadonly<api.RootUiComponent> | null) {
5865
return getPageIcon(page)
66+
},
67+
getPageComponentTypes() {
68+
return getPageComponentTypes()
5969
}
6070
}
6171
}

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

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,12 @@
1010
<b>Page ID:</b> {{ uid || f7route.params.uid }}<br />
1111
<b>Component:</b> <code class="text-color-red">{{ page.component }}</code>
1212
</p>
13+
<div v-if="suggestions.length">
14+
<b>Did you mean:</b>
15+
<ul>
16+
<li v-for="s in suggestions" :key="s">{{ s }}</li>
17+
</ul>
18+
</div>
1319
</f7-block>
1420

1521
<f7-block>
@@ -19,6 +25,8 @@
1925
</template>
2026

2127
<script>
28+
import { getPageComponentTypes } from '@/pages/page-type-mixin'
29+
2230
export default {
2331
props: {
2432
uid: String,
@@ -27,7 +35,8 @@ export default {
2735
},
2836
data() {
2937
return {
30-
page: null
38+
page: null,
39+
suggestions: []
3140
}
3241
},
3342
methods: {
@@ -38,10 +47,53 @@ export default {
3847
.get('/rest/ui/components/ui:page/' + uid)
3948
.then((data) => {
4049
this.page = data
50+
this.computeSuggestions()
4151
})
4252
.catch(() => {
4353
this.page = null
54+
this.suggestions = []
4455
})
56+
},
57+
computeSuggestions() {
58+
if (!this.page || !this.page.component) {
59+
this.suggestions = []
60+
return
61+
}
62+
const target = String(this.page.component).toLowerCase()
63+
const candidates = getPageComponentTypes()
64+
const scored = candidates.map((c) => ({
65+
name: c,
66+
dist: this.levenshtein(c.toLowerCase(), target)
67+
}))
68+
scored.sort((a, b) => a.dist - b.dist)
69+
// pick top 3 suggestions with reasonable distance
70+
const threshold = Math.max(3, Math.floor(target.length / 3))
71+
this.suggestions = scored
72+
.filter((s) => s.dist <= threshold)
73+
.slice(0, 3)
74+
.map((s) => s.name)
75+
},
76+
levenshtein(a, b) {
77+
const al = a.length
78+
const bl = b.length
79+
if (al === 0) return bl
80+
if (bl === 0) return al
81+
const prev = new Array(bl + 1)
82+
for (let j = 0; j <= bl; j++) prev[j] = j
83+
for (let i = 1; i <= al; i++) {
84+
let cur = new Array(bl + 1)
85+
cur[0] = i
86+
for (let j = 1; j <= bl; j++) {
87+
const cost = a[i - 1] === b[j - 1] ? 0 : 1
88+
cur[j] = Math.min(
89+
prev[j] + 1, // deletion
90+
cur[j - 1] + 1, // insertion
91+
prev[j - 1] + cost // substitution
92+
)
93+
}
94+
for (let j = 0; j <= bl; j++) prev[j] = cur[j]
95+
}
96+
return prev[bl]
4597
}
4698
}
4799
}

0 commit comments

Comments
 (0)