@aprendomx/sinpapel-vue
v0.4.2
Published
Vue 3 workflow-tracking widgets for the sinpapel-drf API
Maintainers
Readme
@aprendomx/sinpapel-vue
v0.4.1 — Vue 3 UI layer for sinpapel.
Workflow-tracking widgets on top of the sinpapel-drf REST API: audit history, document requirements + uploads, structured metadata, transition preview, SLA status, and polymorphic electronic signature — without hand-writing a single request, store, or form.
Table of Contents
- What is sinpapel-vue?
- Installation
- Quick start
- Components
- Client API
- Store & composables
- Internationalization (i18n)
- Theming
- TypeScript
- Compatibility
- Development & testing
- Known limitations & Roadmap
- Versioning & Stability
- Documentation & agent skills
- License & Contributing
1. What is sinpapel-vue?
@aprendomx/sinpapel-vue is the front-end layer of the sinpapel ecosystem. Where sinpapel-drf auto-publishes REST endpoints for every @workflow_enabled Django model, this library auto-renders the UI that drives them: one <SeguimientoPanel> gives an end user the full case-tracking experience.
Where it fits
| Package | Runtime | Role | |---|---|---| | sinpapel | Django | Engine — versioned state machines, immutable audit, signing backends, predicates, SLA, metadata | | sinpapel-drf | Django + DRF | HTTP layer — the API this package consumes | | sinpapel-webhooks | Django | Event-driven outbound/inbound HTTP communication | | sinpapel-reports | Django | Template-driven document generation (PDF overlay + DOCX) | | @aprendomx/sinpapel-vue | Vue 3 | Runtime UI — case tracking for end users (this package) | | sinpapel-designer | Vue 3 SPA | Design-time UI — visual flow editor, schema v0.2 import/export |
Rule of thumb: sinpapel-designer models the flow, sinpapel-vue runs it. The designer is a standalone SPA for authoring flows; this package is an embeddable component library for the people who move cases through those flows.
Endpoint coverage
Every sinpapel-drf instance endpoint has a client method and a component behind it:
| sinpapel-drf endpoint | Verb | Client method | Component |
|---|---|---|---|
| available-transitions/ | GET | availableTransitions() | TransitionDialog (target selector) |
| transition/ | POST | transition(payload) | TransitionDialog |
| history/ | GET | history({page, pageSize}) | HistoryTimeline |
| preview-transition/ | POST | previewTransition(targetState) | PreviewTransitionPanel |
| metadatos/ | GET / PATCH | getMetadatos() / patchMetadatos(values) | MetadatosForm |
| sla-status/ | POST | slaStatus() | SlaStatusPanel |
| requisitos/ | GET | requisitos() | RequisitosPanel, DocumentosPanel |
| documentos/ | GET / POST | listDocumentos() / uploadDocumento(payload) | DocumentosPanel |
| documentos/<id>/ | DELETE | deleteDocumento(id) | DocumentosPanel |
Design pillars
- Zero boilerplate in the consumer. No stores, no serializers, no fetch code. Mount one component with a resource slug and a pk.
- Bring your own transport. You inject a configured
axiosinstance (auth, CSRF,baseURL, interceptors). The library ships no HTTP dependency of its own. - Polymorphic signature UI.
TransitionDialogmirrors the backend'sSignatureRequestSerializerdispatch: FIEL client-side (recommended), FIEL server-side (gated), manual, or fake. - Backend drives enforcement. Whether a transition requires a signature comes from
preview-transition'sfirma_requerida, not from client-side config. - Graceful degradation. Features that need a newer
sinpapel-drfdetect their absence and fall back (e.g. withoutfirma_requeridathe signature stays optional). - Headless-friendly. The client, the Pinia store and the composables are exported, so you can keep the logic and render your own UI.
2. Installation
npm install @aprendomx/sinpapel-vue
# required peer dependencies:
npm install vue pinia quasarNote: Quasar is a hard peer dependency. Widgets reuse
q-*components (e.g.,q-dialog,q-icon).
axios is not a dependency: you pass your own instance (see below).
3. Quick start
<script setup>
import axios from 'axios'
import { SeguimientoPanel } from '@aprendomx/sinpapel-vue'
import '@aprendomx/sinpapel-vue/style.css'
const http = axios.create({ withCredentials: true })
</script>
<template>
<SeguimientoPanel
:axios="http"
base-path="/sinpapel/api"
resource="solicitudes"
:pk="42"
current-state="EN_REVISION"
/>
</template>base-path must match where you mounted the SinpapelRouter in urls.py. The resource prop must be the effective_slug of the model decorated with @workflow_enabled (i.e. endpoint_slug if declared, otherwise workflow_key + "s"). There is no auto-discovery.
Important:
SeguimientoPanelcreates its store from the initial props. Ifpkorresourcechange dynamically, pass:key="pk"to force a remount.
4. Components
SeguimientoPanel
Main composed widget. Renders the current state badge, the tab bar (History / Requirements / Documents / Preview / Metadata / SLA) and the transition dialog.
Props:
| Prop | Type | Required | Default | Description |
|------|------|----------|---------|-------------|
| axios | Object | Yes | — | Axios instance (auth, baseURL, interceptors) |
| basePath | string | No | /sinpapel/api | Base path where the API is mounted |
| resource | string | Yes | — | Resource slug (effective_slug) |
| pk | number \| string | Yes | — | Instance ID |
| currentState | string | No | '' | Current state to show in the badge |
| canEvaluateSla | boolean | No | false | Show the SLA tab |
| locale | string | No | 'es' | Language (es or en) |
Emits: none (everything handled internally via the store).
StateBadge
State pill with a color dot.
Props:
| Prop | Type | Required | Default |
|------|------|----------|---------|
| estado | string | Yes | — |
| color | string | No | '' |
| label | string | No | '' |
The default label humanizes the state name (EN_REVISION → EN REVISION). If color is passed, color-mix is used for the background.
HistoryTimeline
Vertical timeline over history entries.
Props:
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| entries | Array | [] | History rows |
| page | number | 1 | Current page |
| pageSize | number | 0 | Page size (0 = no pagination) |
| count | number | 0 | Total records |
Emits: prev, next.
TransitionDialog
Modal dialog to execute a state transition. Includes target state selector, comments, conditions and polymorphic signature (FIEL client-side/server-side, manual, fake).
Props:
| Prop | Type | Required | Default |
|------|------|----------|---------|
| modelValue | boolean | No | false |
| client | Object | Yes | — |
| currentState | string | No | '' |
| estados | Array | No | [] |
Emits: update:modelValue, transitioned(result).
Validation:
- Target state is required
- A signature backend is required when the backend reports
firma_requeridafor the chosen target (the "no signature" option is disabled and the fieldset is marked as required) .cer,.keyfiles and password required for FIEL server-side
PreviewTransitionPanel
Read-only panel that previews the impact of a transition before executing it: blocking reasons, missing documents, failed predicates, and a "requires signature" indicator when the report carries firma_requerida.
Props:
| Prop | Type | Required | Default |
|------|------|----------|---------|
| client | Object | Yes | — |
| targetState | string | No | '' |
Debounced by 300ms on targetState changes.
MetadatosForm
Form generated from the backend metadata schema (SCHEMA_METADATOS exposed by GET .../metadatos/).
Props:
| Prop | Type | Required |
|------|------|----------|
| client | Object | Yes |
Emits: saved(values).
SlaStatusPanel
Panel to evaluate SLA status (admin only — the endpoint is permission-gated server-side).
Props:
| Prop | Type | Required |
|------|------|----------|
| client | Object | Yes |
RequisitosPanel
Read-only checklist of documentary requirements for the current state
(RequisitoEstadoDocumento fulfillment). Consumes GET …/requisitos/.
Props:
| Prop | Type | Required |
|------|------|----------|
| client | Object | Yes |
DocumentosPanel
Lists, uploads (multipart) and deletes documents for the case. Consumes
GET/POST …/documentos/, DELETE …/documentos/{id}/ and GET …/requisitos/.
The upload form uses selects: the document type comes from the current
state's requirements and the document is a dependent select of the type
(e.g. "Identificación" → "Pasaporte" / "INE"). No percentage is asked — it is
set by the requirement config (RequisitoEstadoDocumento.porcentaje).
Requires sinpapel-drf >= 0.4.0.
Props:
| Prop | Type | Required |
|------|------|----------|
| client | Object | Yes |
Emits: changed (after upload or delete).
5. Client API
import { createSinpapelClient } from '@aprendomx/sinpapel-vue'
const client = createSinpapelClient({
axios: myAxiosInstance, // required
basePath: '/sinpapel/api', // default
resource: 'solicitudes', // required
pk: 42, // can be changed later via client.pk = ...
})Methods:
| Method | HTTP | Path | Returns |
|--------|------|------|---------|
| availableTransitions() | GET | /{resource}/{pk}/available-transitions/ | Estado[] |
| history({page, pageSize}) | GET | /{resource}/{pk}/history/ | HistoryResponse \| HistoryEntry[] |
| previewTransition(targetState) | POST | /{resource}/{pk}/preview-transition/ | PreviewReport |
| getMetadatos() | GET | /{resource}/{pk}/metadatos/ | {schema, values} |
| patchMetadatos(values) | PATCH | /{resource}/{pk}/metadatos/ | updated values |
| slaStatus() | POST | /{resource}/{pk}/sla-status/ | SlaAction[] |
| transition(payload) | POST | /{resource}/{pk}/transition/ | TransitionResult |
| requisitos() | GET | /{resource}/{pk}/requisitos/ | RequisitoStatus[] |
| listDocumentos() | GET | /{resource}/{pk}/documentos/ | InstanciaDocumento[] |
| uploadDocumento(payload) | POST | /{resource}/{pk}/documentos/ | InstanciaDocumento |
| deleteDocumento(id) | DELETE | /{resource}/{pk}/documentos/{id}/ | — |
transition(payload) accepts { target_state, comentarios?, condiciones?, signature? }. The exported helper buildTransitionRequest(payload) picks the wire format: plain JSON, or multipart/form-data when the signature block carries FIEL server-side files.
uploadDocumento({ archivo, documento?, tipo_documento?, porcentaje?, metadatos? }) is sent as multipart/form-data and must include documento or tipo_documento. The buildDocumentoUpload(payload) helper builds the FormData (encoding metadatos as JSON).
All calls support AbortController for cancellation. The store creates an AbortController per action and exposes cancel().
Error mapping follows sinpapel-drf: 403 for permission/predicate failures, 400 for validation and signature errors. Responses surface untouched in store.error / tx.error.
6. Store & composables
useSeguimientoStore
import { useSeguimientoStore } from '@aprendomx/sinpapel-vue'
const store = useSeguimientoStore({ axios, resource: 'solicitudes', pk: 42 })Reactive state:
estados,historial,historialCount,metadatos,preview,slaActions,documentos,requisitosloading:{ estados, historial, metadatos, transicion, documentos, requisitos }(booleans)error: last API error
Actions:
cargarEstados(),cargarHistorial(page?),ejecutarTransicion(payload),cargarMetadatos(),guardarMetadatos(values),cargarPreview(targetState),evaluarSla()cargarRequisitos(),cargarDocumentos(),subirDocumento(payload),eliminarDocumento(id)(the last two refresh list + requirements)cancel(): aborts all in-flight requests
useTransition(client)
Manages the state and logic of a transition.
const tx = useTransition(client)
tx.targetState.value = 'APROBADA'
await tx.checkFirmaRequerida() // asks preview-transition whether a signature is mandatory
tx.comentarios.value = 'Approved by committee'
await tx.submit() // validates, builds payload, sends, resets on successReturns: { targetState, comentarios, condiciones, signatureBackend, signatureMode, signatureFields, signaturePayload, firmaRequerida, checkFirmaRequerida, loading, error, errors, buildPayload, submit, reset, validate }
checkFirmaRequerida() is tolerant: clients without previewTransition, older backends, or network errors all resolve to false (signature optional).
useSpLabels()
Gets localized labels. Used automatically inside child components of SeguimientoPanel.
buildSignaturePayload(backend, mode, fields)
Pure helper that shapes the signature block per backend × mode, mirroring SignatureRequestSerializer. Exported for custom transition UIs.
7. Internationalization (i18n)
Supports es (Spanish) and en (English) with no external dependencies.
<SeguimientoPanel ... locale="en" />To add a new language, create a file in src/locales/ and register it in useSpLabels.js.
8. Theming
CSS variables --sp-* can be overridden in your scope:
:root {
--sp-color-primary: #3a4a5c;
--sp-surface: #ffffff;
--sp-border: #dfe3e8;
/* ...see src/styles/tokens.css */
}Remember to import the stylesheet once: import '@aprendomx/sinpapel-vue/style.css'.
9. TypeScript
Type definitions are in types/index.d.ts and resolve automatically:
import { createSinpapelClient, SeguimientoPanel, useTransition } from '@aprendomx/sinpapel-vue'
import type { SinpapelClient, TransitionPayload, Estado, PreviewReport } from '@aprendomx/sinpapel-vue'10. Compatibility
| Vue | Pinia | Quasar | Node (CI) | |---|---|---|---| | 3.5+ | 3.0+ | 2.16+ | 20, 22 |
Backend matrix:
| Backend package | Minimum | Notes |
|---|---|---|
| sinpapel | 0.8.x | Engine behind the API |
| sinpapel-drf | 0.3.x | Baseline: transitions, history, preview, metadata, SLA |
| sinpapel-drf | 0.4.0 | Required by DocumentosPanel (dependent selects: tipo_documento_id, documentos_disponibles) |
| sinpapel-drf | 0.4.4 | Required for mandatory-signature enforcement (firma_requerida in the preview report) |
Newer features degrade to their previous behavior on older backends rather than breaking.
11. Development & testing
npm install
npm run dev # development server (demo/)
npm test # full vitest suite (77 tests)
npm run test:watch # watch mode
npm run build # library build → dist/
npm run lint # eslintCI (.github/workflows/ci.yml) runs lint, tests and build on Node 20 and 22 for every push and pull request to main/master.
Publishing: npm publish. The prepublishOnly script guarantees only code that passes lint + tests + build ships.
12. Known limitations & Roadmap
Limitations:
GET …/history/returns thin django-simple-history records. Comments and signatures are not shown unless the backend exposes them.- No auto-discovery of the
resourceslug; the consumer must pass it explicitly. SeguimientoPanelbuilds its store from the initial props — dynamicpk/resourceneed a:keyremount.- Quasar is required even if you only use a subset of the widgets.
Roadmap:
- Slot-based customization of the panel tabs.
- Optional Quasar-free build.
- Richer history rows once
sinpapel-drfexposes them.
13. Versioning & Stability
This package follows Semantic Versioning. The current release is v0.4.0 (Beta). Pre-1.0 contract: minor releases may include breaking changes (documented in the changelog); patch releases are fixes only. Pin the minor ("@aprendomx/sinpapel-vue": "~0.4.0") until 1.0.0.
The public surface is what src/index.js exports: components, createSinpapelClient, buildTransitionRequest, buildDocumentoUpload, useSeguimientoStore, useTransition, buildSignaturePayload.
14. Documentation & agent skills
- Changelog
- sinpapel usage guide — engine concepts (states, transitions, predicates, requirements, signing)
- sinpapel-drf README — the API contract this library consumes
- sinpapel-boilerplate — Django + Vue project skeleton with the ecosystem versions pinned
For AI agents: sinpapel-skills publishes multi-provider skills (Claude, Cursor, OpenCode) for the whole ecosystem. Four of them cover this package: sinpapel-vue-setup, sinpapel-vue-client, sinpapel-vue-components and sinpapel-vue-store.
15. License & Contributing
GPL-3.0-or-later — see LICENSE.
Copyright (C) 2024-2026 AprendoMX. This software is free: you can redistribute it and/or modify it under the terms of the GNU GPL v3. It is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY.
Issues + PRs at https://github.com/aprendomx/sinpapel-vue/issues. Tag with area/sinpapel-vue.
Related projects:
- sinpapel — engine core (workflow + signature + audit + predicates + SLA + metadata)
- sinpapel-drf — REST layer consumed by this library
- sinpapel-webhooks — event-driven HTTP communication
- sinpapel-reports — template-driven document generation
- sinpapel-designer — visual workflow editor
