ywana-core8 0.0.269 → 0.0.272
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 +37 -10
- package/dist/index.cjs.map +1 -1
- package/dist/index.modern.js +37 -10
- package/dist/index.modern.js.map +1 -1
- package/dist/index.umd.js +39 -13
- package/dist/index.umd.js.map +1 -1
- package/package.json +2 -2
- package/src/html/table.js +4 -4
- package/src/html/text.js +2 -2
- package/src/site/site.js +19 -13
- package/src/site/site.test.js +23 -5
- package/src/widgets/kanban/Kanban.test.js +11 -10
- package/src/widgets/upload/Upload.test.js +35 -0
- package/src/widgets/upload/UploadArea.js +56 -0
- package/src/widgets/upload/UploadDialog.js +41 -0
- package/src/widgets/upload/UploadFile.js +24 -0
- package/src/widgets/upload/UploadProgress.js +21 -0
- package/src/widgets/upload/Uploader.css +77 -0
- package/src/widgets/upload/Uploader.js +73 -0
- package/src/widgets/upload/index.js +4 -0
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "ywana-core8",
|
3
|
-
"version": "0.0.
|
3
|
+
"version": "0.0.272",
|
4
4
|
"description": "ywana-core8",
|
5
5
|
"author": "Ernesto Roldan Garcia",
|
6
6
|
"license": "MIT",
|
@@ -35,7 +35,7 @@
|
|
35
35
|
"moment-range": "^4.0.2",
|
36
36
|
"react-datepicker": "^4.6.0",
|
37
37
|
"react-error-overlay": "^6.0.10",
|
38
|
-
"react-notifications": "^
|
38
|
+
"react-notifications-component": "^3.4.1",
|
39
39
|
"react-switch": "^6.0.0",
|
40
40
|
"react-tooltip": "^4.2.21",
|
41
41
|
"resumablejs": "^1.1.0"
|
package/src/html/table.js
CHANGED
@@ -13,7 +13,7 @@ const isFunction = value => value && (Object.prototype.toString.call(value) ===
|
|
13
13
|
*/
|
14
14
|
export const DataTable = (props) => {
|
15
15
|
|
16
|
-
const { columns = [], rows = [], onRowSelection, onSort, onCheckAll, editable, outlined } = props
|
16
|
+
const { columns = [], rows = [], onRowSelection, onSort, onCheckAll, editable, outlined, expanded = false } = props
|
17
17
|
const [sortDir, setSortDir] = useState({})
|
18
18
|
|
19
19
|
function multiSort(array, sortObject = {}) {
|
@@ -103,7 +103,7 @@ export const DataTable = (props) => {
|
|
103
103
|
<tbody>
|
104
104
|
{
|
105
105
|
multiSort(rows, sortDir).map(row => (
|
106
|
-
<DataTableRow key={row.id} row={row} columns={columns} onSelect={select} onDrop={sort} editable={editable} />
|
106
|
+
<DataTableRow key={row.id} row={row} columns={columns} onSelect={select} onDrop={sort} editable={editable} expanded={expanded} />
|
107
107
|
))
|
108
108
|
}
|
109
109
|
</tbody>
|
@@ -117,9 +117,9 @@ export const DataTable = (props) => {
|
|
117
117
|
*/
|
118
118
|
const DataTableRow = (props) => {
|
119
119
|
|
120
|
-
const { row, columns = [], onSelect, editable } = props
|
120
|
+
const { row, columns = [], onSelect, editable, expanded = false } = props
|
121
121
|
const { className} = row
|
122
|
-
const [isInfoOpen, toggleInfo] = useState(
|
122
|
+
const [isInfoOpen, toggleInfo] = useState(expanded)
|
123
123
|
const infoIcon = isInfoOpen ? 'expand_more' : 'expand_less'
|
124
124
|
|
125
125
|
return (
|
package/src/html/text.js
CHANGED
@@ -14,7 +14,7 @@ export const TEXTFORMATS = {
|
|
14
14
|
/**
|
15
15
|
* Text
|
16
16
|
*/
|
17
|
-
export const Text = ({ format, children }) => {
|
17
|
+
export const Text = ({ format, children, className }) => {
|
18
18
|
|
19
19
|
const site = useContext(SiteContext)
|
20
20
|
let value = children
|
@@ -31,6 +31,6 @@ export const Text = ({ format, children }) => {
|
|
31
31
|
case TEXTFORMATS.NUMERIC: value = formatter.format(children); break;
|
32
32
|
}
|
33
33
|
|
34
|
-
return children ? <span>{value}</span> : ''
|
34
|
+
return children ? <span className={className}>{value}</span> : ''
|
35
35
|
|
36
36
|
}
|
package/src/site/site.js
CHANGED
@@ -4,14 +4,11 @@ import { Tabs, Tab } from '../html/tab'
|
|
4
4
|
import { Header } from '../html/header'
|
5
5
|
import { Page } from './page'
|
6
6
|
import { SiteContext } from './siteContext'
|
7
|
+
import './site.css'
|
7
8
|
|
8
|
-
|
9
|
-
import
|
10
|
-
import { NotificationContainer } from 'react-notifications'
|
11
|
-
*/
|
9
|
+
import { ReactNotifications, Store } from 'react-notifications-component'
|
10
|
+
import 'react-notifications-component/dist/theme.css'
|
12
11
|
|
13
|
-
import './site.css'
|
14
|
-
import 'react-notifications/lib/notifications.css';
|
15
12
|
|
16
13
|
|
17
14
|
/**
|
@@ -74,8 +71,20 @@ export const SiteProvider = ({ children, siteLang, siteDictionary, showConsole }
|
|
74
71
|
|
75
72
|
confirm: (message) => window.confirm(message),
|
76
73
|
|
77
|
-
notify: ({ title, body }) => {
|
78
|
-
|
74
|
+
notify: ({ title, body, type = "success" }) => {
|
75
|
+
Store.addNotification({
|
76
|
+
title,
|
77
|
+
message: body,
|
78
|
+
type,
|
79
|
+
insert: "top",
|
80
|
+
container: "top-right",
|
81
|
+
animationIn: ["animate__animated", "animate__fadeIn"],
|
82
|
+
animationOut: ["animate__animated", "animate__fadeOut"],
|
83
|
+
dismiss: {
|
84
|
+
duration: 3000,
|
85
|
+
onScreen: true
|
86
|
+
}
|
87
|
+
});
|
79
88
|
}
|
80
89
|
}
|
81
90
|
|
@@ -93,7 +102,7 @@ export const Site = ({ icon, logo, title, toolbar, children, init, min, lang, di
|
|
93
102
|
return (
|
94
103
|
<SiteProvider siteLang={lang} siteDictionary={dictionary}>
|
95
104
|
<div className="site6">
|
96
|
-
<SiteHeader icon={icon} />
|
105
|
+
<SiteHeader icon={icon} title={title}/>
|
97
106
|
<SiteToolBar >{toolbar}</SiteToolBar>
|
98
107
|
<SiteMenu logo={logo} title={title} min={min} >{children}</SiteMenu>
|
99
108
|
<SitePage init={init}>
|
@@ -112,10 +121,7 @@ export const Site = ({ icon, logo, title, toolbar, children, init, min, lang, di
|
|
112
121
|
|
113
122
|
const SiteNotifications = () => {
|
114
123
|
return (
|
115
|
-
<
|
116
|
-
)
|
117
|
-
return (
|
118
|
-
<NotificationContainer />
|
124
|
+
<ReactNotifications />
|
119
125
|
)
|
120
126
|
}
|
121
127
|
|
package/src/site/site.test.js
CHANGED
@@ -1,19 +1,37 @@
|
|
1
|
-
import React, { useState } from 'react'
|
1
|
+
import React, { useContext, useEffect, useState } from 'react'
|
2
2
|
import { Site } from './site'
|
3
3
|
import { Page } from './page'
|
4
4
|
import './site.css'
|
5
5
|
import './page.css'
|
6
|
+
import { Fragment } from 'react/cjs/react.production.min'
|
7
|
+
import { SiteContext } from './siteContext'
|
6
8
|
|
7
9
|
const SiteTest = (prop) => {
|
8
|
-
|
9
10
|
return (
|
10
11
|
<Site icon="star" title="Site Test" init={"PAGE1"}>
|
11
|
-
<Page id="PAGE1" section="SECTION1" icon="description" title="Page 1">
|
12
|
-
|
12
|
+
<Page id="PAGE1" section="SECTION1" icon="description" title="Page 1" layout="workspace">
|
13
|
+
<Page1 />
|
13
14
|
</Page>
|
14
|
-
<Page id="PAGE2" section="SECTION1" icon="description" title="Page 2">
|
15
|
+
<Page id="PAGE2" section="SECTION1" icon="description" title="Page 2" layout="workspace">
|
15
16
|
222
|
16
17
|
</Page>
|
17
18
|
</Site>
|
18
19
|
)
|
20
|
+
}
|
21
|
+
|
22
|
+
const Page1 = (props) => {
|
23
|
+
|
24
|
+
const site = useContext(SiteContext)
|
25
|
+
useEffect(() => {
|
26
|
+
|
27
|
+
site.notify({ title: "Notification 1", body: "Lorem ipsum dolor sit amet"})
|
28
|
+
}, [])
|
29
|
+
|
30
|
+
return (
|
31
|
+
<Fragment>
|
32
|
+
<header>Page 1</header>
|
33
|
+
<main>1</main>
|
34
|
+
<footer>f1</footer>
|
35
|
+
</Fragment>
|
36
|
+
)
|
19
37
|
}
|
@@ -3,16 +3,17 @@ import { Kanban, KanbanCard, KanbanColumn } from './Kanban'
|
|
3
3
|
|
4
4
|
const KanbanTest = (prop) => {
|
5
5
|
return (
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
6
|
+
<Kanban>
|
7
|
+
<KanbanColumn title="TODO" badge="1">
|
8
|
+
<KanbanCard />
|
9
|
+
</KanbanColumn>
|
10
|
+
<KanbanColumn title="IN PROGRESS" badge="0">
|
11
11
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
12
|
+
</KanbanColumn>
|
13
|
+
<KanbanColumn title="DONE" badge="2">
|
14
|
+
<KanbanCard />
|
15
|
+
<KanbanCard />
|
16
|
+
</KanbanColumn>
|
17
|
+
</Kanban>
|
17
18
|
)
|
18
19
|
}
|
@@ -0,0 +1,35 @@
|
|
1
|
+
import React from 'react'
|
2
|
+
import { UploadArea } from './UploadArea'
|
3
|
+
import { Uploader, UPLOAD_STATES } from './Uploader'
|
4
|
+
import { UploadProgress } from './UploadProgress'
|
5
|
+
|
6
|
+
const UploadAreaTest = (props) => {
|
7
|
+
|
8
|
+
return (
|
9
|
+
<div style={{ padding: "1rem" }}>
|
10
|
+
<UploadArea icon="cloud_upload" label="UploadArea Test" />
|
11
|
+
</div>
|
12
|
+
)
|
13
|
+
}
|
14
|
+
|
15
|
+
const UploadProgressTest = (prop) => {
|
16
|
+
|
17
|
+
const files = [
|
18
|
+
{ icon: "image", fileName: "fileName1", uploadState: UPLOAD_STATES.RUNNING, progress: () => { return 50 } },
|
19
|
+
{ icon: "image", fileName: "fileName4", uploadState: UPLOAD_STATES.SUCCESS, progress: () => { return 70 } },
|
20
|
+
{ icon: "description", fileName: "fileName2", uploadState: UPLOAD_STATES.ERROR, progress: () => { return 70 }, uploadError: "Unknow error" },
|
21
|
+
]
|
22
|
+
|
23
|
+
return (
|
24
|
+
<UploadProgress files={files} />
|
25
|
+
)
|
26
|
+
}
|
27
|
+
|
28
|
+
const UploaderTest = (prop) => {
|
29
|
+
|
30
|
+
return (
|
31
|
+
<div style={{ padding: "1rem" }}>
|
32
|
+
<Uploader target="https://maso.developxp.com/kiosk/api/upload" />
|
33
|
+
</div>
|
34
|
+
)
|
35
|
+
}
|
@@ -0,0 +1,56 @@
|
|
1
|
+
import React, { useState, useEffect, useRef } from 'react'
|
2
|
+
import { Icon } from '../../html'
|
3
|
+
|
4
|
+
/**
|
5
|
+
* Upload Area
|
6
|
+
*/
|
7
|
+
export const UploadArea = (props) => {
|
8
|
+
|
9
|
+
const { icon, label = 'Add file or drop file here...' } = props
|
10
|
+
const areaElement = useRef()
|
11
|
+
const [drag, setDrag] = useState(false)
|
12
|
+
|
13
|
+
useEffect(() => {
|
14
|
+
const { resumable } = props
|
15
|
+
if (resumable && areaElement) resumable.assignDrop(areaElement.current)
|
16
|
+
}, [])
|
17
|
+
|
18
|
+
const onDragOver = () => {
|
19
|
+
setDrag(true)
|
20
|
+
}
|
21
|
+
|
22
|
+
const onDragLeave = () => {
|
23
|
+
setDrag(false)
|
24
|
+
}
|
25
|
+
|
26
|
+
const dragging = drag === true ? 'drag-over' : ''
|
27
|
+
|
28
|
+
return (
|
29
|
+
<div className={`upload-area6 ${dragging}`}
|
30
|
+
onDragOver={onDragOver}
|
31
|
+
onDragLeave={onDragLeave}
|
32
|
+
ref={areaElement}
|
33
|
+
>
|
34
|
+
<UploadIcon icon={icon} resumable={props.resumable} />
|
35
|
+
<label>{label}</label>
|
36
|
+
</div>
|
37
|
+
)
|
38
|
+
}
|
39
|
+
|
40
|
+
/**
|
41
|
+
* Upload Icon
|
42
|
+
*/
|
43
|
+
const UploadIcon = ({ icon = "folder_open", resumable }) => {
|
44
|
+
|
45
|
+
const iconElement = useRef()
|
46
|
+
|
47
|
+
useEffect(() => {
|
48
|
+
if (resumable && iconElement) resumable.assignBrowse(iconElement.current)
|
49
|
+
}, [])
|
50
|
+
|
51
|
+
return (
|
52
|
+
<div className="upload-icon" ref={iconElement}>
|
53
|
+
<Icon icon={icon} clickable/>
|
54
|
+
</div>
|
55
|
+
)
|
56
|
+
}
|
@@ -0,0 +1,41 @@
|
|
1
|
+
import React, { Fragment, useContext, useState } from 'react';
|
2
|
+
import { Uploader } from './Uploader'
|
3
|
+
import { Button, Text } from '../html';
|
4
|
+
import { SiteContext, Dialog } from '../site';
|
5
|
+
import { UploadFile } from './UploadFile';
|
6
|
+
|
7
|
+
/**
|
8
|
+
* Upload Dialog
|
9
|
+
*/
|
10
|
+
export const UploadDialog = ({ label, target, accept, onSuccess, onOK, onError, onClose, onActionClose = true }) => {
|
11
|
+
|
12
|
+
const site = useContext(SiteContext);
|
13
|
+
const [file, setFile] = useState();
|
14
|
+
const [errors, setErrors] = useState([])
|
15
|
+
|
16
|
+
function onComplete(uploads) {
|
17
|
+
setFile(uploads[0]);
|
18
|
+
if (onSuccess) onSuccess(uploads[0])
|
19
|
+
}
|
20
|
+
|
21
|
+
function onAction(action) {
|
22
|
+
if (action === 'CLOSE' || onActionClose === true) {
|
23
|
+
site.closeDialog();
|
24
|
+
onClose()
|
25
|
+
}
|
26
|
+
}
|
27
|
+
|
28
|
+
const actions = (
|
29
|
+
<Fragment>
|
30
|
+
<Button label="CLOSE" action={() => onAction("CLOSE")} />
|
31
|
+
</Fragment>
|
32
|
+
)
|
33
|
+
|
34
|
+
const title = <Text use="headline6">{label}</Text>
|
35
|
+
return (
|
36
|
+
<Dialog title={title} open={true} onAction={onAction} actions={actions}>
|
37
|
+
{file ? <UploadFile file={file} /> : <Uploader label={label} accept={accept} target={target} onComplete={onComplete} />}
|
38
|
+
{errors.map(error => <Text use="overline" tag="div" className="error">{error}</Text>)}
|
39
|
+
</Dialog>
|
40
|
+
)
|
41
|
+
}
|
@@ -0,0 +1,24 @@
|
|
1
|
+
import React, { Fragment } from 'react'
|
2
|
+
import { Icon, Text, LinearProgress } from '../../html'
|
3
|
+
import { UPLOAD_STATES } from './Uploader'
|
4
|
+
import './Uploader.css'
|
5
|
+
|
6
|
+
/**
|
7
|
+
* Upload File
|
8
|
+
*/
|
9
|
+
export const UploadFile = ({ file }) => {
|
10
|
+
|
11
|
+
const { icon, name, state, progress, error } = file
|
12
|
+
|
13
|
+
return (
|
14
|
+
<Fragment>
|
15
|
+
<div className="upload-file">
|
16
|
+
{ icon ? <Icon icon={icon} /> : null }
|
17
|
+
<label>{name}</label>
|
18
|
+
{state === UPLOAD_STATES.RUNNING ? <main><LinearProgress progress={progress} /><Icon icon="close" clickable /></main> : ''}
|
19
|
+
{state === UPLOAD_STATES.SUCCESS ? <main><Icon icon="done" /></main> : ''}
|
20
|
+
{state === UPLOAD_STATES.ERROR ? <main><div className="error">{error}</div><Icon icon="error" /></main> : ''}
|
21
|
+
</div>
|
22
|
+
</Fragment>
|
23
|
+
)
|
24
|
+
}
|
@@ -0,0 +1,21 @@
|
|
1
|
+
import React from 'react'
|
2
|
+
import { UPLOAD_STATES } from './Uploader';
|
3
|
+
import { UploadFile } from './UploadFile';
|
4
|
+
|
5
|
+
export const UploadProgress = ({ files = [], state }) => {
|
6
|
+
|
7
|
+
return (
|
8
|
+
<div>
|
9
|
+
{files.map((file) => {
|
10
|
+
const f = {
|
11
|
+
icon: "image",
|
12
|
+
name: file.fileName,
|
13
|
+
progress: file.progress() * 100,
|
14
|
+
state: file.uploadState,
|
15
|
+
error: file.uploadError
|
16
|
+
}
|
17
|
+
return <UploadFile key={f.name} file={f} />;
|
18
|
+
})}
|
19
|
+
</div>
|
20
|
+
);
|
21
|
+
};
|
@@ -0,0 +1,77 @@
|
|
1
|
+
.uploader {
|
2
|
+
display: flex;
|
3
|
+
flex-direction: column;
|
4
|
+
flex: 1;
|
5
|
+
}
|
6
|
+
|
7
|
+
.demo-uploader {
|
8
|
+
width: 40rem;
|
9
|
+
height: 30rem;
|
10
|
+
margin: 5rem auto;
|
11
|
+
flex-direction: column;
|
12
|
+
}
|
13
|
+
|
14
|
+
/***************** Upload Area ***********************/
|
15
|
+
|
16
|
+
.upload-area6 {
|
17
|
+
flex: 1;
|
18
|
+
margin: 0 0 1rem 0;
|
19
|
+
border: dashed 2px var(--divider-color);
|
20
|
+
display: flex;
|
21
|
+
flex-direction: column;
|
22
|
+
align-items: center;
|
23
|
+
justify-content: center;
|
24
|
+
border-radius: 1rem;
|
25
|
+
min-height: 10rem;
|
26
|
+
}
|
27
|
+
|
28
|
+
.upload-area6 > label {
|
29
|
+
font-size: 1.1rem;
|
30
|
+
font-weight: 500;
|
31
|
+
}
|
32
|
+
|
33
|
+
.upload-area6.drag-over {
|
34
|
+
background-color: rgba(200, 200, 200, 0.1);
|
35
|
+
}
|
36
|
+
|
37
|
+
/***************** Upload File ***********************/
|
38
|
+
|
39
|
+
.upload-file {
|
40
|
+
display: flex;
|
41
|
+
align-items: center;
|
42
|
+
}
|
43
|
+
|
44
|
+
.upload-file > label {
|
45
|
+
min-width: 30%;
|
46
|
+
overflow: hidden;
|
47
|
+
text-overflow: ellipsis;
|
48
|
+
white-space: nowrap;
|
49
|
+
margin-right: 1rem;
|
50
|
+
}
|
51
|
+
|
52
|
+
.upload-file > main {
|
53
|
+
flex: 1;
|
54
|
+
display: flex;
|
55
|
+
align-items: center;
|
56
|
+
justify-content: flex-end;
|
57
|
+
}
|
58
|
+
|
59
|
+
.upload-file .error {
|
60
|
+
color: red;
|
61
|
+
text-align: center;
|
62
|
+
}
|
63
|
+
|
64
|
+
.upload-file progress {
|
65
|
+
appearance: none;
|
66
|
+
border: solid 1px var(--divider-color);
|
67
|
+
}
|
68
|
+
|
69
|
+
.upload-file ::-webkit-progress-bar {
|
70
|
+
border: solid 1px rgb(235, 235, 235);
|
71
|
+
background-color: rgb(241, 241, 241);
|
72
|
+
}
|
73
|
+
|
74
|
+
.upload-file ::-webkit-progress-value {
|
75
|
+
background-color: rgb(182, 182, 182);
|
76
|
+
opacity: 1;
|
77
|
+
}
|
@@ -0,0 +1,73 @@
|
|
1
|
+
import React, { useState, useMemo } from 'react'
|
2
|
+
import ResumableJS from 'resumablejs'
|
3
|
+
import { UploadArea } from "./UploadArea";
|
4
|
+
import { UploadProgress } from './UploadProgress';
|
5
|
+
import './Uploader.css'
|
6
|
+
|
7
|
+
export const UPLOAD_STATES = {
|
8
|
+
IDLE: 0, RUNNING: 1, SUCCESS: 2, ERROR: 3, COMPLETED: 4
|
9
|
+
}
|
10
|
+
|
11
|
+
/**
|
12
|
+
* Uploader
|
13
|
+
*/
|
14
|
+
export const Uploader = ({ label, target, accept, simultaneousUploads = 1, className, onProgress, onSuccess, onError, onComplete }) => {
|
15
|
+
|
16
|
+
const resumable = useMemo(() => {
|
17
|
+
const config = {
|
18
|
+
target: target,
|
19
|
+
chunkSize: 1 * 1024 * 1024,
|
20
|
+
simultaneousUploads,
|
21
|
+
testChunks: false,
|
22
|
+
throttleProgressCallbacks: 1,
|
23
|
+
fileType: accept
|
24
|
+
}
|
25
|
+
const resumable = new ResumableJS(config)
|
26
|
+
resumable.on('fileAdded', onFileAdded)
|
27
|
+
resumable.on('fileProgress', onFileProgress)
|
28
|
+
resumable.on('fileSuccess', onFileSuccess)
|
29
|
+
resumable.on('fileError', onFileError)
|
30
|
+
resumable.on('complete', onAllComplete)
|
31
|
+
return resumable
|
32
|
+
}, [])
|
33
|
+
|
34
|
+
const [progress, setProgress] = useState(0)
|
35
|
+
const [state, setState] = useState(UPLOAD_STATES.IDLE)
|
36
|
+
const [files, setFiles] = useState([])
|
37
|
+
|
38
|
+
function onFileAdded(file) {
|
39
|
+
files.push(file)
|
40
|
+
setFiles(files)
|
41
|
+
setState(UPLOAD_STATES.RUNNING)
|
42
|
+
resumable.upload()
|
43
|
+
}
|
44
|
+
|
45
|
+
function onFileProgress(file) {
|
46
|
+
file.uploadState = UPLOAD_STATES.RUNNING
|
47
|
+
const progress = file.progress()
|
48
|
+
setProgress(progress)
|
49
|
+
if (onProgress) onProgress(files);
|
50
|
+
}
|
51
|
+
|
52
|
+
function onFileSuccess(file, message) {
|
53
|
+
file.uploadState = UPLOAD_STATES.SUCCESS
|
54
|
+
if (onSuccess) onSuccess(file, message)
|
55
|
+
}
|
56
|
+
|
57
|
+
function onFileError(file, message) {
|
58
|
+
file.uploadState = UPLOAD_STATES.ERROR
|
59
|
+
file.uploadError = message
|
60
|
+
if (onError) onError(file, message)
|
61
|
+
}
|
62
|
+
|
63
|
+
function onAllComplete() {
|
64
|
+
setState(UPLOAD_STATES.COMPLETED)
|
65
|
+
if (onComplete) onComplete(files)
|
66
|
+
}
|
67
|
+
|
68
|
+
return (
|
69
|
+
<div className={`uploader ${className}`}>
|
70
|
+
{state === UPLOAD_STATES.IDLE ? <UploadArea resumable={resumable} label={label} /> : <UploadProgress files={files} state={state} /> }
|
71
|
+
</div>
|
72
|
+
)
|
73
|
+
}
|