Skip to content

Commit f4e786d

Browse files
committed
Refactor to TypeScript Composition API
Signed-off-by: Florian Hotze <dev@florianhotze.com>
1 parent 714e030 commit f4e786d

1 file changed

Lines changed: 124 additions & 113 deletions

File tree

Lines changed: 124 additions & 113 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<template>
2-
<f7-card v-if="item.type !== 'Group' || item.groupType">
2+
<f7-card v-if="item.type !== 'Group' || 'groupType' in item">
33
<f7-card-content v-if="loaded && services.length > 0">
44
<f7-list media-list>
55
<f7-list-item
@@ -33,124 +33,135 @@
3333
right 6px
3434
</style>
3535

36-
<script>
37-
export default {
38-
props: {
39-
item: Object
40-
},
41-
computed: {
42-
strategies () {
43-
const strategies = {}
44-
this.services.forEach((service) => strategies[service.id] = this.serviceStrategies(service.id))
45-
return strategies
46-
},
47-
persistedBadges () {
48-
const badges = {}
49-
this.services.forEach((service) => {
50-
const persisted = service.persisted
51-
if (!persisted) {
52-
// Query for persistence items not supported
53-
badges[service.id] = null
54-
} else if (persisted.count != null && Number.isInteger(Number(persisted.count))) {
55-
// Show numeric count when available
56-
badges[service.id] = String(persisted.count)
57-
} else if (persisted.name) {
58-
// No numeric count, but persisted value(s): show a presence indicator (empty badge)
59-
badges[service.id] = ' '
60-
} else {
61-
// Item has not been persisted
62-
// badges[service.id] = '0'
63-
// TODO: Currently, the API call does not distinguish between API call not supported for service and item not persisted.
64-
// To avoid showing misleading information, don't show badge if we don't get anything back (should be covered by first case if REST API is fixed.)
65-
// This can be reverted to showing 0 if the API is fixed.
66-
badges[service.id] = null
67-
}
68-
})
69-
return badges
36+
<script setup lang="ts">
37+
import { computed, onMounted, ref } from 'vue'
38+
import * as api from '@/api'
39+
import { ApiError } from '@/js/hey-api.ts'
40+
41+
// props
42+
const props = defineProps<{ item: api.EnrichedItem | api.EnrichedGroupItem }>()
43+
44+
// data
45+
interface PersistenceService extends api.PersistenceService {
46+
configs: Array<api.PersistenceItemConfiguration>
47+
aliases: Record<string, string>
48+
editable: boolean
49+
persisted: api.PersistenceItemInfo | null
50+
}
51+
52+
const services = ref<Array<PersistenceService>>([])
53+
const loaded = ref<boolean>(false)
54+
55+
// computed
56+
const strategies = computed(() => {
57+
const strategies: Record<string, Array<string>> = {}
58+
services.value.forEach((service) => strategies[service.id] = serviceStrategies(service))
59+
return strategies
60+
})
61+
62+
const persistedBadges = computed(() => {
63+
const badges: Record<string, string | null> = {}
64+
services.value.forEach((service) => {
65+
const persisted = service.persisted
66+
if (!persisted) {
67+
// Query for persistence items not supported
68+
badges[service.id] = null
69+
} else if (persisted.count != null && Number.isInteger(Number(persisted.count))) {
70+
// Show numeric count when available
71+
badges[service.id] = String(persisted.count)
72+
} else if (persisted.name) {
73+
// No numeric count, but persisted value(s): show a presence indicator (empty badge)
74+
badges[service.id] = ' '
75+
} else {
76+
// Item has not been persisted
77+
// badges[service.id] = '0'
78+
// TODO: Currently, the API call does not distinguish between API call not supported for service and item not persisted.
79+
// To avoid showing misleading information, don't show badge if we don't get anything back (should be covered by first case if REST API is fixed.)
80+
// This can be reverted to showing 0 if the API is fixed.
81+
badges[service.id] = null
7082
}
71-
},
72-
data () {
73-
return {
74-
services: [],
75-
loaded: false
83+
})
84+
return badges
85+
})
86+
87+
// hooks
88+
onMounted(() => {
89+
load()
90+
})
91+
92+
// methods
93+
const load = async () => {
94+
loaded.value = false
95+
const availableServices = (await api.getPersistenceServices())!
96+
services.value = (await Promise.all(
97+
availableServices.map((service) => loadService(service))
98+
)).sort((s1, s2) => s1.label.localeCompare(s2.label))
99+
loaded.value = true
100+
}
101+
102+
const loadService = async (service: api.PersistenceService): Promise<PersistenceService> => {
103+
let serviceConfig: api.PersistenceServiceConfiguration | null = null
104+
try {
105+
serviceConfig = (await api.getPersistenceServiceConfiguration({ serviceId: service.id })) ?? null
106+
} catch (err: unknown) {
107+
if (err instanceof ApiError && (err.response.statusText === 'Not Found' || err.response.status === 404)) {
108+
// No configuration yet, continue with an empty one
109+
} else {
110+
console.debug('Error loading persistence config for', service.id, err)
76111
}
77-
},
78-
mounted () {
79-
this.load()
80-
},
81-
methods: {
82-
async load () {
83-
this.loaded = false
84-
const services = await this.$oh.api.get('/rest/persistence')
85-
this.services = (await Promise.all(
86-
services.map((service) => this.loadService(service))
87-
)).sort((s1, s2) => s1.label.localeCompare(s2.label))
88-
this.loaded = true
89-
},
90-
async loadService (service) {
91-
let serviceConfig = {}
92-
try {
93-
serviceConfig = await this.$oh.api.get('/rest/persistence/' + service.id)
94-
} catch (err) {
95-
if (err?.response?.status === 404) {
96-
// No configuration yet, continue with an empty one
97-
} else {
98-
console.debug('Error loading persistence config for', service.id, err)
99-
}
100-
}
112+
}
101113
102-
let itemsPersisted = null
103-
try {
104-
itemsPersisted = await this.$oh.api.get('/rest/persistence/items?serviceId=' + service.id)
105-
} catch (err) {
106-
if (err?.response?.status === 400) {
107-
// Not supported for service, leave itemsPersisted null
108-
} else {
109-
console.debug('Error loading persistence items for', service.id, err)
110-
}
111-
}
114+
let itemsPersisted: Array<api.PersistenceItemInfo> = []
115+
try {
116+
itemsPersisted = await api.getItemsForPersistenceService({ serviceId: service.id }) ?? []
117+
} catch (err: unknown) {
118+
if (err instanceof ApiError && (err.response.statusText === 'Not Found' || err.response.status === 404)) {
119+
// Not supported for service, leave itemsPersisted null
120+
} else {
121+
console.debug('Error loading persistence items for', service.id, err)
122+
}
123+
}
112124
113-
return {
114-
...service,
115-
configs: serviceConfig.configs || [],
116-
aliases: serviceConfig.aliases,
117-
editable: serviceConfig.editable === undefined ? true : serviceConfig.editable,
118-
persisted: itemsPersisted ? (itemsPersisted.find((item) => item.name === this.item.name) || {}) : null
119-
}
120-
},
121-
serviceStrategies (serviceId) {
122-
let strategies = []
123-
const persistenceConfig = this.services.find((persistence) => persistence.id === serviceId)
124-
persistenceConfig?.configs?.forEach((config) => {
125-
const items = config.items
126-
if (items && config.strategies?.length) {
127-
if (!this.matchesItem(this.item, items, true) && this.matchesItem(this.item, items, false)) {
128-
// No negative match and a positive match
129-
strategies = [...strategies, ...config.strategies]
130-
}
131-
}
132-
})
133-
return [...new Set(strategies)]
134-
},
135-
matchesItem (item, items, negativeMatch) {
136-
if (!items || !Array.isArray(items)) {
137-
return false
138-
}
139-
const itemName = item.name
140-
const groupNames = item.groupNames || []
141-
let itemPattern
142-
let groupPatterns
143-
if (!negativeMatch) {
144-
if (items.includes('*')) return true
145-
itemPattern = itemName
146-
groupPatterns = items.filter((configItem) => !configItem.startsWith('!') && configItem.endsWith('*')).map((configItem) => configItem.slice(0, -1))
147-
} else {
148-
itemPattern = '!' + itemName
149-
groupPatterns = items.filter((configItem) => configItem.startsWith('!') && configItem.endsWith('*')).map((configItem) => configItem.slice(1, -1))
125+
return {
126+
...service,
127+
configs: serviceConfig?.configs ?? [],
128+
aliases: serviceConfig?.aliases ?? {},
129+
editable: serviceConfig?.editable === undefined ? true : serviceConfig?.editable,
130+
persisted: itemsPersisted.find((item) => item.name === props.item.name) ?? null
131+
} satisfies PersistenceService
132+
}
133+
134+
const serviceStrategies = (service: PersistenceService) => {
135+
let strategies: Array<string> = []
136+
service.configs?.forEach((config) => {
137+
const items = config.items
138+
if (items && config.strategies?.length) {
139+
if (!matchesItem(props.item, items, true) && matchesItem(props.item, items, false)) {
140+
// No negative match and a positive match
141+
strategies = [...strategies, ...config.strategies]
150142
}
151-
if (items.includes(itemPattern)) return true
152-
return groupPatterns.some((groupName) => groupNames.includes(groupName))
153143
}
144+
})
145+
return [...new Set(strategies)]
146+
}
147+
148+
const matchesItem = (item: api.EnrichedItem | api.EnrichedGroupItem, items: Array<string>, negativeMatch: boolean) => {
149+
if (!items || !Array.isArray(items)) {
150+
return false
151+
}
152+
const itemName = item.name
153+
const groupNames = item.groupNames || []
154+
let itemPattern: string | null = null
155+
let groupPatterns: Array<string> = []
156+
if (!negativeMatch) {
157+
if (items.includes('*')) return true
158+
itemPattern = itemName
159+
groupPatterns = items.filter((configItem) => !configItem.startsWith('!') && configItem.endsWith('*')).map((configItem) => configItem.slice(0, -1))
160+
} else {
161+
itemPattern = '!' + itemName
162+
groupPatterns = items.filter((configItem) => configItem.startsWith('!') && configItem.endsWith('*')).map((configItem) => configItem.slice(1, -1))
154163
}
164+
if (items.includes(itemPattern)) return true
165+
return groupPatterns.some((groupName) => groupNames.includes(groupName))
155166
}
156167
</script>

0 commit comments

Comments
 (0)