ywana-core8 0.0.1

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.
Files changed (101) hide show
  1. package/dist/index.cjs +2 -0
  2. package/dist/index.cjs.map +1 -0
  3. package/dist/index.css +2 -0
  4. package/dist/index.css.map +1 -0
  5. package/dist/index.modern.js +2 -0
  6. package/dist/index.modern.js.map +1 -0
  7. package/dist/index.umd.js +2 -0
  8. package/dist/index.umd.js.map +1 -0
  9. package/package.json +27 -0
  10. package/publish.sh +5 -0
  11. package/src/css/fonts.css +162 -0
  12. package/src/css/html.css +36 -0
  13. package/src/css/theme.css +89 -0
  14. package/src/css/theme_dark.css +85 -0
  15. package/src/css/theme_light.css +87 -0
  16. package/src/domain/CollectionPage.css +34 -0
  17. package/src/domain/CollectionPage.js +346 -0
  18. package/src/domain/ContentEditor.css +174 -0
  19. package/src/domain/ContentEditor.js +425 -0
  20. package/src/domain/ContentForm.js +74 -0
  21. package/src/domain/ContentType.js +187 -0
  22. package/src/domain/CreateContentDialog.js +59 -0
  23. package/src/domain/EditContentDialog.js +50 -0
  24. package/src/domain/TablePage.css +29 -0
  25. package/src/domain/TablePage.js +395 -0
  26. package/src/domain/index.js +5 -0
  27. package/src/fonts/Assistant-Bold.ttf +0 -0
  28. package/src/fonts/Assistant-ExtraBold.ttf +0 -0
  29. package/src/fonts/Assistant-ExtraLight.ttf +0 -0
  30. package/src/fonts/Assistant-Light.ttf +0 -0
  31. package/src/fonts/Assistant-Medium.ttf +0 -0
  32. package/src/fonts/Assistant-Regular.ttf +0 -0
  33. package/src/fonts/Assistant-SemiBold.ttf +0 -0
  34. package/src/fonts/Assistant-VariableFont_wght.ttf +0 -0
  35. package/src/html/button.css +79 -0
  36. package/src/html/button.js +26 -0
  37. package/src/html/checkbox.css +51 -0
  38. package/src/html/checkbox.js +33 -0
  39. package/src/html/chip.css +63 -0
  40. package/src/html/chip.js +39 -0
  41. package/src/html/form.css +17 -0
  42. package/src/html/form.js +80 -0
  43. package/src/html/header.css +64 -0
  44. package/src/html/header.js +30 -0
  45. package/src/html/icon.css +53 -0
  46. package/src/html/icon.js +21 -0
  47. package/src/html/index.js +18 -0
  48. package/src/html/list.css +72 -0
  49. package/src/html/list.js +78 -0
  50. package/src/html/menu.css +76 -0
  51. package/src/html/menu.js +80 -0
  52. package/src/html/progress.css +20 -0
  53. package/src/html/progress.js +27 -0
  54. package/src/html/property.css +18 -0
  55. package/src/html/property.js +16 -0
  56. package/src/html/radio.css +50 -0
  57. package/src/html/radio.js +25 -0
  58. package/src/html/section.css +6 -0
  59. package/src/html/section.js +31 -0
  60. package/src/html/tab.css +45 -0
  61. package/src/html/tab.js +68 -0
  62. package/src/html/table.css +56 -0
  63. package/src/html/table.js +186 -0
  64. package/src/html/text.js +20 -0
  65. package/src/html/textfield-outlined.css +52 -0
  66. package/src/html/textfield.css +130 -0
  67. package/src/html/textfield.js +99 -0
  68. package/src/html/tokenfield.css +51 -0
  69. package/src/html/tokenfield.js +74 -0
  70. package/src/html/tree.css +63 -0
  71. package/src/html/tree.js +49 -0
  72. package/src/http/client.js +62 -0
  73. package/src/http/index.js +2 -0
  74. package/src/http/session.js +39 -0
  75. package/src/index.js +9 -0
  76. package/src/site/details.css +58 -0
  77. package/src/site/dialog.css +63 -0
  78. package/src/site/dialog.js +43 -0
  79. package/src/site/index.js +3 -0
  80. package/src/site/layouts.css +27 -0
  81. package/src/site/page.css +44 -0
  82. package/src/site/page.js +36 -0
  83. package/src/site/site.css +85 -0
  84. package/src/site/site.js +234 -0
  85. package/src/site/siteContext.js +4 -0
  86. package/src/site/workspace.js +57 -0
  87. package/src/upload/UploadArea.js +64 -0
  88. package/src/upload/UploadDialog.js +41 -0
  89. package/src/upload/UploadFile.js +31 -0
  90. package/src/upload/index.js +1 -0
  91. package/src/upload/uploader.css +57 -0
  92. package/src/upload/uploader.js +69 -0
  93. package/src/widgets/index.js +4 -0
  94. package/src/widgets/kanban/Kanban.css +80 -0
  95. package/src/widgets/kanban/Kanban.js +65 -0
  96. package/src/widgets/login/LoginBox.css +89 -0
  97. package/src/widgets/login/LoginBox.js +66 -0
  98. package/src/widgets/login/ResetPasswordBox.css +50 -0
  99. package/src/widgets/login/ResetPasswordBox.js +56 -0
  100. package/src/widgets/viewer/Viewer.css +87 -0
  101. package/src/widgets/viewer/Viewer.js +47 -0
@@ -0,0 +1,346 @@
1
+ import { Fragment, useContext, useEffect, useState, useRef } from 'react'
2
+ import equal from 'deep-equal'
3
+ import { Content, ContentEditor, EditContentDialog, TabbedContentEditor, TreededContentEditor } from '.'
4
+ import { HTTPClient, Session, PageContext, SiteContext } from '..'
5
+ import { Header, List, Text, Button, Icon, MenuIcon, Menu, MenuItem, Tree, TreeNode, TreeItem } from '../html'
6
+ import "./CollectionPage.css"
7
+
8
+ const http = HTTPClient(window.API || process.env.REACT_APP_API, Session);
9
+
10
+ /**
11
+ * Collection Page
12
+ */
13
+ export const CollectionPage = (props) => {
14
+
15
+ const site = useContext(SiteContext)
16
+ const { id = "collection", icon, title, name = "Collection 1", schema, url, groupBy, editor, field, autosave = false, delay = 1000, actions, levels } = props
17
+ const [pageContext, setPageContext] = useContext(PageContext)
18
+ const context = CollectionContext(url, field)
19
+
20
+ useEffect(async () => {
21
+ await context.load()
22
+ setPageContext(context)
23
+ }, [])
24
+
25
+ async function reload() {
26
+ await pageContext.load()
27
+ setPageContext(Object.assign({}, pageContext))
28
+ }
29
+
30
+ function add() {
31
+ const onOK = async (form) => {
32
+ await pageContext.create(form);
33
+ setPageContext(Object.assign({}, pageContext))
34
+ }
35
+ site.openDialog(<EditContentDialog label={`Crear ${name}`} type={schema} onOK={onOK} />);
36
+ }
37
+
38
+ return (
39
+ <Fragment>
40
+ <Header className="collection-page" title={<Text>{title}</Text>}>
41
+ <Button icon="add" label="Add" action={add} />
42
+ <Button icon="refresh" label="Reload" action={reload} />
43
+ {actions}
44
+ </Header>
45
+ <menu className="collection-page">
46
+ <Header title={<Text>Lista de {name}</Text>} >
47
+ </Header>
48
+ {levels ? <CollectionTree levels={levels} /> : <CollectionList groupBy={groupBy} />}
49
+ </menu>
50
+ <main key={id} className="collection-page">
51
+ <CollectionEditor icon={icon} schema={schema} layout={editor} autosave={autosave} delay={delay} />
52
+ </main>
53
+ </Fragment>
54
+ )
55
+ }
56
+
57
+ /**
58
+ * Collection List
59
+ */
60
+ const CollectionList = (props) => {
61
+
62
+ const { groupBy } = props
63
+ const [pageContext, setPageContext] = useContext(PageContext)
64
+ const { all = [] } = pageContext
65
+
66
+ function clear() {
67
+ pageContext.clear()
68
+ setPageContext(Object.assign({}, pageContext))
69
+ }
70
+
71
+ async function select(id) {
72
+ clear()
73
+ await pageContext.select(id)
74
+ setPageContext(Object.assign({}, pageContext))
75
+ }
76
+
77
+ const items = all ? all.map(content => ({
78
+ id: content.id,
79
+ line1: content.name,
80
+ line2: content.description,
81
+ content
82
+ })) : []
83
+
84
+ return (
85
+ <List items={items} onSelect={select} groupBy={groupBy} />
86
+ )
87
+ }
88
+
89
+ /**
90
+ * Collection Tree
91
+ */
92
+ const CollectionTree = (props) => {
93
+
94
+ const { levels } = props
95
+ const [pageContext, setPageContext] = useContext(PageContext)
96
+ const { all = [] } = pageContext
97
+
98
+ function clear() {
99
+ pageContext.clear()
100
+ setPageContext(Object.assign({}, pageContext))
101
+ }
102
+
103
+ async function select(id) {
104
+ clear()
105
+ await pageContext.select(id)
106
+ setPageContext(Object.assign({}, pageContext))
107
+ }
108
+
109
+ function group(items, by) {
110
+ return items.reduce((nodes, field) => {
111
+ let node = nodes.find(n => n.name === field[by])
112
+ if (!node) {
113
+ let name = field[by]
114
+ node = { name, items: [], field: by }
115
+ nodes.push(node)
116
+ }
117
+ node.items.push(field)
118
+ return nodes
119
+ }, [])
120
+ }
121
+
122
+ function generateNodes(levels, items) {
123
+ const by = levels[0]
124
+ const nodes = group(items, by)
125
+ if (levels.length > 1) nodes.forEach(node => node.nodes = generateNodes(levels.slice(1), node.items))
126
+ return nodes
127
+ }
128
+
129
+ function renderNodes(nodes) {
130
+ return nodes.map(node => {
131
+ const title = typeof node.name === 'boolean' ? `${node.field} = ${node.name}` : node.name
132
+ return (
133
+ <TreeNode key={node.name} icon={null} label={title} open={true}>
134
+ {node.nodes ? renderNodes(node.nodes) : node.items.map(item => <TreeItem key={item.id} id={item.id} label={item.name} onSelect={select}>item</TreeItem>)}
135
+ </TreeNode>
136
+ )
137
+ })
138
+ }
139
+
140
+ const nodes = generateNodes(levels, all)
141
+ return (
142
+ <main>
143
+ <Tree>
144
+ {renderNodes(nodes)}
145
+ </Tree>
146
+ </main>
147
+ )
148
+ }
149
+
150
+ /**
151
+ * Collection Editor
152
+ */
153
+ const CollectionEditor = (props) => {
154
+ const [pageContext, setPageContext] = useContext(PageContext)
155
+ const { selected } = pageContext
156
+ const { icon, schema, layout, autosave = false, delay = 1000 } = props
157
+ const timer = useRef(null)
158
+ const [form, setForm] = useState(selected)
159
+
160
+ useEffect(() => {
161
+ setForm(selected)
162
+ }, [selected])
163
+
164
+ useEffect(() => {
165
+ if (autosave) {
166
+ clearTimeout(timer.current)
167
+ timer.current = setTimeout(() => {
168
+ if (canSave()) save()
169
+ }, delay)
170
+ }
171
+ }, [form])
172
+
173
+ function clear() {
174
+ pageContext.clear()
175
+ setPageContext(Object.assign({}, pageContext))
176
+ }
177
+
178
+ async function remove() {
179
+ await pageContext.remove(selected.id)
180
+ pageContext.clear()
181
+ setPageContext(Object.assign({}, pageContext))
182
+ }
183
+
184
+ function change(next) {
185
+ setForm(next)
186
+ }
187
+
188
+ function canSave() {
189
+ const can = !equal(form, selected)
190
+ return can
191
+ }
192
+
193
+ async function save() {
194
+ console.log('saving.....')
195
+ await pageContext.update(form)
196
+ setPageContext(Object.assign({}, pageContext))
197
+ }
198
+
199
+ function renderEditor() {
200
+ const content = new Content(schema, form)
201
+ switch (layout) {
202
+ case 'TABBED': return <TabbedContentEditor {...props} content={content} onChange={change} />
203
+ case 'TREEDED': return <TreededContentEditor {...props} content={content} onChange={change} />
204
+ default: return <ContentEditor {...props} content={content} onChange={change} />
205
+ }
206
+ }
207
+
208
+ return selected && form ? (
209
+ <Fragment>
210
+ <Header icon={icon} title={<Text>{selected.name}</Text>}>
211
+ <Icon icon="close" clickable action={clear} />
212
+ <MenuIcon align="alignRight">
213
+ <Menu>
214
+ <MenuItem label="Eliminar" onSelect={remove} />
215
+ </Menu>
216
+ </MenuIcon>
217
+ {autosave === true ? null : <Button icon="save" label="Guardar Cambios" raised disabled={!canSave()} action={save} />}
218
+ </Header>
219
+ {renderEditor()}
220
+ </Fragment>
221
+ ) : null
222
+ }
223
+
224
+ /**
225
+ * Collection Context
226
+ */
227
+ export const CollectionContext = (url, field) => {
228
+
229
+ const API = CollectionAPI(url)
230
+
231
+ return {
232
+
233
+ all: [],
234
+ selected: null,
235
+
236
+ async load() {
237
+ try {
238
+ const data = await API.all();
239
+ this.all = field ? data[field] : data;
240
+ } catch (error) {
241
+ console.log(error)
242
+ }
243
+ return
244
+ },
245
+
246
+ select(id) {
247
+ const result = this.all.find(item => item.id === id);
248
+ this.selected = result;
249
+ },
250
+
251
+ clear() {
252
+ this.selected = null
253
+ },
254
+
255
+ async create(form) {
256
+ try {
257
+ await API.create(form);
258
+ await this.load();
259
+ } catch (error) {
260
+ console.log("CREATE ERROR", error)
261
+ }
262
+ return
263
+ },
264
+
265
+ async update(form) {
266
+ try {
267
+ await API.update(form)
268
+ await this.load()
269
+ } catch (error) {
270
+ console.log(error)
271
+ }
272
+ return
273
+ },
274
+
275
+ async patch(id, form) {
276
+ try {
277
+ await API.patch(id, form)
278
+ await this.load()
279
+ } catch (error) {
280
+ console.log(error)
281
+ }
282
+ return
283
+ },
284
+
285
+ async updateProperty(id, propertyName, form) {
286
+ try {
287
+ await API.updateProperty(id, propertyName, form)
288
+ await this.load()
289
+ } catch (error) {
290
+ console.log(error)
291
+ }
292
+ return
293
+ },
294
+
295
+ async remove(id) {
296
+ try {
297
+ await API.remove(id)
298
+ await this.load()
299
+ } catch (error) {
300
+ console.log(error)
301
+ }
302
+ return
303
+ },
304
+ }
305
+ }
306
+
307
+ /**
308
+ * Collection API
309
+ */
310
+ const CollectionAPI = (url) => {
311
+
312
+ return {
313
+ all() {
314
+ return http.GET(url)
315
+ },
316
+
317
+ find(id) {
318
+ return http.GET(`${url}/${id}`)
319
+ },
320
+
321
+ create(form) {
322
+ const body = JSON.stringify(form)
323
+ return http.POST(url, body)
324
+ },
325
+
326
+ update(form) {
327
+ const body = JSON.stringify(form)
328
+ return http.PUT(`${url}/${form.id}`, body)
329
+ },
330
+
331
+ patch(id, form) {
332
+ const body = JSON.stringify(form)
333
+ return http.PATCH(`${url}/${id}`, body)
334
+ },
335
+
336
+ updateProperty(id, propertyName, form) {
337
+ const body = JSON.stringify(form)
338
+ return http.PUT(`${url}/${id}/${propertyName}`, body)
339
+ },
340
+
341
+ remove(id) {
342
+ return http.DELETE(`${url}/${id}`)
343
+ }
344
+
345
+ }
346
+ }
@@ -0,0 +1,174 @@
1
+ .content-editor {
2
+ padding: 0 1rem;
3
+ }
4
+
5
+ .content-editor>section {
6
+
7
+ margin-bottom: 1rem;
8
+ }
9
+
10
+ .content-editor>section>header {
11
+ padding: .5rem;
12
+ border-bottom: solid 1px var(--divider-color);
13
+ margin-bottom: .5rem;
14
+ }
15
+
16
+ .entity-editor {
17
+ }
18
+
19
+ .entity-editor>header {
20
+ padding: .5rem;
21
+ }
22
+
23
+ .collection-editor {
24
+ }
25
+
26
+ .collection-editor>header {
27
+ padding: 0 .5rem;
28
+ display: flex;
29
+ align-items: flex-end;
30
+ }
31
+
32
+ .collection-editor>header>.actions {
33
+ flex: 1;
34
+ display: flex;
35
+ justify-content: flex-end;
36
+ }
37
+
38
+ .collection-editor>header>.actions button {
39
+ height: 2rem !important;
40
+ padding: 0 !important;
41
+ }
42
+
43
+ .collection-editor>footer {
44
+ display: flex;
45
+ justify-content: flex-end;
46
+ }
47
+
48
+ .collection-editor td {
49
+ padding-left: 0px;
50
+ }
51
+
52
+ .collection-editor .mdc-text-field {
53
+ width: 99%;
54
+ }
55
+
56
+ .collection-editor .actions {
57
+ width: 8rem;
58
+ text-align: right;
59
+ padding: .5rem;
60
+ }
61
+
62
+ .collection-adder {
63
+ display: flex;
64
+ }
65
+
66
+ .collection-adder .data-table {
67
+ width: 100%;
68
+ border: 0px;
69
+ background-color: rgb(242, 242, 242);
70
+ }
71
+
72
+ .collection-adder table {
73
+ width: 100%;
74
+ border: 0px;
75
+ }
76
+
77
+ .collection-adder th {
78
+ display: ;
79
+ }
80
+
81
+ .collection-adder tr {
82
+ border: 0;
83
+ }
84
+
85
+ .collection-adder td {
86
+ padding-left: 0px;
87
+ }
88
+
89
+ .collection-adder td>label {
90
+ background-color: var(--paper-color) !important;
91
+ }
92
+
93
+
94
+ .collection-adder td.actions {
95
+ border: solid 0px red;
96
+ display: flex;
97
+ align-items: center;
98
+ }
99
+
100
+
101
+ .field-editor {
102
+ padding: 0;
103
+ }
104
+
105
+ .field-editor>* {
106
+ width: 100%;
107
+ }
108
+
109
+ .function-editor {
110
+ width: 100%;
111
+ min-height: 10rem;
112
+ display: flex;
113
+ }
114
+
115
+ .function-editor>main {
116
+ flex: 1;
117
+ }
118
+
119
+ .function-editor>aside {
120
+ min-width: 10rem;
121
+ padding: 0 .5rem;
122
+ }
123
+
124
+ .function-editor>aside>table {
125
+ min-width: 20rem;
126
+ border: solid 1px var(--divider-color);
127
+ margin: 0;
128
+ padding: 0;
129
+ }
130
+
131
+ .function-editor>aside>table>tr {
132
+ border-bottom: solid 1px var(--divider-color);
133
+ }
134
+
135
+ .function-editor>aside>table>tr>td {
136
+ width: 10rem;
137
+ overflow: hidden;
138
+ padding: 0 0 0 .5rem;
139
+ }
140
+
141
+ .function-editor>aside>table>tr>td input {
142
+ appearance: none;
143
+ border: 0px;
144
+ background-color: rgba(240,240,240);
145
+ margin: .2rem;
146
+ }
147
+
148
+ .treeded-editor {
149
+ display: flex;
150
+ }
151
+
152
+ .group-caption {
153
+ border-bottom: solid 1px var(--divider-color);
154
+ margin: .5rem 0;
155
+ }
156
+
157
+ .multiselection-editor {
158
+ position: relative;
159
+ border: solid 1px var(--divider-color);
160
+ display: flex;
161
+ align-items: center;
162
+ border-radius: .3rem;
163
+ padding: 1rem;
164
+ margin: 1rem 0;
165
+ }
166
+
167
+ .multiselection-editor>label {
168
+ position: absolute;
169
+ top:-9px;
170
+ padding: 2px 6px 2px 4px;
171
+ font-size: .8rem;
172
+ background-color: var(--paper-color);
173
+ color: var(--text-color-light)
174
+ }