PROTOCOL.md 16.5 KB
Newer Older
1
2
<!-- -*- markdown -*- -->

3
# Client/Server Protocol
Carsten  Rose's avatar
Carsten Rose committed
4

5

Rafael Ostertag's avatar
Rafael Ostertag committed
6
## General Protocol
Carsten  Rose's avatar
Carsten Rose committed
7

Rafael Ostertag's avatar
Rafael Ostertag committed
8
9
The Client may asynchronously send requests to the Server. The Server
is expected to return responses as outlined below.
Carsten  Rose's avatar
Carsten Rose committed
10

Rafael Ostertag's avatar
Rafael Ostertag committed
11
12
13
The response must contain at least a [Minimal Response]. Depending on
the request, it may provide additional responses as outlined in this
section.
14

Carsten  Rose's avatar
Carsten Rose committed
15

Rafael Ostertag's avatar
Rafael Ostertag committed
16
### Minimal Response
17
18
19

Asynchronous request (read AJAX) initiated by the Client receive a
JSON Response from the server containing at least:
Carsten  Rose's avatar
Carsten Rose committed
20

21
22
23
	{
		"status": "success"|"error",
		"message": "<message>"
24
	}
Carsten  Rose's avatar
Carsten Rose committed
25
   
26
`status` indicates whether or not the request has been fulfilled by
27
28
29
the server (`"success"`) or encountered an error (`"error"`). On
`"error"` the Client must display `"<message>"` to the user. On
`"success"`, the Client may display `"<message>"` to the user.
30
31
32

Depending on the request, the server may provide additional
information in the response, as outlined below.
33

34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
### Alert

     {
       "message": "<message>",
       "type": "<type of message>", 
       "timeout": <timeout in milliseconds>, 
       "modal": <boolean>, 
       "buttons": [{
                    "label":  "<label>",
                    "eventName": "<eventName>",
                    "focus": <boolean>
       }]
     }
`"type"` 
: can be `"info"`, `"warning"`, or `"error"`. Default is `"info"`.

`"timeout"` 
: If timeout is less than or equal to 0, the alert won't timeout and stay open until dismissed by the user. Default `n.Alert.constants.NO_TIMEOUT`.

`"modal"` 
: whether or not alert is modal, i.e. prevent clicks anywhere but the dialog. Default is `false`.

`"buttons"` 
: what buttons to display on alert. If empty array is provided, no buttons are displayed and a click anywhere in the alert will dismiss it.
  
`"buttons.label"`
: Label of the button.

`"buttons.eventName"`
: Name of the event to be executed when button is clicked.

`"buttons.focus"`
: Whether or not button has focus by default. Default is `false`.
67

Rafael Ostertag's avatar
Rafael Ostertag committed
68
69
70
71
72
73
### HTML Form Element Validation Response

The Server may perform a serverside validation of values submitted as
part of a HTML Form submission. If the validation fails, it may notify
the Client by adding following name/value pairs to the response JSON
Stream
74
75

	{
76
77
78
79
80
        "status": "error",
        ...
        "field-name": "<field name>",
        "field-message": "<message>",
        ...
81
82
83
84
85
	}
	
Only one validation failure per request can be reported to Client.

The Server is expected to set the status `"status"` to `"error"`, and
Rafael Ostertag's avatar
Rafael Ostertag committed
86
87
the Client is expected to treat the error as explained in [Minimal Response]
and must obey the rules of redirection as explained in [Redirection Response].
88
89
90
91
92
93
94
95
96
97

The Client must visibly highlight the HTML Form Element that caused the
validation failure.

`"field-name"`
:	The value of the `name` attribute of the HTML Form Element that
	caused the validation failure.
	
`"field-message"`
:	Message to the User, indicating the nature of the failure.
Rafael Ostertag's avatar
Rafael Ostertag committed
98
99
100


### Form Group Configuration Response
101
102

As part of the server response, the JSON stream may contain a key
Rafael Ostertag's avatar
Rafael Ostertag committed
103
104
105
106
`form-update`. This response is used to reconfigure HTML Form Elements
and Form Groups on the clientside, based on conditions evaluated on
the serverside. It contains an array of objects
having the following structure
107
108

    {
109
110
111
112
113
114
115
116
117
118
119
120
		...
		"form-update" : [
			{
				"form-element": "<element_name>",
				"hidden": true | false,
				"disabled": true | false,
				"required": true | false,
				"value": <value>
			},
			...
		],
		...
121
122
123
    }

`"form-element"`
124
:	 the name of the HTML Form Element as it appears in the `name` attribute.
125
126

`"hidden"`
127
:   whether the Form Group is visible (value: `false`) or invisible (value: `true`).
128
129
130
131
132
	
`"disabled"`
:   whether or not the Form Element is disabled HTML-wise.

`"required"`
133
:   whether or not the Form Element receives the HTML5 `required` attribute.
134
135

`"value"`
Rafael Ostertag's avatar
Rafael Ostertag committed
136
137
:	For textual HTML Form Input elements, it is supposed to be a scalar
	value, which is set on the element.
138
	
Rafael Ostertag's avatar
Rafael Ostertag committed
139
140
141
142
	When `"form-element"` references a `<select>` element, a scalar
    value selects the corresponding value from the option list. In
    order to replace the entire option list, use an array of objects
    as value to `"value"`, having this format
143
144
	   
	    [
Rafael Ostertag's avatar
Rafael Ostertag committed
145
			...
146
147
148
149
150
151
152
153
154
155
			{
				"value": 100,
				"text": "a",
				"selected": true
			},
			{
				"value": 200,
				"text": "b",
				"selected": false
			}
Rafael Ostertag's avatar
Rafael Ostertag committed
156
			...
157
158
159
160
        ]
		
	`"select"` is optional, as is `"text"`. If `"text"` is omitted, it
    will be derived from value.
161
162
163
164
165
166
167
168
	
	HTML checkboxes are ticked with a `"value"` of `true`. They are
    unchecked with `false`.
	
	HTML radio buttons are activated by providing the value of the
    radio button `value`-attribute to be activated in `"value"`.
	

169
### Element Configuration Response
Rafael Ostertag's avatar
Rafael Ostertag committed
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210

As part of the server response, the JSON stream may contain a key
`element-update`. This key stores information on how to modify HTML elements identified by `id`. Modifying in this 
context refers to:

 * Setting attribute values
 * Deleting attributes
 * Setting content of a HTML element.
 
The content of `element-update` is outlined below

    {
        ...
        "element-update" : {
            "<element_id1>": {
                "attr": {
                    "<attr_name1>": "<value1>" | null,
                    ...
                    "<attr_nameN>": "<valueN>" | null
                },
                "content": "<element_content>"
            },
            ...
            "<element_idN>": {
                "attr": {
                    "<attr_name1>": "<value1>" | null,
                    ...
                    "<attr_nameN>": "<valueN>" | null
                },
                "content": "<element_content>"
            }
        },
        ...
    }
    
The presence of `element-update` is optional. `<element_idN>` refers to the element's `id`-attribute value. It used 
to uniquely identify the HTML element in the DOM. The properties `"attr"` and `"content"` are both optional.

Supplying `null` as value for `"<attr_nameN>"` will remove the attribute from the HTLM element identified by 
`"<element_idN>"`.

211
If the element has no `"<attr_nameN>"` attribute, the attribute will be created. In any case, the attribute's value will be set 
Rafael Ostertag's avatar
Rafael Ostertag committed
212
213
to the value specified by `"<valueN>"`. See above for handling of `null` value.

Rafael Ostertag's avatar
Rafael Ostertag committed
214
### Redirection Response
215
216

Depending on the request, the server may return redirection
Rafael Ostertag's avatar
Rafael Ostertag committed
217
information to the Client. It is up to the Client to respect the
218
219
220
221
222
223
redirection information.

The Client must not perform a redirect in case the status in
`"status"` is `"error"`.

The format of redirect information is outlined below
224
225
226

	{
		...
227
		"redirect": "no" | "url" | "url-skip-history" | "auto" | "close"
228
229
230
231
232
233
		"redirect-url": "<url>"
		...
	}
	

`"redirect"`
234
235
236
237
238
239
240
241
242
:	type of redirection. 

 * `"no"` advises the Client to stay on the	Current Page. 
 * `"close"` the client goes back one in history - if there is no history, stays on the same page.
 * `"auto"` the Client decide where to redirect to.
   * if the user clicks 'save', stay on the same page.
   * if the user clicks 'close', go back one in history - if there is no history, stays on the same page. 
 * `"url"` advices the Client to redirect to the URL provided in `"redirect-url"`. 
 * `"url-skip-history"` behaves like `"url"` but the current page will skip the browser history.
243
244
245
246
	
`"redirect-url"`
:	Used to provide an URL when `"redirect"` is set to `"url"`. It
	should be disregarded unless `"redirect"` is set to `"url"`.
Carsten  Rose's avatar
Carsten Rose committed
247

248
249
250
251
252
253
254
255
256
257
258
259
260
261
### Typeahead dict Response

    {
		...
		[
			{
				"key": "<key value>",
				"value": <display value>
			},
			...
		],
		...
    }

Carsten  Rose's avatar
Carsten Rose committed
262

Rafael Ostertag's avatar
Rafael Ostertag committed
263
## API Endpoints
Carsten  Rose's avatar
Carsten Rose committed
264
265


Rafael Ostertag's avatar
Rafael Ostertag committed
266
### Form Update
Carsten  Rose's avatar
Carsten Rose committed
267

268
269
270
271
272
The Client may request an updated set of Form Group Configuration and
HTLM Element states. In order for the Server to compile the set of
Form Group Configuration and HTML Element states, it requires the
entire HTML Form in the POST body, without any HTML Input Elements of
type `file`.
273

Rafael Ostertag's avatar
Rafael Ostertag committed
274
275
The Client must include the SIP using an HTML Input Element (most
likely of `type` `hidden`).
Carsten  Rose's avatar
Carsten Rose committed
276

Rafael Ostertag's avatar
Rafael Ostertag committed
277
278
Request URL
:	api/load.php
Carsten  Rose's avatar
Carsten Rose committed
279

Rafael Ostertag's avatar
Rafael Ostertag committed
280
281
Request Method
:	POST
Carsten  Rose's avatar
Carsten Rose committed
282

Rafael Ostertag's avatar
Rafael Ostertag committed
283
284
URL Parameters
:	none
Carsten  Rose's avatar
Carsten Rose committed
285

Rafael Ostertag's avatar
Rafael Ostertag committed
286
287
288
Server Response
:   The response contains at least a [Minimal Response]. In addition,
	a [Form Group Configuration Response] may be included.
Carsten  Rose's avatar
Carsten Rose committed
289
290


Rafael Ostertag's avatar
Rafael Ostertag committed
291
### Form Save
Carsten  Rose's avatar
Carsten Rose committed
292

Rafael Ostertag's avatar
Rafael Ostertag committed
293
294
295
The Client submits the HTML Form for persitent storage to the
Server. The submission should not contain `<input>` HTML Elements of
type `file`.
Carsten  Rose's avatar
Carsten Rose committed
296

Rafael Ostertag's avatar
Rafael Ostertag committed
297
298
The Client must include the SIP using an HTML Input Element (most
likely of `type` `hidden`).
Carsten  Rose's avatar
Carsten Rose committed
299

Rafael Ostertag's avatar
Rafael Ostertag committed
300
301
Request URL
:	api/save.php
Carsten  Rose's avatar
Carsten Rose committed
302

Rafael Ostertag's avatar
Rafael Ostertag committed
303
304
Request Method
:	POST
Carsten  Rose's avatar
Carsten Rose committed
305

Rafael Ostertag's avatar
Rafael Ostertag committed
306
URL Parameters
307
:	`submit_reason=save` | `submit_reason=save,close`
Carsten  Rose's avatar
Carsten Rose committed
308

Rafael Ostertag's avatar
Rafael Ostertag committed
309
310
311
312
313
Server Response
:   The response contains at least a [Minimal Response]. In addition, a
	[Form Group Configuration Response],
	[HTML Form Element Validation Response] and/or
	[Redirection Response] may be included.
Carsten  Rose's avatar
Carsten Rose committed
314
315


Rafael Ostertag's avatar
Rafael Ostertag committed
316
### File Upload
Carsten  Rose's avatar
Carsten Rose committed
317

Rafael Ostertag's avatar
Rafael Ostertag committed
318
319
320
321
Files are uploaded asynchronously. Each file to be uploaded requires
one request to the Server, using a Multi part form with file content,
parameter `s` containing SIP, and parameter `name` containing the name
of the HTML Form Element.
Carsten  Rose's avatar
Carsten Rose committed
322

Rafael Ostertag's avatar
Rafael Ostertag committed
323
324
Request
:	api/file.php
Carsten  Rose's avatar
Carsten Rose committed
325

Rafael Ostertag's avatar
Rafael Ostertag committed
326
327
Request Method
:	POST
Carsten  Rose's avatar
Carsten Rose committed
328

Rafael Ostertag's avatar
Rafael Ostertag committed
329
330
URL Parameters
:	`action=upload`
Carsten  Rose's avatar
Carsten Rose committed
331

Rafael Ostertag's avatar
Rafael Ostertag committed
332
333
Server Response
:	The response contains a [Minimal Response].
Carsten  Rose's avatar
Carsten Rose committed
334
335


Rafael Ostertag's avatar
Rafael Ostertag committed
336
### File Delete
Carsten  Rose's avatar
Carsten Rose committed
337

Rafael Ostertag's avatar
Rafael Ostertag committed
338
339
340
341
342
343
Files are delete asynchronously. Each file to be delete on the
serverside requires on request to the Server. The parameters
identifying the file to be deleted are sent as part of the POST
body. The SIP of the request is included in the parameter name
`s`. The value of the `name` attribute of the HTML Form Element is
provided in `name`.
Carsten  Rose's avatar
Carsten Rose committed
344

Rafael Ostertag's avatar
Rafael Ostertag committed
345
346
Request
:	api/file.php
Carsten  Rose's avatar
Carsten Rose committed
347

Rafael Ostertag's avatar
Rafael Ostertag committed
348
349
Request Method
:	POST
Carsten  Rose's avatar
Carsten Rose committed
350

Rafael Ostertag's avatar
Rafael Ostertag committed
351
352
URL Parameters
:	`action=delete`
Carsten  Rose's avatar
Carsten Rose committed
353

Rafael Ostertag's avatar
Rafael Ostertag committed
354
355
Server Response
:	The response contains a [Minimal Response].
Carsten  Rose's avatar
Carsten Rose committed
356
357


358
### Record delete
Carsten  Rose's avatar
Carsten Rose committed
359

360
361
Request the deletion of the record identified by the SIP. The SIP might contain a SIP_TABLE and/or a SIP_FORM.
If both are specified, SIP_FORM will be taken. With SIP_FORM, the tableName is derived from the form. 
Carsten  Rose's avatar
Carsten Rose committed
362

Rafael Ostertag's avatar
Rafael Ostertag committed
363
364
Request
:	api/delete.php
Carsten  Rose's avatar
Carsten Rose committed
365

Rafael Ostertag's avatar
Rafael Ostertag committed
366
367
Request Method
:	POST
Carsten  Rose's avatar
Carsten Rose committed
368

Rafael Ostertag's avatar
Rafael Ostertag committed
369
370
URL Parameters
:	`s=<SIP>`
Carsten  Rose's avatar
Carsten Rose committed
371

Rafael Ostertag's avatar
Rafael Ostertag committed
372
373
Server Response
:	The response contains a [Minimal Response].
374
	[Redirection Response] may be included.
Carsten  Rose's avatar
Carsten Rose committed
375

376
377
378
379
380
381
382
383
384
385
386
387
388
389
### Download

Request
:  api/download.php
 
Request Method
:	GET

URL Parameters
:	`s=<SIP>`

Server Response
:	header("Content-type: $mimetype");
	header("Content-Length: $length");
390
	header("Content-Disposition: inline; filename='$outputFilename'");
391
392
393
394
395
396
397
398
399
	header("Pragma: no-cache");
	header("Expires: 0");
	file_get_contents($file);
 
A download might be:
  * a single file (any type, will be detected on the fly), 
  * an export of several files as a ZIP archive,
  * an export of a T3-'XML'-Page converted to Excel,
  * a converted HTML page to PDF,
400
401
402
403
  * a PDF file, concatenated on single PDF files and/or converted HTML page to PDF,
  * a thumbnail, streamed from cache dir of if not present/recent rendered on request,
  * a file to monitor constantly,
  * a file, delivered as a JSON structure, used in 'copy to clipboard',
404
405
406

'api/download.php' will be called with a SIP (no other vars used). The SIP contains:
  * DOWNLOAD_EXPORT_FILENAME - any target filename, if none given take DOWNLOAD_OUTPUT_PDF ('output.pdf'). 
Carsten  Rose's avatar
Carsten Rose committed
407
  * DONWLOAD_MODE - file / pdf / excel / zip / thumbnail / monitor. If not specified:
Carsten  Rose's avatar
Carsten Rose committed
408
409
      a) 'file' is the default, if only one source is given and if that is a file.
      b) 'pdf' is the default, if there are multiple TOKEN_URL, TOKEN_URL_PARAM, TOKEN_FILE in SIP_DOWNLOAD_PARAMETER found.
410
      
Carsten  Rose's avatar
Carsten Rose committed
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
  * DONWLOAD_MODE: file / pdf / excel / zip    

    * SIP_DOWNLOAD_PARAMETER (base64 encoded) - contains all parameter to source elements.
     
        Format: <format 1>:<element 1>|<format 2>:<element 2>|...|<format n>:<element n>|
        
        <format>: TOKEN_URL, TOKEN_URL_PARAM, TOKEN_FILE, TOKEN_THUMBNAIL_DIMENSION
        <element>: depending on the token - see below
        
        URL:  a) 'u:http://w3c.org', b) 'u:w3c.org/', c) 'u:w3c.org/2017/index.php?issue=23'
        URL_PARAM:  a) 'U:id=export&r=123', b) 'U:id=export&r=123&_orientation=landscape&_page-size=a3'
        FILE: a) 'F:fileadmin/example.png'
          
        * In URL_PARAM extra parameter used by `wkhtmltopdf` can be specified. All Parameter, starting with '-'
          will be extracted from the regular URL_PARAM and instead forwarded as options to `wkhtmlpdf`

  * DONWLOAD_MODE: thumbnail    

      * SIP_DOWNLOAD_PARAMETER (base64 encoded) 

          * T:<pathFilename Source>
          * W:<dimension>
          * r:<render mode>
          * Render the thumbnail

          Download.php will be called with the SIP. After decoding the SIP, the base64 encoded parameter are used with
          DONWLOAD_MODE=file and  SIP_DOWNLOAD_PARAMETER=F:<thumbnail>

  * DONWLOAD_MODE: monitor    

      SIP encoded parameter
442
      
Carsten  Rose's avatar
Carsten Rose committed
443
444
445
446
447
      * file: <filename>
      * tail: <number of last lines>
      * append: 0|1
      
      The retrieved lines are outputted without any conversion.
448
449
450
451
452
453
   
  * DOWNLOAD_OUTPUT_FORMAT: raw (default), json
  
      * If this parameter is missing, 'raw' ist meant.
      * 'json' is used for 'copy to clipboard'.
           
454
  * The base64 encoding is necessary:
Carsten  Rose's avatar
Carsten Rose committed
455
  
456
457
458
    * to deliver multiple elements with the same token (e.g. multiple PDF files to concatenate).
    * special parameter names, like 'id', should not force the regular interpretation of 'id' during conversion to a SIP. 
      
459
During preparing and delivering the download (file / pdf / excel / zip), a popup shows a spinning gear by default. The 
Carsten  Rose's avatar
Carsten Rose committed
460
popup itself will display an individual message. The popup needs some HTML code (only once per T3 page). 
461
462
463
464
465
466
Download links might be generated in `report` as well as in `subrecords of forms`. To trigger the generation of the HTML 
popup code, a variable DOWNLOAD_POPUP_REQUEST in STORE_SYSTEM will be set to 'true' (string) in class Link(), as soon as 
the first download link is rendered. During internal rendering of the download link, the const text token 
DOWNLOAD_POPUP_REPLACE_TEXT and DOWNLOAD_POPUP_REPLACE_TITLE will be replaced with individual texts, defined per download link.


467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
### Typeahead

The Client initiates Typeahead actions via a GET request. A JSON key/value dict will we be send back as response.
The Client GET request contains a 'sip' and the already typed value as 'query' paramter.    

Request URL
:	api/typeahead.php

Request Method
:	GET

URL Parameters
:	`sip`, `query`

Server Response
:   The response contains at least a [Minimal Response]. In addition, a [Typeahead dict],
Carsten  Rose's avatar
Carsten Rose committed
483

484
485
486
487
488
489
490
491
492
493
494
495
496
### Record lock

Request, extend or release a lock for a record, identified by the SIP. The SIP contain a SIP_FORM and a SIP_R (record id).
To detect record change at time of 'record lock' or 'record save', a MD5 hash is provided from the server
and needs to pass back to dirty.php as well.

Request
:	api/dirty.php

Request Method
:	GET

URL Parameters
497
:  `s=<SIP>`   (form, r)
498
499
500
501
502
503
504
505
506
507
508
:  `action=lock`, `action=extend`, `action=release>`
:  `recordHashMd5=<value of hidden form element 'recordHashMd5'>`

Server Response
:	The response contains an [Lock Response].

### Lock Response

Asynchronous request (read AJAX) initiated by the Client receive a
JSON Response from the server (extended [Minimal Response]) containing:

509
510
511
512
:	{
:		"status": "success"|"error"|"conflict"|"conflict_allow_force",
:		"message": "<message>"e5
:    }
513
   
Carsten  Rose's avatar
Carsten Rose committed
514
`status` indicates how the request has been fulfilled by the server. 
515
516
517
518
519
On`"success"`, the Client display nothing to the user. 
On one of`"error"|"conflict"|"conflict_allow_force"` the Client must display `"<message>"` to the user.
On `"conflict"` the Client opens the alert as modal dialog (user can't change anything on the form) with a 'reload current
form' button.
On `"conflict_allow_force"` the Client opens the alert non-modal (default).
bbaer's avatar
bbaer committed
520
521


522
### Drag And Drop (sort)
bbaer's avatar
bbaer committed
523

524
525
Request
:	api/dragAndDrop.php
bbaer's avatar
bbaer committed
526

527
528
529
530
531
532
533
534
535
536
537
538
Request Method
:	GET

URL Parameters:

: `s=<SIP>`  (`form=<formname>`)
:  
: `dragId=<data-dnd-id of dragged element>`
: `dragPosition=<client internal position (numbering) of element before dragging>`
: `setTo=before`, `setTo=after`
: `hoverId=<data-dnd-id of dragged element>`
: `hoverPosition=<client internal position (numbering) of element after dragging>`
bbaer's avatar
bbaer committed
539

540
541
Server Response
:   The response contains at least a [Minimal Response]. In addition, a
Carsten  Rose's avatar
Carsten Rose committed
542
	[HTML Element Update] may be included.
Carsten  Rose's avatar
Carsten Rose committed
543
  
544
545
546
## Glossary

SIP
547
:   Server Id Pairs 
548
549
550
551
552
553
554

HTML Form Element
:   Any `<input>` or `<select>` HTML tag. Synonymous to *Form Element*.

Form Group
:   The sourrounding `<div>` containing the `.control-label`,
    `.form-control` `<div>`s, and `.help-block` `<p>`.
555
556

Client
557
558
559
560
561
562
563
564
565
:   Application that enables a user to interact with QFQ, i.e. a Web Browser.


Current Page
:	The currently displayed page in the Client.

Redirect
:	Issued by the Server. It is a command prompting the Client to
	navigate away from the Current Page.