npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@aprendomx/sinpapel-vue

v0.4.2

Published

Vue 3 workflow-tracking widgets for the sinpapel-drf API

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.

🇪🇸 Leer en Español

npm Vue Quasar Node License: GPL v3 Tests


Table of Contents

  1. What is sinpapel-vue?
  2. Installation
  3. Quick start
  4. Components
  5. Client API
  6. Store & composables
  7. Internationalization (i18n)
  8. Theming
  9. TypeScript
  10. Compatibility
  11. Development & testing
  12. Known limitations & Roadmap
  13. Versioning & Stability
  14. Documentation & agent skills
  15. 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 axios instance (auth, CSRF, baseURL, interceptors). The library ships no HTTP dependency of its own.
  • Polymorphic signature UI. TransitionDialog mirrors the backend's SignatureRequestSerializer dispatch: FIEL client-side (recommended), FIEL server-side (gated), manual, or fake.
  • Backend drives enforcement. Whether a transition requires a signature comes from preview-transition's firma_requerida, not from client-side config.
  • Graceful degradation. Features that need a newer sinpapel-drf detect their absence and fall back (e.g. without firma_requerida the 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 quasar

Note: 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: SeguimientoPanel creates its store from the initial props. If pk or resource change 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_requerida for the chosen target (the "no signature" option is disabled and the fieldset is marked as required)
  • .cer, .key files 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, requisitos
  • loading: { 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 success

Returns: { 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       # eslint

CI (.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 resource slug; the consumer must pass it explicitly.
  • SeguimientoPanel builds its store from the initial props — dynamic pk/resource need a :key remount.
  • 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-drf exposes 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

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: