obm-upload-form-ui
v0.3.6
Published
Reusable UI component library for rendering and submitting OpenBioMaps upload forms via obm-project-api
Downloads
1,107
Readme
obm-upload-form-ui
A reusable UI component library for rendering and submitting OpenBioMaps
upload forms, built on the obm-project-api v3 form schema
(GET /forms, GET /forms/{publishedFormId}, POST /forms/{formId}).
Status: v0, work in progress. Photo/attachment upload (
file_id/photo_idfields, ADR 0007) is implemented. Thespatialandcustom_checkvalidation rules are not evaluated client-side and report as "unsupported". ADR 0008 records whyspatialstays that way (the boundary geometry is in the schema, but as hex EWKB, and it's enforced server-side anyway). ADR 0009 records whycustom_checkstays that way (it names arbitrary project-specific server PHP with no generic contract to mirror — and its one dispatch path turns out to have been broken, an uncaught server error, since 2019, unreachable in practice).
Installation
npm install obm-upload-form-uiThe /custom-elements entry point is also published to npm, so no-build hosts can load it straight
from a CDN mirror instead of installing it, e.g.:
<script
type="module"
src="https://cdn.jsdelivr.net/npm/obm-upload-form-ui/dist/custom-elements/obm-upload-form.js"
></script>Packages in one repo
| Entry point | What it is | Dependencies |
| ------------------------------------ | ----------------------------------------------------------------------------------------------------------- | ---------------------------------------- |
| obm-upload-form-ui | Framework-free core: typed form schema, API client, validation engine, submit client, WKT↔GeoJSON utilities | none |
| obm-upload-form-ui/vue | Vue 3 field widgets and the <UploadForm> orchestrator | vue (peer) |
| obm-upload-form-ui/vue-leaflet | Leaflet-based geometry field widget | vue, leaflet, leaflet-draw (peers) |
| obm-upload-form-ui/custom-elements | Self-contained <obm-upload-form> custom element (ES + IIFE bundles, Vue inlined) for no-build hosts | none |
Quick start (core)
import {
createFormApi,
cookieAuth,
validateForm,
canSubmit,
submitObservation,
buildMetadata,
} from 'obm-upload-form-ui';
const config = {
baseUrl: 'https://example.org/projects/my_project/api/v3',
language: 'en', // sent as Accept-Language (lowercased); localizes column short_name only
appVersion: 'my-app 1.0.0',
auth: cookieAuth(),
};
const api = createFormApi(config);
const forms = await api.listForms();
const schema = await api.getForm(forms[0].published_form_id);
const data = { species: 'Lanius collurio', number: 5 };
const result = validateForm(schema, data, 'final');
if (canSubmit(result)) {
const live = await api.resolveLiveForm(schema.header.published_form_id);
await submitObservation(config, {
formId: live.formId,
data,
metadata: buildMetadata({ formVersion: live.formVersion, appVersion: config.appVersion }),
});
}Validation model
The API currently performs no field-level validation on write (it proxies to the legacy
upload engine), so this library's validation engine is the enforcement layer. See
docs/adr/0002-validation-policy-model.md:
- Document states:
draft(skips checks by default, matching existing OBM client behavior) andfinal(enforces). softrules warn but never block.ValidationPolicy.enforcementcan be set to'warn'to make all validation non-blocking once server-side validation exists.
Linked submissions (repeated groups)
The form schema has no repeated/nested field groups. The established OBM convention is separate
linked forms sharing a client-generated UUID as a foreign key. submitLinked() orchestrates this:
one parent POST plus N child POSTs, all stamped with the shared id. There is no server-side
transaction — partial failure is reported per item (failed + remaining), and
resumeLinked(config, plan, result) finishes the submission under the same shared id, posting
only the items not yet accepted. Don't retry by calling submitLinked() again: it re-posts the
parent, which a unique shared-id column refuses (or, without one, duplicates). Note that
remaining excludes the failed item itself; outstandingItems(result) lists both.
Development
npm install
npm test # unit + component tests (integration tests skip without OBM_API_BASE)
npm run dev # Storybook
npm run build # library + custom-elements bundles into dist/
npm run typecheck
npm run lintTesting against a live API
Contract fixtures under tests/fixtures/forms/ prefixed synthetic- are hand-derived from the
API source, not captured responses. Replace them with real captures:
OBM_API_BASE=https://example.org/projects/my_project/api/v3 OBM_ACCESS_TOKEN=... npm run capture:fixtures
OBM_API_BASE=... npm run test:integrationNote: the API allows localhost/127.0.0.1 origins only when its ENV != PROD.
Demo app
demo/ is a Vite app deployable into an OBM project via the spa_integration module. See
docs/spa-integration-deployment.md for build/packaging constraints and known host-side bugs.
npm run demo:dev # local dev server
npm run demo:build # dist + dist-archives/<appName>.zip ready for uploadReleases
Versioning, CHANGELOG.md, GitLab Releases, and npm publishing are all automated by
semantic-release from commit messages on main — see
.releaserc.json. Use Conventional Commits prefixes
(feat:, fix:, docs:, refactor:, etc.) so the pipeline can compute the next version
correctly; a feat: commit triggers a minor release, fix:/docs:/refactor:/... trigger a
patch release, and a BREAKING CHANGE: footer (or ! after the type) triggers a major release.
See docs/adr/0004-release-and-publish-strategy.md for the full pipeline design.
Publishing to npm uses Trusted Publishing (OIDC) —
the CI pipeline exchanges a short-lived GitLab-issued token for a one-time npm publish token, so no
long-lived NPM_TOKEN is stored in the project. See
docs/adr/0005-npm-trusted-publishing.md for the setup and the one-time manual bootstrap it
required.
Design documents
- Architecture decisions:
docs/adr/ - Live-verification checklist (what automated tests cannot cover):
docs/live-verification.md - Findings and production-readiness verdict from the THR SPA rebuild (0.3.0 → 0.3.5):
docs/reviews/002-thr-spa-rebuild.md - Upstream feasibility study:
web-app/docs/architecture/upload-form-component-library-feasibility-study.md
License
GPL-3.0-or-later, matching the OpenBioMaps ecosystem. Note: GPL on a library means consumers must be GPL-compatible; if embedding into non-GPL third-party apps ever becomes a goal, LGPL would be the deliberate alternative — relicensing later requires all contributors' consent (see ADR 0001).
