ywana-core8 0.0.271 → 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 +26 -5
- package/dist/index.cjs.map +1 -1
- package/dist/index.modern.js +26 -5
- package/dist/index.modern.js.map +1 -1
- package/dist/index.umd.js +28 -8
- package/dist/index.umd.js.map +1 -1
- package/package.json +2 -2
- package/src/html/text.js +2 -2
- package/src/site/site.js +18 -12
- 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/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
|
|
@@ -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
|
+
}
|