ywana-core8 0.0.535 → 0.0.538

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ywana-core8",
3
- "version": "0.0.535",
3
+ "version": "0.0.538",
4
4
  "description": "ywana-core8",
5
5
  "homepage": "https://ywana.github.io/workspace",
6
6
  "author": "Ernesto Roldan Garcia",
@@ -30,25 +30,7 @@ main.collection-page {
30
30
  flex-direction: column;
31
31
  }
32
32
 
33
- .collection-page .content-editor {
33
+ main.collection-page>.content-editor {
34
34
  flex: 1;
35
35
  }
36
36
 
37
- .collection-page .content-editor>section {
38
- border: solid 1px var(--divider-color);
39
- background-color: var(--paper-color);
40
- padding: 0 1rem 1rem 1rem;
41
- }
42
-
43
- .collection-page .content-editor.tabbed>section {
44
- border: solid 1px var(--divider-color);
45
- border-width: 0 1px 1px 1px;
46
- background-color: var(--paper-color);
47
- padding: 0 1rem 1rem 1rem;
48
- }
49
-
50
- .collection-page > article {
51
- display: flex;
52
- overflow: hidden;
53
- }
54
-
@@ -20,7 +20,7 @@ export const CollectionPage = (props) => {
20
20
  icon, title, name = "Collection 1", className,
21
21
  schema, url, field, host, page, fetching = false,
22
22
  actions = [], onSelect,
23
- canFilter = false, canAdd = false, canDelete = false, canEdit = false,
23
+ canFilter = false, canAdd = false, canDelete = false, canEdit = false, searchBy,
24
24
  autosave = false, delay = 1000,
25
25
  groupBy, levels, sorter,
26
26
  editor,
@@ -68,7 +68,7 @@ export const CollectionPage = (props) => {
68
68
  <Header title={<Text>{name}</Text>} >
69
69
  </Header>
70
70
  {canFilter ? <CollectionFilters schema={schema} /> : null}
71
- {levels ? <CollectionTree icon={icon} levels={levels} onSelect={onSelect} sorter={sorter} /> : <CollectionList groupBy={groupBy} onSelect={onSelect} />}
71
+ {levels ? <CollectionTree icon={icon} levels={levels} onSelect={onSelect} sorter={sorter} searchBy={searchBy} /> : <CollectionList groupBy={groupBy} onSelect={onSelect} searchBy={searchBy} />}
72
72
  </menu>
73
73
  <main key={id} className={`collection-page ${className}`}>
74
74
  <CollectionEditor icon={icon} schema={schema} layout={editor} autosave={autosave} delay={delay} />
@@ -133,9 +133,10 @@ export const CollectionFilters = (props) => {
133
133
  */
134
134
  const CollectionList = (props) => {
135
135
 
136
- const { groupBy, onSelect } = props
136
+ const { groupBy, onSelect, searchBy=[] } = props
137
137
  const [pageContext, setPageContext] = useContext(PageContext)
138
138
  const { all = [] } = pageContext
139
+ const [filter, setFilter] = useState()
139
140
 
140
141
  function clear() {
141
142
  pageContext.clear()
@@ -149,15 +150,40 @@ const CollectionList = (props) => {
149
150
  if (onSelect) onSelect(id)
150
151
  }
151
152
 
152
- const items = all ? all.map(content => ({
153
+ function changeSearch(id, value) {
154
+ setFilter(value)
155
+ }
156
+
157
+ function search() {
158
+ const items = filter ? all.filter(item => {
159
+ const result = searchBy.some(fieldName => {
160
+ const value = item[fieldName]
161
+ return value ? value.indexOf(filter.toUpperCase()) >= 0 : false
162
+ })
163
+ return result
164
+ }) : all
165
+ return items
166
+ }
167
+
168
+ const items = search()
169
+ const items2 = items.map(content => ({
153
170
  id: content.id,
154
171
  line1: content.name || content.centre || content.tag, // centre: Signflow legacy
155
172
  line2: content.description,
156
173
  content
157
- })) : []
174
+ }))
158
175
 
159
176
  return (
160
- <List items={items} onSelect={select} groupBy={groupBy} />
177
+ <>
178
+ <main>
179
+ <List items={items2} onSelect={select} groupBy={groupBy} />
180
+ </main>
181
+ <footer>
182
+ <div className='search-box'>
183
+ <TextField icon="search" label="Search" onChange={changeSearch} outlined className="search-box" />
184
+ </div>
185
+ </footer>
186
+ </>
161
187
  )
162
188
  }
163
189
 
@@ -166,7 +192,7 @@ const CollectionList = (props) => {
166
192
  */
167
193
  export const CollectionTree = (props) => {
168
194
 
169
- const { icon = "description", levels, onSelect, sorter } = props
195
+ const { icon = "description", levels, onSelect, sorter, searchBy=[] } = props
170
196
  const [pageContext, setPageContext] = useContext(PageContext)
171
197
  const { all = [] } = pageContext
172
198
  const [filter, setFilter] = useState()
@@ -183,7 +209,7 @@ export const CollectionTree = (props) => {
183
209
  if (onSelect) onSelect(id)
184
210
  }
185
211
 
186
- function search(id, value) {
212
+ function changeSearch(id, value) {
187
213
  setFilter(value)
188
214
  }
189
215
 
@@ -218,8 +244,19 @@ export const CollectionTree = (props) => {
218
244
  })
219
245
  }
220
246
 
221
- const items = sorter ? sorter(all) : all
222
- const items2 = filter ? items.filter(item => item.name.toUpperCase().indexOf(filter.toUpperCase()) >= 0) : items
247
+ function search() {
248
+ const items = filter ? all.filter(item => {
249
+ const result = searchBy.some(fieldName => {
250
+ const value = item[fieldName]
251
+ return value ? value.indexOf(filter.toUpperCase()) >= 0 : false
252
+ })
253
+ return result
254
+ }) : all
255
+ return items
256
+ }
257
+
258
+ const items = search()
259
+ const items2 = sorter ? sorter(items) : items
223
260
  const nodes = generateNodes(levels, items2)
224
261
  return (
225
262
  <>
@@ -230,7 +267,7 @@ export const CollectionTree = (props) => {
230
267
  </main>
231
268
  <footer>
232
269
  <div className='search-box'>
233
- <TextField icon="search" label="Search" onChange={search} outlined className="search-box" />
270
+ <TextField icon="search" label="Search" onChange={changeSearch} outlined className="search-box" />
234
271
  </div>
235
272
  </footer>
236
273
  </>
@@ -1,19 +1,43 @@
1
+ /**************************************/
2
+ /*********** content-editor ***********/
3
+ /**************************************/
4
+
1
5
  .content-editor {
2
- padding: 0 1rem;
6
+ padding: .5rem;
3
7
  }
4
8
 
5
- .content-editor>section,
6
- .entity-editor>section {
7
- margin-bottom: 1rem;
9
+ /**************************************/
10
+ /******* content-editor tabbed ********/
11
+ /**************************************/
12
+
13
+ .content-editor.tabbed {
14
+ overflow: hidden !important;
15
+ display: flex;
16
+ flex-direction: column;
8
17
  }
9
18
 
10
- .content-editor>section>header,
11
- .entity-editor>section>header {
19
+ .content-editor.tabbed>.tabs {
20
+ min-height: 3rem;
21
+ }
22
+
23
+ .content-editor.tabbed>section {
24
+ border: solid 1px var(--divider-color);
25
+ border-width: 0 1px 1px 1px;
26
+ background-color: var(--paper-color);
27
+ padding: 1rem;
28
+ overflow: auto;
29
+ }
30
+
31
+ .content-editor>section>header {
12
32
  padding: .5rem;
13
33
  border-bottom: solid 1px var(--divider-color);
14
34
  margin-bottom: .5rem;
15
35
  }
16
36
 
37
+ /**************************************/
38
+ /************ entity-editor ***********/
39
+ /**************************************/
40
+
17
41
  .entity-editor {
18
42
  }
19
43
 
@@ -21,20 +45,19 @@
21
45
  padding: .5rem;
22
46
  }
23
47
 
24
- .collection-editor {
48
+ .entity-editor>section {
49
+ margin-bottom: 1rem;
25
50
  }
26
51
 
27
- .collection-editor>header {
28
- padding: 0 .5rem;
29
- display: flex;
30
- align-items: flex-end;
52
+ .entity-editor>section>header {
53
+ padding: .5rem;
54
+ border-bottom: solid 1px var(--divider-color);
55
+ margin-bottom: .5rem;
31
56
  }
32
57
 
33
- .collection-editor>header>.actions {
34
- flex: 1;
35
- display: flex;
36
- justify-content: flex-end;
37
- }
58
+ /**************************************/
59
+ /********* collection-editor **********/
60
+ /**************************************/
38
61
 
39
62
  .collection-editor>header>.actions button {
40
63
  height: 2rem !important;
@@ -54,12 +77,6 @@
54
77
  width: 99%;
55
78
  }
56
79
 
57
- .collection-editor .actions {
58
- width: 8rem;
59
- text-align: right;
60
- padding: .5rem;
61
- }
62
-
63
80
  .collection-adder {
64
81
  display: flex;
65
82
  }
@@ -97,6 +114,10 @@
97
114
  align-items: center;
98
115
  }
99
116
 
117
+ /**************************************/
118
+ /************ field-editor ************/
119
+ /**************************************/
120
+
100
121
  .field-editor {
101
122
  padding: 0;
102
123
  }
@@ -105,6 +126,10 @@
105
126
  width: 100%;
106
127
  }
107
128
 
129
+ /**************************************/
130
+ /*********** function-editor **********/
131
+ /**************************************/
132
+
108
133
  .function-editor {
109
134
  width: 100%;
110
135
  min-height: 10rem;
@@ -1,10 +1,9 @@
1
1
  import React, { Fragment, useState } from 'react';
2
- import { Button, CheckBox, DataTable, DropDown, Icon, Stack, Tab, Tabs, Text, TextField, Tree, TreeNode, TreeItem, TokenField, Property } from '../html';
3
- import { CHECK, Content, TYPES } from './ContentType';
4
- import './ContentEditor.css';
5
- import { FORMATS } from './ContentType';
6
- import { ColorField } from '../html/color';
2
+ import { Button, CheckBox, DataTable, DropDown, Icon, Stack, Tab, Tabs, Text, TextField, Tree, TreeNode, TreeItem, TokenField, Header } from '../html';
3
+ import { CHECK, Content, TYPES, FORMATS } from './ContentType';
7
4
  import { DateRange } from '../html/textfield';
5
+ import { ColorField } from '../html/color';
6
+ import './ContentEditor.css';
8
7
 
9
8
  /**
10
9
  * Content Editor
@@ -81,33 +80,28 @@ export const TabbedContentEditor = ({ content, filter, grouped = false, onChange
81
80
  const { title, fields } = section
82
81
  return (
83
82
  <section key={title}>
84
- <nav>
85
- &nbsp;
86
- </nav>
87
- <main>
88
- {
89
- grouped ?
90
- group(section)
91
- .map(group => {
92
- return (
93
- <Fragment>
94
- {group.name.length > 0 ? <div className="group-caption">{group.name}</div> : null}
95
- {
96
- group.fields
97
- .filter(field => field.id !== 'id')
98
- .filter(field => filter ? filter(field) : true)
99
- .map((field) => <FieldEditor key={field.id} field={field} onChange={change} content={content} />)
100
- }
101
- </Fragment>
102
- )
103
- })
104
- :
105
- fields
106
- .filter(field => field.id !== 'id')
107
- .filter(field => filter ? filter(field) : true)
108
- .map((field) => <FieldEditor key={field.id} field={field} onChange={change} content={content} />)
109
- }
110
- </main>
83
+ {
84
+ grouped ?
85
+ group(section)
86
+ .map(group => {
87
+ return (
88
+ <Fragment>
89
+ {group.name.length > 0 ? <div className="group-caption">{group.name}</div> : null}
90
+ {
91
+ group.fields
92
+ .filter(field => field.id !== 'id')
93
+ .filter(field => filter ? filter(field) : true)
94
+ .map((field) => <FieldEditor key={field.id} field={field} onChange={change} content={content} />)
95
+ }
96
+ </Fragment>
97
+ )
98
+ })
99
+ :
100
+ fields
101
+ .filter(field => field.id !== 'id')
102
+ .filter(field => filter ? filter(field) : true)
103
+ .map((field) => <FieldEditor key={field.id} field={field} onChange={change} content={content} />)
104
+ }
111
105
  </section>
112
106
  )
113
107
  })}
@@ -404,7 +398,9 @@ export const CollectionEditor = ({ field, value = [], onChange }) => {
404
398
  }
405
399
  }
406
400
 
407
- const columns = Object.values(item).map((item) => ({ ...item, onChange: change }))
401
+ const columns = Object.values(item)
402
+ .filter(field => field.column === true)
403
+ .map((item) => ({ ...item, onChange: change }))
408
404
  columns.push({ id: 'actions', label: 'Actions' })
409
405
 
410
406
  const rows = value.map((item, index) => ({
@@ -419,14 +415,15 @@ export const CollectionEditor = ({ field, value = [], onChange }) => {
419
415
 
420
416
  return (
421
417
  <div className='collection-editor'>
422
- <header>
423
- <Text use='caption'>{label}</Text>
424
- <div className="actions" >
425
- {Feeder ? <Feeder onAdd={add} /> : null}
426
- </div>
427
- </header>
428
- {Renderer ? <Renderer field={field} value={value} onRemove={remove} onChange={onChange} /> : <DataTable {...table} editable={editable} />}
418
+ {
419
+ Renderer ?
420
+ <Renderer field={field} value={value} onRemove={remove} onChange={onChange} />
421
+ // : <DataTable {...table} editable={editable} />
422
+ : <TableEditor icon={"info"} title={label} data={value} schema={item} groupBy={"field1"} />
423
+
424
+ }
429
425
  <footer>
426
+ {Feeder ? <Feeder onAdd={add} /> : null}
430
427
  {Adder ? <CollectionAdder item={item} onAdd={add} /> : null}
431
428
  </footer>
432
429
  </div>
@@ -470,4 +467,113 @@ const CollectionAdder = ({ item, onAdd }) => {
470
467
  {edit ? <DataTable {...table} editable={true} /> : <Button icon='add' label='Añadir' action={toggle} />}
471
468
  </div>
472
469
  )
473
- }
470
+ }
471
+
472
+
473
+ /**
474
+ * Table Editor
475
+ */
476
+ const TableEditor = (props) => {
477
+
478
+ const { data = [], icon, title, schema, editable, canDelete, filter, actions, className } = props
479
+ const [groupBy, setGroupBy] = useState(props.groupBy)
480
+
481
+ function changeGroup(id, value) {
482
+ setGroupBy(value)
483
+ }
484
+
485
+ async function select(row) {
486
+ if (onSelect) onSelect(row.id)
487
+ }
488
+
489
+ function renderGroupLabel(groupName) {
490
+ const grouper = schema[groupBy]
491
+ if (!groupName || !grouper) return ""
492
+ if (grouper.options) {
493
+ const options = CHECK['isFunction'](grouper.options) ? grouper.options() : grouper.options
494
+ const option = options.find(option => option.value === groupName)
495
+ return option ? option.label : groupName
496
+ } else {
497
+ return groupName
498
+ }
499
+ }
500
+
501
+ function renderGroups() {
502
+ const items = filter ? filter(data) : data
503
+
504
+ if (items.length === 0) return (
505
+ <div className='empty-message'>
506
+ <Icon icon="search_off" />
507
+ <Text>No Result Found</Text>
508
+ </div>
509
+ )
510
+
511
+ const groups = items.reduce((groups, item) => {
512
+ const groupName = item[groupBy]
513
+ const group = groups[groupName]
514
+ if (!group) groups[groupName] = []
515
+ groups[groupName].push(item)
516
+ return groups
517
+ }, {})
518
+
519
+ return Object.keys(groups).map(groupName => {
520
+ const table = {
521
+ columns: Object.values(schema)
522
+ .filter(field => field.column === true)
523
+ .map(field => {
524
+ let options = field.options;
525
+ if (options && typeof (options) == 'function') {
526
+ options = options()
527
+ }
528
+ return {
529
+ id: field.id,
530
+ label: field.label,
531
+ type: field.type,
532
+ format: field.format,
533
+ item: field.item ? field.item : [],
534
+ onChange: field.id === "checked" ? checkOne : field.editable ? change : null, /* checked has it´s own handler */
535
+ options
536
+ }
537
+ }),
538
+ rows: groups[groupName]
539
+ .map(item => {
540
+ item.actions = actions ? actions.map(action => {
541
+ return action.filter ?
542
+ action.filter(item) ? <Icon icon={action.icon} clickable size="small" action={() => run(action, item)} /> : null
543
+ : <Icon icon={action.icon} clickable size="small" action={() => run(action, item)} />
544
+ }) : []
545
+ if (canDelete) item.actions.push(<Icon icon="delete" size="small" clickable action={() => remove(item.id)} />)
546
+ return item
547
+ })
548
+ }
549
+ table.columns.push({ id: "actions" })
550
+ const groupSize = groups[groupName].length
551
+ const title = <span><span className="size">{groupSize}</span>{renderGroupLabel(groupName)}</span>
552
+ return (
553
+ <Fragment key={groupName}>
554
+ <Header title={title} >
555
+ <span className="size">{groupSize}</span>
556
+ </Header>
557
+ <DataTable {...table} onRowSelection={select} editable={editable} className={className} />
558
+ </Fragment>
559
+ )
560
+ })
561
+ }
562
+
563
+ function buildGroupOptions(schema) {
564
+ return Object.values(schema)
565
+ .filter(field => field.grouper === true)
566
+ .map(field => ({ label: field.label, value: field.id }))
567
+ }
568
+
569
+ return (
570
+ <Fragment>
571
+ <Header icon={icon} title={<Text>{title}</Text>}>
572
+ <DropDown id="groupBy" label="Agrupar Por" value={groupBy} options={buildGroupOptions(schema)} onChange={changeGroup} />
573
+ </Header>
574
+ <main className="table-editor">
575
+ {renderGroups()}
576
+ </main>
577
+ </Fragment>
578
+ )
579
+ }
@@ -426,6 +426,7 @@ export const TableEditor = (props) => {
426
426
  groups[groupName].push(item)
427
427
  return groups
428
428
  }, {})
429
+
429
430
  return Object.keys(groups).map(groupName => {
430
431
  const table = {
431
432
  columns: Object.values(schema)
@@ -192,14 +192,14 @@ const Page4 = (props) => {
192
192
  const Page5 = (props) => {
193
193
 
194
194
  const ENTITYTYPE = {
195
- name : { id: "name" , section: "", type: TYPES.STRING, format: FORMATS.NONE , required: true, tab: false, grouper: true , column: true , filter: true , like: true, label: "Name" },
196
- field1: { id: "field1", section: "E-INFO1", type: TYPES.STRING, format: FORMATS.NONE , required: true, tab: false, grouper: true , column: true , filter: true , label: "E field1" },
197
- field2: { id: "field2", section: "E-INFO2", type: TYPES.STRING, format: FORMATS.NONE , required: true, tab: false, grouper: true , column: true , filter: true , label: "E field2" },
198
- field3: { id: "field3", section: "E-INFO2", type: TYPES.STRING, format: FORMATS.NONE , required: true, tab: false, grouper: true , column: true , filter: true , label: "E field3" },
199
-
195
+ name : { id: "name" , section: "", type: TYPES.STRING, format: FORMATS.NONE , required: true, tab: false, grouper: true , column: true , filter: true , like: true, label: "Name" },
196
+ field1: { id: "field1", section: "", type: TYPES.STRING, format: FORMATS.NONE , required: true, tab: false, grouper: true , column: false, filter: true , label: "E field1" },
197
+ field2: { id: "field2", section: "", type: TYPES.STRING, format: FORMATS.NONE , required: true, tab: false, grouper: true , column: false, filter: true , label: "E field2" },
198
+ field3: { id: "field3", section: "", type: TYPES.STRING, format: FORMATS.NONE , required: true, tab: false, grouper: true , column: true , filter: true , label: "E field3" },
200
199
  }
201
200
 
202
201
  const schema = {
202
+ field6: { id: "field6", section: "C", type: TYPES.ARRAY , item: ENTITYTYPE, label: "Collection 100" },
203
203
  name : { id: "name" , section: "A", type: TYPES.STRING, format: FORMATS.NONE , required: true, tab: false, grouper: true , column: true , filter: true , like: true, label: "Name" },
204
204
  state : { id: "state" , section: "A", type: TYPES.STRING, format: FORMATS.NONE , required: true, tab: true , grouper: true , column: true , filter: false , label: "State" , options: [
205
205
  { label: "Pendiente", value: "NOT_CLASSIFIED" },
@@ -209,12 +209,17 @@ const Page5 = (props) => {
209
209
  field2: { id: "field2", section: "B", type: TYPES.STRING , format: FORMATS.NONE , required: true, tab: false, grouper: true , column: true , filter: true , label: "field2" },
210
210
  field4: { id: "field4", section: "B", type: TYPES.STRING , format: FORMATS.COLOR, required: true, tab: false, grouper: true , column: true , filter: true , label: "Color" },
211
211
  field5: { id: "field5", section: "B", type: TYPES.ENTITY, item: ENTITYTYPE, format: FORMATS.NONE , editable: true, tab: false, grouper: false, column: true , filter: true , like: false, label: "Entity5"},
212
-
212
+ id : { id: "id", type: TYPES.STRING },
213
213
  }
214
214
 
215
215
  return (
216
216
  <Fragment>
217
- <CollectionPage title="Referencias" schema={schema} host="http://localhost:3000" url="/references" levels={["color"]} canAdd={true} />
217
+ <CollectionPage
218
+ title="Referencias"
219
+ schema={schema} host="http://localhost:3000" url="/references" fetching={true} // resource
220
+ searchBy={["field1"]} levels={["color"]} // menu
221
+ editor="TABBED" canAdd={true} // editor
222
+ />
218
223
  </Fragment>
219
224
  )
220
225
  }