ywana-core8 0.0.698 → 0.0.700
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/db/db.json +22 -1
- package/dist/index.cjs +31 -27
- package/dist/index.cjs.map +1 -1
- package/dist/index.modern.js +31 -28
- package/dist/index.modern.js.map +1 -1
- package/dist/index.umd.js +31 -27
- package/dist/index.umd.js.map +1 -1
- package/package.json +1 -1
- package/src/domain/CollectionAPI.js +0 -2
- package/src/domain/CollectionPage.js +3 -1
- package/src/domain/CollectionPage2.js +0 -0
- package/src/domain2/CollectionAPI.js +83 -0
- package/src/domain2/CollectionAPI.test.js +19 -0
- package/src/domain2/CollectionContext.js +160 -0
- package/src/domain2/CollectionContext.test.js +58 -0
- package/src/domain2/CollectionEditor.js +17 -0
- package/src/domain2/CollectionFilters.css +28 -0
- package/src/domain2/CollectionFilters.js +69 -0
- package/src/domain2/CollectionList.js +30 -0
- package/src/domain2/CollectionPage.css +36 -0
- package/src/domain2/CollectionPage.js +31 -0
- package/src/domain2/CollectionPage.test.js +88 -0
- package/src/domain2/CollectionQueries.js +10 -0
- package/src/domain2/DynamicForm.css +14 -0
- package/src/domain2/DynamicForm.js +82 -0
- package/src/domain2/DynamicForm.test.js +46 -0
- package/src/domain2/FORMATS.js +1 -1
- package/src/html/index.js +1 -1
- package/src/html/textfield.js +4 -1
- package/src/incubator/task-test.js +2 -10
- package/src/incubator/task.js +7 -5
- package/src/site/site.test.js +9 -8
- package/src/domain2/Content.js +0 -33
- package/src/domain2/ContentFilters.js +0 -74
- package/src/domain2/ContentPage.js +0 -96
package/package.json
CHANGED
@@ -25,7 +25,6 @@ import { isEmpty} from '../commons'
|
|
25
25
|
const paramString = notEmptyFields.reduce((query, key) => {
|
26
26
|
const value = obj[key]
|
27
27
|
const like = likes.includes(key) ? '%' : ''
|
28
|
-
|
29
28
|
if (Array.isArray(value)) {
|
30
29
|
const values = value.map(v => `${key}=${like}${v}${like}`).join("&")
|
31
30
|
return `${query}${values}&`
|
@@ -39,7 +38,6 @@ import { isEmpty} from '../commons'
|
|
39
38
|
return `${query}${key}=${like}${value}${like}&`
|
40
39
|
}
|
41
40
|
}, "")
|
42
|
-
|
43
41
|
return paramString
|
44
42
|
}
|
45
43
|
|
@@ -24,6 +24,7 @@ export const CollectionPage = (props) => {
|
|
24
24
|
autosave = false, delay = 1000, patch = false, versioning = false,
|
25
25
|
groupBy, levels, sorter, namer,
|
26
26
|
editor, editorTitle, editorActions,
|
27
|
+
filters,
|
27
28
|
footer,
|
28
29
|
children
|
29
30
|
} = props
|
@@ -78,7 +79,7 @@ export const CollectionPage = (props) => {
|
|
78
79
|
{renderActions()}
|
79
80
|
</Header>
|
80
81
|
<menu className={`collection-page ${className} ${hiddenStyle}`}>
|
81
|
-
{canFilter ? <CollectionFilters schema={schema} /> : null}
|
82
|
+
{canFilter ? <CollectionFilters schema={schema} initial={filters} /> : null}
|
82
83
|
{levels ? <CollectionTree schema={schema} icon={icon} levels={levels} onSelect={onSelect} sorter={sorter} searchBy={searchBy} namer={namer} /> : <CollectionList groupBy={groupBy} onSelect={onSelect} searchBy={searchBy} />}
|
83
84
|
</menu>
|
84
85
|
<main key={id} className={`collection-page ${className}`}>
|
@@ -97,6 +98,7 @@ export const CollectionPage = (props) => {
|
|
97
98
|
*/
|
98
99
|
export const CollectionFilters = (props) => {
|
99
100
|
|
101
|
+
const [pageContext, setPageContext] = useContext(PageContext)
|
100
102
|
const { schema, initial = {}, onChange } = props
|
101
103
|
const [form, setForm] = useState(initial)
|
102
104
|
const [showFilters, setShowFilters] = useState(false)
|
File without changes
|
@@ -0,0 +1,83 @@
|
|
1
|
+
import { HTTPClient, Session } from '../http'
|
2
|
+
import { isEmpty} from '../commons'
|
3
|
+
|
4
|
+
/**
|
5
|
+
* Collection API
|
6
|
+
*/
|
7
|
+
export const CollectionAPI = (url, host) => {
|
8
|
+
|
9
|
+
const http = HTTPClient(host || window.API || process.env.REACT_APP_API, Session);
|
10
|
+
|
11
|
+
/**
|
12
|
+
* objectToQueryParamString
|
13
|
+
*
|
14
|
+
* @param {*} obj
|
15
|
+
* @returns
|
16
|
+
*/
|
17
|
+
function objectToQueryParamString(obj, likes) {
|
18
|
+
|
19
|
+
if (isEmpty(obj)) {
|
20
|
+
return ""
|
21
|
+
}
|
22
|
+
|
23
|
+
const notEmptyFields = Object.keys(obj).filter(key => !isEmpty(obj[key]))
|
24
|
+
|
25
|
+
const paramString = notEmptyFields.reduce((query, key) => {
|
26
|
+
const value = obj[key]
|
27
|
+
const like = likes.includes(key) ? '%' : ''
|
28
|
+
if (Array.isArray(value)) {
|
29
|
+
const values = value.map(v => `${key}=${like}${v}${like}`).join("&")
|
30
|
+
return `${query}${values}&`
|
31
|
+
} else if (typeof value === "object") {
|
32
|
+
const params = objectToQueryParamString(value, likes)
|
33
|
+
params.split("&").forEach(param => {
|
34
|
+
query = query.concat(`${key}.${param}&`)
|
35
|
+
})
|
36
|
+
return query
|
37
|
+
} else {
|
38
|
+
return `${query}${key}=${like}${value}${like}&`
|
39
|
+
}
|
40
|
+
}, "")
|
41
|
+
return paramString
|
42
|
+
}
|
43
|
+
|
44
|
+
return {
|
45
|
+
|
46
|
+
all(filters, likes = [], page) {
|
47
|
+
let queryParams = page ? `?page=${page}&` : "?"
|
48
|
+
const filterQuery = objectToQueryParamString(filters, likes)
|
49
|
+
queryParams = `${queryParams}${filterQuery}`
|
50
|
+
queryParams = queryParams.substring(0, queryParams.length - 1)
|
51
|
+
return http.GET(`${url}${queryParams}`)
|
52
|
+
},
|
53
|
+
|
54
|
+
find(id) {
|
55
|
+
return http.GET(`${url}/${id}`)
|
56
|
+
},
|
57
|
+
|
58
|
+
create(form) {
|
59
|
+
const body = JSON.stringify(form)
|
60
|
+
return http.POST(url, body)
|
61
|
+
},
|
62
|
+
|
63
|
+
update(form) {
|
64
|
+
const body = JSON.stringify(form)
|
65
|
+
return http.PUT(`${url}/${form.id}`, body)
|
66
|
+
},
|
67
|
+
|
68
|
+
updateProperty(id, propertyName, form) {
|
69
|
+
const body = JSON.stringify(form)
|
70
|
+
return http.PUT(`${url}/${id}/${propertyName}`, body)
|
71
|
+
},
|
72
|
+
|
73
|
+
patch(id, form) {
|
74
|
+
const body = JSON.stringify(form)
|
75
|
+
return http.PATCH(`${url}/${id}`, body)
|
76
|
+
},
|
77
|
+
|
78
|
+
remove(id) {
|
79
|
+
return http.DELETE(`${url}/${id}`)
|
80
|
+
},
|
81
|
+
|
82
|
+
}
|
83
|
+
}
|
@@ -0,0 +1,19 @@
|
|
1
|
+
import React, { useState } from 'react'
|
2
|
+
import { Button } from '../html'
|
3
|
+
|
4
|
+
import { CollectionAPI } from './CollectionAPI'
|
5
|
+
|
6
|
+
const CollectionAPITest = (prop) => {
|
7
|
+
|
8
|
+
const API = CollectionAPI('/references', 'http://localhost:3000')
|
9
|
+
|
10
|
+
function all() {
|
11
|
+
API.all({ name: "2223"}, ["name"]).then(res => console.log(res))
|
12
|
+
}
|
13
|
+
|
14
|
+
return (
|
15
|
+
<>
|
16
|
+
<Button label="ALL" action={all} />
|
17
|
+
</>
|
18
|
+
)
|
19
|
+
}
|
@@ -0,0 +1,160 @@
|
|
1
|
+
import React, { useState } from 'react'
|
2
|
+
import { CollectionAPI } from "./CollectionAPI";
|
3
|
+
|
4
|
+
export const CollectionContext = React.createContext()
|
5
|
+
|
6
|
+
/**
|
7
|
+
* Collection Context
|
8
|
+
*/
|
9
|
+
export const CollectionContextProvider = (props) => {
|
10
|
+
|
11
|
+
const { host, url, page, fetching=true, field, versioning = false, children } = props
|
12
|
+
const API = CollectionAPI(url, host)
|
13
|
+
|
14
|
+
const [all, setAll] = useState([])
|
15
|
+
const [filters, setFilters] = useState({})
|
16
|
+
const [likes, setLikes] = useState([])
|
17
|
+
const [customFilters, setCustomFilters] = useState({})
|
18
|
+
const [queries, setQueries] = useState([])
|
19
|
+
const [selected, setSelected] = useState(null)
|
20
|
+
|
21
|
+
async function load() {
|
22
|
+
|
23
|
+
const runCustomFilters = (all) => {
|
24
|
+
const cfs = Object.values(customFilters)
|
25
|
+
const data = cfs.length ? cfs.reduce((acc, filter) => filter(acc), all) : all;
|
26
|
+
return data
|
27
|
+
}
|
28
|
+
|
29
|
+
try {
|
30
|
+
const response = await API.all(filters, likes, page);
|
31
|
+
const next = field ? response[field] : response;
|
32
|
+
const data = runCustomFilters(next)
|
33
|
+
setAll(data)
|
34
|
+
} catch (error) {
|
35
|
+
console.log(error)
|
36
|
+
}
|
37
|
+
return
|
38
|
+
}
|
39
|
+
|
40
|
+
async function select(id) {
|
41
|
+
if (fetching) {
|
42
|
+
const result = await this.fetch(id)
|
43
|
+
setSelected(result)
|
44
|
+
} else {
|
45
|
+
const result = this.all.find(item => item.id === id);
|
46
|
+
setSelected(result)
|
47
|
+
}
|
48
|
+
}
|
49
|
+
|
50
|
+
function addCustomFilter(id, filter) {
|
51
|
+
setCustomFilters({ ...customFilters, [id]: filter })
|
52
|
+
}
|
53
|
+
|
54
|
+
function removeCustomFilter(id) {
|
55
|
+
const next = { ...customFilters }
|
56
|
+
delete next[id]
|
57
|
+
setCustomFilters(next)
|
58
|
+
}
|
59
|
+
|
60
|
+
/*
|
61
|
+
async function reloadSelection() {
|
62
|
+
const result = await this.fetch(this.selected.id)
|
63
|
+
this.selected = result
|
64
|
+
}
|
65
|
+
|
66
|
+
async function fetch(id) {
|
67
|
+
try {
|
68
|
+
const result = await API.find(id)
|
69
|
+
return result
|
70
|
+
} catch (error) {
|
71
|
+
console.log(error)
|
72
|
+
}
|
73
|
+
}
|
74
|
+
|
75
|
+
function clear() {
|
76
|
+
this.selected = null
|
77
|
+
}
|
78
|
+
|
79
|
+
async function create(form) {
|
80
|
+
try {
|
81
|
+
if (versioning) form.version = 1
|
82
|
+
await API.create(form);
|
83
|
+
await this.load();
|
84
|
+
} catch (error) {
|
85
|
+
console.log(error)
|
86
|
+
}
|
87
|
+
return
|
88
|
+
}
|
89
|
+
|
90
|
+
async function update(form) {
|
91
|
+
try {
|
92
|
+
if (versioning) form.version = form.version ? form.version + 1 : 1
|
93
|
+
await API.update(form)
|
94
|
+
await this.load()
|
95
|
+
} catch (error) {
|
96
|
+
console.log(error)
|
97
|
+
}
|
98
|
+
return
|
99
|
+
}
|
100
|
+
|
101
|
+
async function patch(id, form) {
|
102
|
+
try {
|
103
|
+
if (versioning) form.version = form.version ? form.version + 1 : 1
|
104
|
+
await API.patch(id, form)
|
105
|
+
await this.load()
|
106
|
+
} catch (error) {
|
107
|
+
console.log(error)
|
108
|
+
}
|
109
|
+
return
|
110
|
+
}
|
111
|
+
|
112
|
+
async function updateProperty(id, propertyName, form) {
|
113
|
+
try {
|
114
|
+
await API.updateProperty(id, propertyName, form)
|
115
|
+
await this.load()
|
116
|
+
} catch (error) {
|
117
|
+
console.log(error)
|
118
|
+
}
|
119
|
+
return
|
120
|
+
}
|
121
|
+
|
122
|
+
async function remove(id) {
|
123
|
+
try {
|
124
|
+
await API.remove(id)
|
125
|
+
await this.load()
|
126
|
+
} catch (error) {
|
127
|
+
console.log(error)
|
128
|
+
}
|
129
|
+
return
|
130
|
+
}
|
131
|
+
|
132
|
+
*/
|
133
|
+
|
134
|
+
const value = {
|
135
|
+
all,
|
136
|
+
load,
|
137
|
+
|
138
|
+
selected,
|
139
|
+
select,
|
140
|
+
|
141
|
+
filters,
|
142
|
+
setFilters,
|
143
|
+
setLikes,
|
144
|
+
|
145
|
+
customFilters,
|
146
|
+
addCustomFilter,
|
147
|
+
removeCustomFilter,
|
148
|
+
|
149
|
+
queries,
|
150
|
+
setQueries,
|
151
|
+
|
152
|
+
}
|
153
|
+
|
154
|
+
return (
|
155
|
+
< CollectionContext.Provider value = { value } >
|
156
|
+
{ children }
|
157
|
+
</CollectionContext.Provider >
|
158
|
+
)
|
159
|
+
}
|
160
|
+
|
@@ -0,0 +1,58 @@
|
|
1
|
+
import React, { useContext } from 'react'
|
2
|
+
import { CheckBox } from '../html'
|
3
|
+
import { CollectionContext, CollectionContextProvider } from './CollectionContext'
|
4
|
+
import { CollectionEditor } from './CollectionEditor'
|
5
|
+
import { CollectionFilters } from './CollectionFilters'
|
6
|
+
import { CollectionList } from './CollectionList'
|
7
|
+
|
8
|
+
const CollectionContextTest = (props) => {
|
9
|
+
|
10
|
+
const config = {
|
11
|
+
host: "http://localhost:3000",
|
12
|
+
url: "/references",
|
13
|
+
}
|
14
|
+
|
15
|
+
const style = {
|
16
|
+
display: "flex",
|
17
|
+
flexDirection: "row",
|
18
|
+
}
|
19
|
+
|
20
|
+
const schema = [
|
21
|
+
{ id: "id", type: "string", label: "ID" },
|
22
|
+
{ id: "name", type: "string", label: "Name", filter: true, like: true },
|
23
|
+
{ id: "gender", type: "string", label: "Gender", filter: true, options: [
|
24
|
+
{ label: "Masculine", value: 1 },
|
25
|
+
{ label: "Feminine", value: 0 }
|
26
|
+
]},
|
27
|
+
{ id: "description", type: "string", label: "Description" },
|
28
|
+
]
|
29
|
+
|
30
|
+
return (
|
31
|
+
<div style={style}>
|
32
|
+
<CollectionContextProvider {...config}>
|
33
|
+
<CollectionFilters schema={schema} >
|
34
|
+
<CustomFilter1 />
|
35
|
+
</CollectionFilters>
|
36
|
+
<CollectionList />
|
37
|
+
<CollectionEditor />
|
38
|
+
</CollectionContextProvider>
|
39
|
+
</div>
|
40
|
+
|
41
|
+
)
|
42
|
+
}
|
43
|
+
|
44
|
+
const CustomFilter1 = (props) => {
|
45
|
+
const collectionContext = useContext(CollectionContext)
|
46
|
+
const { filters, setFilters } = collectionContext
|
47
|
+
|
48
|
+
function change(id, value) {
|
49
|
+
setFilters({ ...filters, [id]: value })
|
50
|
+
}
|
51
|
+
|
52
|
+
return (
|
53
|
+
<div>
|
54
|
+
<CheckBox id="custom1" label="Custom Filter 1" value={filters.custom1} onChange={change} />
|
55
|
+
</div>
|
56
|
+
)
|
57
|
+
}
|
58
|
+
|
@@ -0,0 +1,17 @@
|
|
1
|
+
import React, { useContext } from 'react'
|
2
|
+
import { CollectionContext } from './CollectionContext'
|
3
|
+
|
4
|
+
/**
|
5
|
+
* Collection Editor
|
6
|
+
*/
|
7
|
+
export const CollectionEditor = (props) => {
|
8
|
+
|
9
|
+
const context = useContext(CollectionContext)
|
10
|
+
const { selected } = context
|
11
|
+
|
12
|
+
return (
|
13
|
+
<div className="collection-editor">
|
14
|
+
editor
|
15
|
+
</div>
|
16
|
+
)
|
17
|
+
}
|
@@ -0,0 +1,28 @@
|
|
1
|
+
.collection-filters {
|
2
|
+
display: flex;
|
3
|
+
flex-direction: column;
|
4
|
+
width: 30rem;
|
5
|
+
background-color: rgb(237, 237, 237);
|
6
|
+
}
|
7
|
+
|
8
|
+
.collection-filters>header {
|
9
|
+
display: flex;
|
10
|
+
flex-direction: row;
|
11
|
+
justify-content: space-between;
|
12
|
+
align-items: center;
|
13
|
+
border-bottom: 1px solid rgb(207, 207, 207);
|
14
|
+
}
|
15
|
+
|
16
|
+
.custom-filters {
|
17
|
+
display: flex;
|
18
|
+
flex-direction: row;
|
19
|
+
justify-content: space-between;
|
20
|
+
align-items: center;
|
21
|
+
padding: 0.5rem;
|
22
|
+
}
|
23
|
+
|
24
|
+
.dynamic-filters {
|
25
|
+
display: flex;
|
26
|
+
flex-direction: column;
|
27
|
+
padding: 0 0 1rem 0;
|
28
|
+
}
|
@@ -0,0 +1,69 @@
|
|
1
|
+
import React, { useContext, useEffect, useState } from 'react'
|
2
|
+
import { Icon, Tooltip } from '../html'
|
3
|
+
import { CollectionContext } from './CollectionContext'
|
4
|
+
import { DynamicForm } from './DynamicForm'
|
5
|
+
import './CollectionFilters.css'
|
6
|
+
|
7
|
+
/*.
|
8
|
+
* Collection Filters
|
9
|
+
*/
|
10
|
+
export const CollectionFilters = (props) => {
|
11
|
+
|
12
|
+
const { schema, children } = props
|
13
|
+
const context = useContext(CollectionContext)
|
14
|
+
const { filters } = context
|
15
|
+
const [open, setOpen] = useState(false)
|
16
|
+
|
17
|
+
useEffect(() => {
|
18
|
+
context.setLikes(schema.filter(field => field.like).map(field => field.id))
|
19
|
+
}, [schema])
|
20
|
+
|
21
|
+
function change(id, value) {
|
22
|
+
context.setFilters({ ...filters, [id]: value })
|
23
|
+
}
|
24
|
+
|
25
|
+
function toggle() {
|
26
|
+
setOpen(!open)
|
27
|
+
}
|
28
|
+
|
29
|
+
const toggleIcon = open ? "expand_less" : "expand_more"
|
30
|
+
return (
|
31
|
+
<div className="collection-filters">
|
32
|
+
<header>
|
33
|
+
<div className='custom-filters'>
|
34
|
+
{children}
|
35
|
+
</div>
|
36
|
+
<CollectionFiltersResume schema={schema} />
|
37
|
+
<Icon icon={toggleIcon} clickable action={toggle} />
|
38
|
+
</header>
|
39
|
+
{ open ? <div className='dynamic-filters'>
|
40
|
+
<DynamicForm schema={schema} values={filters} onChange={change} />
|
41
|
+
</div> : null }
|
42
|
+
</div>
|
43
|
+
)
|
44
|
+
}
|
45
|
+
|
46
|
+
const CollectionFiltersResume = (props) => {
|
47
|
+
|
48
|
+
const { schema } = props
|
49
|
+
const context = useContext(CollectionContext)
|
50
|
+
const { filters } = context
|
51
|
+
const fields = Object.keys(filters)
|
52
|
+
|
53
|
+
if (!fields.length) return null
|
54
|
+
|
55
|
+
return (
|
56
|
+
<>
|
57
|
+
{fields.map(id => {
|
58
|
+
const field = schema.find(field => field.id === id)
|
59
|
+
const value = filters[id]
|
60
|
+
return (
|
61
|
+
<div className='collection-filter-resume'>
|
62
|
+
<span className='collection-filter-resume-label'>{field.label}</span>
|
63
|
+
<span className='collection-filter-resume-value'>{value}</span>
|
64
|
+
</div>
|
65
|
+
)
|
66
|
+
})}
|
67
|
+
</>
|
68
|
+
)
|
69
|
+
}
|
@@ -0,0 +1,30 @@
|
|
1
|
+
import React, { useContext, useEffect } from 'react'
|
2
|
+
import { List } from '../html'
|
3
|
+
import { CollectionContext } from './CollectionContext'
|
4
|
+
|
5
|
+
/**
|
6
|
+
* Collection List
|
7
|
+
*/
|
8
|
+
export const CollectionList = (props) => {
|
9
|
+
|
10
|
+
const context = useContext(CollectionContext)
|
11
|
+
const { all = [], selected, filters, customFilters } = context
|
12
|
+
|
13
|
+
useEffect(() => {
|
14
|
+
context.load()
|
15
|
+
}, [filters, customFilters])
|
16
|
+
|
17
|
+
const items = all.map(item => {
|
18
|
+
return {
|
19
|
+
icon: "folder",
|
20
|
+
line1: item.name,
|
21
|
+
meta: item.state,
|
22
|
+
}
|
23
|
+
})
|
24
|
+
|
25
|
+
return (
|
26
|
+
<div className="collection-list">
|
27
|
+
<List items={items} />
|
28
|
+
</div>
|
29
|
+
)
|
30
|
+
}
|
@@ -0,0 +1,36 @@
|
|
1
|
+
.collection-page.ide {
|
2
|
+
display: grid;
|
3
|
+
grid-template-areas: "header header"
|
4
|
+
"filters main"
|
5
|
+
"list main";
|
6
|
+
grid-template-columns: auto 1fr;
|
7
|
+
grid-template-rows: auto auto 1fr;
|
8
|
+
}
|
9
|
+
|
10
|
+
.collection-page.ide .header {
|
11
|
+
grid-area: header;
|
12
|
+
}
|
13
|
+
|
14
|
+
.collection-page.ide .collection-filters {
|
15
|
+
grid-area: filters;
|
16
|
+
}
|
17
|
+
|
18
|
+
.collection-page.ide .collection-editor {
|
19
|
+
grid-area: main;
|
20
|
+
}
|
21
|
+
|
22
|
+
.collection-page.ide .collection-aside {
|
23
|
+
grid-area: aside;
|
24
|
+
}
|
25
|
+
|
26
|
+
.collection-page.ide .collection-list {
|
27
|
+
grid-area: list;
|
28
|
+
}
|
29
|
+
|
30
|
+
.collection-page.ide .collection-console {
|
31
|
+
grid-area: console;
|
32
|
+
}
|
33
|
+
|
34
|
+
.collection-page.ide .footer {
|
35
|
+
grid-area: footer;
|
36
|
+
}
|
@@ -0,0 +1,31 @@
|
|
1
|
+
import React from 'react'
|
2
|
+
import { CollectionContextProvider } from './CollectionContext'
|
3
|
+
import { CollectionFilters } from './CollectionFilters'
|
4
|
+
import { CollectionList } from './CollectionList'
|
5
|
+
import { CollectionEditor } from './CollectionEditor'
|
6
|
+
import './CollectionPage.css'
|
7
|
+
import { Header } from '../html'
|
8
|
+
|
9
|
+
/**
|
10
|
+
* Collection Page
|
11
|
+
*/
|
12
|
+
export const CollectionPage = (props) => {
|
13
|
+
|
14
|
+
const {
|
15
|
+
host, url, schema,
|
16
|
+
layout,
|
17
|
+
canFilter, customFilters
|
18
|
+
} = props
|
19
|
+
|
20
|
+
return (
|
21
|
+
<div className={`collection-page ${layout}`}>
|
22
|
+
<CollectionContextProvider host={host} url={url}>
|
23
|
+
<Header title="CollectionPage" />
|
24
|
+
{canFilter ? <CollectionFilters schema={schema} >{customFilters}</CollectionFilters> : null}
|
25
|
+
<CollectionList />
|
26
|
+
<CollectionEditor />
|
27
|
+
</CollectionContextProvider>
|
28
|
+
</div>
|
29
|
+
|
30
|
+
)
|
31
|
+
}
|
@@ -0,0 +1,88 @@
|
|
1
|
+
import React, { useContext, useEffect, useState } from 'react'
|
2
|
+
import { CheckBox } from '../html'
|
3
|
+
import { CollectionContext } from './CollectionContext'
|
4
|
+
import { CollectionPage } from './CollectionPage'
|
5
|
+
|
6
|
+
const CollectionPageTest = (prop) => {
|
7
|
+
|
8
|
+
const schema = [
|
9
|
+
{ id: "id", type: "string", label: "ID" },
|
10
|
+
{ id: "name", type: "string", label: "Name", filter: true },
|
11
|
+
{ id: "gender", type: "string", label: "Gender", filter: true, options: [
|
12
|
+
{ label: "Masculine", value: 1 },
|
13
|
+
{ label: "Feminine", value: 0 }
|
14
|
+
]},
|
15
|
+
]
|
16
|
+
|
17
|
+
const props = {
|
18
|
+
host: "http://localhost:3000",
|
19
|
+
url: "/references",
|
20
|
+
schema,
|
21
|
+
layout: "ide",
|
22
|
+
canFilter: true,
|
23
|
+
customFilters: [<CustomFilter1 />,<CustomFilter2 />]
|
24
|
+
}
|
25
|
+
|
26
|
+
return (
|
27
|
+
<>
|
28
|
+
<CollectionPage {...props} />
|
29
|
+
</>
|
30
|
+
)
|
31
|
+
}
|
32
|
+
|
33
|
+
const CustomFilter1 = (props) => {
|
34
|
+
|
35
|
+
const context = useContext(CollectionContext)
|
36
|
+
const [active, setActive] = useState(false)
|
37
|
+
|
38
|
+
useEffect(() => {
|
39
|
+
if (active) {
|
40
|
+
context.addCustomFilter("custom1", filter)
|
41
|
+
} else {
|
42
|
+
context.removeCustomFilter("custom1")
|
43
|
+
}
|
44
|
+
}, [active])
|
45
|
+
|
46
|
+
function change(id, value) {
|
47
|
+
setActive(value)
|
48
|
+
}
|
49
|
+
|
50
|
+
function filter(all) {
|
51
|
+
return all.filter(item => {
|
52
|
+
return item.name.startsWith("1")
|
53
|
+
})
|
54
|
+
}
|
55
|
+
|
56
|
+
return (
|
57
|
+
<CheckBox id="custom1" value={active} label="Active" onChange={change}/>
|
58
|
+
)
|
59
|
+
}
|
60
|
+
|
61
|
+
const CustomFilter2 = (props) => {
|
62
|
+
|
63
|
+
const { value = false } = props
|
64
|
+
const context = useContext(CollectionContext)
|
65
|
+
const [active, setActive] = useState(value)
|
66
|
+
|
67
|
+
useEffect(() => {
|
68
|
+
if (active) {
|
69
|
+
context.addCustomFilter("custom2", filter)
|
70
|
+
} else {
|
71
|
+
context.removeCustomFilter("custom2")
|
72
|
+
}
|
73
|
+
}, [active])
|
74
|
+
|
75
|
+
function change(id, value) {
|
76
|
+
setActive(value)
|
77
|
+
}
|
78
|
+
|
79
|
+
function filter(all) {
|
80
|
+
return all.filter(item => {
|
81
|
+
return item.name.endsWith("1")
|
82
|
+
})
|
83
|
+
}
|
84
|
+
|
85
|
+
return (
|
86
|
+
<CheckBox id="custom1" value={active} label="Locked" onChange={change}/>
|
87
|
+
)
|
88
|
+
}
|