ywana-core8 0.0.238 → 0.0.239
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/__reactpreview__/Wrapper.tsx +16 -7
- package/dist/index.cjs +2 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.css +9 -3
- package/dist/index.css.map +1 -1
- package/dist/index.modern.js +2 -2
- package/dist/index.modern.js.map +1 -1
- package/dist/index.umd.js +2 -2
- package/dist/index.umd.js.map +1 -1
- package/package.json +3 -1
- package/src/html/header.css +2 -1
- package/src/html/textfield.css +7 -2
- package/src/html/textfield.js +2 -2
- package/src/html/textfield.test.js +21 -0
- package/src/widgets/kanban/Kanban.test.js +18 -0
- package/src/widgets/planner/Planner.css +179 -0
- package/src/widgets/planner/Planner.js +208 -0
- package/src/widgets/planner/Planner.test.js +25 -0
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "ywana-core8",
|
3
|
-
"version": "0.0.
|
3
|
+
"version": "0.0.239",
|
4
4
|
"description": "ywana-core8",
|
5
5
|
"author": "Ernesto Roldan Garcia",
|
6
6
|
"license": "MIT",
|
@@ -31,6 +31,8 @@
|
|
31
31
|
"dependencies": {
|
32
32
|
"deep-equal": "^2.0.5",
|
33
33
|
"material-design-icons-iconfont": "^6.1.1",
|
34
|
+
"moment": "^2.29.1",
|
35
|
+
"moment-range": "^4.0.2",
|
34
36
|
"react-datepicker": "^4.6.0",
|
35
37
|
"react-error-overlay": "^6.0.10",
|
36
38
|
"react-notifications": "^1.7.3",
|
package/src/html/header.css
CHANGED
@@ -5,6 +5,7 @@
|
|
5
5
|
align-items: center;
|
6
6
|
background-repeat: no-repeat;
|
7
7
|
background-size: cover;
|
8
|
+
overflow: visible;
|
8
9
|
}
|
9
10
|
|
10
11
|
.header>.icon .header>img {
|
@@ -50,7 +51,7 @@
|
|
50
51
|
display: flex;
|
51
52
|
flex-direction: row-reverse;
|
52
53
|
align-items: center;
|
53
|
-
overflow:
|
54
|
+
overflow: visible;
|
54
55
|
}
|
55
56
|
|
56
57
|
.header.primary {
|
package/src/html/textfield.css
CHANGED
@@ -31,11 +31,16 @@
|
|
31
31
|
|
32
32
|
.textfield>.icon {
|
33
33
|
position: absolute;
|
34
|
-
top: 1.
|
34
|
+
top: 1.5rem;
|
35
35
|
right: .2rem;
|
36
36
|
color: rgba(150,150,150,1);
|
37
37
|
}
|
38
38
|
|
39
|
+
.textfield-date>.icon,
|
40
|
+
.textfield-DATE>.icon {
|
41
|
+
right: 2.5rem;
|
42
|
+
}
|
43
|
+
|
39
44
|
.textfield > label {
|
40
45
|
color: var(--primary-color);
|
41
46
|
font-size: .9rem;
|
@@ -120,7 +125,7 @@ input:read-only ~ label,
|
|
120
125
|
}
|
121
126
|
|
122
127
|
.dropdown>menu {
|
123
|
-
z-index:
|
128
|
+
z-index: 11;
|
124
129
|
position: absolute;
|
125
130
|
top: 3.8rem;
|
126
131
|
left: 0px;
|
package/src/html/textfield.js
CHANGED
@@ -43,7 +43,7 @@ export const TextField = (props) => {
|
|
43
43
|
|
44
44
|
const borderStyle = outlined ? "textfield-outlined" : "textfield"
|
45
45
|
const labelStyle = label ? "" : "no-label"
|
46
|
-
const style = `${labelStyle} ${borderStyle}`
|
46
|
+
const style = `${labelStyle} ${borderStyle} textfield-${type}`
|
47
47
|
const labelTxt = <Text>{label}</Text>
|
48
48
|
|
49
49
|
return (
|
@@ -83,7 +83,7 @@ export const DropDown = (props) => {
|
|
83
83
|
}
|
84
84
|
|
85
85
|
function toggle() {
|
86
|
-
if (site) {
|
86
|
+
if (site && site.changeFocus) {
|
87
87
|
site.changeFocus({
|
88
88
|
lose: () => {
|
89
89
|
setOpen(false)
|
@@ -0,0 +1,21 @@
|
|
1
|
+
import React, { useState } from 'react'
|
2
|
+
import { DropDown, TextField } from '.'
|
3
|
+
import { Wrapper } from '../../__reactpreview__/Wrapper'
|
4
|
+
|
5
|
+
const KanbanTest = (prop) => {
|
6
|
+
|
7
|
+
const [form, setForm] = useState({})
|
8
|
+
|
9
|
+
function change(id, value) {
|
10
|
+
const next = Object.assign({}, form, { [id]: value })
|
11
|
+
setForm(next)
|
12
|
+
}
|
13
|
+
|
14
|
+
return (
|
15
|
+
<>
|
16
|
+
<TextField id="date1" type="DATE" label="Date" value={form.date1} onChange={change}/>
|
17
|
+
<div/>
|
18
|
+
<DropDown id="gender1" label="Gender" value={form.gender1} onChange={change} options={[ {label: "Male", value: "M"}, { label: "Female", value: "F" }]} />
|
19
|
+
</>
|
20
|
+
)
|
21
|
+
}
|
@@ -0,0 +1,18 @@
|
|
1
|
+
import React from 'react'
|
2
|
+
import { Kanban, KanbanCard, KanbanColumn } from './Kanban'
|
3
|
+
|
4
|
+
const KanbanTest = (prop) => {
|
5
|
+
return (
|
6
|
+
<Kanban>
|
7
|
+
<KanbanColumn title="TODO">
|
8
|
+
<KanbanCard />
|
9
|
+
</KanbanColumn>
|
10
|
+
<KanbanColumn title="IN PROGRESS">
|
11
|
+
|
12
|
+
</KanbanColumn>
|
13
|
+
<KanbanColumn title="DONE">
|
14
|
+
|
15
|
+
</KanbanColumn>
|
16
|
+
</Kanban>
|
17
|
+
)
|
18
|
+
}
|
@@ -0,0 +1,179 @@
|
|
1
|
+
.planner-box {
|
2
|
+
flex:1;
|
3
|
+
display: flex;
|
4
|
+
flex-direction: column;
|
5
|
+
overflow: hidden;
|
6
|
+
border: solid 1px var(--divider-color);
|
7
|
+
}
|
8
|
+
|
9
|
+
.planner-box > header > label {
|
10
|
+
min-width:13rem;
|
11
|
+
}
|
12
|
+
|
13
|
+
.planner {
|
14
|
+
flex: 1;
|
15
|
+
display: flex;
|
16
|
+
height: 70rem;
|
17
|
+
overflow-y: auto;
|
18
|
+
margin: 1rem;
|
19
|
+
|
20
|
+
--row-height: 8rem;
|
21
|
+
--column-width: 14rem;
|
22
|
+
}
|
23
|
+
|
24
|
+
.planner > .column0 {
|
25
|
+
position: sticky;
|
26
|
+
left: 0px;
|
27
|
+
z-index: 11;
|
28
|
+
background-color: var(--paper-color);
|
29
|
+
width: var(--column-width);
|
30
|
+
border-right: solid 1px var(--divider-color);
|
31
|
+
}
|
32
|
+
|
33
|
+
.column-header {
|
34
|
+
width: var(--column-width);
|
35
|
+
background-color: var(--paper-color);
|
36
|
+
height: 2.6rem;
|
37
|
+
}
|
38
|
+
|
39
|
+
.date-header {
|
40
|
+
display: flex;
|
41
|
+
padding: 0.5rem 1rem;
|
42
|
+
align-items: baseline;
|
43
|
+
}
|
44
|
+
|
45
|
+
.weekend {
|
46
|
+
background-color: rgb(245, 245, 245);
|
47
|
+
}
|
48
|
+
|
49
|
+
.month-header {
|
50
|
+
padding: 0.5rem 1rem;
|
51
|
+
border-top: solid 1px var(--divider-color);
|
52
|
+
}
|
53
|
+
|
54
|
+
.month-header>* {
|
55
|
+
display: none
|
56
|
+
}
|
57
|
+
|
58
|
+
.month-header.first {
|
59
|
+
border-left: solid 1px var(--divider-color);
|
60
|
+
}
|
61
|
+
|
62
|
+
.month-header.first>* {
|
63
|
+
display: block
|
64
|
+
}
|
65
|
+
|
66
|
+
.column0 > .column-header {
|
67
|
+
position: sticky;
|
68
|
+
top: 0px;
|
69
|
+
height: 6rem;
|
70
|
+
border-bottom: solid 1px var(--divider-color);
|
71
|
+
border-right: solid 1px var(--divider-color);
|
72
|
+
}
|
73
|
+
|
74
|
+
.row-header {
|
75
|
+
width: var(--column-width);
|
76
|
+
height: var(--row-height);
|
77
|
+
border-bottom: solid 1px var(--divider-color);
|
78
|
+
display: flex;
|
79
|
+
justify-content: center;
|
80
|
+
align-items: center;
|
81
|
+
}
|
82
|
+
|
83
|
+
.planner > .rows {
|
84
|
+
flex: 1;
|
85
|
+
}
|
86
|
+
|
87
|
+
.planner .row {
|
88
|
+
height: var(--row-height);
|
89
|
+
border-bottom: solid 1px var(--divider-color);
|
90
|
+
display: flex;
|
91
|
+
}
|
92
|
+
|
93
|
+
.planner .row0 {
|
94
|
+
position: sticky;
|
95
|
+
top: 0px;
|
96
|
+
z-index: 10;
|
97
|
+
height: 3rem;
|
98
|
+
background-color: var(--paper-color);
|
99
|
+
border-bottom: solid 1px var(--divider-color);
|
100
|
+
}
|
101
|
+
|
102
|
+
.planner .row1 {
|
103
|
+
position: sticky;
|
104
|
+
top: 3rem;
|
105
|
+
z-index: 10;
|
106
|
+
height: 3rem;
|
107
|
+
background-color: var(--paper-color);
|
108
|
+
border-bottom: solid 1px var(--divider-color);
|
109
|
+
}
|
110
|
+
|
111
|
+
.planner .cell {
|
112
|
+
width: var(--column-width);
|
113
|
+
height: 100%;
|
114
|
+
padding: 0.5rem;
|
115
|
+
display: flex;
|
116
|
+
justify-content: center;
|
117
|
+
align-items: center;
|
118
|
+
border-right: dotted 1px var(--divider-color);
|
119
|
+
}
|
120
|
+
|
121
|
+
.photoshoot-icon {
|
122
|
+
border: solid 0px var(--divider-color);
|
123
|
+
border-radius: 4px;
|
124
|
+
flex: 1;
|
125
|
+
height: 100%;
|
126
|
+
padding: 0.5rem;
|
127
|
+
display: flex;
|
128
|
+
justify-content: center;
|
129
|
+
align-items: center;
|
130
|
+
color: rgba(200, 200, 200, 0.5);
|
131
|
+
}
|
132
|
+
|
133
|
+
.photoshoot-icon.dragOver {
|
134
|
+
background-color: rgba(225,225,250);
|
135
|
+
}
|
136
|
+
|
137
|
+
.photoshoot-card {
|
138
|
+
border: solid 1px var(--divider-color);
|
139
|
+
border-radius: 4px;
|
140
|
+
flex: 1;
|
141
|
+
width: 100%;
|
142
|
+
height: 100%;
|
143
|
+
display: flex;
|
144
|
+
flex-direction: column;
|
145
|
+
overflow: hidden;
|
146
|
+
}
|
147
|
+
|
148
|
+
.photoshoot-card > * {
|
149
|
+
background-color: #FFF;
|
150
|
+
opacity: .8;
|
151
|
+
}
|
152
|
+
|
153
|
+
.photoshoot-card > header {
|
154
|
+
padding: 0 0.5rem ;
|
155
|
+
|
156
|
+
}
|
157
|
+
|
158
|
+
.photoshoot-card > main {
|
159
|
+
padding: 0 0.5rem ;
|
160
|
+
flex: 1;
|
161
|
+
}
|
162
|
+
|
163
|
+
.photoshoot-card > footer {
|
164
|
+
display: flex;
|
165
|
+
}
|
166
|
+
|
167
|
+
.photoshoot-card.disabled {
|
168
|
+
opacity: 0.3;
|
169
|
+
}
|
170
|
+
|
171
|
+
.photoshoot-card:hover {
|
172
|
+
cursor: pointer;
|
173
|
+
box-shadow: var(--shadow1);
|
174
|
+
}
|
175
|
+
|
176
|
+
.expand {
|
177
|
+
flex: 1;
|
178
|
+
}
|
179
|
+
|
@@ -0,0 +1,208 @@
|
|
1
|
+
import React, { useEffect, useMemo, useState } from "react";
|
2
|
+
import { DropDown, Header, Icon, Text, TextField } from "../../html";
|
3
|
+
import moment from "moment";
|
4
|
+
import { extendMoment } from "moment-range";
|
5
|
+
import "./Planner.css";
|
6
|
+
|
7
|
+
const ranges = extendMoment(moment);
|
8
|
+
|
9
|
+
const DATE_RANGE = [
|
10
|
+
{ label: "Week", value: "week" },
|
11
|
+
{ label: "Month", value: "month" },
|
12
|
+
];
|
13
|
+
|
14
|
+
/**
|
15
|
+
* Planner
|
16
|
+
*/
|
17
|
+
export const Planner = ({ title, events = [], lanes = [], selected = false, editable = false, navigation = true, onSelect, onAdd, onDelete, onMove }) => {
|
18
|
+
|
19
|
+
const [dateRange, setDateRange] = useState("month");
|
20
|
+
const [from, setFrom] = useState("2021-02-26");
|
21
|
+
const [to, setTo] = useState("2021-04-01");
|
22
|
+
|
23
|
+
useEffect(() => {
|
24
|
+
const today = moment();
|
25
|
+
const from_date = today.startOf(dateRange).format("YYYY-MM-DD");
|
26
|
+
const to_date = today.endOf(dateRange).format("YYYY-MM-DD");
|
27
|
+
setFrom(from_date);
|
28
|
+
setTo(to_date);
|
29
|
+
}, [dateRange]);
|
30
|
+
|
31
|
+
function next() {
|
32
|
+
const actual = moment(from);
|
33
|
+
const next = actual.add(1, dateRange);
|
34
|
+
const from_date = next.startOf(dateRange).format("YYYY-MM-DD");
|
35
|
+
const to_date = next.endOf(dateRange).format("YYYY-MM-DD");
|
36
|
+
setFrom(from_date);
|
37
|
+
setTo(to_date);
|
38
|
+
}
|
39
|
+
|
40
|
+
function prev() {
|
41
|
+
const actual = moment(from);
|
42
|
+
const next = actual.subtract(1, dateRange);
|
43
|
+
const from_date = next.startOf(dateRange).format("YYYY-MM-DD");
|
44
|
+
const to_date = next.endOf(dateRange).format("YYYY-MM-DD");
|
45
|
+
setFrom(from_date);
|
46
|
+
setTo(to_date);
|
47
|
+
}
|
48
|
+
|
49
|
+
function add(set, date) {
|
50
|
+
if (onAdd) onAdd(date, set);
|
51
|
+
}
|
52
|
+
|
53
|
+
function remove(id) {
|
54
|
+
if (onDelete) onDelete(id);
|
55
|
+
}
|
56
|
+
|
57
|
+
function move(form) {
|
58
|
+
if (onMove) onMove(form);
|
59
|
+
}
|
60
|
+
|
61
|
+
function select({ id, plan }) {
|
62
|
+
if (onSelect) onSelect(plan);
|
63
|
+
}
|
64
|
+
|
65
|
+
const period = useMemo(() => {
|
66
|
+
const start = ranges(from, "YYYY-MM-DD");
|
67
|
+
const end = ranges(to, "YYYY-MM-DD");
|
68
|
+
const range = ranges.range(start, end);
|
69
|
+
const period = Array.from(range.by("day")).map((m) => ({
|
70
|
+
year: m.year(),
|
71
|
+
month: m.month(),
|
72
|
+
day: m.date(),
|
73
|
+
moment: m,
|
74
|
+
}));
|
75
|
+
return period;
|
76
|
+
}, [from, to]);
|
77
|
+
|
78
|
+
const label = <Text use="headline6">{title}</Text>;
|
79
|
+
return (
|
80
|
+
<div className="planner-box">
|
81
|
+
|
82
|
+
{navigation ? (
|
83
|
+
<Header title={label}>
|
84
|
+
<Icon icon="chevron_right" clickable action={next} />
|
85
|
+
<TextField id="to" type="date" label="To" value={to} onChange={(id, value) => setTo(value)} />
|
86
|
+
<div className="expand"></div>
|
87
|
+
<DropDown id="ranges" label="Date Range" options={DATE_RANGE} value={dateRange} onChange={(id, value) => setDateRange(value)} />
|
88
|
+
<div className="expand"></div>
|
89
|
+
<TextField id="from" type="date" label="From" value={from} onChange={(id, value) => setFrom(value)} />
|
90
|
+
<Icon icon="chevron_left" clickable action={prev} />
|
91
|
+
</Header>
|
92
|
+
) : null}
|
93
|
+
|
94
|
+
|
95
|
+
<main className="planner">
|
96
|
+
|
97
|
+
<div className="column0">
|
98
|
+
<div className="column-header"></div>
|
99
|
+
{lanes.map((lane) => (
|
100
|
+
<div className="row-header">
|
101
|
+
{lane.label}
|
102
|
+
</div>
|
103
|
+
))}
|
104
|
+
</div>
|
105
|
+
|
106
|
+
<div className="rows">
|
107
|
+
<div className="row row0">
|
108
|
+
{period.map((date, index) => {
|
109
|
+
const first = index === 0 || date.day === 1 ? "first" : "";
|
110
|
+
return (
|
111
|
+
<div className="column-header">
|
112
|
+
<div className={`month-header ${first}`}>
|
113
|
+
<Text use="overline">{date.moment.format("MMM")}</Text>
|
114
|
+
</div>
|
115
|
+
</div>
|
116
|
+
);
|
117
|
+
})}
|
118
|
+
</div>
|
119
|
+
<div className="row row1">
|
120
|
+
{period.map((date) => {
|
121
|
+
const isWekend = [0, 6].includes(date.moment.day());
|
122
|
+
const weekend = isWekend ? "weekend" : "";
|
123
|
+
return (
|
124
|
+
<div className="column-header">
|
125
|
+
<div className={`date-header ${weekend}`}>
|
126
|
+
<Text use="headline6">{date.moment.format("DD")}</Text>
|
127
|
+
|
128
|
+
<Text use="caption">{date.moment.format("ddd")}</Text>
|
129
|
+
</div>
|
130
|
+
</div>
|
131
|
+
);
|
132
|
+
})}
|
133
|
+
</div>
|
134
|
+
|
135
|
+
{lanes.map((lane) => <PlannerRow lane={lane} events={events} period={period} />)}
|
136
|
+
|
137
|
+
</div>
|
138
|
+
</main>
|
139
|
+
</div>
|
140
|
+
);
|
141
|
+
};
|
142
|
+
|
143
|
+
/**
|
144
|
+
* Planner Row
|
145
|
+
*/
|
146
|
+
const PlannerRow = (props) => {
|
147
|
+
|
148
|
+
const { lane, events = [], period } = props
|
149
|
+
const rowEvents = events.filter(event => event.lane === lane.id)
|
150
|
+
|
151
|
+
return (
|
152
|
+
<div className="row">
|
153
|
+
{period.map((date) => {
|
154
|
+
const slotDate = new Date(date.year, date.month, date.day);
|
155
|
+
slotDate.setHours(0, 0, 0);
|
156
|
+
const cellEvents = rowEvents.filter( event => {
|
157
|
+
const eventDate = new Date(event.date);
|
158
|
+
eventDate.setHours(0, 0, 0);
|
159
|
+
return eventDate.getTime() === slotDate.getTime();
|
160
|
+
})
|
161
|
+
return (
|
162
|
+
<PlannerCell date={date} events={cellEvents}/>
|
163
|
+
);
|
164
|
+
})}
|
165
|
+
</div>
|
166
|
+
)
|
167
|
+
}
|
168
|
+
|
169
|
+
/**
|
170
|
+
* Planner Cell
|
171
|
+
*/
|
172
|
+
const PlannerCell = ({ lane, events, date, disabled = false, onAdd, onDelete, onSelect, onDrop, editable = false }) => {
|
173
|
+
|
174
|
+
const [dragOver, setDragOver] = useState(false);
|
175
|
+
|
176
|
+
function onDragOver(event) {
|
177
|
+
if (!dragOver) setDragOver(true);
|
178
|
+
event.stopPropagation();
|
179
|
+
event.preventDefault();
|
180
|
+
}
|
181
|
+
|
182
|
+
function onDragLeave(event) {
|
183
|
+
setDragOver(false);
|
184
|
+
event.stopPropagation();
|
185
|
+
event.preventDefault();
|
186
|
+
}
|
187
|
+
|
188
|
+
function drop(event) {
|
189
|
+
event.stopPropagation();
|
190
|
+
event.preventDefault();
|
191
|
+
const id = event.dataTransfer.getData("text");
|
192
|
+
if (onDrop)
|
193
|
+
onDrop({
|
194
|
+
id,
|
195
|
+
lane: lane.id,
|
196
|
+
date: date.moment.format("YYYY-MM-DD")
|
197
|
+
});
|
198
|
+
}
|
199
|
+
|
200
|
+
const isWekend = [0, 6].includes(date.moment.day());
|
201
|
+
const weekend = isWekend ? "weekend" : "";
|
202
|
+
|
203
|
+
return (
|
204
|
+
<div className={`cell ${weekend}`} onDragOver={onDragOver} onDragLeave={onDragLeave} onDrop={drop}>
|
205
|
+
c
|
206
|
+
</div>
|
207
|
+
);
|
208
|
+
};
|
@@ -0,0 +1,25 @@
|
|
1
|
+
import React from 'react'
|
2
|
+
import { Planner } from './Planner'
|
3
|
+
|
4
|
+
const PlannerTest = (prop) => {
|
5
|
+
|
6
|
+
const lanes = [
|
7
|
+
{ id: "lane1", label: "Lane 1" },
|
8
|
+
{ id: "lane2", label: "Lane 2" },
|
9
|
+
{ id: "lane3", label: "Lane 3" },
|
10
|
+
{ id: "lane3", label: "Lane 3" },
|
11
|
+
{ id: "lane3", label: "Lane 3" },
|
12
|
+
{ id: "lane3", label: "Lane 3" },
|
13
|
+
{ id: "lane3", label: "Lane 3" },
|
14
|
+
]
|
15
|
+
|
16
|
+
const events = []
|
17
|
+
|
18
|
+
return (
|
19
|
+
|
20
|
+
<Planner title="Planner 1" lanes={lanes} events={events} navigation={true} >
|
21
|
+
|
22
|
+
</Planner>
|
23
|
+
|
24
|
+
)
|
25
|
+
}
|