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.
- package/dist/index.cjs +2 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.css +2 -0
- package/dist/index.css.map +1 -0
- package/dist/index.modern.js +2 -0
- package/dist/index.modern.js.map +1 -0
- package/dist/index.umd.js +2 -0
- package/dist/index.umd.js.map +1 -0
- package/package.json +27 -0
- package/publish.sh +5 -0
- package/src/css/fonts.css +162 -0
- package/src/css/html.css +36 -0
- package/src/css/theme.css +89 -0
- package/src/css/theme_dark.css +85 -0
- package/src/css/theme_light.css +87 -0
- package/src/domain/CollectionPage.css +34 -0
- package/src/domain/CollectionPage.js +346 -0
- package/src/domain/ContentEditor.css +174 -0
- package/src/domain/ContentEditor.js +425 -0
- package/src/domain/ContentForm.js +74 -0
- package/src/domain/ContentType.js +187 -0
- package/src/domain/CreateContentDialog.js +59 -0
- package/src/domain/EditContentDialog.js +50 -0
- package/src/domain/TablePage.css +29 -0
- package/src/domain/TablePage.js +395 -0
- package/src/domain/index.js +5 -0
- package/src/fonts/Assistant-Bold.ttf +0 -0
- package/src/fonts/Assistant-ExtraBold.ttf +0 -0
- package/src/fonts/Assistant-ExtraLight.ttf +0 -0
- package/src/fonts/Assistant-Light.ttf +0 -0
- package/src/fonts/Assistant-Medium.ttf +0 -0
- package/src/fonts/Assistant-Regular.ttf +0 -0
- package/src/fonts/Assistant-SemiBold.ttf +0 -0
- package/src/fonts/Assistant-VariableFont_wght.ttf +0 -0
- package/src/html/button.css +79 -0
- package/src/html/button.js +26 -0
- package/src/html/checkbox.css +51 -0
- package/src/html/checkbox.js +33 -0
- package/src/html/chip.css +63 -0
- package/src/html/chip.js +39 -0
- package/src/html/form.css +17 -0
- package/src/html/form.js +80 -0
- package/src/html/header.css +64 -0
- package/src/html/header.js +30 -0
- package/src/html/icon.css +53 -0
- package/src/html/icon.js +21 -0
- package/src/html/index.js +18 -0
- package/src/html/list.css +72 -0
- package/src/html/list.js +78 -0
- package/src/html/menu.css +76 -0
- package/src/html/menu.js +80 -0
- package/src/html/progress.css +20 -0
- package/src/html/progress.js +27 -0
- package/src/html/property.css +18 -0
- package/src/html/property.js +16 -0
- package/src/html/radio.css +50 -0
- package/src/html/radio.js +25 -0
- package/src/html/section.css +6 -0
- package/src/html/section.js +31 -0
- package/src/html/tab.css +45 -0
- package/src/html/tab.js +68 -0
- package/src/html/table.css +56 -0
- package/src/html/table.js +186 -0
- package/src/html/text.js +20 -0
- package/src/html/textfield-outlined.css +52 -0
- package/src/html/textfield.css +130 -0
- package/src/html/textfield.js +99 -0
- package/src/html/tokenfield.css +51 -0
- package/src/html/tokenfield.js +74 -0
- package/src/html/tree.css +63 -0
- package/src/html/tree.js +49 -0
- package/src/http/client.js +62 -0
- package/src/http/index.js +2 -0
- package/src/http/session.js +39 -0
- package/src/index.js +9 -0
- package/src/site/details.css +58 -0
- package/src/site/dialog.css +63 -0
- package/src/site/dialog.js +43 -0
- package/src/site/index.js +3 -0
- package/src/site/layouts.css +27 -0
- package/src/site/page.css +44 -0
- package/src/site/page.js +36 -0
- package/src/site/site.css +85 -0
- package/src/site/site.js +234 -0
- package/src/site/siteContext.js +4 -0
- package/src/site/workspace.js +57 -0
- package/src/upload/UploadArea.js +64 -0
- package/src/upload/UploadDialog.js +41 -0
- package/src/upload/UploadFile.js +31 -0
- package/src/upload/index.js +1 -0
- package/src/upload/uploader.css +57 -0
- package/src/upload/uploader.js +69 -0
- package/src/widgets/index.js +4 -0
- package/src/widgets/kanban/Kanban.css +80 -0
- package/src/widgets/kanban/Kanban.js +65 -0
- package/src/widgets/login/LoginBox.css +89 -0
- package/src/widgets/login/LoginBox.js +66 -0
- package/src/widgets/login/ResetPasswordBox.css +50 -0
- package/src/widgets/login/ResetPasswordBox.js +56 -0
- package/src/widgets/viewer/Viewer.css +87 -0
- package/src/widgets/viewer/Viewer.js +47 -0
@@ -0,0 +1,59 @@
|
|
1
|
+
import React, { Fragment, useContext, useMemo, useState } from 'react';
|
2
|
+
import { Button, Text } from '../html';
|
3
|
+
import { Dialog } from '../site/dialog'
|
4
|
+
import { SiteContext } from '../site/siteContext';
|
5
|
+
import { ContentForm } from './ContentForm';
|
6
|
+
import { Content } from './ContentType';
|
7
|
+
|
8
|
+
/**
|
9
|
+
* Create Content Dialog
|
10
|
+
*/
|
11
|
+
export const CreateContentDialog = ({ label, type, validator, onOK, onError, onActionClose = true }) => {
|
12
|
+
|
13
|
+
const site = useContext(SiteContext);
|
14
|
+
const [form, setForm] = useState({})
|
15
|
+
const [isValid, setValid] = useState(false)
|
16
|
+
const [errors, setErrors] = useState([])
|
17
|
+
|
18
|
+
function change(form, validForm) {
|
19
|
+
setForm(form)
|
20
|
+
if (validator) {
|
21
|
+
const { validation, errors = [] } = validator(form)
|
22
|
+
setValid(validForm && validation)
|
23
|
+
setErrors(errors)
|
24
|
+
} else {
|
25
|
+
setValid(validForm)
|
26
|
+
}
|
27
|
+
}
|
28
|
+
|
29
|
+
function onAction(action) {
|
30
|
+
if (action === 'OK' && onOK) onOK(form)
|
31
|
+
if (action === 'CLOSE' || onActionClose === true) site.closeDialog();
|
32
|
+
}
|
33
|
+
|
34
|
+
function isRequired(field) {
|
35
|
+
const { required = false } = field
|
36
|
+
return required
|
37
|
+
}
|
38
|
+
|
39
|
+
function isOptional(field) {
|
40
|
+
const { creation = false } = field
|
41
|
+
return creation
|
42
|
+
}
|
43
|
+
|
44
|
+
const actions = (
|
45
|
+
<Fragment>
|
46
|
+
<Button label="CLOSE" action={() => onAction("CLOSE")}/>
|
47
|
+
<Button label="OK" action={() => onAction("OK")} disabled={!isValid} raised />
|
48
|
+
</Fragment>
|
49
|
+
)
|
50
|
+
|
51
|
+
const title = <Text use="headline6">{label}</Text>
|
52
|
+
const content = new Content(type, form)
|
53
|
+
return (
|
54
|
+
<Dialog title={title} open={true} onAction={onAction} actions={actions}>
|
55
|
+
<ContentForm content={content} filter={(field) => isRequired(field) || isOptional(field)} onChange={change} />
|
56
|
+
{ errors.map ( error => <Text use="overline" tag="div" className="error">{error}</Text> )}
|
57
|
+
</Dialog>
|
58
|
+
)
|
59
|
+
}
|
@@ -0,0 +1,50 @@
|
|
1
|
+
import React, { Fragment, useState, useContext, useMemo } from 'react';
|
2
|
+
import { Dialog } from '../site'
|
3
|
+
import { SiteContext } from '../site/siteContext'
|
4
|
+
import { Text, Button } from '../html';
|
5
|
+
import { Content } from './ContentType'
|
6
|
+
import { ContentEditor } from './ContentEditor'
|
7
|
+
|
8
|
+
/**
|
9
|
+
* Edit Content Dialog
|
10
|
+
*/
|
11
|
+
export const EditContentDialog = ({ label, type, value = {}, filter, validator, onOK, onError }) => {
|
12
|
+
|
13
|
+
const site = useContext(SiteContext);
|
14
|
+
const [form, setForm] = useState(value)
|
15
|
+
const [isValid, setValid] = useState(false)
|
16
|
+
const [errors, setErrors] = useState([])
|
17
|
+
|
18
|
+
function change(form) {
|
19
|
+
setForm(form)
|
20
|
+
if (validator) {
|
21
|
+
const { validation, errors = [] } = validator(form)
|
22
|
+
setValid(validation)
|
23
|
+
setErrors(errors)
|
24
|
+
} else {
|
25
|
+
setValid(true)
|
26
|
+
}
|
27
|
+
}
|
28
|
+
|
29
|
+
function onAction(action) {
|
30
|
+
if (action === 'OK' && onOK) onOK(Object.assign({}, value, form))
|
31
|
+
site.closeDialog();
|
32
|
+
}
|
33
|
+
|
34
|
+
const actions = (
|
35
|
+
<Fragment>
|
36
|
+
<Button label="CLOSE" action={() => onAction("CLOSE")} />
|
37
|
+
<div className="expand" />
|
38
|
+
<Button label="OK" action={() => onAction("OK")} disabled={!isValid} raised />
|
39
|
+
</Fragment>
|
40
|
+
)
|
41
|
+
|
42
|
+
const title = <Text use="headline6">{label}</Text>
|
43
|
+
const content = new Content(type, form)
|
44
|
+
return (
|
45
|
+
<Dialog title={title} open={true} onAction={onAction} actions={actions}>
|
46
|
+
<ContentEditor content={content} onChange={change} filter={filter} />
|
47
|
+
{errors.map(error => <Text use="overline" tag="div" className="error">{error}</Text>)}
|
48
|
+
</Dialog>
|
49
|
+
)
|
50
|
+
}
|
@@ -0,0 +1,29 @@
|
|
1
|
+
.table-page .datatable8 {
|
2
|
+
margin: 0 1rem;
|
3
|
+
}
|
4
|
+
|
5
|
+
menu.table-page>header {
|
6
|
+
padding-right: .5rem;
|
7
|
+
}
|
8
|
+
|
9
|
+
menu.table-page>main {
|
10
|
+
}
|
11
|
+
|
12
|
+
main.table-page {
|
13
|
+
display: flex;
|
14
|
+
flex-direction: column;
|
15
|
+
}
|
16
|
+
|
17
|
+
main.table-page>header {
|
18
|
+
padding-bottom: 1rem;
|
19
|
+
padding-right: 1rem;
|
20
|
+
}
|
21
|
+
|
22
|
+
aside.table-page {
|
23
|
+
width: 25rem;
|
24
|
+
}
|
25
|
+
|
26
|
+
main.table-editor {
|
27
|
+
flex: 1;
|
28
|
+
overflow: auto;
|
29
|
+
}
|
@@ -0,0 +1,395 @@
|
|
1
|
+
import equal from 'deep-equal'
|
2
|
+
import { Fragment, useContext, useEffect, useMemo, useRef, useState } from 'react'
|
3
|
+
import { EditContentDialog } from '.'
|
4
|
+
import { Content, ContentEditor, HTTPClient, PageContext, Session, SiteContext } from '..'
|
5
|
+
import { SCENARIO1 } from '../../dev/scenario1'
|
6
|
+
import { BuildGroupOptions } from '../../pages/kinds/options'
|
7
|
+
import { Button, DataTable, DropDown, Header, Icon, MenuIcon, MenuItem, Text } from '../html'
|
8
|
+
import "./TablePage.css"
|
9
|
+
|
10
|
+
const http = HTTPClient(window.API || process.env.REACT_APP_API, Session);
|
11
|
+
|
12
|
+
/**
|
13
|
+
* Table Page
|
14
|
+
*/
|
15
|
+
export const TablePage = (props) => {
|
16
|
+
|
17
|
+
const site = useContext(SiteContext)
|
18
|
+
const { id = "table", icon, title, name = "table 1", schema, url, field, delay = 1000, actions, editable, canAdd = true, dev = true, autosave = true, groupBy, validator, scenario } = props
|
19
|
+
const [pageContext, setPageContext] = useContext(PageContext)
|
20
|
+
const { selected } = pageContext
|
21
|
+
const timer = useRef(null)
|
22
|
+
const [form, setForm] = useState(selected)
|
23
|
+
|
24
|
+
useEffect(() => {
|
25
|
+
setForm(selected)
|
26
|
+
}, [selected])
|
27
|
+
|
28
|
+
useEffect(() => {
|
29
|
+
if (autosave) {
|
30
|
+
clearTimeout(timer.current)
|
31
|
+
timer.current = setTimeout(() => {
|
32
|
+
if (canSave()) save()
|
33
|
+
}, delay)
|
34
|
+
}
|
35
|
+
}, [form])
|
36
|
+
|
37
|
+
useEffect(async () => {
|
38
|
+
const context = TableContext(url, field)
|
39
|
+
await context.load()
|
40
|
+
setPageContext(context)
|
41
|
+
}, [])
|
42
|
+
|
43
|
+
function add() {
|
44
|
+
const onOK = async (form) => {
|
45
|
+
await pageContext.create(form);
|
46
|
+
setPageContext(Object.assign({}, pageContext))
|
47
|
+
}
|
48
|
+
site.openDialog(<EditContentDialog label={`Crear ${name}`} type={schema} onOK={onOK} validator={validator} />);
|
49
|
+
}
|
50
|
+
|
51
|
+
function change(next) {
|
52
|
+
setForm(next)
|
53
|
+
}
|
54
|
+
|
55
|
+
function canSave() {
|
56
|
+
const can = !equal(form, selected)
|
57
|
+
return can
|
58
|
+
}
|
59
|
+
|
60
|
+
async function save() {
|
61
|
+
console.log('saving.....')
|
62
|
+
await pageContext.update(form)
|
63
|
+
setPageContext(Object.assign({}, pageContext))
|
64
|
+
}
|
65
|
+
|
66
|
+
async function playScenario() {
|
67
|
+
const promises1 = pageContext.all.map(async item => await pageContext.remove(item.id))
|
68
|
+
Promise.all(promises1).then(async () => {
|
69
|
+
const promises2 = SCENARIO1.map(async (item) => await pageContext.create(item))
|
70
|
+
Promise.all(promises2).then(async () => {
|
71
|
+
await pageContext.load()
|
72
|
+
setPageContext(Object.assign({}, pageContext))
|
73
|
+
})
|
74
|
+
})
|
75
|
+
}
|
76
|
+
|
77
|
+
function closeAside() {
|
78
|
+
pageContext.select(null)
|
79
|
+
setPageContext(Object.assign({}, pageContext))
|
80
|
+
}
|
81
|
+
|
82
|
+
function renderAside() {
|
83
|
+
if (selected && form) {
|
84
|
+
const content = new Content(schema, form)
|
85
|
+
return (
|
86
|
+
<aside className="table-page">
|
87
|
+
<Header icon="local_offer" title={selected.name || "Propiedades"}>
|
88
|
+
<Icon icon="close" clickable action={closeAside} />
|
89
|
+
</Header>
|
90
|
+
<ContentEditor content={content} onChange={change} />
|
91
|
+
</aside>
|
92
|
+
)
|
93
|
+
}
|
94
|
+
return null;
|
95
|
+
}
|
96
|
+
|
97
|
+
return (
|
98
|
+
<Fragment>
|
99
|
+
<Header className="table-page" title={<Text>{title}</Text>}>
|
100
|
+
{canAdd ? <Button icon="add" label="Añadir" action={add} raised /> : null}
|
101
|
+
{dev ? (
|
102
|
+
<MenuIcon align="alignRight">
|
103
|
+
<MenuItem label="Cargar Escenario 1" onSelect={playScenario} />
|
104
|
+
</MenuIcon>
|
105
|
+
) : null}
|
106
|
+
{actions}
|
107
|
+
</Header>
|
108
|
+
<menu className="table-page">
|
109
|
+
<TableFilters schema={schema} />
|
110
|
+
</menu>
|
111
|
+
<main key={id} className="table-page">
|
112
|
+
<TableEditor icon={icon} title={name} schema={schema} delay={delay} editable={editable} groupBy={groupBy} />
|
113
|
+
</main>
|
114
|
+
{renderAside()}
|
115
|
+
</Fragment>
|
116
|
+
)
|
117
|
+
}
|
118
|
+
|
119
|
+
/**
|
120
|
+
* Table Filters
|
121
|
+
*/
|
122
|
+
const TableFilters = (props) => {
|
123
|
+
|
124
|
+
const [pageContext, setPageContext] = useContext(PageContext)
|
125
|
+
const { schema } = props
|
126
|
+
const [form, setForm] = useState({})
|
127
|
+
|
128
|
+
const filterSchema = useMemo(() => {
|
129
|
+
const filterSchema = Object.assign({}, schema)
|
130
|
+
Object.values(filterSchema).forEach(field => field.section = null)
|
131
|
+
delete filterSchema.flows
|
132
|
+
return filterSchema
|
133
|
+
}, [schema])
|
134
|
+
|
135
|
+
async function change(next) {
|
136
|
+
setForm(next)
|
137
|
+
await pageContext.load(next)
|
138
|
+
setPageContext(Object.assign({}, pageContext))
|
139
|
+
}
|
140
|
+
|
141
|
+
function clear() {
|
142
|
+
setForm({})
|
143
|
+
}
|
144
|
+
|
145
|
+
const content = new Content(filterSchema, form)
|
146
|
+
return (
|
147
|
+
<Fragment>
|
148
|
+
<Header title={<Text>Filtros</Text>} >
|
149
|
+
<Button icon="filter_list_off" label="Limpiar" action={clear} />
|
150
|
+
</Header>
|
151
|
+
<main>
|
152
|
+
<ContentEditor content={content} onChange={change} />
|
153
|
+
</main>
|
154
|
+
</Fragment>
|
155
|
+
)
|
156
|
+
}
|
157
|
+
|
158
|
+
/**
|
159
|
+
* Table Editor
|
160
|
+
*/
|
161
|
+
const TableEditor = (props) => {
|
162
|
+
|
163
|
+
const [pageContext, setPageContext] = useContext(PageContext)
|
164
|
+
const { all = [], filters } = pageContext
|
165
|
+
const { icon, title, schema, editable } = props
|
166
|
+
const [groupBy, setGroupBy] = useState(props.groupBy)
|
167
|
+
|
168
|
+
function changeGroup(id, value) {
|
169
|
+
setGroupBy(value)
|
170
|
+
}
|
171
|
+
|
172
|
+
async function remove(id) {
|
173
|
+
await pageContext.remove(id)
|
174
|
+
pageContext.clear()
|
175
|
+
setPageContext(Object.assign({}, pageContext))
|
176
|
+
}
|
177
|
+
|
178
|
+
function change(rowID, cellID, value) {
|
179
|
+
const row = all.find(r => r.id === rowID)
|
180
|
+
const next = Object.assign({}, row, { [cellID]: value })
|
181
|
+
delete next.actions
|
182
|
+
pageContext.update(next)
|
183
|
+
setPageContext(Object.assign({}, pageContext))
|
184
|
+
}
|
185
|
+
|
186
|
+
function clear() {
|
187
|
+
pageContext.clear()
|
188
|
+
setPageContext(Object.assign({}, pageContext))
|
189
|
+
}
|
190
|
+
|
191
|
+
async function select(row, event) {
|
192
|
+
clear()
|
193
|
+
await pageContext.select(row.id)
|
194
|
+
setPageContext(Object.assign({}, pageContext))
|
195
|
+
}
|
196
|
+
|
197
|
+
function renderGroups() {
|
198
|
+
|
199
|
+
const groups = all.reduce((groups, filter) => {
|
200
|
+
const groupName = filter[groupBy]
|
201
|
+
const group = groups[groupName]
|
202
|
+
if (!group) groups[groupName] = []
|
203
|
+
groups[groupName].push(filter)
|
204
|
+
return groups
|
205
|
+
}, {})
|
206
|
+
|
207
|
+
|
208
|
+
return Object.keys(groups).map(groupName => {
|
209
|
+
|
210
|
+
const table = {
|
211
|
+
columns: Object.values(schema)
|
212
|
+
.filter(field => field.column === true)
|
213
|
+
.map(field => {
|
214
|
+
let options = field.options;
|
215
|
+
if (options && typeof (options) == 'function') {
|
216
|
+
options = options()
|
217
|
+
}
|
218
|
+
return {
|
219
|
+
id: field.id,
|
220
|
+
label: field.label,
|
221
|
+
type: field.type,
|
222
|
+
onChange: field.editable ? change : null,
|
223
|
+
options
|
224
|
+
}
|
225
|
+
}),
|
226
|
+
rows: groups[groupName]
|
227
|
+
.map(item => {
|
228
|
+
item.actions = [<Icon icon="delete" size="small" clickable action={() => remove(item.id)} />]
|
229
|
+
return item
|
230
|
+
})
|
231
|
+
}
|
232
|
+
|
233
|
+
table.columns.push({ id: "actions" })
|
234
|
+
|
235
|
+
return (
|
236
|
+
<Fragment key={groupName}>
|
237
|
+
<Header title={groupName} />
|
238
|
+
<DataTable {...table} onRowSelection={select} editable={editable} />
|
239
|
+
</Fragment>
|
240
|
+
)
|
241
|
+
})
|
242
|
+
}
|
243
|
+
|
244
|
+
const table = {
|
245
|
+
columns: Object.values(schema)
|
246
|
+
.filter(field => field.column === true)
|
247
|
+
.map(field => {
|
248
|
+
let options = field.options;
|
249
|
+
if (options && typeof (options) == 'function') {
|
250
|
+
options = options()
|
251
|
+
}
|
252
|
+
return {
|
253
|
+
id: field.id,
|
254
|
+
label: field.label,
|
255
|
+
type: field.type,
|
256
|
+
onChange: field.editable ? change : null,
|
257
|
+
options
|
258
|
+
}
|
259
|
+
}),
|
260
|
+
rows: all
|
261
|
+
.map(item => {
|
262
|
+
item.actions = [<Icon icon="delete" size="small" clickable action={() => remove(item.id)} />]
|
263
|
+
return item
|
264
|
+
})
|
265
|
+
}
|
266
|
+
|
267
|
+
table.columns.push({ id: "actions" })
|
268
|
+
|
269
|
+
return (
|
270
|
+
<Fragment>
|
271
|
+
<Header icon={icon} title={<Text>{title}</Text>}>
|
272
|
+
<DropDown id="groupBy" label="Agrupar Por" value={groupBy} options={BuildGroupOptions(schema)} onChange={changeGroup} />
|
273
|
+
</Header>
|
274
|
+
<main className="table-editor">
|
275
|
+
{renderGroups()}
|
276
|
+
</main>
|
277
|
+
</Fragment>
|
278
|
+
)
|
279
|
+
}
|
280
|
+
|
281
|
+
/**
|
282
|
+
* table Context
|
283
|
+
*/
|
284
|
+
const TableContext = (url, field) => {
|
285
|
+
|
286
|
+
const API = TableAPI(url)
|
287
|
+
|
288
|
+
return {
|
289
|
+
|
290
|
+
all: [],
|
291
|
+
selected: null,
|
292
|
+
filters: {},
|
293
|
+
|
294
|
+
async load(filter) {
|
295
|
+
try {
|
296
|
+
|
297
|
+
const filters = filter ? Object.keys(filter).reduce((filters, key) => {
|
298
|
+
const field = filter[key];
|
299
|
+
if (field) filters[key] = field;
|
300
|
+
return filters;
|
301
|
+
}, {}) : []
|
302
|
+
|
303
|
+
const data = await API.all(filters);
|
304
|
+
this.all = field ? data[field] : data;
|
305
|
+
} catch (error) {
|
306
|
+
console.log(error)
|
307
|
+
}
|
308
|
+
return
|
309
|
+
},
|
310
|
+
|
311
|
+
select(id) {
|
312
|
+
const result = this.all.find(item => item.id === id);
|
313
|
+
this.selected = result;
|
314
|
+
},
|
315
|
+
|
316
|
+
clear() {
|
317
|
+
this.selected = null
|
318
|
+
},
|
319
|
+
|
320
|
+
async create(form) {
|
321
|
+
try {
|
322
|
+
await API.create(form);
|
323
|
+
await this.load();
|
324
|
+
} catch (error) {
|
325
|
+
console.log(error)
|
326
|
+
}
|
327
|
+
return
|
328
|
+
},
|
329
|
+
|
330
|
+
async update(form) {
|
331
|
+
try {
|
332
|
+
await API.update(form)
|
333
|
+
await this.load()
|
334
|
+
} catch (error) {
|
335
|
+
console.log(error)
|
336
|
+
}
|
337
|
+
return
|
338
|
+
},
|
339
|
+
|
340
|
+
async remove(id) {
|
341
|
+
try {
|
342
|
+
await API.remove(id)
|
343
|
+
await this.load()
|
344
|
+
} catch (error) {
|
345
|
+
console.log(error)
|
346
|
+
}
|
347
|
+
return
|
348
|
+
},
|
349
|
+
|
350
|
+
changeFilters(filters) {
|
351
|
+
this.filters = filters
|
352
|
+
}
|
353
|
+
}
|
354
|
+
}
|
355
|
+
|
356
|
+
/**
|
357
|
+
* table API
|
358
|
+
*/
|
359
|
+
const TableAPI = (url) => {
|
360
|
+
|
361
|
+
return {
|
362
|
+
all(filters) {
|
363
|
+
let queryParams = "?"
|
364
|
+
if (filters) {
|
365
|
+
const filterQuery = Object.keys(filters).reduce((query, key) => {
|
366
|
+
if (typeof (filters[key]) === 'boolean') {
|
367
|
+
return query.concat(`${key}=${filters[key]}&`)
|
368
|
+
} else {
|
369
|
+
return query.concat(`${key}=%${filters[key]}%&`)
|
370
|
+
}
|
371
|
+
}, "")
|
372
|
+
queryParams = queryParams.concat(filterQuery)
|
373
|
+
}
|
374
|
+
return http.GET(url + queryParams)
|
375
|
+
},
|
376
|
+
|
377
|
+
find(id) {
|
378
|
+
return http.GET(`${url}/${id}`)
|
379
|
+
},
|
380
|
+
|
381
|
+
create(form) {
|
382
|
+
const body = JSON.stringify(form)
|
383
|
+
return http.POST(url, body)
|
384
|
+
},
|
385
|
+
|
386
|
+
update(form) {
|
387
|
+
const body = JSON.stringify(form)
|
388
|
+
return http.PUT(`${url}/${form.id}`, body)
|
389
|
+
},
|
390
|
+
|
391
|
+
remove(id) {
|
392
|
+
return http.DELETE(`${url}/${id}`)
|
393
|
+
}
|
394
|
+
}
|
395
|
+
}
|
@@ -0,0 +1,5 @@
|
|
1
|
+
export { TYPES, Content } from './ContentType'
|
2
|
+
export { ContentForm } from './ContentForm'
|
3
|
+
export { ContentEditor, TabbedContentEditor, CollectionEditor, TreededContentEditor, FieldEditor, ListEditor } from './ContentEditor'
|
4
|
+
export { CreateContentDialog } from './CreateContentDialog'
|
5
|
+
export { EditContentDialog } from './EditContentDialog'
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
@@ -0,0 +1,79 @@
|
|
1
|
+
.btn {
|
2
|
+
position: relative;
|
3
|
+
padding: .2rem .5rem;
|
4
|
+
display: flex;
|
5
|
+
align-items: center;
|
6
|
+
overflow: hidden;
|
7
|
+
border-width: 0;
|
8
|
+
outline: none;
|
9
|
+
transition: background-color .3s;
|
10
|
+
display: flex;
|
11
|
+
color: var(--primary-color);
|
12
|
+
min-height: 2.5rem;
|
13
|
+
}
|
14
|
+
|
15
|
+
|
16
|
+
.btn.outlined {
|
17
|
+
color: var(--primary-color);
|
18
|
+
border: solid 1px var(--primary-color);
|
19
|
+
}
|
20
|
+
|
21
|
+
.btn.outlined.disabled {
|
22
|
+
border: solid 1px rgba(200,200,200,.3) !important;
|
23
|
+
color: rgba(100,100,100,.5) !important;
|
24
|
+
cursor: not-allowed;
|
25
|
+
}
|
26
|
+
|
27
|
+
.btn.raised {
|
28
|
+
color: var(--primary-color-text);
|
29
|
+
background-color: var(--primary-color)
|
30
|
+
}
|
31
|
+
|
32
|
+
.btn.raised.disabled {
|
33
|
+
background-color: rgba(200,200,200,.3) !important;
|
34
|
+
color: rgba(100,100,100,.5) !important;
|
35
|
+
cursor: not-allowed;
|
36
|
+
}
|
37
|
+
|
38
|
+
.btn:hover, .btn:focus {
|
39
|
+
background-color: rgba(171, 171, 171, 0.3);
|
40
|
+
cursor: pointer;
|
41
|
+
}
|
42
|
+
|
43
|
+
.btn.raised:hover, .btn.raised:focus {
|
44
|
+
background-color: var(--primary-color-dark);
|
45
|
+
cursor: pointer;
|
46
|
+
}
|
47
|
+
|
48
|
+
.btn > * {
|
49
|
+
position: relative;
|
50
|
+
}
|
51
|
+
|
52
|
+
.btn span {
|
53
|
+
flex: 1;
|
54
|
+
display: block;
|
55
|
+
}
|
56
|
+
|
57
|
+
.btn:before {
|
58
|
+
content: "";
|
59
|
+
position: absolute;
|
60
|
+
top: 50%;
|
61
|
+
left: 50%;
|
62
|
+
display: block;
|
63
|
+
width: 0;
|
64
|
+
padding-top: 0;
|
65
|
+
border-radius: 100%;
|
66
|
+
background-color: rgba(236, 240, 241, .3);
|
67
|
+
-webkit-transform: translate(-50%, -50%);
|
68
|
+
-moz-transform: translate(-50%, -50%);
|
69
|
+
-ms-transform: translate(-50%, -50%);
|
70
|
+
-o-transform: translate(-50%, -50%);
|
71
|
+
transform: translate(-50%, -50%);
|
72
|
+
}
|
73
|
+
|
74
|
+
.btn:active:before {
|
75
|
+
width: 120%;
|
76
|
+
padding-top: 120%;
|
77
|
+
transition: width .2s ease-out, padding-top .2s ease-out;
|
78
|
+
}
|
79
|
+
|
@@ -0,0 +1,26 @@
|
|
1
|
+
import React from 'react'
|
2
|
+
import './button.css'
|
3
|
+
import { Icon } from './icon'
|
4
|
+
|
5
|
+
/**
|
6
|
+
* HTML Button
|
7
|
+
*/
|
8
|
+
export const Button = ({ label, icon, action, disabled = false, outlined, raised }) => {
|
9
|
+
|
10
|
+
function click(event) {
|
11
|
+
if (!disabled) {
|
12
|
+
event.stopPropagation();
|
13
|
+
event.preventDefault();
|
14
|
+
if (action) action()
|
15
|
+
}
|
16
|
+
}
|
17
|
+
|
18
|
+
let style = raised ? 'raised' : outlined ? 'outlined' : 'normal'
|
19
|
+
if (disabled) style = `${style} disabled`
|
20
|
+
return (
|
21
|
+
<button className={`btn ${style}`} onClick={click}>
|
22
|
+
{ icon ? <Icon icon={icon} size="small" /> : null }
|
23
|
+
<span>{ label }</span>
|
24
|
+
</button>
|
25
|
+
)
|
26
|
+
}
|