ywana-core8 0.0.469 → 0.0.470

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/db/db.json ADDED
@@ -0,0 +1,50 @@
1
+ {
2
+ "references": [
3
+ {
4
+ "name": "1",
5
+ "state": "NOT_CLASSIFIED",
6
+ "field1": "1",
7
+ "field2": "1",
8
+ "id": 1
9
+ },
10
+ {
11
+ "name": "3",
12
+ "state": "CLASSIFIED",
13
+ "field1": "3",
14
+ "field2": "3",
15
+ "field4": "#4d19c8",
16
+ "id": 3
17
+ },
18
+ {
19
+ "name": "44",
20
+ "state": "NOT_CLASSIFIED",
21
+ "field1": "44",
22
+ "field2": "44",
23
+ "field4": "#0bda81",
24
+ "id": 4
25
+ },
26
+ {
27
+ "name": "555",
28
+ "state": "CLASSIFIED",
29
+ "field1": "555",
30
+ "field2": "555",
31
+ "id": 5
32
+ },
33
+ {
34
+ "name": "666",
35
+ "state": "NOT_CLASSIFIED",
36
+ "field1": "666",
37
+ "field2": "666",
38
+ "field4": "#cae407",
39
+ "id": 6
40
+ },
41
+ {
42
+ "name": "7777",
43
+ "state": "NOT_CLASSIFIED",
44
+ "field1": "777",
45
+ "field2": "777",
46
+ "field4": "#09dee1",
47
+ "id": 7
48
+ }
49
+ ]
50
+ }
package/db/routes.json ADDED
File without changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ywana-core8",
3
- "version": "0.0.469",
3
+ "version": "0.0.470",
4
4
  "description": "ywana-core8",
5
5
  "homepage": "https://ywana.github.io/workspace",
6
6
  "author": "Ernesto Roldan Garcia",
@@ -0,0 +1,713 @@
1
+ import equal from 'deep-equal'
2
+ import React, { Fragment, useContext, useEffect, useMemo, useRef, useState } from 'react'
3
+ import { Button, DataTable, DropDown, Header, Icon, MenuIcon, MenuItem, Text, Tabs, Tab } from '../html'
4
+ import { HTTPClient, Session } from '../http'
5
+ import { PageContext, SiteContext } from '../site'
6
+ import { ContentEditor } from './ContentEditor'
7
+ import { CHECK, Content, TYPES } from './ContentType'
8
+ import { ContentViewer } from './ContentViewer'
9
+ import { CreateContentDialog } from './CreateContentDialog'
10
+ import { QUERY } from './squema'
11
+ import "./TablePage.css"
12
+
13
+ /**
14
+ * Tabbed Table Page
15
+ */
16
+ export const TabbedTablePage = (props) => {
17
+
18
+ const site = useContext(SiteContext)
19
+ const { id = "table",
20
+ icon, title, name,
21
+ schema, url, field, host,
22
+ autosave = true, delay = 1000,
23
+ editable,
24
+ actions = [], dev = false, tableActions, selectionActions = [],
25
+ canFilter = false, canAdd = true, canDelete = true, canEdit = true,
26
+ canQuery = false, urlQuery, user,
27
+ groupBy, validator, scenario,
28
+ formFilter, tableFilter, editorFilter = false,
29
+ children
30
+ } = props
31
+
32
+ const [pageContext, setPageContext] = useContext(PageContext)
33
+ const context = TableContext(url, field, host, urlQuery)
34
+ const { selected, tab } = pageContext
35
+ const timer = useRef(null)
36
+ const [form, setForm] = useState(selected)
37
+ const [tabs, setTabs] = useState([])
38
+
39
+ useEffect(async () => {
40
+ const field = Object.values(schema).find(field => field.tab && field.tab === true)
41
+ const tabs = field.options.map(option => Object.assign({}, option, { field: field.id}))
42
+ setTabs(tabs)
43
+ context.changeTab(tabs[0])
44
+ setPageContext(context)
45
+ }, [])
46
+
47
+ useEffect( async () => {
48
+ console.log("TAB", tab)
49
+ if (tab) {
50
+ const filter = { [tab.field]: tab.value }
51
+ await pageContext.load(filter, false)
52
+ setPageContext(Object.assign({}, pageContext))
53
+ }
54
+ }, [tab])
55
+
56
+ useEffect(() => {
57
+ setForm(selected)
58
+ }, [selected])
59
+
60
+ useEffect(() => {
61
+ if (autosave) {
62
+ clearTimeout(timer.current)
63
+ timer.current = setTimeout(() => {
64
+ if (canSave()) save()
65
+ }, delay)
66
+ }
67
+ }, [form])
68
+
69
+ async function reload() {
70
+ const filter = { [tab.field]: tab.value }
71
+ await pageContext.load(filter, false)
72
+ setPageContext(Object.assign({}, pageContext))
73
+ }
74
+
75
+ function add() {
76
+ const onOK = async (form) => {
77
+ await pageContext.create(form);
78
+ setPageContext(Object.assign({}, pageContext))
79
+ }
80
+ site.openDialog(<CreateContentDialog label={`Crear ${name}`} type={schema} onOK={onOK} validator={validator} filter={formFilter} />);
81
+ }
82
+
83
+ function saveQuery(filters) {
84
+ const onOK = async (form) => {
85
+ form.filters = filters
86
+ form.layout = {}
87
+ form.user = user
88
+ form.url = url
89
+ await pageContext.createQuery(form, user)
90
+ setPageContext(Object.assign({}, pageContext))
91
+ }
92
+ site.openDialog(<CreateContentDialog label="Nueva query" type={QUERY} onOK={onOK} />)
93
+ }
94
+
95
+ function change(next) {
96
+ setForm(next)
97
+ }
98
+
99
+ function canSave() {
100
+ const can = !equal(form, selected)
101
+ return can
102
+ }
103
+
104
+ async function save() {
105
+ console.log('saving.....')
106
+ await pageContext.update(form)
107
+ setPageContext(Object.assign({}, pageContext))
108
+ }
109
+
110
+ async function playScenario() {
111
+ const promises1 = pageContext.all.map(async item => await pageContext.remove(item.id))
112
+ Promise.all(promises1).then(async () => {
113
+ const promises2 = scenario.map(async (item) => await pageContext.create(item))
114
+ Promise.all(promises2).then(async () => {
115
+ await pageContext.load()
116
+ setPageContext(Object.assign({}, pageContext))
117
+ })
118
+ })
119
+ }
120
+
121
+ function closeAside() {
122
+ pageContext.select(null)
123
+ setPageContext(Object.assign({}, pageContext))
124
+ }
125
+
126
+ function renderAside() {
127
+ const rowSelected = selected && form
128
+ const rowChecked = pageContext.checked && pageContext.checked.size > 0
129
+ if (rowSelected || rowChecked) {
130
+ return (
131
+ <aside className="table-page">
132
+ {rowSelected ? <TableRowEditor content={new Content(schema, form)} filter={editorFilter} onChange={change} onClose={closeAside} editable={canEdit} /> : null}
133
+ {rowChecked ? <TableSelector schema={schema} actions={selectionActions} /> : null}
134
+ </aside>
135
+ )
136
+ }
137
+ return null;
138
+ }
139
+
140
+ function renderActions() {
141
+ return actions.map(element => {
142
+ const action = () => element.props.action(pageContext)
143
+ const clone = React.cloneElement(element, { action })
144
+ return clone
145
+ })
146
+ }
147
+
148
+ function changeTab(id) {
149
+ const tab = tabs.find(tab => tab.value === id)
150
+ pageContext.changeTab(tab)
151
+ setPageContext(Object.assign({}, pageContext))
152
+ }
153
+
154
+ function renderTabs() {
155
+ const selected = tab ? tab.value : null
156
+ console.log(selected)
157
+ return (
158
+ <Tabs selected={selected} onChange={changeTab}>
159
+ {tabs.map(tab => <Tab id={tab.value} label={tab.label} />)}
160
+ </Tabs>
161
+ )
162
+ }
163
+
164
+ return (
165
+ <Fragment>
166
+ <Header className="table-page" title={<Text>{title}</Text>}>
167
+ {canAdd ? <Button icon="add" label="Añadir" action={add} raised /> : null}
168
+ &nbsp;
169
+ <Button icon="refresh" label="Reload" action={reload} />
170
+ {dev ? (
171
+ <MenuIcon align="alignRight">
172
+ <MenuItem label="Cargar Escenario 1" onSelect={playScenario} />
173
+ </MenuIcon>
174
+ ) : null}
175
+ {renderActions()}
176
+
177
+ {renderTabs()}
178
+
179
+ </Header>
180
+ {canQuery || canFilter ? (
181
+ <menu className="table-page">
182
+ {canQuery ? <TableQueries schema={schema} url={url} user={user} /> : null}
183
+ {canFilter ? <TableFilters schema={schema} onSave={canQuery ? saveQuery : null} /> : null}
184
+ </menu>
185
+ ) : null}
186
+ <main key={id} className="table-page">
187
+ <TableEditor icon={icon} title={name} schema={schema} delay={delay} editable={editable} groupBy={groupBy} filter={tableFilter} actions={tableActions} canDelete={canDelete} />
188
+ {children ? <article>{children}</article> : null}
189
+ </main>
190
+ {renderAside()}
191
+ </Fragment>
192
+ )
193
+ }
194
+
195
+ /**
196
+ * TableRowEditor
197
+ */
198
+ const TableRowEditor = (props) => {
199
+ const { name, content, filter, editable, onChange, onClose } = props
200
+ return (
201
+ <div className="table-row-editor">
202
+ <Header icon="local_offer" title={name || "Propiedades"}>
203
+ <Icon icon="close" clickable action={onClose} />
204
+ </Header>
205
+ <main>
206
+ {editable ? <ContentEditor content={content} onChange={onChange} filter={filter} /> : <ContentViewer content={content} />}
207
+ </main>
208
+ </div>
209
+ )
210
+ }
211
+
212
+ /**
213
+ * Table Selector
214
+ */
215
+ const TableSelector = (props) => {
216
+
217
+ const { schema, actions = [] } = props
218
+ const [pageContext, setPageContext] = useContext(PageContext)
219
+ const { all, checked } = pageContext
220
+
221
+ const count = `${checked.size}/${all.length}`
222
+
223
+ const columns = Object.keys(schema)
224
+ .filter(key => schema[key].selectorColumn === true)
225
+ .map(key => {
226
+ const field = schema[key]
227
+ return { id: field.id, label: field.label }
228
+ })
229
+
230
+ const rows = all.filter(item => checked.has(item.id))
231
+ const table = {
232
+ columns,
233
+ rows: rows || []
234
+ }
235
+ const buttons = actions.map(({ label, action, validate }) => {
236
+ return <Button
237
+ label={label} raised
238
+ action={() => action(checked, pageContext, async () => {
239
+ await pageContext.load()
240
+ setPageContext(Object.assign({}, pageContext))
241
+ }, rows)}
242
+ disabled={!validate(checked, rows)}
243
+ />
244
+ })
245
+
246
+ return (
247
+ <div className="table-selector">
248
+ <Header icon="checklist_rtl" title="Selección">
249
+ <span className="size">{count}</span>
250
+ </Header>
251
+ <main>
252
+ <DataTable {...table} />
253
+ </main>
254
+ <footer>
255
+ {buttons}
256
+ </footer>
257
+ </div>
258
+ )
259
+ }
260
+
261
+ /**
262
+ * Table Queries
263
+ */
264
+ const TableQueries = (props) => {
265
+
266
+ const [pageContext, setPageContext] = useContext(PageContext)
267
+ const { url, user } = props
268
+ const { queries = [] } = pageContext
269
+ const [selected, setSelected] = useState()
270
+
271
+ function select(query) {
272
+ setSelected(query.id)
273
+ pageContext.changeFilters(query.filters)
274
+ setPageContext(Object.assign({}, pageContext))
275
+ }
276
+
277
+ async function remove(id) {
278
+ await pageContext.removeQuery(id, user)
279
+ setPageContext(Object.assign({}, pageContext))
280
+ }
281
+
282
+ return (
283
+ <Fragment>
284
+ <Header className="table-queries" title={<Text>Queries</Text>} />
285
+ <main className="table-queries">
286
+ {queries ? queries
287
+ .filter(query => query.url === url)
288
+ .map(query => {
289
+ const style = selected === query.id ? "selected" : ""
290
+ return (
291
+ <div className={`table-queries-item ${style}`} onClick={() => select(query)}>
292
+ <Icon icon="star" size="small" />
293
+ <label>{query.name}</label>
294
+ <Icon icon="close" clickable size="small" action={() => remove(query.id)} />
295
+ </div>
296
+ )
297
+ }) : <div>...empty...</div>}
298
+ </main>
299
+ </Fragment>
300
+ )
301
+ }
302
+
303
+ /**
304
+ * Table Filters
305
+ */
306
+ const TableFilters = (props) => {
307
+
308
+ const [pageContext, setPageContext] = useContext(PageContext)
309
+ const { filters } = pageContext
310
+ const { schema, onSave } = props
311
+ const [form, setForm] = useState({})
312
+
313
+ const filterSchema = useMemo(() => {
314
+ const filterSchema = Object.assign({}, schema)
315
+ for (var key in filterSchema) {
316
+ if (filterSchema[key].filter === false) {
317
+ delete filterSchema[key]
318
+ } else {
319
+ if (filterSchema[key].type === TYPES.ENTITY) {
320
+ const fs = filterSchema[key].item
321
+ for (var key in fs) {
322
+ if (fs[key].filter === false) delete fs[key]
323
+ }
324
+ }
325
+ }
326
+ }
327
+ //Object.values(filterSchema).forEach(field => field.section = null)
328
+ delete filterSchema.flows
329
+ return filterSchema
330
+ }, [schema])
331
+
332
+ useEffect(() => {
333
+ if (filters) setForm(filters)
334
+ }, [filters])
335
+
336
+ useEffect(() => {
337
+ reload()
338
+ }, [form])
339
+
340
+ async function change(next) {
341
+ setForm(next)
342
+ }
343
+
344
+ async function reload() {
345
+ await pageContext.load(form)
346
+ setPageContext(Object.assign({}, pageContext))
347
+ }
348
+
349
+ function clear() {
350
+ change({})
351
+ }
352
+
353
+ function save() {
354
+ if (onSave) {
355
+ onSave(form)
356
+ }
357
+ }
358
+
359
+ const content = new Content(filterSchema, form)
360
+ return (
361
+ <Fragment>
362
+ <Header className="table-filters" title={<Text>Filters</Text>} >
363
+ <Icon icon="filter_list_off" size="small" clickable action={clear} />
364
+ {onSave ? <Icon icon="save" size="small" clickable action={save} /> : null}
365
+ </Header>
366
+ <main className="table-filters">
367
+ <ContentEditor content={content} onChange={change} />
368
+ </main>
369
+ </Fragment>
370
+ )
371
+ }
372
+
373
+ /**
374
+ * Table Editor
375
+ */
376
+ export const TableEditor = (props) => {
377
+
378
+ const site = useContext(SiteContext)
379
+ const [pageContext, setPageContext] = useContext(PageContext)
380
+ const { all = [], filters } = pageContext
381
+ const { icon, title, schema, editable, canDelete, filter, actions } = props
382
+ const [groupBy, setGroupBy] = useState(props.groupBy)
383
+
384
+ function changeGroup(id, value) {
385
+ setGroupBy(value)
386
+ }
387
+
388
+ async function remove(id) {
389
+ const confirm = await site.confirm("Are you sure ?")
390
+ if (confirm) {
391
+ await pageContext.remove(id)
392
+ pageContext.clear()
393
+ setPageContext(Object.assign({}, pageContext))
394
+ }
395
+ }
396
+
397
+ function change(rowID, cellID, value) {
398
+ const row = all.find(r => r.id === rowID)
399
+ const next = Object.assign({}, row, { [cellID]: value })
400
+ delete next.actions
401
+ pageContext.update(next)
402
+ setPageContext(Object.assign({}, pageContext))
403
+ }
404
+
405
+ function clear() {
406
+ pageContext.clear()
407
+ setPageContext(Object.assign({}, pageContext))
408
+ }
409
+
410
+ async function select(row, event) {
411
+ clear()
412
+ await pageContext.select(row.id)
413
+ setPageContext(Object.assign({}, pageContext))
414
+ }
415
+
416
+ async function check(ids, value) {
417
+ pageContext.check(ids, value)
418
+ setPageContext(Object.assign({}, pageContext))
419
+ }
420
+
421
+ async function checkOne(id, field, value) {
422
+ check([id], value)
423
+ }
424
+
425
+ function run(action, item) {
426
+ action.action(item.id, pageContext, async () => {
427
+ await pageContext.load()
428
+ setPageContext(Object.assign({}, pageContext))
429
+ })
430
+ }
431
+
432
+ function renderGroupLabel(groupName) {
433
+ const grouper = schema[groupBy]
434
+ if (!groupName || !grouper) return ""
435
+ if (grouper.options) {
436
+ const options = CHECK['isFunction'](grouper.options) ? grouper.options() : grouper.options
437
+ const option = options.find(option => option.value === groupName)
438
+ return option ? option.label : groupName
439
+ } else {
440
+ return groupName
441
+ }
442
+ }
443
+
444
+ function renderGroups() {
445
+ const items = filter ? filter(all) : all
446
+ const groups = items.reduce((groups, item) => {
447
+ const groupName = item[groupBy]
448
+ const group = groups[groupName]
449
+ if (!group) groups[groupName] = []
450
+ groups[groupName].push(item)
451
+ return groups
452
+ }, {})
453
+ return Object.keys(groups).map(groupName => {
454
+ const table = {
455
+ columns: Object.values(schema)
456
+ .filter(field => field.column === true)
457
+ .map(field => {
458
+ let options = field.options;
459
+ if (options && typeof (options) == 'function') {
460
+ options = options()
461
+ }
462
+ return {
463
+ id: field.id,
464
+ label: field.label,
465
+ type: field.type,
466
+ format: field.format,
467
+ item: field.item ? field.item : [],
468
+ onChange: field.id === "checked" ? checkOne : field.editable ? change : null, /* checked has it´s own handler */
469
+ options
470
+ }
471
+ }),
472
+ rows: groups[groupName]
473
+ .map(item => {
474
+ item.checked = pageContext.checked ? pageContext.checked.has(item.id) : false
475
+ item.actions = actions ? actions.map(action => {
476
+ return action.filter ?
477
+ action.filter(item) ? <Icon icon={action.icon} clickable size="small" action={() => run(action, item)} /> : null
478
+ : <Icon icon={action.icon} clickable size="small" action={() => run(action, item)} />
479
+ }) : []
480
+ if (canDelete) item.actions.push(<Icon icon="delete" size="small" clickable action={() => remove(item.id)} />)
481
+ return item
482
+ })
483
+ }
484
+ table.columns.push({ id: "actions" })
485
+ const groupSize = groups[groupName].length
486
+ const title = <span><span className="size">{groupSize}</span>{renderGroupLabel(groupName)}</span>
487
+ return (
488
+ <Fragment key={groupName}>
489
+ <Header title={title} >
490
+ <span className="size">{groupSize}</span>
491
+ </Header>
492
+ <DataTable {...table} onRowSelection={select} editable={editable} onCheckAll={check} />
493
+ </Fragment>
494
+ )
495
+ })
496
+ }
497
+
498
+ function buildGroupOptions(schema) {
499
+ return Object.values(schema)
500
+ .filter(field => field.grouper === true)
501
+ .map(field => ({ label: field.label, value: field.id }))
502
+ }
503
+
504
+ return (
505
+ <Fragment>
506
+ <Header icon={icon} title={<Text>{title}</Text>}>
507
+ <DropDown id="groupBy" label="Agrupar Por" value={groupBy} options={buildGroupOptions(schema)} onChange={changeGroup} />
508
+ </Header>
509
+ <main className="table-editor">
510
+ {renderGroups()}
511
+ </main>
512
+ </Fragment>
513
+ )
514
+ }
515
+
516
+ /**
517
+ * Table Context
518
+ */
519
+ const TableContext = (url, field, host, urlQuery) => {
520
+
521
+ const API = TableAPI(url, host)
522
+
523
+ return {
524
+
525
+ all: [],
526
+ checked: new Set([]),
527
+ selected: null,
528
+ filters: {},
529
+ queries: [],
530
+ tab: null,
531
+
532
+ async load(filter, like) {
533
+ try {
534
+ const filters = filter ? Object.keys(filter).reduce((filters, key) => {
535
+ const field = filter[key];
536
+ if (field) {
537
+ if (CHECK['isObject'](field)) {
538
+ Object.keys(field).forEach(key2 => {
539
+ const subfield = field[key2]
540
+ if (subfield) filters[`${key}.${key2}`] = subfield
541
+ })
542
+ } else {
543
+ filters[key] = field;
544
+ }
545
+ }
546
+
547
+ return filters;
548
+ }, {}) : []
549
+
550
+ if (this.tab) {
551
+ filters[this.tab.field] = this.tab.value
552
+ }
553
+
554
+ const data = await API.all(filters, like);
555
+ this.all = field ? data[field] : data;
556
+ } catch (error) {
557
+ console.log(error)
558
+ }
559
+ return
560
+ },
561
+
562
+ check(ids, isChecked = true) {
563
+ if (isChecked) {
564
+ ids.forEach(id => this.checked.add(id))
565
+ } else {
566
+ ids.forEach(id => this.checked.delete(id))
567
+ }
568
+ },
569
+
570
+ changeTab(tab) {
571
+ this.tab = tab
572
+ },
573
+
574
+ select(id) {
575
+ const result = this.all.find(item => item.id === id);
576
+ this.selected = result;
577
+ },
578
+
579
+ clear() {
580
+ this.selected = null
581
+ },
582
+
583
+ async create(form) {
584
+ try {
585
+ await API.create(form);
586
+ await this.load({}, false);
587
+ } catch (error) {
588
+ console.log(error)
589
+ }
590
+ return
591
+ },
592
+
593
+ async update(form) {
594
+ try {
595
+ await API.update(form)
596
+ await this.load()
597
+ } catch (error) {
598
+ console.log(error)
599
+ }
600
+ return
601
+ },
602
+
603
+ async remove(id) {
604
+ try {
605
+ await API.remove(id)
606
+ await this.load()
607
+ } catch (error) {
608
+ console.log(error)
609
+ }
610
+ return
611
+ },
612
+
613
+ changeFilters(filters) {
614
+ this.filters = filters
615
+ },
616
+
617
+ async loadQueries(user) {
618
+ try {
619
+ this.queries = await API.queries(user, urlQuery)
620
+ } catch (error) {
621
+ console.log(error)
622
+ }
623
+ },
624
+
625
+ async createQuery(query, user) {
626
+ try {
627
+ await API.createQuery(query, urlQuery)
628
+ await this.loadQueries(user)
629
+ } catch (error) {
630
+ console.log(error)
631
+ }
632
+ },
633
+
634
+ async removeQuery(id, user) {
635
+ try {
636
+ await API.removeQuery(id, urlQuery)
637
+ await this.loadQueries(user)
638
+ } catch (error) {
639
+ console.log(error)
640
+ }
641
+ return
642
+ }
643
+
644
+ }
645
+ }
646
+
647
+ /**
648
+ * table API
649
+ */
650
+ const TableAPI = (url, host) => {
651
+
652
+ const http = HTTPClient(host || window.API || process.env.REACT_APP_API, Session);
653
+
654
+ return {
655
+ all(filters, like = true) {
656
+ let queryParams = "?"
657
+ if (filters) {
658
+ const filterQuery = Object.keys(filters).reduce((query, key) => {
659
+ const value = filters[key]
660
+ if (typeof (value) === 'boolean') {
661
+ return query.concat(`${key}=${value}&`)
662
+ } else if (Array.isArray(value)) {
663
+ const param = value.length === 0 ? '' : value.reduce((param, item) => {
664
+ param = param.concat(`${key}=${item}&`)
665
+ return param
666
+ }, "")
667
+ return query.concat(param)
668
+ } else {
669
+ return like ? query.concat(`${key}=%${filters[key]}%&`) : query.concat(`${key}=${filters[key]}&`)
670
+ }
671
+ }, "")
672
+ queryParams = queryParams.concat(filterQuery)
673
+ }
674
+ return http.GET(url + queryParams)
675
+ },
676
+
677
+ find(id) {
678
+ return http.GET(`${url}/${id}`)
679
+ },
680
+
681
+ create(form) {
682
+ const body = JSON.stringify(form)
683
+ return http.POST(url, body)
684
+ },
685
+
686
+ update(form) {
687
+ const body = JSON.stringify(form)
688
+ return http.PUT(`${url}/${form.id}`, body)
689
+ },
690
+
691
+ remove(id) {
692
+ return http.DELETE(`${url}/${id}`)
693
+ },
694
+
695
+ queries(user, url2) {
696
+ let url3 = url2 ? url2 : url
697
+ url3 = url3 + "queries"
698
+ if (user) url3 = url3 + `?user=${user}`
699
+ return http.GET(url3)
700
+ },
701
+
702
+ createQuery(form, url2) {
703
+ const url3 = url2 ? url2 : url
704
+ const body = JSON.stringify(form)
705
+ return http.POST(`${url3}queries`, body)
706
+ },
707
+
708
+ removeQuery(id, url2) {
709
+ const url3 = url2 ? url2 : url
710
+ return http.DELETE(`${url3}queries/${id}`)
711
+ },
712
+ }
713
+ }
@@ -8,20 +8,24 @@ import { Dialog } from './dialog'
8
8
  import { Button, DropDown, TextField, TextArea } from '../html'
9
9
  import { UploadDialog } from '../widgets/upload/UploadDialog'
10
10
  import { Uploader } from '../widgets/upload/Uploader'
11
- import { TablePage } from '../domain/TablePage'
11
+ import { TabbedTablePage } from '../domain/TabbedTablePage'
12
+ import { FORMATS, TYPES } from '../domain/ContentType'
12
13
 
13
14
  const SiteTest = (prop) => {
14
15
 
15
16
  const footer = <div>FOOTER</div>
16
17
 
17
18
  return (
18
- <Site icon="star" title="Site Test" init={"PAGE1"} footer={footer}>
19
+ <Site icon="star" title="Site Test" init={"PAGE3"} footer={footer}>
19
20
  <Page id="PAGE1" section="SECTION1" icon="description" title="Page 1" layout="workspace">
20
21
  <Page1 />
21
22
  </Page>
22
23
  <Page id="PAGE2" section="SECTION1" icon="description" title="Page 2" layout="workspace">
23
24
  <Page2 />
24
25
  </Page>
26
+ <Page id="PAGE3" section="SECTION1" icon="description" title="Page 3" layout="workspace">
27
+ <Page3 />
28
+ </Page>
25
29
  </Site>
26
30
  )
27
31
  }
@@ -110,10 +114,20 @@ const Page2 = (props) => {
110
114
 
111
115
  const Page3 = (props) => {
112
116
 
113
- const site = useContext(SiteContext)
117
+ const schema = {
118
+ name : { id: "name" , type: TYPES.STRING, format: FORMATS.NONE , required: true, tab: false, column: true , filter: true , label: "Name" },
119
+ state : { id: "state" , type: TYPES.STRING, format: FORMATS.NONE , required: true, tab: true , column: true , filter: false, label: "State" , options: [
120
+ { label: "Pendiente", value: "NOT_CLASSIFIED" },
121
+ { label: "Clasificada", value: "CLASSIFIED"},
122
+ ]},
123
+ field1: { id: "field1", type: TYPES.STRING, format: FORMATS.NONE , required: true, tab: false, column: true , filter: true , label: "field1" },
124
+ field2: { id: "field2", type: TYPES.STRING, format: FORMATS.NONE , required: true, tab: false, column: true , filter: true , label: "field2" },
125
+ field4: { id: "field4", type: TYPES.STRING, format: FORMATS.COLOR, required: true, tab: false, column: true , filter: true , label: "Color" },
126
+ }
114
127
 
115
128
  return (
116
129
  <Fragment>
130
+ <TabbedTablePage title="Referencias" schema={schema} host="http://localhost:3000" url="/references"/>
117
131
  </Fragment>
118
132
  )
119
133
  }