@seatsyoo/vue 1.0.0 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +40 -1
- package/dist/SeatsyooChart.d.ts +4 -1
- package/dist/SeatsyooChart.js +3 -1
- package/dist/SeatsyooDesigner.d.ts +71 -0
- package/dist/SeatsyooDesigner.js +138 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.js +2 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -240,7 +240,43 @@ hidrata y monta el visor. En Nuxt funciona tal cual (también dentro de `<Client
|
|
|
240
240
|
No va en el paquete: el visor la descarga de `${server}/sdk/butacas-3d.js` cuando alguien la abre. Si tu web
|
|
241
241
|
tiene una política de seguridad de contenidos (CSP), añade esa dirección a `script-src`, o pasa `:view3d="false"`.
|
|
242
242
|
|
|
243
|
-
|
|
243
|
+
## El diseñador de planos
|
|
244
|
+
|
|
245
|
+
`<SeatsyooDesigner>` abre en tu web el diseñador de planos de Seatsyoo, para que tus clientes dibujen sus recintos.
|
|
246
|
+
Tu servidor abre una sesión para un plano con su clave secreta (`POST /api/v1/charts/{plano}/designer-sessions`, o
|
|
247
|
+
`charts.designerSession` de `@seatsyoo/node`) y le da el token a tu web:
|
|
248
|
+
|
|
249
|
+
```vue
|
|
250
|
+
<script setup lang="ts">
|
|
251
|
+
import { SeatsyooDesigner } from "@seatsyoo/vue";
|
|
252
|
+
|
|
253
|
+
defineProps<{ token: string }>();
|
|
254
|
+
const emit = defineEmits<{ cerrar: [] }>();
|
|
255
|
+
// Tu servidor abre otra sesión del mismo plano y te da el token (aquí, una ruta tuya).
|
|
256
|
+
const pedirToken = (): Promise<string> =>
|
|
257
|
+
fetch("/mi-api/disenador/teatro", { method: "POST" }).then((r) => r.json()).then((s: { token: string }) => s.token);
|
|
258
|
+
</script>
|
|
259
|
+
|
|
260
|
+
<template>
|
|
261
|
+
<SeatsyooDesigner
|
|
262
|
+
server="https://seatsyoo.example"
|
|
263
|
+
:token="token"
|
|
264
|
+
:refresh-token="pedirToken"
|
|
265
|
+
style="height: 80vh"
|
|
266
|
+
@publish="({ version }) => console.log('Publicada la versión', version)"
|
|
267
|
+
@close="emit('cerrar')"
|
|
268
|
+
/>
|
|
269
|
+
</template>
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
Props: `server`, `token`, `language` y `refreshToken` (pide a tu servidor otro token del mismo plano antes de que
|
|
273
|
+
caduque: sin ella, al caducar deja de guardar). Eventos: `ready`, `save`, `publish`, `close` («←» sale si hay quien
|
|
274
|
+
escuche `@close` al montarse) y `error`. `class`, `style` e `id` van al `<div>`, que necesita alto. Un `token` nuevo se le
|
|
275
|
+
manda sin volver a montarlo; cambiar `server` o `language`, o pasar o quitar `refreshToken`, lo vuelve a montar. Con
|
|
276
|
+
una ref de plantilla, `disenador.value.designer` es el diseñador (`setToken()`, `iframe`). `app.use(SeatsyooPlugin)`
|
|
277
|
+
también lo registra. En el servidor (SSR) pinta solo el `<div>`.
|
|
278
|
+
|
|
279
|
+
La referencia completa de opciones, avisos y métodos está en la documentación de Seatsyoo (**/docs/visor**, **/docs/disenador** y
|
|
244
280
|
**/docs/frameworks**).
|
|
245
281
|
|
|
246
282
|
## Licencia
|
|
@@ -273,6 +309,9 @@ npm install @seatsyoo/vue
|
|
|
273
309
|
(never the selected keys). -->
|
|
274
310
|
```
|
|
275
311
|
|
|
312
|
+
- **Embedded designer**: `<SeatsyooDesigner server :token :refresh-token @publish @close style="height: 80vh" />` opens
|
|
313
|
+
the Seatsyoo chart designer in your website, with a session token your server opens with its secret key
|
|
314
|
+
(`POST /api/v1/charts/{chart}/designer-sessions`).
|
|
276
315
|
- **Props**: every viewer option except `container` and the callbacks; `class`, `style`, `id` and other attributes
|
|
277
316
|
go to the wrapping `<div>`. `app.use(SeatsyooPlugin)` registers `<SeatsyooChart>` globally.
|
|
278
317
|
- **Events**: `ready`, `change`, `select`, `deselect`, `error`, `hold-expired`, `hold-token-change`,
|
package/dist/SeatsyooChart.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { type ChartDocument, type Language, type SeatingChart, type SelectedObject, type StatusStyle, type View3DModule } from "@seatsyoo/visor";
|
|
2
2
|
import { type ComponentOptionsMixin, type DefineComponent, type ExtractPublicPropTypes, type Plugin, type PropType } from "vue";
|
|
3
|
+
import { SeatsyooDesigner } from "./SeatsyooDesigner.js";
|
|
3
4
|
declare const props: {
|
|
4
5
|
/** URL base del servidor de Seatsyoo, p. ej. https://seatsyoo.example */
|
|
5
6
|
server: {
|
|
@@ -139,12 +140,14 @@ export type SeatsyooChartComponent = DefineComponent<typeof props, SeatsyooChart
|
|
|
139
140
|
* mientras no hay ninguno.
|
|
140
141
|
*/
|
|
141
142
|
export declare const SeatsyooChart: SeatsyooChartComponent;
|
|
142
|
-
/** Plugin que registra <SeatsyooChart> en toda la aplicación: `app.use(SeatsyooPlugin)`. */
|
|
143
|
+
/** Plugin que registra <SeatsyooChart> y <SeatsyooDesigner> en toda la aplicación: `app.use(SeatsyooPlugin)`. */
|
|
143
144
|
export declare const SeatsyooPlugin: Plugin;
|
|
144
145
|
declare module "vue" {
|
|
145
146
|
interface GlobalComponents {
|
|
146
147
|
/** El visor de Seatsyoo (registrado con `app.use(SeatsyooPlugin)`). */
|
|
147
148
|
SeatsyooChart: typeof SeatsyooChart;
|
|
149
|
+
/** El diseñador de planos de Seatsyoo (registrado con `app.use(SeatsyooPlugin)`). */
|
|
150
|
+
SeatsyooDesigner: typeof SeatsyooDesigner;
|
|
148
151
|
}
|
|
149
152
|
}
|
|
150
153
|
export {};
|
package/dist/SeatsyooChart.js
CHANGED
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
// ese momento, sin volver a montar.
|
|
12
12
|
import { render, } from "@seatsyoo/visor";
|
|
13
13
|
import { defineComponent, getCurrentInstance, h, onBeforeUnmount, onMounted, shallowRef, toRaw, watch, } from "vue";
|
|
14
|
+
import { SeatsyooDesigner } from "./SeatsyooDesigner.js";
|
|
14
15
|
import { aplicarEnVivo, avisarEnConsola, copiaDeDatos, enVivoDe, errorDeOpciones, identidadDe, igual, opcionesEnVivo, sinIndefinidos, sueltaAlCambiar, } from "./opciones.js";
|
|
15
16
|
// Los booleanos con `default: undefined`: sin él, Vue los pone a false si no se pasan, y el visor los quiere
|
|
16
17
|
// sin indicar (su valor por defecto es «sí»).
|
|
@@ -216,9 +217,10 @@ const componente = defineComponent({
|
|
|
216
217
|
* mientras no hay ninguno.
|
|
217
218
|
*/
|
|
218
219
|
export const SeatsyooChart = componente;
|
|
219
|
-
/** Plugin que registra <SeatsyooChart> en toda la aplicación: `app.use(SeatsyooPlugin)`. */
|
|
220
|
+
/** Plugin que registra <SeatsyooChart> y <SeatsyooDesigner> en toda la aplicación: `app.use(SeatsyooPlugin)`. */
|
|
220
221
|
export const SeatsyooPlugin = {
|
|
221
222
|
install(app) {
|
|
222
223
|
app.component("SeatsyooChart", SeatsyooChart);
|
|
224
|
+
app.component("SeatsyooDesigner", SeatsyooDesigner);
|
|
223
225
|
},
|
|
224
226
|
};
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { type EmbeddedDesigner, type Language } from "@seatsyoo/visor";
|
|
2
|
+
import { type ComponentOptionsMixin, type DefineComponent, type ExtractPublicPropTypes, type PropType } from "vue";
|
|
3
|
+
type Estado = "draft" | "published" | "published-with-draft";
|
|
4
|
+
declare const props: {
|
|
5
|
+
/** URL base del servidor de Seatsyoo, p. ej. https://seatsyoo.example */
|
|
6
|
+
server: {
|
|
7
|
+
type: StringConstructor;
|
|
8
|
+
required: true;
|
|
9
|
+
};
|
|
10
|
+
/** El token de la sesión del diseñador (dsg_…), que abre tu servidor con su clave secreta. */
|
|
11
|
+
token: {
|
|
12
|
+
type: StringConstructor;
|
|
13
|
+
required: true;
|
|
14
|
+
};
|
|
15
|
+
/** Idioma del diseñador: «es» (por defecto) o «en». */
|
|
16
|
+
language: PropType<Language>;
|
|
17
|
+
/** Pide a tu servidor otro token del mismo plano antes de que caduque (sin ella, al caducar deja de guardar). */
|
|
18
|
+
refreshToken: PropType<() => Promise<string>>;
|
|
19
|
+
};
|
|
20
|
+
declare const emits: {
|
|
21
|
+
/** El diseñador está abierto con el plano. */
|
|
22
|
+
ready: (info: {
|
|
23
|
+
chart: string;
|
|
24
|
+
status: Estado;
|
|
25
|
+
publishedVersion: number | null;
|
|
26
|
+
canPublish: boolean;
|
|
27
|
+
}) => boolean;
|
|
28
|
+
/** Se han guardado los cambios en el borrador. */
|
|
29
|
+
save: (info: {
|
|
30
|
+
chart: string;
|
|
31
|
+
status: Estado;
|
|
32
|
+
}) => boolean;
|
|
33
|
+
/** Se ha publicado una versión nueva. */
|
|
34
|
+
publish: (info: {
|
|
35
|
+
chart: string;
|
|
36
|
+
version: number;
|
|
37
|
+
}) => boolean;
|
|
38
|
+
/** Se ha pulsado «←» (sale solo si hay quien escuche @close al montarse). */
|
|
39
|
+
close: () => boolean;
|
|
40
|
+
/** Algo ha fallado: `{ code, message }`. Sin oyente, se escribe en la consola. */
|
|
41
|
+
error: (error: {
|
|
42
|
+
code: string;
|
|
43
|
+
message: string;
|
|
44
|
+
}) => boolean;
|
|
45
|
+
};
|
|
46
|
+
/** Props de SeatsyooDesigner: las opciones del diseñador, sin `container` ni los avisos (que son eventos). */
|
|
47
|
+
export type SeatsyooDesignerProps = ExtractPublicPropTypes<typeof props>;
|
|
48
|
+
/** Lo que expone el componente a una ref de plantilla. */
|
|
49
|
+
export interface SeatsyooDesignerExposed {
|
|
50
|
+
/** El diseñador abierto (`setToken()`, `iframe`), o null mientras no hay ninguno. */
|
|
51
|
+
designer: EmbeddedDesigner | null;
|
|
52
|
+
}
|
|
53
|
+
/** Su tipo público, escrito a mano como el de SeatsyooChart (con los parámetros que no han cambiado desde Vue 3.3). */
|
|
54
|
+
export type SeatsyooDesignerComponent = DefineComponent<typeof props, SeatsyooDesignerExposed, {}, {}, {}, ComponentOptionsMixin, ComponentOptionsMixin, typeof emits>;
|
|
55
|
+
/**
|
|
56
|
+
* El diseñador de planos de Seatsyoo en tu web, con el token de una sesión que abre tu servidor con su clave secreta
|
|
57
|
+
* (`POST /api/v1/charts/{plano}/designer-sessions`, o `charts.designerSession` de `@seatsyoo/node`).
|
|
58
|
+
*
|
|
59
|
+
* ```vue
|
|
60
|
+
* <SeatsyooDesigner
|
|
61
|
+
* server="https://seatsyoo.example"
|
|
62
|
+
* :token="token"
|
|
63
|
+
* :refresh-token="pedirToken"
|
|
64
|
+
* style="height: 80vh"
|
|
65
|
+
* @publish="({ version }) => console.log(version)"
|
|
66
|
+
* @close="abierto = false"
|
|
67
|
+
* />
|
|
68
|
+
* ```
|
|
69
|
+
*/
|
|
70
|
+
export declare const SeatsyooDesigner: SeatsyooDesignerComponent;
|
|
71
|
+
export {};
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
// SeatsyooDesigner: el diseñador de planos de Seatsyoo, incrustado en tu web, como componente de Vue 3 (3.3 o posterior),
|
|
2
|
+
// sin SFC (defineComponent y una función render), como SeatsyooChart.
|
|
3
|
+
//
|
|
4
|
+
// - Se monta en onMounted: en el servidor (SSR) solo se pinta el <div> vacío. Antes de desmontar, destroy().
|
|
5
|
+
// - Vuelve a montarse si cambia `server` o `language`, o si se pasa o se quita `refreshToken`: la página del diseñador
|
|
6
|
+
// sabe al abrirse si puede pedir tokens nuevos. «←» sale si al montarse hay quien escuche @close.
|
|
7
|
+
// - Un `token` nuevo con el diseñador abierto no lo vuelve a montar: se le manda (setToken), como al renovarlo.
|
|
8
|
+
// - Los avisos salen como eventos de Vue (ready, save, publish, close, error); refreshToken es una prop (devuelve el
|
|
9
|
+
// token) y se llama siempre la última recibida.
|
|
10
|
+
import { designer } from "@seatsyoo/visor";
|
|
11
|
+
import { defineComponent, getCurrentInstance, h, onBeforeUnmount, onMounted, shallowRef, watch, } from "vue";
|
|
12
|
+
import { avisarEnConsola, errorDeOpciones } from "./opciones.js";
|
|
13
|
+
const props = {
|
|
14
|
+
/** URL base del servidor de Seatsyoo, p. ej. https://seatsyoo.example */
|
|
15
|
+
server: { type: String, required: true },
|
|
16
|
+
/** El token de la sesión del diseñador (dsg_…), que abre tu servidor con su clave secreta. */
|
|
17
|
+
token: { type: String, required: true },
|
|
18
|
+
/** Idioma del diseñador: «es» (por defecto) o «en». */
|
|
19
|
+
language: String,
|
|
20
|
+
/** Pide a tu servidor otro token del mismo plano antes de que caduque (sin ella, al caducar deja de guardar). */
|
|
21
|
+
refreshToken: Function,
|
|
22
|
+
};
|
|
23
|
+
// Los parámetros solo dan el tipo de cada evento (Vue valida con lo que devuelven: siempre sí).
|
|
24
|
+
const emits = {
|
|
25
|
+
/** El diseñador está abierto con el plano. */
|
|
26
|
+
ready: (info) => true,
|
|
27
|
+
/** Se han guardado los cambios en el borrador. */
|
|
28
|
+
save: (info) => true,
|
|
29
|
+
/** Se ha publicado una versión nueva. */
|
|
30
|
+
publish: (info) => true,
|
|
31
|
+
/** Se ha pulsado «←» (sale solo si hay quien escuche @close al montarse). */
|
|
32
|
+
close: () => true,
|
|
33
|
+
/** Algo ha fallado: `{ code, message }`. Sin oyente, se escribe en la consola. */
|
|
34
|
+
error: (error) => true,
|
|
35
|
+
};
|
|
36
|
+
const componente = defineComponent({
|
|
37
|
+
name: "SeatsyooDesigner",
|
|
38
|
+
props,
|
|
39
|
+
emits,
|
|
40
|
+
expose: ["designer"],
|
|
41
|
+
setup(props, { emit }) {
|
|
42
|
+
const abierto = shallowRef(null);
|
|
43
|
+
const el = shallowRef(null);
|
|
44
|
+
const instancia = getCurrentInstance();
|
|
45
|
+
let vivo = false;
|
|
46
|
+
/** El último token que se le dio al diseñador abierto. */
|
|
47
|
+
let token = "";
|
|
48
|
+
/** ¿Hay alguien escuchando ese evento ahora mismo? */
|
|
49
|
+
function escuchan(evento) {
|
|
50
|
+
const p = instancia?.vnode.props;
|
|
51
|
+
const f = p?.[evento] ?? p?.[`${evento}Once`];
|
|
52
|
+
return typeof f === "function" || Array.isArray(f);
|
|
53
|
+
}
|
|
54
|
+
function desmontar() {
|
|
55
|
+
const anterior = abierto.value;
|
|
56
|
+
abierto.value = null;
|
|
57
|
+
anterior?.destroy();
|
|
58
|
+
}
|
|
59
|
+
function montar() {
|
|
60
|
+
desmontar();
|
|
61
|
+
const div = el.value;
|
|
62
|
+
if (!div)
|
|
63
|
+
return;
|
|
64
|
+
const refresh = props.refreshToken;
|
|
65
|
+
try {
|
|
66
|
+
abierto.value = designer({
|
|
67
|
+
container: div,
|
|
68
|
+
server: props.server,
|
|
69
|
+
token: props.token,
|
|
70
|
+
...(props.language ? { language: props.language } : {}),
|
|
71
|
+
...(refresh ? { refreshToken: () => (props.refreshToken ?? refresh)() } : {}),
|
|
72
|
+
...(escuchan("onClose") ? { onClose: () => emit("close") } : {}),
|
|
73
|
+
onReady: (i) => emit("ready", i),
|
|
74
|
+
onSave: (i) => emit("save", i),
|
|
75
|
+
onPublish: (i) => emit("publish", i),
|
|
76
|
+
onError: (e) => (escuchan("onError") ? emit("error", e) : avisarEnConsola(e)),
|
|
77
|
+
});
|
|
78
|
+
token = props.token;
|
|
79
|
+
}
|
|
80
|
+
catch (err) {
|
|
81
|
+
const error = errorDeOpciones(err);
|
|
82
|
+
if (escuchan("onError"))
|
|
83
|
+
emit("error", error);
|
|
84
|
+
else
|
|
85
|
+
console.error("[seatsyoo]", error.message);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
onMounted(() => {
|
|
89
|
+
vivo = true;
|
|
90
|
+
montar();
|
|
91
|
+
});
|
|
92
|
+
onBeforeUnmount(() => {
|
|
93
|
+
vivo = false;
|
|
94
|
+
desmontar();
|
|
95
|
+
});
|
|
96
|
+
watch(() => [props.server, props.language, !!props.refreshToken], () => {
|
|
97
|
+
if (vivo)
|
|
98
|
+
montar();
|
|
99
|
+
});
|
|
100
|
+
watch(() => props.token, (nuevo) => {
|
|
101
|
+
const d = abierto.value;
|
|
102
|
+
if (!vivo || !d || nuevo === token)
|
|
103
|
+
return;
|
|
104
|
+
try {
|
|
105
|
+
d.setToken(nuevo);
|
|
106
|
+
token = nuevo;
|
|
107
|
+
}
|
|
108
|
+
catch (err) {
|
|
109
|
+
const error = errorDeOpciones(err);
|
|
110
|
+
if (escuchan("onError"))
|
|
111
|
+
emit("error", error);
|
|
112
|
+
else
|
|
113
|
+
avisarEnConsola(error);
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
return { designer: abierto, el };
|
|
117
|
+
},
|
|
118
|
+
render() {
|
|
119
|
+
// class, style, id y demás atributos pasan solos a este <div> (inheritAttrs).
|
|
120
|
+
return h("div", { ref: "el" });
|
|
121
|
+
},
|
|
122
|
+
});
|
|
123
|
+
/**
|
|
124
|
+
* El diseñador de planos de Seatsyoo en tu web, con el token de una sesión que abre tu servidor con su clave secreta
|
|
125
|
+
* (`POST /api/v1/charts/{plano}/designer-sessions`, o `charts.designerSession` de `@seatsyoo/node`).
|
|
126
|
+
*
|
|
127
|
+
* ```vue
|
|
128
|
+
* <SeatsyooDesigner
|
|
129
|
+
* server="https://seatsyoo.example"
|
|
130
|
+
* :token="token"
|
|
131
|
+
* :refresh-token="pedirToken"
|
|
132
|
+
* style="height: 80vh"
|
|
133
|
+
* @publish="({ version }) => console.log(version)"
|
|
134
|
+
* @close="abierto = false"
|
|
135
|
+
* />
|
|
136
|
+
* ```
|
|
137
|
+
*/
|
|
138
|
+
export const SeatsyooDesigner = componente;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,2 +1,3 @@
|
|
|
1
1
|
export { SeatsyooChart, type SeatsyooChartExposed, type SeatsyooChartProps, SeatsyooPlugin } from "./SeatsyooChart.js";
|
|
2
|
-
export
|
|
2
|
+
export { SeatsyooDesigner, type SeatsyooDesignerExposed, type SeatsyooDesignerProps } from "./SeatsyooDesigner.js";
|
|
3
|
+
export type { ChartDocument, EmbeddedDesigner, EmbeddedDesignerOptions, Language, RenderOptions, SeatingChart, SelectedObject, StatusStyle, } from "@seatsyoo/visor";
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1,3 @@
|
|
|
1
|
-
// @seatsyoo/vue: el visor de mapas de asientos de Seatsyoo como
|
|
1
|
+
// @seatsyoo/vue: el visor de mapas de asientos de Seatsyoo y su diseñador de planos como componentes de Vue 3.
|
|
2
2
|
export { SeatsyooChart, SeatsyooPlugin } from "./SeatsyooChart.js";
|
|
3
|
+
export { SeatsyooDesigner } from "./SeatsyooDesigner.js";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@seatsyoo/vue",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "Componente de Vue para el visor de mapas de asientos de Seatsyoo: elegir butacas, retenerlas y venderlas en tiempo real.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"keywords": [
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
"dist/*.d.ts"
|
|
28
28
|
],
|
|
29
29
|
"dependencies": {
|
|
30
|
-
"@seatsyoo/visor": "^1.
|
|
30
|
+
"@seatsyoo/visor": "^1.1.0"
|
|
31
31
|
},
|
|
32
32
|
"peerDependencies": {
|
|
33
33
|
"vue": "^3.3.0"
|