OR-backed widgets
Some MyDash widgets surface data from OpenRegister (OR). OR is an optional dependency: MyDash MUST work on a plain Nextcloud installation with no OR present.
This page documents the canonical pattern every OR-backed widget MUST follow.
The three rules
- Feature-detect at runtime. Never assume OR is installed. Always
call
useOrFeatureDetect()and checkenabled.valuebefore any OR API call. - Pass
?_lang=when fetching translatable data. OR stores translatable content in multiple languages. Pass the current user locale so OR returns the correct language variant. - Render a documented empty state when OR is absent or returns 5xx. A widget that silently fails is worse than one that shows a clear "OpenRegister not available" notice.
Canonical pattern
<template>
<NcEmptyContent
v-if="!or.enabled.value"
icon="icon-openregister"
:name="t('mydash', 'OpenRegister not available')"
:description="t('mydash', 'Enable OpenRegister to surface this data.')"
/>
<div v-else-if="loading">
<NcLoadingIcon />
</div>
<ul v-else>
<li v-for="item in items" :key="item.id">{{ item.name }}</li>
</ul>
</template>
<script>
import { ref, onMounted } from 'vue'
import axios from '@nextcloud/axios'
import { generateUrl } from '@nextcloud/router'
import { translate as t } from '@nextcloud/l10n'
import { useOrFeatureDetect } from '../composables/useOrFeatureDetect.js'
export default {
name: 'MyOrWidget',
setup() {
const or = useOrFeatureDetect()
const items = ref([])
const loading = ref(false)
onMounted(async () => {
if (!or.enabled.value) return // graceful empty state
loading.value = true
try {
// Pass ?_lang= for translatable OR data (ADR-025).
const lang = document.documentElement.lang || 'en'
const url = generateUrl('/apps/openregister/api/objects')
const { data } = await axios.get(url, {
params: {
register: 'my-register',
schema: 'my-schema',
_lang: lang,
},
})
items.value = data.results ?? []
} catch {
// 5xx / network failure: leave items empty, widget stays visible
// but shows no rows (acceptable degraded state per spec REQ-OR-005).
} finally {
loading.value = false
}
})
return { or, items, loading, t }
},
}
</script>
useTenantContext() (pending multi-tenancy-context)
When OR surfaces tenant-scoped data, widgets SHOULD additionally use
useTenantContext() from @conduction/nextcloud-vue to pass the active
tenant scope. This composable is in nc-vue PR #113; once released as a
versioned package, OR-backed widgets that are tenant-aware MUST adopt it.
Until then, widgets MAY omit tenant filtering — OR's server-side ACL still enforces per-session access.
Migration checklist for existing widgets
- Import
useOrFeatureDetectinstead of callinguseAppStatus('openregister')directly. - Guard every
axios.get('/apps/openregister/...')withif (!or.enabled.value) return. - Add
params: { _lang: document.documentElement.lang }to every OR fetch that requests translatable fields. - Add an
NcEmptyContentfallback for the OR-absent case.
See openspec/specs/runtime-or-consumption/spec.md for the full
requirements and acceptance criteria.