jsegd-bpm 0.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/LICENSE.md +48 -0
- package/README.md +553 -0
- package/dist/assets/workflow-C51JnySw.css +72 -0
- package/dist/jsegd-bpm.d.ts +1045 -0
- package/dist/jsegd-bpm.js +2 -0
- package/dist/jsegd-bpm.js.map +1 -0
- package/dist/jsegd-fluig.d.ts +892 -0
- package/dist/jsegd-fluig.js +2 -0
- package/dist/jsegd-fluig.js.map +1 -0
- package/package.json +59 -0
|
@@ -0,0 +1,1045 @@
|
|
|
1
|
+
import { ICache } from 'jsegd';
|
|
2
|
+
import { Alpine } from 'alpinejs';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Resposta de sucesso retornada pelo endpoint `/dataset/api/v2/dataset-handle/search` (HTTP 200).
|
|
6
|
+
*/
|
|
7
|
+
interface DatasetResponse {
|
|
8
|
+
/** Nomes dos campos retornados pelo dataset. */
|
|
9
|
+
columns: string[];
|
|
10
|
+
/** Linhas de dados retornadas pelo dataset. */
|
|
11
|
+
values: DatasetRow[];
|
|
12
|
+
}
|
|
13
|
+
/** Uma linha do dataset — chaves são os nomes dos campos retornados. */
|
|
14
|
+
type DatasetRow = Record<string, unknown>;
|
|
15
|
+
/**
|
|
16
|
+
* Resposta de erro retornada pela API Fluig (HTTP 400, 401, 500).
|
|
17
|
+
*/
|
|
18
|
+
interface DatasetError {
|
|
19
|
+
/** Código de erro. */
|
|
20
|
+
code: string;
|
|
21
|
+
/** Mensagem resumida do erro. */
|
|
22
|
+
message: string;
|
|
23
|
+
/** Mensagem detalhada do erro. */
|
|
24
|
+
detailedMessage: string;
|
|
25
|
+
/** URL de ajuda, quando disponível. */
|
|
26
|
+
helpUrl?: string;
|
|
27
|
+
/** Detalhes adicionais do erro, quando presentes. */
|
|
28
|
+
details?: unknown[];
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
declare enum ConstraintsType {
|
|
32
|
+
MUST = "MUST",
|
|
33
|
+
MUST_NOT = "MUST_NOT",
|
|
34
|
+
SHOULD = "SHOULD"
|
|
35
|
+
}
|
|
36
|
+
interface SearchParams {
|
|
37
|
+
/** Código do dataset — obrigatório. */
|
|
38
|
+
datasetId: string;
|
|
39
|
+
/** Campos a retornar; omitir para retornar todos os campos. */
|
|
40
|
+
field?: string[];
|
|
41
|
+
/** Registros a ignorar — usado para paginação (padrão: 0). */
|
|
42
|
+
offset?: number;
|
|
43
|
+
/** Máximo de registros a retornar (padrão: 300; 0 = todos). */
|
|
44
|
+
limit?: number;
|
|
45
|
+
/** Nome do campo para ordenação, opcionalmente sufixado com _ASC ou _DESC. */
|
|
46
|
+
orderby?: string;
|
|
47
|
+
constraintsField?: string[];
|
|
48
|
+
constraintsInitialValue?: string[];
|
|
49
|
+
constraintsFinalValue?: string[];
|
|
50
|
+
constraintsType?: ConstraintsType[];
|
|
51
|
+
/** Quando verdadeiro, o curinga % é aceito no valor inicial/final correspondente. */
|
|
52
|
+
constraintsLikeSearch?: boolean[];
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Promise cancelável retornada por {@link WorkerManager.query}.
|
|
57
|
+
*/
|
|
58
|
+
type CancelablePromise<T> = {
|
|
59
|
+
/** Promise que resolve com o resultado da consulta. */
|
|
60
|
+
promise: Promise<T>;
|
|
61
|
+
/** Função para cancelar a requisição e liberar o worker. */
|
|
62
|
+
cancel: () => void;
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
type CacheOptions = {
|
|
66
|
+
storeName: string;
|
|
67
|
+
cacheExpirationMs: number;
|
|
68
|
+
};
|
|
69
|
+
interface WorkerManagerOptions {
|
|
70
|
+
poolSize?: number;
|
|
71
|
+
/** Injeta uma instância existente de ICache (compartilhada entre componentes). */
|
|
72
|
+
cache?: ICache;
|
|
73
|
+
/** Cria um LocalCache interno com as opções fornecidas. */
|
|
74
|
+
cacheOptions?: CacheOptions;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Gerencia um pool de Web Workers para executar consultas à API de Datasets do Fluig fora da thread principal.
|
|
78
|
+
* Suporta deduplicacão de requisições, cache em IndexedDB e cancelamento HTTP real via AbortController.
|
|
79
|
+
*
|
|
80
|
+
* @example
|
|
81
|
+
* ```typescript
|
|
82
|
+
* import { WorkerManager, ConstraintsType } from 'jsegd-bpm'
|
|
83
|
+
*
|
|
84
|
+
* const manager = new WorkerManager({
|
|
85
|
+
* poolSize: 4,
|
|
86
|
+
* cacheOptions: { storeName: 'datasetCache', cacheExpirationMs: 24 * 60 * 60 * 1000 }
|
|
87
|
+
* })
|
|
88
|
+
*
|
|
89
|
+
* const { promise, cancel } = manager.query('https://tenant.fluig.com', {
|
|
90
|
+
* datasetId: 'dsColaboradores',
|
|
91
|
+
* field: ['nome', 'email'],
|
|
92
|
+
* constraintsField: ['ativo'],
|
|
93
|
+
* constraintsInitialValue: ['true'],
|
|
94
|
+
* constraintsType: [ConstraintsType.MUST],
|
|
95
|
+
* })
|
|
96
|
+
*
|
|
97
|
+
* // Cancelar se necessário:
|
|
98
|
+
* // cancel()
|
|
99
|
+
*
|
|
100
|
+
* const result = await promise
|
|
101
|
+
* console.log(result.columns) // ['nome', 'email']
|
|
102
|
+
* console.log(result.values) // [{ nome: 'João', email: 'joao@co.com' }, ...]
|
|
103
|
+
* ```
|
|
104
|
+
*/
|
|
105
|
+
declare class WorkerManager {
|
|
106
|
+
private pool;
|
|
107
|
+
private workerMeta;
|
|
108
|
+
private taskQueue;
|
|
109
|
+
private inFlight;
|
|
110
|
+
private cache;
|
|
111
|
+
private nextRequestId;
|
|
112
|
+
constructor(options?: WorkerManagerOptions);
|
|
113
|
+
/**
|
|
114
|
+
* Consulta a API de Datasets do Fluig. Retorna uma CancelablePromise.
|
|
115
|
+
* Chame `cancel()` para abortar a requisição HTTP e liberar o worker imediatamente.
|
|
116
|
+
*/
|
|
117
|
+
query(baseUrl: string, params: SearchParams): CancelablePromise<DatasetResponse>;
|
|
118
|
+
/**
|
|
119
|
+
* Encerra todos os workers do pool. Chame quando o gerenciador não for mais necessário
|
|
120
|
+
* para evitar vazamentos de memória e workers zumbis.
|
|
121
|
+
*/
|
|
122
|
+
terminate(): void;
|
|
123
|
+
private deduplicateOrEnqueue;
|
|
124
|
+
private enqueueRequest;
|
|
125
|
+
private scheduleNext;
|
|
126
|
+
private abortRequest;
|
|
127
|
+
private handleResponse;
|
|
128
|
+
private buildUrl;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
type UploadStatus = 'success' | 'error' | 'reset';
|
|
132
|
+
interface UploadEventDetail {
|
|
133
|
+
status: UploadStatus;
|
|
134
|
+
}
|
|
135
|
+
declare global {
|
|
136
|
+
interface WindowEventMap {
|
|
137
|
+
'jsegd:upload:success': CustomEvent<UploadEventDetail>;
|
|
138
|
+
'jsegd:upload:error': CustomEvent<UploadEventDetail>;
|
|
139
|
+
'jsegd:upload:reset': CustomEvent<UploadEventDetail>;
|
|
140
|
+
'jsegd:attachment:download': CustomEvent<{
|
|
141
|
+
documentId: number;
|
|
142
|
+
}>;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/** Origem do upload de um anexo */
|
|
147
|
+
type AttachmentSource = 'button' | 'toolbar' | 'drag-drop';
|
|
148
|
+
/**
|
|
149
|
+
* Metadados associados a um único documento anexado ao processo.
|
|
150
|
+
* Persiste informações que o ECM não armazena nativamente.
|
|
151
|
+
*/
|
|
152
|
+
interface AttachmentRecord {
|
|
153
|
+
/** ID do documento no ECM */
|
|
154
|
+
documentId: number;
|
|
155
|
+
/** Mecanismo pelo qual o arquivo foi adicionado */
|
|
156
|
+
source: AttachmentSource;
|
|
157
|
+
/**
|
|
158
|
+
* Descrição base do `AttachButton` que originou o upload.
|
|
159
|
+
* Presente apenas quando `source === 'button'`.
|
|
160
|
+
*/
|
|
161
|
+
buttonDescription?: string;
|
|
162
|
+
/** Filtro de tipos de arquivo ativo no momento do upload (`null` = qualquer tipo) */
|
|
163
|
+
accept: string | null;
|
|
164
|
+
/** Número de sequência da movimentação do processo em que foi anexado */
|
|
165
|
+
workflowSequence: number;
|
|
166
|
+
/** Data e hora do upload em ISO 8601 */
|
|
167
|
+
uploadedAt: string;
|
|
168
|
+
/**
|
|
169
|
+
* Metadados arbitrários adicionados pelo consumidor da biblioteca.
|
|
170
|
+
* Nunca interpretado internamente — apenas serializado/desserializado.
|
|
171
|
+
*/
|
|
172
|
+
custom?: Record<string, unknown>;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* @protected
|
|
177
|
+
*/
|
|
178
|
+
declare class Attach {
|
|
179
|
+
private static instance;
|
|
180
|
+
/** Origem do último upload iniciado (atualizado por `add()` e `uploadBlob()`) */
|
|
181
|
+
static currentUploadSource: AttachmentSource;
|
|
182
|
+
/** Filtro de tipos do último upload iniciado */
|
|
183
|
+
static currentUploadAccept: string | null;
|
|
184
|
+
private constructor();
|
|
185
|
+
static getInstance(): Attach;
|
|
186
|
+
private interceptUploadEvents;
|
|
187
|
+
/**
|
|
188
|
+
* Abre o seletor de arquivos para adicionar um novo anexo ao processo.
|
|
189
|
+
* Aplica versionamento automático ao nome quando já existe um anexo com a mesma descrição.
|
|
190
|
+
*
|
|
191
|
+
* @param attachmentDescription Descrição (label) do anexo — usada como nome do arquivo no ECM
|
|
192
|
+
* @param accept Tipos de arquivo aceitos pelo seletor (ex: ".pdf,.docx"). `null` aceita qualquer tipo.
|
|
193
|
+
*/
|
|
194
|
+
add(attachmentDescription: string, accept: string | null | undefined): void;
|
|
195
|
+
/**
|
|
196
|
+
* Abre o visualizador de documentos para o anexo informado.
|
|
197
|
+
* Quando há mais de um anexo com a mesma descrição, exibe um modal de seleção.
|
|
198
|
+
* Bloqueia ação em processos não iniciados e valida permissões de leitura.
|
|
199
|
+
*
|
|
200
|
+
* @param attachmentDescription Descrição do anexo a ser visualizado
|
|
201
|
+
*/
|
|
202
|
+
view(attachmentDescription: string): void;
|
|
203
|
+
/**
|
|
204
|
+
* Remove um anexo do processo após confirmação via modal.
|
|
205
|
+
* Quando há mais de um anexo com a mesma descrição, exibe um modal de seleção.
|
|
206
|
+
* Valida permissões de exclusão antes de prosseguir.
|
|
207
|
+
*
|
|
208
|
+
* @param attachmentDescription Descrição do anexo a ser removido
|
|
209
|
+
*/
|
|
210
|
+
remove(attachmentDescription: string): void;
|
|
211
|
+
/**
|
|
212
|
+
* Inicia o download de um anexo pelo seu identificador de documento.
|
|
213
|
+
* Bloqueia a ação em processos não iniciados.
|
|
214
|
+
*
|
|
215
|
+
* @param documentId Identificador do documento a ser baixado
|
|
216
|
+
*/
|
|
217
|
+
static download(documentId: number): void;
|
|
218
|
+
/**
|
|
219
|
+
* Abre o painel de edição de conteúdo para o anexo informado.
|
|
220
|
+
* Filtra apenas anexos publicados que o usuário tem permissão de editar.
|
|
221
|
+
* Quando há mais de um anexo editável, exibe modal de seleção.
|
|
222
|
+
* Bloqueia a ação em processos não iniciados.
|
|
223
|
+
*
|
|
224
|
+
* @param attachmentDescription Descrição do anexo a ser editado
|
|
225
|
+
*/
|
|
226
|
+
edit(attachmentDescription: string): void;
|
|
227
|
+
/**
|
|
228
|
+
* Retorna todos os anexos do processo atual.
|
|
229
|
+
* @returns Lista de todos os objetos `Attachment` presentes no processo
|
|
230
|
+
*/
|
|
231
|
+
static getAllAttachments(): Attachment[];
|
|
232
|
+
/**
|
|
233
|
+
* Inicia o download de um Blob diretamente no navegador do usuário,
|
|
234
|
+
* sem interação com o ECM ou com o processo em execução.
|
|
235
|
+
*
|
|
236
|
+
* @param blob Conteúdo a ser baixado
|
|
237
|
+
* @param filename Nome do arquivo que será sugerido ao navegador
|
|
238
|
+
* @param type Tipo MIME do arquivo. Quando omitido, usa `blob.type`.
|
|
239
|
+
*/
|
|
240
|
+
static downloadBlob(blob: Blob, filename: string, type?: string): void;
|
|
241
|
+
/**
|
|
242
|
+
* Faz upload programático de um Blob como anexo do processo,
|
|
243
|
+
* sem abrir o seletor de arquivos nativo. Sanitiza o nome antes do envio.
|
|
244
|
+
*
|
|
245
|
+
* @param blob Arquivo no formato `Blob` — deve ser não-vazio
|
|
246
|
+
* @param description Nome/descrição do arquivo que será exibido no ECM
|
|
247
|
+
* @param type Tipo MIME do arquivo. Quando omitido, usa `blob.type`.
|
|
248
|
+
* @throws {Error} Via toast quando o Blob é inválido, o MIME está ausente ou o contexto não está disponível
|
|
249
|
+
*/
|
|
250
|
+
static uploadBlob(blob: Blob, description: string, type?: string): void;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
/**
|
|
254
|
+
* Implementa um botão para gerenciar anexos
|
|
255
|
+
* @hideconstructor
|
|
256
|
+
* @example
|
|
257
|
+
* ```html
|
|
258
|
+
* <attachment-button description="CONTRATO"></attachment-button>
|
|
259
|
+
* ```
|
|
260
|
+
*/
|
|
261
|
+
declare class AttachButton extends HTMLElement {
|
|
262
|
+
/**
|
|
263
|
+
* Descrição do tipo de anexo gerenciado pelo botão.
|
|
264
|
+
* Quando vazio, um modal é exibido para o usuário informar a descrição no momento do upload.
|
|
265
|
+
* @defaultValue `''`
|
|
266
|
+
*/
|
|
267
|
+
description: string;
|
|
268
|
+
/**
|
|
269
|
+
* Filtro de tipos de arquivo aceitos pelo seletor nativo (ex: `".pdf,.docx"`).
|
|
270
|
+
* `null` aceita qualquer tipo de arquivo.
|
|
271
|
+
*/
|
|
272
|
+
accept: string | null;
|
|
273
|
+
noaddbutton: string | null;
|
|
274
|
+
noviewbutton: string | null;
|
|
275
|
+
noeditbutton: string | null;
|
|
276
|
+
nodeletebutton: string | null;
|
|
277
|
+
private handleSuccess;
|
|
278
|
+
private handleError;
|
|
279
|
+
private handleDefault;
|
|
280
|
+
constructor();
|
|
281
|
+
static get observedAttributes(): string[];
|
|
282
|
+
attributeChangedCallback(name: string, _oldValue: string, newValue: string): void;
|
|
283
|
+
disconnectedCallback(): void;
|
|
284
|
+
/**
|
|
285
|
+
* @internal
|
|
286
|
+
*/
|
|
287
|
+
connectedCallback(): void;
|
|
288
|
+
private displayButtons;
|
|
289
|
+
private addButton;
|
|
290
|
+
private viewButton;
|
|
291
|
+
private editButton;
|
|
292
|
+
private removeButton;
|
|
293
|
+
private showModal;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
/**
|
|
297
|
+
* Modo de operação da tabela de anexos.
|
|
298
|
+
* - `buttons-only` — somente download por linha; uploads exclusivamente via `AttachButton` externos
|
|
299
|
+
* - `self-managed` — gerencia seu próprio ciclo de upload; exibe ações completas por linha;
|
|
300
|
+
* aceita `AttachButton` externos cujos atributos são herdados pela linha do anexo
|
|
301
|
+
*/
|
|
302
|
+
type AttachmentsTableMode = 'buttons-only' | 'self-managed';
|
|
303
|
+
/** Opções de configuração de `AttachmentsTable` */
|
|
304
|
+
interface AttachmentsTableOptions {
|
|
305
|
+
/** Modo de operação. Obrigatório — sem valor padrão. */
|
|
306
|
+
mode: AttachmentsTableMode;
|
|
307
|
+
/**
|
|
308
|
+
* Tipos de arquivo aceitos nos uploads avulsos do modo `self-managed`.
|
|
309
|
+
* Ex: `".pdf,.docx"`. `null` aceita qualquer tipo.
|
|
310
|
+
*/
|
|
311
|
+
accept?: string | null;
|
|
312
|
+
}
|
|
313
|
+
/**
|
|
314
|
+
* Registro de um `AttachButton` na `AttachmentsTable`.
|
|
315
|
+
* Armazenado para associar anexos existentes ao botão que os originou.
|
|
316
|
+
*/
|
|
317
|
+
interface AttachButtonRegistration {
|
|
318
|
+
/** Descrição base usada pelo botão (sem sufixo `_V\d+`). */
|
|
319
|
+
description: string;
|
|
320
|
+
/** Filtro de tipos de arquivo definido no botão. */
|
|
321
|
+
accept: string | null;
|
|
322
|
+
}
|
|
323
|
+
/**
|
|
324
|
+
* Cria e gerencia uma tabela de anexos customizada no frame pai,
|
|
325
|
+
* mantendo a tabela nativa do Fluig oculta.
|
|
326
|
+
* @hideconstructor
|
|
327
|
+
*/
|
|
328
|
+
declare class AttachmentsTable {
|
|
329
|
+
private static instance;
|
|
330
|
+
private static options;
|
|
331
|
+
private static attachInstance;
|
|
332
|
+
private static buttonRegistry;
|
|
333
|
+
private constructor();
|
|
334
|
+
/**
|
|
335
|
+
* Retorna a instância singleton da tabela de anexos.
|
|
336
|
+
* Deve ser chamado uma única vez durante a inicialização do form.
|
|
337
|
+
*
|
|
338
|
+
* @param options Configuração obrigatória de modo e accept
|
|
339
|
+
*/
|
|
340
|
+
static getInstance(options: AttachmentsTableOptions): AttachmentsTable;
|
|
341
|
+
/**
|
|
342
|
+
* Registra um `AttachButton` para que seus metadados sejam associados
|
|
343
|
+
* às linhas de anexo originadas por aquele botão.
|
|
344
|
+
* Só tem efeito no modo `self-managed`.
|
|
345
|
+
* @internal Chamado por `AttachButton` durante sua inicialização.
|
|
346
|
+
*/
|
|
347
|
+
static registerButton(registration: AttachButtonRegistration): void;
|
|
348
|
+
private static resolveButtonRegistration;
|
|
349
|
+
private static start;
|
|
350
|
+
private static render;
|
|
351
|
+
private static hydrateFromMetadata;
|
|
352
|
+
private static persistMetadata;
|
|
353
|
+
private static openNameInputModal;
|
|
354
|
+
private static getRows;
|
|
355
|
+
private static setOrder;
|
|
356
|
+
private static sortBy;
|
|
357
|
+
private static getCellValue;
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
/** Entrada de um arquivo para upload em lote via drag-and-drop */
|
|
361
|
+
type DragDropEntry = {
|
|
362
|
+
file: File;
|
|
363
|
+
name: string;
|
|
364
|
+
};
|
|
365
|
+
|
|
366
|
+
type FieldError = {
|
|
367
|
+
field?: HTMLElement | null;
|
|
368
|
+
errorMessage: string;
|
|
369
|
+
};
|
|
370
|
+
declare class BeforeSendValidate {
|
|
371
|
+
private static clearAllErrors;
|
|
372
|
+
static throwValidationError(fields: FieldError[]): never;
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
/**
|
|
376
|
+
* Override de `sendRequestEvent()` do widget de processo.
|
|
377
|
+
* Executa os hooks `beforeValidate` e `afterValidate` em sequência antes de enviar a solicitação.
|
|
378
|
+
* Reabilita os botões de ação em caso de erro ou quando a validação falha.
|
|
379
|
+
*/
|
|
380
|
+
declare function sendRequestEvent(this: ECM_WKFView): Promise<void>;
|
|
381
|
+
|
|
382
|
+
/**
|
|
383
|
+
* Contrato dos hooks customizáveis do widget de processo.
|
|
384
|
+
* Estas funções são registradas pelo `WorkflowViewPatcher` e executadas em `send-request.ts`.
|
|
385
|
+
*/
|
|
386
|
+
interface IWorkflowViewHooks {
|
|
387
|
+
/**
|
|
388
|
+
* Executado ANTES da validação principal do widget.
|
|
389
|
+
* Se lançar exceção (sync ou async), o envio é cancelado e os botões são reabilitados.
|
|
390
|
+
*/
|
|
391
|
+
beforeValidate?: () => void | Promise<void>;
|
|
392
|
+
/**
|
|
393
|
+
* Executado APÓS `beforeSendValidate` retornar `true`, mas ANTES do envio efetivo.
|
|
394
|
+
* Se lançar exceção (sync ou async), o envio é cancelado e os botões são reabilitados.
|
|
395
|
+
*/
|
|
396
|
+
afterValidate?: () => void | Promise<void>;
|
|
397
|
+
/**
|
|
398
|
+
* Executado quando a movimentação do processo é concluída com sucesso.
|
|
399
|
+
*/
|
|
400
|
+
onMoveSuccess?: () => void | Promise<void>;
|
|
401
|
+
/**
|
|
402
|
+
* Executado quando ocorre erro na movimentação do processo.
|
|
403
|
+
*/
|
|
404
|
+
onMoveError?: () => void | Promise<void>;
|
|
405
|
+
/**
|
|
406
|
+
* Executado para manipular os links exibidos na página de conclusão da movimentação.
|
|
407
|
+
*
|
|
408
|
+
* @param message - Objeto de mensagem de conclusão do processo.
|
|
409
|
+
*/
|
|
410
|
+
onCompletionLinkAdd?: (message: ProcessCompletionMessage) => void | Promise<void>;
|
|
411
|
+
}
|
|
412
|
+
/**
|
|
413
|
+
* Shape do objeto de mensagem de conclusão do processo.
|
|
414
|
+
* Passado como parâmetro para o hook `onCompletionLinkAdd`.
|
|
415
|
+
*/
|
|
416
|
+
interface ProcessCompletionMessage {
|
|
417
|
+
links: ProcessCompletionLink[];
|
|
418
|
+
[key: string]: unknown;
|
|
419
|
+
}
|
|
420
|
+
/**
|
|
421
|
+
* Shape de um link na página de conclusão da movimentação.
|
|
422
|
+
*/
|
|
423
|
+
interface ProcessCompletionLink {
|
|
424
|
+
description: string;
|
|
425
|
+
href?: string;
|
|
426
|
+
bind?: string;
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
type HooksMap = {
|
|
430
|
+
beforeValidate: Array<() => void | Promise<void>>;
|
|
431
|
+
afterValidate: Array<() => void | Promise<void>>;
|
|
432
|
+
onMoveSuccess: Array<() => void | Promise<void>>;
|
|
433
|
+
onMoveError: Array<() => void | Promise<void>>;
|
|
434
|
+
onCompletionLinkAdd: Array<(message: ProcessCompletionMessage) => void | Promise<void>>;
|
|
435
|
+
};
|
|
436
|
+
|
|
437
|
+
/**
|
|
438
|
+
* Mapa de substituições que serão aplicadas ao widget nativo de processo.
|
|
439
|
+
*/
|
|
440
|
+
declare const overrides: {
|
|
441
|
+
sendRequestEvent: typeof sendRequestEvent;
|
|
442
|
+
};
|
|
443
|
+
/**
|
|
444
|
+
* Tipo do mapa de substituições.
|
|
445
|
+
*/
|
|
446
|
+
type OverrideMap = typeof overrides;
|
|
447
|
+
/**
|
|
448
|
+
* Classe utilitária para substituir métodos no widget nativo de processo.
|
|
449
|
+
*
|
|
450
|
+
* Preserva os métodos originais para permitir reversão via `restore()`.
|
|
451
|
+
*
|
|
452
|
+
* @example
|
|
453
|
+
* ```typescript
|
|
454
|
+
* // Aguardar inicialização do widget de processo
|
|
455
|
+
* await WorkflowViewPatcher.init()
|
|
456
|
+
*
|
|
457
|
+
* // Aplicar todos os patches registrados
|
|
458
|
+
* WorkflowViewPatcher.patchAll()
|
|
459
|
+
*
|
|
460
|
+
* // Registrar hooks
|
|
461
|
+
* WorkflowViewPatcher.addBeforeValidate(async () => {
|
|
462
|
+
* console.log('Antes da validação')
|
|
463
|
+
* })
|
|
464
|
+
*
|
|
465
|
+
* WorkflowViewPatcher.addAfterValidate(async () => {
|
|
466
|
+
* console.log('Após a validação')
|
|
467
|
+
* })
|
|
468
|
+
* ```
|
|
469
|
+
*/
|
|
470
|
+
declare class WorkflowViewPatcher {
|
|
471
|
+
private static isInitialized;
|
|
472
|
+
private static isInitializing;
|
|
473
|
+
private static originalMethods;
|
|
474
|
+
/**
|
|
475
|
+
* Inicializa o patcher aguardando o carregamento do widget de processo no frame pai.
|
|
476
|
+
*
|
|
477
|
+
* Chamadas repetidas retornam imediatamente se já inicializado.
|
|
478
|
+
*
|
|
479
|
+
* @param timeout - Tempo máximo de espera em ms (padrão: 5000ms)
|
|
480
|
+
* @returns Promise<void>
|
|
481
|
+
*
|
|
482
|
+
* @throws {Error} Se outra chamada a `init()` já estiver em progresso
|
|
483
|
+
* @throws {Error} Se o widget `ECM_WKFView` não estiver disponível após o timeout
|
|
484
|
+
*
|
|
485
|
+
* @example
|
|
486
|
+
* ```typescript
|
|
487
|
+
* await WorkflowViewPatcher.init()
|
|
488
|
+
* WorkflowViewPatcher.patchAll()
|
|
489
|
+
* ```
|
|
490
|
+
*/
|
|
491
|
+
static init(timeout?: number): Promise<void>;
|
|
492
|
+
/**
|
|
493
|
+
* Aplica o patch de um override específico no widget de processo.
|
|
494
|
+
*
|
|
495
|
+
* Salva o método original antes de sobrescrever, permitindo reversão via `restore()`.
|
|
496
|
+
*
|
|
497
|
+
* @param attr - Nome do método a ser substituído
|
|
498
|
+
* @throws {Error} Se `init()` não tiver sido chamado antes
|
|
499
|
+
* @throws {Error} Se o override não estiver registrado no mapa de substituições
|
|
500
|
+
*/
|
|
501
|
+
static patch(attr: keyof OverrideMap): void;
|
|
502
|
+
/**
|
|
503
|
+
* Aplica patches para múltiplos métodos do widget de processo.
|
|
504
|
+
*
|
|
505
|
+
* @param attrs - Array com nomes dos métodos a serem substituídos
|
|
506
|
+
* @throws {Error} Se `init()` não tiver sido chamado antes
|
|
507
|
+
*/
|
|
508
|
+
static patchMany(attrs: (keyof OverrideMap)[]): void;
|
|
509
|
+
/**
|
|
510
|
+
* Aplica todos os patches registrados no mapa de substituições.
|
|
511
|
+
* @throws {Error} Se `init()` não tiver sido chamado antes
|
|
512
|
+
*/
|
|
513
|
+
static patchAll(): void;
|
|
514
|
+
/**
|
|
515
|
+
* Restaura todos os métodos do widget para as implementações originais.
|
|
516
|
+
*
|
|
517
|
+
* Deve ser chamado ao desmontar o componente em SPAs, para evitar que os patches
|
|
518
|
+
* persistam além do ciclo de vida do formulário. Também zera os flags de estado
|
|
519
|
+
* interno, permitindo reinicialização via `init()`.
|
|
520
|
+
*
|
|
521
|
+
* @example
|
|
522
|
+
* ```typescript
|
|
523
|
+
* // Ao desmontar o formulário
|
|
524
|
+
* WorkflowViewPatcher.restore()
|
|
525
|
+
* ```
|
|
526
|
+
*/
|
|
527
|
+
static restore(): void;
|
|
528
|
+
/**
|
|
529
|
+
* Acessa a lista interna de hooks para um tipo específico.
|
|
530
|
+
* Usado por `sendRequestEvent` para executar os hooks em sequência.
|
|
531
|
+
*
|
|
532
|
+
* @internal
|
|
533
|
+
*/
|
|
534
|
+
static getHooks<K extends keyof HooksMap>(key: K): HooksMap[K];
|
|
535
|
+
/**
|
|
536
|
+
* Registra uma função executada ANTES da validação principal do widget.
|
|
537
|
+
*
|
|
538
|
+
* Múltiplas chamadas acumulam handlers — nenhuma sobrescreve a anterior.
|
|
539
|
+
* Se o handler lançar exceção (sync ou async), o envio é cancelado e os botões são reabilitados.
|
|
540
|
+
*
|
|
541
|
+
* @param fn - Função a ser executada (pode ser async).
|
|
542
|
+
*
|
|
543
|
+
* @example
|
|
544
|
+
* ```typescript
|
|
545
|
+
* WorkflowViewPatcher.addBeforeValidate(async () => {
|
|
546
|
+
* const value = getValue('campo_obrigatorio')
|
|
547
|
+
* if (!value) {
|
|
548
|
+
* throw new Error('Campo obrigatório não preenchido')
|
|
549
|
+
* }
|
|
550
|
+
* })
|
|
551
|
+
* ```
|
|
552
|
+
*/
|
|
553
|
+
static addBeforeValidate(fn: () => void | Promise<void>): void;
|
|
554
|
+
/**
|
|
555
|
+
* Registra uma função executada APÓS `beforeSendValidate` retornar `true`,
|
|
556
|
+
* mas ANTES do envio efetivo da solicitação.
|
|
557
|
+
*
|
|
558
|
+
* Múltiplas chamadas acumulam handlers — nenhuma sobrescreve a anterior.
|
|
559
|
+
* Se o handler lançar exceção (sync ou async), o envio é cancelado e os botões são reabilitados.
|
|
560
|
+
*
|
|
561
|
+
* @param fn - Função a ser executada (pode ser async).
|
|
562
|
+
*
|
|
563
|
+
* @example
|
|
564
|
+
* ```typescript
|
|
565
|
+
* WorkflowViewPatcher.addAfterValidate(async () => {
|
|
566
|
+
* console.log('Validação concluída, preparando envio...')
|
|
567
|
+
* await salvarDadosLocais()
|
|
568
|
+
* })
|
|
569
|
+
* ```
|
|
570
|
+
*/
|
|
571
|
+
static addAfterValidate(fn: () => void | Promise<void>): void;
|
|
572
|
+
/**
|
|
573
|
+
* Registra uma função executada quando a movimentação do processo é concluída com sucesso.
|
|
574
|
+
*
|
|
575
|
+
* Múltiplas chamadas acumulam handlers — nenhuma sobrescreve a anterior.
|
|
576
|
+
*
|
|
577
|
+
* @param fn - Função callback executada em caso de sucesso (pode ser async).
|
|
578
|
+
*
|
|
579
|
+
* @example
|
|
580
|
+
* ```typescript
|
|
581
|
+
* WorkflowViewPatcher.addOnMoveSuccess(() => {
|
|
582
|
+
* console.log('Processo movimentado com sucesso')
|
|
583
|
+
* })
|
|
584
|
+
* ```
|
|
585
|
+
*/
|
|
586
|
+
static addOnMoveSuccess(fn: () => void | Promise<void>): void;
|
|
587
|
+
/**
|
|
588
|
+
* Registra uma função executada quando ocorre erro na movimentação do processo.
|
|
589
|
+
*
|
|
590
|
+
* Múltiplas chamadas acumulam handlers — nenhuma sobrescreve a anterior.
|
|
591
|
+
*
|
|
592
|
+
* @param fn - Função callback executada em caso de erro (pode ser async).
|
|
593
|
+
*
|
|
594
|
+
* @example
|
|
595
|
+
* ```typescript
|
|
596
|
+
* WorkflowViewPatcher.addOnMoveError(() => {
|
|
597
|
+
* console.error('Erro ao movimentar processo')
|
|
598
|
+
* })
|
|
599
|
+
* ```
|
|
600
|
+
*/
|
|
601
|
+
static addOnMoveError(fn: () => void | Promise<void>): void;
|
|
602
|
+
/**
|
|
603
|
+
* Registra uma função para manipular os links da página de conclusão da movimentação.
|
|
604
|
+
*
|
|
605
|
+
* Múltiplas chamadas acumulam handlers — nenhuma sobrescreve a anterior.
|
|
606
|
+
*
|
|
607
|
+
* @param fn - Função que recebe o objeto de conclusão e pode adicionar ou modificar links (pode ser async).
|
|
608
|
+
*
|
|
609
|
+
* @example
|
|
610
|
+
* ```typescript
|
|
611
|
+
* WorkflowViewPatcher.addOnCompletionLinkAdd((message: ProcessCompletionMessage) => {
|
|
612
|
+
* message.links.push({ description: 'Voltar ao início', href: '/inicio' })
|
|
613
|
+
* })
|
|
614
|
+
* ```
|
|
615
|
+
*/
|
|
616
|
+
static addOnCompletionLinkAdd(fn: (message: ProcessCompletionMessage) => void | Promise<void>): void;
|
|
617
|
+
}
|
|
618
|
+
|
|
619
|
+
/**
|
|
620
|
+
* Contrato agnóstico ao EGD para acesso a dados do formulário e tabelas filhas.
|
|
621
|
+
* Implementado por `BpmFormRepository` (produção) e `MockFormRepository` (testes).
|
|
622
|
+
*
|
|
623
|
+
* **Convenção de nomenclatura:** campos do formulário devem seguir `{domínio}_{atributo_snake_case}`.
|
|
624
|
+
* `load` e `save` gerenciam a conversão entre nome DOM e atributo do modelo automaticamente.
|
|
625
|
+
*/
|
|
626
|
+
interface IFormRepository {
|
|
627
|
+
/**
|
|
628
|
+
* Lê campos do formulário cujo `name` começa com `{section}_`.
|
|
629
|
+
*
|
|
630
|
+
* O prefixo `{section}_` é removido e o restante convertido de `snake_case` para `camelCase`
|
|
631
|
+
* antes de retornar — o modelo recebe atributos limpos, sem o prefixo de domínio.
|
|
632
|
+
*
|
|
633
|
+
* @param section Prefixo de domínio dos campos no formulário (ex: `'contrato'`, `'imovel'`)
|
|
634
|
+
* @returns Objeto parcial com os valores lidos, chaves em camelCase
|
|
635
|
+
*
|
|
636
|
+
* @example
|
|
637
|
+
* ```typescript
|
|
638
|
+
* // DOM: input[name="contrato_indice"], input[name="contrato_primeiro_pagamento"]
|
|
639
|
+
* const data = repository.load<Contrato>('contrato')
|
|
640
|
+
* // data.indice, data.primeiroPagamento
|
|
641
|
+
* ```
|
|
642
|
+
*/
|
|
643
|
+
load<T>(section: string): Partial<T>;
|
|
644
|
+
/**
|
|
645
|
+
* Lê todas as linhas visíveis de uma tabela filha do formulário.
|
|
646
|
+
* Cada linha corresponde a um `<tr>` visível da tabela com o `tablename` informado.
|
|
647
|
+
*
|
|
648
|
+
* @param tableName Valor do atributo `tablename` na `<table>` do formulário BPM
|
|
649
|
+
* @returns Array de objetos com os valores dos campos de cada linha
|
|
650
|
+
*/
|
|
651
|
+
loadTable<T>(tableName: string): T[];
|
|
652
|
+
/**
|
|
653
|
+
* Escreve valores no DOM do formulário para os campos do domínio informado.
|
|
654
|
+
*
|
|
655
|
+
* Converte cada chave camelCase do modelo para `{section}_{snake_case}` antes de
|
|
656
|
+
* escrever — espelha exatamente o que `load` desfaz.
|
|
657
|
+
*
|
|
658
|
+
* @param section Prefixo de domínio dos campos (ex: `'contrato'`, `'imovel'`)
|
|
659
|
+
* @param data Objeto com os valores a persistir (chaves em camelCase)
|
|
660
|
+
*
|
|
661
|
+
* @example
|
|
662
|
+
* ```typescript
|
|
663
|
+
* // Escreve input[name="contrato_indice"] e input[name="contrato_primeiro_pagamento"]
|
|
664
|
+
* repository.save<Contrato>('contrato', { indice: 'IGPM', primeiroPagamento: '2026-02-01' })
|
|
665
|
+
* ```
|
|
666
|
+
*/
|
|
667
|
+
save<T>(section: string, data: Partial<T>): void;
|
|
668
|
+
/**
|
|
669
|
+
* Substitui as linhas de uma tabela filha, removendo as existentes e
|
|
670
|
+
* recriando via `wdkAddChild`. Encapsula toda a interação com o DOM.
|
|
671
|
+
*
|
|
672
|
+
* @param tableName Valor do atributo `tablename` na `<table>` do formulário BPM
|
|
673
|
+
* @param rows Array de objetos a persistir como linhas da tabela
|
|
674
|
+
*/
|
|
675
|
+
saveTable<T>(tableName: string, rows: T[]): void;
|
|
676
|
+
}
|
|
677
|
+
|
|
678
|
+
/**
|
|
679
|
+
* Adapter de produção que isola o acesso ao DOM do formulário BPM e às
|
|
680
|
+
* funções globais `wdkAddChild`/`fnWdkRemoveChild` (definidas em `wdkdetail.js`).
|
|
681
|
+
*
|
|
682
|
+
* Segue o mesmo padrão de fronteira estabelecido por `process-context/` —
|
|
683
|
+
* este é o único arquivo autorizado a referenciar as globais do formulário BPM.
|
|
684
|
+
*/
|
|
685
|
+
declare class BpmFormRepository implements IFormRepository {
|
|
686
|
+
load<T>(section: string): Partial<T>;
|
|
687
|
+
loadTable<T>(tableName: string): T[];
|
|
688
|
+
save<T>(section: string, data: Partial<T>): void;
|
|
689
|
+
saveTable<T>(tableName: string, rows: T[]): void;
|
|
690
|
+
}
|
|
691
|
+
|
|
692
|
+
/**
|
|
693
|
+
* Implementação em memória de `IFormRepository` para uso em testes unitários.
|
|
694
|
+
* Não depende de DOM, jQuery ou da plataforma — permite testar Presenters em isolamento.
|
|
695
|
+
*
|
|
696
|
+
* Aplica a mesma lógica de prefixo e conversão de `BpmFormRepository`: armazena
|
|
697
|
+
* internamente com o nome DOM completo (`{section}_{snake_case}`) e converte para
|
|
698
|
+
* camelCase ao retornar — garantindo que os testes reflitam o comportamento real.
|
|
699
|
+
*
|
|
700
|
+
* @example
|
|
701
|
+
* const repo = new MockFormRepository()
|
|
702
|
+
* repo.save('vigencia', { prazo: '12', tipoDePrazo: 'Meses' })
|
|
703
|
+
* const data = repo.load<Vigencia>('vigencia')
|
|
704
|
+
* // data.prazo === '12'
|
|
705
|
+
* // data.tipoDePrazo === 'Meses'
|
|
706
|
+
*
|
|
707
|
+
* @example
|
|
708
|
+
* const repo = new MockFormRepository()
|
|
709
|
+
* repo.save('imovel', { cep: '01310100', logradouro: 'Av. Paulista' })
|
|
710
|
+
* repo.save('contrato', { indice: 'IGPM', primeiroPagamento: '2026-02-01' })
|
|
711
|
+
* // imovel_cep e contrato_indice são domínios distintos — sem colisão
|
|
712
|
+
*/
|
|
713
|
+
declare class MockFormRepository implements IFormRepository {
|
|
714
|
+
/** Armazena valores com chave no formato DOM completo: `{section}_{snake_case}`. */
|
|
715
|
+
private readonly store;
|
|
716
|
+
private readonly tables;
|
|
717
|
+
load<T>(section: string): Partial<T>;
|
|
718
|
+
loadTable<T>(tableName: string): T[];
|
|
719
|
+
save<T>(section: string, data: Partial<T>): void;
|
|
720
|
+
saveTable<T>(tableName: string, rows: T[]): void;
|
|
721
|
+
/**
|
|
722
|
+
* Limpa todo o estado interno — campos e tabelas.
|
|
723
|
+
* Ideal para uso em `beforeEach` nos testes.
|
|
724
|
+
*/
|
|
725
|
+
reset(): void;
|
|
726
|
+
}
|
|
727
|
+
|
|
728
|
+
/**
|
|
729
|
+
* Lê campos do formulário por mapeamento explícito `{ propriedadeModelo: nomeDOM }`.
|
|
730
|
+
*
|
|
731
|
+
* Utilitário para **processos legados** cujos campos não seguem a convenção
|
|
732
|
+
* `{domínio}_{atributo}` — use quando o nome DOM não pode ser alterado sem
|
|
733
|
+
* migração de dados no banco EGD.
|
|
734
|
+
*
|
|
735
|
+
* Novos processos devem usar `IFormRepository.load(section)` diretamente.
|
|
736
|
+
*
|
|
737
|
+
* @param fieldMap Mapeamento de propriedade do modelo → nome do campo no DOM
|
|
738
|
+
* @returns Objeto parcial com os valores lidos, chaveado pelos atributos do modelo
|
|
739
|
+
*
|
|
740
|
+
* @example
|
|
741
|
+
* ```typescript
|
|
742
|
+
* // Processo legado: campos com sufixo em vez de prefixo
|
|
743
|
+
* import { loadFields } from 'jsegd-bpm'
|
|
744
|
+
*
|
|
745
|
+
* interface Solicitante {
|
|
746
|
+
* nome: string
|
|
747
|
+
* email: string
|
|
748
|
+
* }
|
|
749
|
+
*
|
|
750
|
+
* const dados = loadFields<Solicitante>({
|
|
751
|
+
* nome: 'nome_solicitante',
|
|
752
|
+
* email: 'email_solicitante',
|
|
753
|
+
* })
|
|
754
|
+
* // dados.nome === valor de input[name="nome_solicitante"]
|
|
755
|
+
* ```
|
|
756
|
+
*/
|
|
757
|
+
declare function loadFields<T>(fieldMap: {
|
|
758
|
+
[K in keyof T]?: string;
|
|
759
|
+
}): Partial<T>;
|
|
760
|
+
|
|
761
|
+
/** Categoria de uma atividade — determina o comportamento na barra de progresso */
|
|
762
|
+
type ActivityKind =
|
|
763
|
+
/** Ação de usuário — estágio atual destacado na barra */
|
|
764
|
+
'human'
|
|
765
|
+
/** Aguardando retorno externo (webhook) — exibe spinner no estágio atual */
|
|
766
|
+
| 'system'
|
|
767
|
+
/** Suporte transversal — sobrepõe banner de alerta; não avança a barra */
|
|
768
|
+
| 'support'
|
|
769
|
+
/** Roteamento interno do motor BPM — invisível na barra */
|
|
770
|
+
| 'routing';
|
|
771
|
+
/** Definição de um módulo (aba/seção) do formulário BPM */
|
|
772
|
+
interface WorkflowModuleDefinition {
|
|
773
|
+
/** Identificador único do módulo — usado como chave nas políticas de atividade */
|
|
774
|
+
moduleId: string;
|
|
775
|
+
/** Rótulo exibido na navegação */
|
|
776
|
+
label: string;
|
|
777
|
+
/** Nome do ícone exibido junto ao rótulo */
|
|
778
|
+
icon: string;
|
|
779
|
+
/** Posição na ordem de exibição — menor valor aparece primeiro */
|
|
780
|
+
order: number;
|
|
781
|
+
/** Exibe o módulo na barra de navegação lateral/superior */
|
|
782
|
+
showInNavigation: boolean;
|
|
783
|
+
/** Renderiza o conteúdo do módulo no DOM quando visível */
|
|
784
|
+
renderContent: boolean;
|
|
785
|
+
/** Caminho do arquivo HTML incluído como conteúdo do módulo */
|
|
786
|
+
contentIncludePath: string;
|
|
787
|
+
}
|
|
788
|
+
/**
|
|
789
|
+
* Políticas de visibilidade e editabilidade dos módulos para uma atividade.
|
|
790
|
+
* `TModuleId` é inferido automaticamente por `defineWorkflowConfig`.
|
|
791
|
+
*/
|
|
792
|
+
interface ActivityModulePolicy<TModuleId extends string = string> {
|
|
793
|
+
/** Módulos visíveis nesta atividade */
|
|
794
|
+
visible: readonly TModuleId[];
|
|
795
|
+
/** Módulos editáveis nesta atividade (subconjunto de `visible`) */
|
|
796
|
+
editable: readonly TModuleId[];
|
|
797
|
+
/** Módulo ativo (tab selecionada) ao abrir o formulário nesta atividade */
|
|
798
|
+
active?: TModuleId;
|
|
799
|
+
}
|
|
800
|
+
/** Definição de uma atividade do workflow com suas políticas de módulo */
|
|
801
|
+
interface WorkflowActivityDefinition<TModuleId extends string = string> {
|
|
802
|
+
/** Número de sequência da atividade no motor BPM EGD */
|
|
803
|
+
sequence: number;
|
|
804
|
+
/** Descrição legível da atividade para fins de diagnóstico */
|
|
805
|
+
description: string;
|
|
806
|
+
/** Categoria da atividade — controla comportamento na barra de progresso */
|
|
807
|
+
kind: ActivityKind;
|
|
808
|
+
/**
|
|
809
|
+
* Estágio de negócio representado por esta atividade na barra de progresso.
|
|
810
|
+
* Obrigatório para `'human'` e `'system'`. Omitido para `'routing'`.
|
|
811
|
+
* Para `'support'`: identifica o estágio que está sendo interrompido.
|
|
812
|
+
*/
|
|
813
|
+
stage?: string;
|
|
814
|
+
/** Políticas de visibilidade e editabilidade dos módulos */
|
|
815
|
+
modules?: ActivityModulePolicy<TModuleId>;
|
|
816
|
+
}
|
|
817
|
+
/**
|
|
818
|
+
* Configuração tipada de um workflow BPM — retornada por `defineWorkflowConfig`.
|
|
819
|
+
* `TModuleId` é inferido automaticamente do array de módulos.
|
|
820
|
+
*/
|
|
821
|
+
interface WorkflowConfig<TModules extends readonly WorkflowModuleDefinition[], TModuleId extends string = TModules[number]['moduleId']> {
|
|
822
|
+
readonly modules: TModules;
|
|
823
|
+
readonly activities: readonly WorkflowActivityDefinition<TModuleId>[];
|
|
824
|
+
}
|
|
825
|
+
|
|
826
|
+
/**
|
|
827
|
+
* Define a configuração de workflow de um projeto BPM a partir de uma
|
|
828
|
+
* declaração única de módulos e atividades. O tipo `ModuleId` é inferido
|
|
829
|
+
* automaticamente do array de módulos — nenhum type alias manual é necessário.
|
|
830
|
+
*
|
|
831
|
+
* @param config Objeto com `modules` (definições de módulo) e `activities` (políticas por atividade)
|
|
832
|
+
* @returns Configuração tipada pronta para uso em `resolveWorkflowScreen` e `extractCompletedStages`
|
|
833
|
+
*
|
|
834
|
+
* @example
|
|
835
|
+
* const workflowConfig = defineWorkflowConfig({
|
|
836
|
+
* modules: [
|
|
837
|
+
* { moduleId: 'solicitante', label: 'Dados Iniciais', icon: 'file', order: 1,
|
|
838
|
+
* showInNavigation: true, renderContent: true, contentIncludePath: 'solicitante.html' },
|
|
839
|
+
* { moduleId: 'juridico', label: 'Jurídico', icon: 'gavel', order: 2,
|
|
840
|
+
* showInNavigation: true, renderContent: true, contentIncludePath: 'juridico.html' },
|
|
841
|
+
* ],
|
|
842
|
+
* activities: [
|
|
843
|
+
* { sequence: 9, description: 'Solicitação inicial', kind: 'human', stage: 'solicitacao',
|
|
844
|
+
* modules: { visible: ['solicitante'], editable: ['solicitante'], active: 'solicitante' } },
|
|
845
|
+
* { sequence: 88, description: 'Roteamento', kind: 'routing' },
|
|
846
|
+
* ]
|
|
847
|
+
* } as const)
|
|
848
|
+
* // Tipo de ModuleId inferido automaticamente: 'solicitante' | 'juridico'
|
|
849
|
+
*/
|
|
850
|
+
declare function defineWorkflowConfig<const M extends readonly (WorkflowModuleDefinition & {
|
|
851
|
+
moduleId: string;
|
|
852
|
+
})[]>(config: {
|
|
853
|
+
modules: M;
|
|
854
|
+
activities: readonly WorkflowActivityDefinition<M[number]['moduleId']>[];
|
|
855
|
+
}): WorkflowConfig<M, M[number]['moduleId']>;
|
|
856
|
+
|
|
857
|
+
/**
|
|
858
|
+
* Entrada do histórico do processo BPM retornada por
|
|
859
|
+
* `parent.ECM.workflowView.processDefinition.urlHistory`.
|
|
860
|
+
* As chaves do objeto pai são arbitrárias — usar apenas `movementDate` e
|
|
861
|
+
* `movementHour` para determinar a ordem cronológica real.
|
|
862
|
+
*/
|
|
863
|
+
interface BpmHistoryEntry {
|
|
864
|
+
/** `null` = ação de usuário; `'SYSTEM'` = tarefa de sistema; `'OBSERVATION'`/`'ATTACHMENT'` = ignorar */
|
|
865
|
+
historyType: 'SYSTEM' | 'OBSERVATION' | 'ATTACHMENT' | null;
|
|
866
|
+
/** Equivalente a `WorkflowActivityDefinition.sequence` */
|
|
867
|
+
stateSequence: number;
|
|
868
|
+
/** `0` = atividade de usuário/sistema | `1` = gateway/decisão automática */
|
|
869
|
+
stateType: number;
|
|
870
|
+
/** Timestamp numérico para ordenação — `null` em sub-registros sem posição cronológica */
|
|
871
|
+
movementDate: number | null;
|
|
872
|
+
/** Hora no formato `"HH:mm:ss"` — desempate na ordenação quando `movementDate` é igual */
|
|
873
|
+
movementHour: string | null;
|
|
874
|
+
/** Rótulo da atividade no motor BPM */
|
|
875
|
+
labelActivity: string | null;
|
|
876
|
+
}
|
|
877
|
+
/** Mapa bruto retornado por `urlHistory` — chaves são arbitrárias, ignorar na ordenação */
|
|
878
|
+
type BpmHistoryMap = Record<string, BpmHistoryEntry>;
|
|
879
|
+
/** Histórico processado — alimenta `ScreenContext` para construir a barra de progresso */
|
|
880
|
+
interface ProcessHistory {
|
|
881
|
+
/** Estágios concluídos em ordem cronológica real; deduplica estágios repetidos */
|
|
882
|
+
completedStages: string[];
|
|
883
|
+
/** Estágio atual com seu status; `null` se a atividade atual não tiver stage mapeado */
|
|
884
|
+
currentStage: {
|
|
885
|
+
stage: string;
|
|
886
|
+
status: 'current' | 'waiting';
|
|
887
|
+
} | null;
|
|
888
|
+
}
|
|
889
|
+
/**
|
|
890
|
+
* Extrai os estágios concluídos do histórico BPM na ordem cronológica real.
|
|
891
|
+
* Ignora gateways (`stateType === 1`), entradas `SYSTEM`, `OBSERVATION` e `ATTACHMENT`,
|
|
892
|
+
* e sub-registros sem `movementDate`. Deduplica estágios — a primeira ocorrência
|
|
893
|
+
* cronológica define a posição na barra de progresso.
|
|
894
|
+
*
|
|
895
|
+
* @param history Mapa bruto retornado por `urlHistory` do processo BPM
|
|
896
|
+
* @param activities Array de definições de atividade do `WorkflowConfig`
|
|
897
|
+
* @returns Array de stage IDs na ordem em que ocorreram no processo
|
|
898
|
+
*/
|
|
899
|
+
declare function extractCompletedStages(history: BpmHistoryMap, activities: readonly WorkflowActivityDefinition[]): string[];
|
|
900
|
+
/**
|
|
901
|
+
* Determina o estágio atual e seu status (`'current'` ou `'waiting'`).
|
|
902
|
+
* Retorna `null` se a sequência atual não tiver um `stage` mapeado na configuração.
|
|
903
|
+
*
|
|
904
|
+
* @param currentSequence Número de sequência da atividade atual do processo
|
|
905
|
+
* @param currentHistoryType `historyType` da entrada atual — `null` para ação humana, `'SYSTEM'` para espera
|
|
906
|
+
* @param activities Array de definições de atividade do `WorkflowConfig`
|
|
907
|
+
* @returns Objeto com `stage` e `status`, ou `null`
|
|
908
|
+
*/
|
|
909
|
+
declare function extractCurrentStage(currentSequence: number, currentHistoryType: 'SYSTEM' | null, activities: readonly WorkflowActivityDefinition[]): {
|
|
910
|
+
stage: string;
|
|
911
|
+
status: 'current' | 'waiting';
|
|
912
|
+
} | null;
|
|
913
|
+
|
|
914
|
+
/** Módulo com políticas de visibilidade e editabilidade resolvidas para a atividade atual */
|
|
915
|
+
interface ResolvedModule {
|
|
916
|
+
moduleId: string;
|
|
917
|
+
label: string;
|
|
918
|
+
icon: string;
|
|
919
|
+
order: number;
|
|
920
|
+
showInNavigation: boolean;
|
|
921
|
+
renderContent: boolean;
|
|
922
|
+
contentIncludePath: string;
|
|
923
|
+
isVisible: boolean;
|
|
924
|
+
isEditable: boolean;
|
|
925
|
+
isActive: boolean;
|
|
926
|
+
}
|
|
927
|
+
/**
|
|
928
|
+
* Contexto de tela para uma atividade de workflow.
|
|
929
|
+
* Consultado por Presenters para decidir visibilidade/editabilidade
|
|
930
|
+
* sem conhecer números de sequência.
|
|
931
|
+
*
|
|
932
|
+
* @hideconstructor
|
|
933
|
+
*/
|
|
934
|
+
declare class ScreenContext {
|
|
935
|
+
private readonly activity;
|
|
936
|
+
private readonly resolvedModules;
|
|
937
|
+
private readonly history;
|
|
938
|
+
constructor(activity: WorkflowActivityDefinition, resolvedModules: readonly ResolvedModule[], history: ProcessHistory);
|
|
939
|
+
/**
|
|
940
|
+
* Retorna `true` se o módulo é visível na atividade atual.
|
|
941
|
+
*
|
|
942
|
+
* @param moduleId Identificador do módulo
|
|
943
|
+
*/
|
|
944
|
+
isVisible(moduleId: string): boolean;
|
|
945
|
+
/**
|
|
946
|
+
* Retorna `true` se o módulo é editável na atividade atual.
|
|
947
|
+
*
|
|
948
|
+
* @param moduleId Identificador do módulo
|
|
949
|
+
*/
|
|
950
|
+
isEditable(moduleId: string): boolean;
|
|
951
|
+
/**
|
|
952
|
+
* Retorna `true` se o módulo é o ativo (tab selecionada) na atividade atual.
|
|
953
|
+
*
|
|
954
|
+
* @param moduleId Identificador do módulo
|
|
955
|
+
*/
|
|
956
|
+
isActive(moduleId: string): boolean;
|
|
957
|
+
/**
|
|
958
|
+
* Retorna o número de sequência da atividade atual no motor BPM EGD.
|
|
959
|
+
*
|
|
960
|
+
* Equivalente a `WorkflowActivityDefinition.sequence`. Exposto para presenters
|
|
961
|
+
* que precisam do valor em regras de domínio baseadas em sequências específicas
|
|
962
|
+
* (ex: listas de sequences especiais para exibir/ocultar campos).
|
|
963
|
+
*/
|
|
964
|
+
getSequence(): number;
|
|
965
|
+
/**
|
|
966
|
+
* Retorna `true` se a atividade atual está aguardando um sistema externo
|
|
967
|
+
* (`kind === 'system'` ou `currentStage.status === 'waiting'`).
|
|
968
|
+
*/
|
|
969
|
+
isAwaitingSystem(): boolean;
|
|
970
|
+
/**
|
|
971
|
+
* Retorna `true` se a atividade atual é uma atividade de suporte transversal.
|
|
972
|
+
*/
|
|
973
|
+
isInSupport(): boolean;
|
|
974
|
+
/**
|
|
975
|
+
* Retorna os estágios para renderizar na barra de progresso.
|
|
976
|
+
* Inclui os estágios concluídos do histórico (`'done'`) e o estágio atual
|
|
977
|
+
* (`'current'` ou `'waiting'`), sem duplicar.
|
|
978
|
+
*/
|
|
979
|
+
getProgressBarStages(): Array<{
|
|
980
|
+
stage: string;
|
|
981
|
+
status: 'done' | 'current' | 'waiting';
|
|
982
|
+
}>;
|
|
983
|
+
/**
|
|
984
|
+
* Retorna todos os módulos resolvidos, incluindo os não-visíveis.
|
|
985
|
+
*/
|
|
986
|
+
getModules(): readonly ResolvedModule[];
|
|
987
|
+
/**
|
|
988
|
+
* Retorna apenas os módulos visíveis, ordenados por `order` ascendente.
|
|
989
|
+
*/
|
|
990
|
+
getVisibleModules(): readonly ResolvedModule[];
|
|
991
|
+
/**
|
|
992
|
+
* Retorna os módulos que aparecem na navegação (`showInNavigation && isVisible`),
|
|
993
|
+
* ordenados por `order` ascendente.
|
|
994
|
+
*/
|
|
995
|
+
getNavigationModules(): readonly ResolvedModule[];
|
|
996
|
+
}
|
|
997
|
+
|
|
998
|
+
/**
|
|
999
|
+
* Resolve a tela para a sequência informada, cruzando a configuração do workflow
|
|
1000
|
+
* com o histórico do processo para produzir um `ScreenContext`.
|
|
1001
|
+
*
|
|
1002
|
+
* @param config Configuração gerada por `defineWorkflowConfig`
|
|
1003
|
+
* @param sequence Número de sequência da atividade atual no processo BPM
|
|
1004
|
+
* @param history Histórico processado via `extractCompletedStages` e `extractCurrentStage`
|
|
1005
|
+
* @returns `ScreenContext` pronto para consulta pelos Presenters
|
|
1006
|
+
*
|
|
1007
|
+
* @throws {Error} Se a sequência não estiver mapeada na configuração
|
|
1008
|
+
*
|
|
1009
|
+
* @example
|
|
1010
|
+
* const screen = resolveWorkflowScreen(workflowConfig, 53, processHistory)
|
|
1011
|
+
* screen.isVisible('juridico') // true
|
|
1012
|
+
* screen.isEditable('juridico') // true
|
|
1013
|
+
* screen.isInSupport() // false
|
|
1014
|
+
*/
|
|
1015
|
+
declare function resolveWorkflowScreen(config: WorkflowConfig<readonly WorkflowModuleDefinition[]>, sequence: number, history: ProcessHistory): ScreenContext;
|
|
1016
|
+
|
|
1017
|
+
/** Mapa de stores: chave = nome do store, valor = objeto do store */
|
|
1018
|
+
type StoreMap = Record<string, object>;
|
|
1019
|
+
/**
|
|
1020
|
+
* Tipo utilitário que gera um proxy com getters tipados para cada store registrado.
|
|
1021
|
+
* Permite `stores.contador` ao invés de `Alpine.store('contador') as ContadorStore`.
|
|
1022
|
+
*/
|
|
1023
|
+
type StoreProxy<T extends StoreMap> = {
|
|
1024
|
+
readonly [K in keyof T]: T[K];
|
|
1025
|
+
};
|
|
1026
|
+
/**
|
|
1027
|
+
* Registra múltiplos Alpine stores e retorna um proxy tipado para acesso direto.
|
|
1028
|
+
* Deve ser chamado no ponto de inicialização da aplicação, antes de `Alpine.start()`.
|
|
1029
|
+
*
|
|
1030
|
+
* @param alpine Instância Alpine — aceita `Pick<Alpine, 'store'>` para facilitar mock em testes
|
|
1031
|
+
* @param storeMap Objeto com pares `{ nomeDoStore: objetoInicial }`
|
|
1032
|
+
* @returns Proxy tipado para leitura dos stores sem casting manual
|
|
1033
|
+
*
|
|
1034
|
+
* @example
|
|
1035
|
+
* const stores = registerStores(Alpine, {
|
|
1036
|
+
* usuario: { nome: '', perfil: '' as PerfilId },
|
|
1037
|
+
* ui: { carregando: false, erro: null as string | null }
|
|
1038
|
+
* })
|
|
1039
|
+
* // stores.usuario.nome está tipado como string
|
|
1040
|
+
* // Internamente: Alpine.store('usuario', { nome: '', perfil: '' })
|
|
1041
|
+
*/
|
|
1042
|
+
declare function registerStores<T extends StoreMap>(alpine: Pick<Alpine, 'store'>, storeMap: T): StoreProxy<T>;
|
|
1043
|
+
|
|
1044
|
+
export { Attach, AttachButton, AttachmentsTable, BeforeSendValidate, BpmFormRepository, ConstraintsType, MockFormRepository, ScreenContext, WorkerManager, WorkflowViewPatcher, defineWorkflowConfig, extractCompletedStages, extractCurrentStage, loadFields, registerStores, resolveWorkflowScreen, sendRequestEvent };
|
|
1045
|
+
export type { ActivityKind, ActivityModulePolicy, AttachButtonRegistration, AttachmentRecord, AttachmentSource, AttachmentsTableMode, AttachmentsTableOptions, BpmHistoryEntry, BpmHistoryMap, CacheOptions, CancelablePromise, DatasetError, DatasetResponse, DatasetRow, DragDropEntry, FieldError, IFormRepository, IWorkflowViewHooks, ProcessCompletionLink, ProcessCompletionMessage, ProcessHistory, ResolvedModule, SearchParams, StoreMap, StoreProxy, WorkerManagerOptions, WorkflowActivityDefinition, WorkflowConfig, WorkflowModuleDefinition };
|