proje-react-panel 1.5.0 → 1.6.0
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/components/list/cells/BooleanCell.d.ts +5 -2
- package/dist/components/list/cells/DateCell.d.ts +5 -2
- package/dist/components/list/cells/DefaultCell.d.ts +3 -2
- package/dist/components/list/cells/DownloadCell.d.ts +3 -2
- package/dist/components/list/cells/ImageCell.d.ts +3 -2
- package/dist/components/list/cells/UUIDCell.d.ts +5 -2
- package/dist/decorators/list/Cell.d.ts +4 -0
- package/dist/decorators/list/List.d.ts +7 -2
- package/dist/index.cjs.js +1 -1
- package/dist/index.esm.js +1 -1
- package/package.json +1 -1
- package/src/components/list/CellField.tsx +19 -10
- package/src/components/list/Datagrid.tsx +26 -12
- package/src/components/list/cells/BooleanCell.tsx +7 -2
- package/src/components/list/cells/DateCell.tsx +6 -2
- package/src/components/list/cells/DefaultCell.tsx +4 -4
- package/src/components/list/cells/DownloadCell.tsx +4 -2
- package/src/components/list/cells/ImageCell.tsx +4 -2
- package/src/components/list/cells/LinkCell.tsx +3 -2
- package/src/components/list/cells/UUIDCell.tsx +6 -2
- package/src/decorators/list/Cell.ts +4 -0
- package/src/decorators/list/List.ts +3 -2
- package/src/store/store.ts +1 -1
- package/src/styles/components/button.scss +14 -0
- package/src/styles/index.scss +1 -1
- package/src/styles/list.scss +8 -1
@@ -20,31 +20,40 @@ export function CellField<T extends AnyClass>({
|
|
20
20
|
}: CellFieldProps<T>): React.ReactElement {
|
21
21
|
let render;
|
22
22
|
|
23
|
-
const value = item[configuration.name];
|
24
|
-
|
25
23
|
switch (configuration.type) {
|
26
24
|
case 'boolean':
|
27
|
-
render = <BooleanCell
|
25
|
+
render = <BooleanCell item={item} configuration={configuration} />;
|
28
26
|
break;
|
29
27
|
case 'date':
|
30
|
-
render = <DateCell
|
28
|
+
render = <DateCell item={item} configuration={configuration} />;
|
31
29
|
break;
|
32
30
|
case 'image':
|
33
|
-
render = <ImageCell
|
31
|
+
render = <ImageCell item={item} configuration={configuration} />;
|
34
32
|
break;
|
35
33
|
case 'uuid':
|
36
|
-
render = <UUIDCell
|
34
|
+
render = <UUIDCell item={item} configuration={configuration} />;
|
37
35
|
break;
|
38
36
|
case 'download':
|
39
|
-
render = <DownloadCell
|
37
|
+
render = <DownloadCell item={item} configuration={configuration} />;
|
40
38
|
break;
|
41
39
|
case 'link':
|
42
40
|
render = <LinkCell item={item} configuration={configuration} />;
|
43
41
|
break;
|
44
42
|
default:
|
45
|
-
render = <DefaultCell
|
43
|
+
render = <DefaultCell item={item} configuration={configuration} />;
|
46
44
|
break;
|
47
45
|
}
|
48
|
-
|
49
|
-
|
46
|
+
const width = configuration.style?.width;
|
47
|
+
const minWidth = configuration.style?.minWidth;
|
48
|
+
return (
|
49
|
+
<td
|
50
|
+
key={configuration.name}
|
51
|
+
style={{
|
52
|
+
minWidth,
|
53
|
+
width,
|
54
|
+
}}
|
55
|
+
>
|
56
|
+
{render}
|
57
|
+
</td>
|
58
|
+
);
|
50
59
|
}
|
@@ -24,10 +24,10 @@ export function Datagrid<T extends AnyClass>({
|
|
24
24
|
}: DatagridProps<T>) {
|
25
25
|
const cells = listPageMeta.cells;
|
26
26
|
const listData = useAppStore(state => state.listData[listPageMeta.class.key]);
|
27
|
-
const
|
28
|
-
? typeof listPageMeta.class.
|
29
|
-
? listPageMeta.class.
|
30
|
-
: listPageMeta.class.
|
27
|
+
const listActions = data?.[0]
|
28
|
+
? typeof listPageMeta.class.actions === 'function'
|
29
|
+
? listPageMeta.class.actions?.(data[0])
|
30
|
+
: listPageMeta.class.actions
|
31
31
|
: null;
|
32
32
|
|
33
33
|
return (
|
@@ -39,20 +39,27 @@ export function Datagrid<T extends AnyClass>({
|
|
39
39
|
<thead>
|
40
40
|
<tr>
|
41
41
|
{cells.map(cellOptions => (
|
42
|
-
<th
|
42
|
+
<th
|
43
|
+
key={cellOptions.name}
|
44
|
+
style={{ width: cellOptions.style?.width, minWidth: cellOptions.style?.minWidth }}
|
45
|
+
>
|
46
|
+
{cellOptions.title ?? cellOptions.name}
|
47
|
+
</th>
|
43
48
|
))}
|
44
|
-
{(
|
45
|
-
|
46
|
-
|
49
|
+
{(listActions?.details ||
|
50
|
+
listActions?.edit ||
|
51
|
+
listActions?.delete ||
|
52
|
+
listActions?.customActions?.length) && <th style={{ width: '30px' }}>Actions</th>}
|
47
53
|
</tr>
|
48
54
|
</thead>
|
49
55
|
<tbody>
|
50
56
|
{data.map((item, index) => {
|
51
57
|
const listCells = item
|
52
|
-
? typeof listPageMeta.class.
|
53
|
-
? listPageMeta.class.
|
54
|
-
: listPageMeta.class.
|
58
|
+
? typeof listPageMeta.class.actions === 'function'
|
59
|
+
? listPageMeta.class.actions?.(item)
|
60
|
+
: listPageMeta.class.actions
|
55
61
|
: null;
|
62
|
+
//TODO: memoize this
|
56
63
|
const listDataItem = listPageMeta.class.primaryId
|
57
64
|
? (listData?.[item[listPageMeta.class.primaryId!] as string] as
|
58
65
|
| Record<string, unknown>
|
@@ -73,7 +80,7 @@ export function Datagrid<T extends AnyClass>({
|
|
73
80
|
);
|
74
81
|
})}
|
75
82
|
{(listCells?.details || listCells?.edit || listCells?.delete) && (
|
76
|
-
<td>
|
83
|
+
<td style={{ width: '30px' }}>
|
77
84
|
<div className="util-cell-actions">
|
78
85
|
<p className="util-cell-actions-label">
|
79
86
|
Actions <DownArrowIcon className="icon icon-down" />
|
@@ -118,6 +125,13 @@ export function Datagrid<T extends AnyClass>({
|
|
118
125
|
</a>
|
119
126
|
</li>
|
120
127
|
)}
|
128
|
+
{listCells?.customActions?.map(action => (
|
129
|
+
<li key={action.label}>
|
130
|
+
<a onClick={() => action.onClick(item)} className="util-cell-link">
|
131
|
+
<span className="util-cell-label">{action.label}</span>
|
132
|
+
</a>
|
133
|
+
</li>
|
134
|
+
))}
|
121
135
|
</ul>
|
122
136
|
</div>
|
123
137
|
</td>
|
@@ -1,12 +1,17 @@
|
|
1
1
|
import React from 'react';
|
2
2
|
import CheckIcon from '../../../assets/icons/svg/check.svg';
|
3
3
|
import CrossIcon from '../../../assets/icons/svg/cross.svg';
|
4
|
+
import { AnyClass } from '../../../types/AnyClass';
|
5
|
+
import { CellConfiguration } from '../../../decorators/list/Cell';
|
4
6
|
|
5
7
|
interface BooleanCellProps {
|
6
|
-
|
8
|
+
item: AnyClass;
|
9
|
+
configuration: CellConfiguration;
|
7
10
|
}
|
8
11
|
|
9
|
-
export function BooleanCell({
|
12
|
+
export function BooleanCell({ item, configuration }: BooleanCellProps) {
|
13
|
+
const value = item[configuration.name];
|
14
|
+
|
10
15
|
return value ? (
|
11
16
|
<CheckIcon className="icon icon-true" />
|
12
17
|
) : (
|
@@ -1,10 +1,14 @@
|
|
1
1
|
import React from 'react';
|
2
|
+
import { AnyClass } from '../../../types/AnyClass';
|
3
|
+
import { CellConfiguration } from '../../../decorators/list/Cell';
|
2
4
|
|
3
5
|
interface DateCellProps {
|
4
|
-
|
6
|
+
item: AnyClass;
|
7
|
+
configuration: CellConfiguration;
|
5
8
|
}
|
6
9
|
|
7
|
-
export function DateCell({
|
10
|
+
export function DateCell({ item, configuration }: DateCellProps) {
|
11
|
+
const value = item[configuration.name];
|
8
12
|
if (!value) return <>-</>;
|
9
13
|
|
10
14
|
const date = new Date(value);
|
@@ -1,13 +1,13 @@
|
|
1
1
|
import React from 'react';
|
2
2
|
import { CellConfiguration } from '../../../decorators/list/Cell';
|
3
|
+
import { AnyClass } from '../../../types/AnyClass';
|
3
4
|
|
4
5
|
interface DefaultCellProps {
|
5
|
-
|
6
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
7
|
-
value: any;
|
6
|
+
item: AnyClass;
|
8
7
|
configuration: CellConfiguration;
|
9
8
|
}
|
10
9
|
|
11
|
-
export function DefaultCell({
|
10
|
+
export function DefaultCell({ item, configuration }: DefaultCellProps): React.ReactElement {
|
11
|
+
const value = item[configuration.name];
|
12
12
|
return <>{value ? value.toString() : configuration.placeHolder}</>;
|
13
13
|
}
|
@@ -1,13 +1,15 @@
|
|
1
1
|
import React from 'react';
|
2
2
|
import { CellConfiguration } from '../../../decorators/list/Cell';
|
3
3
|
import { DownloadCellConfiguration } from '../../../decorators/list/cells/DownloadCell';
|
4
|
+
import { AnyClass } from '../../../types/AnyClass';
|
4
5
|
|
5
6
|
interface DownloadCellProps {
|
6
|
-
|
7
|
+
item: AnyClass;
|
7
8
|
configuration: CellConfiguration;
|
8
9
|
}
|
9
10
|
|
10
|
-
export function DownloadCell({
|
11
|
+
export function DownloadCell({ item, configuration }: DownloadCellProps): React.ReactElement {
|
12
|
+
const value = item[configuration.name];
|
11
13
|
if (!value) return <>-</>;
|
12
14
|
|
13
15
|
const downloadConfiguration = configuration as DownloadCellConfiguration;
|
@@ -1,14 +1,16 @@
|
|
1
1
|
import React from 'react';
|
2
2
|
import { CellConfiguration } from '../../../decorators/list/Cell';
|
3
3
|
import { ImageCellConfiguration } from '../../../decorators/list/cells/ImageCell';
|
4
|
+
import { AnyClass } from '../../../types/AnyClass';
|
4
5
|
|
5
6
|
interface ImageCellProps {
|
6
|
-
|
7
|
+
item: AnyClass;
|
7
8
|
configuration: CellConfiguration;
|
8
9
|
}
|
9
10
|
|
10
|
-
export function ImageCell({
|
11
|
+
export function ImageCell({ item, configuration }: ImageCellProps) {
|
11
12
|
const imageConfiguration = configuration as ImageCellConfiguration;
|
13
|
+
const value = item[configuration.name];
|
12
14
|
if (!value) return <>-</>;
|
13
15
|
|
14
16
|
return (
|
@@ -15,13 +15,14 @@ export function LinkCell<T>({ item, configuration }: LinkCellProps<T>) {
|
|
15
15
|
return (
|
16
16
|
<Link to={linkConfiguration.path ?? linkConfiguration.url ?? ''}>
|
17
17
|
{linkConfiguration.onClick ? (
|
18
|
-
<
|
18
|
+
<a
|
19
|
+
className="util-cell-link"
|
19
20
|
onClick={() => {
|
20
21
|
linkConfiguration.onClick?.(item as T);
|
21
22
|
}}
|
22
23
|
>
|
23
24
|
{value?.toString()}
|
24
|
-
</
|
25
|
+
</a>
|
25
26
|
) : (
|
26
27
|
value?.toString() || linkConfiguration.placeHolder
|
27
28
|
)}
|
@@ -1,10 +1,14 @@
|
|
1
1
|
import React from 'react';
|
2
|
+
import { AnyClass } from '../../../types/AnyClass';
|
3
|
+
import { CellConfiguration } from '../../../decorators/list/Cell';
|
2
4
|
|
3
5
|
interface UUIDCellProps {
|
4
|
-
|
6
|
+
item: AnyClass;
|
7
|
+
configuration: CellConfiguration;
|
5
8
|
}
|
6
9
|
|
7
|
-
export function UUIDCell({
|
10
|
+
export function UUIDCell({ item, configuration }: UUIDCellProps) {
|
11
|
+
const value = item[configuration.name];
|
8
12
|
if (!value || typeof value !== 'string' || value.length < 6) return <>-</>;
|
9
13
|
|
10
14
|
return <>{`${value.slice(0, 3)}...${value.slice(-3)}`}</>;
|
@@ -22,6 +22,10 @@ export interface CellOptions {
|
|
22
22
|
type?: CellTypes;
|
23
23
|
placeHolder?: string;
|
24
24
|
filter?: Filter | StaticSelectFilter;
|
25
|
+
style?: {
|
26
|
+
minWidth?: string;
|
27
|
+
width?: string;
|
28
|
+
};
|
25
29
|
}
|
26
30
|
|
27
31
|
export interface CellConfiguration extends Omit<CellOptions, 'type'> {
|
@@ -25,7 +25,8 @@ export interface ListHeaderOptions {
|
|
25
25
|
create?: { path: string; label: string };
|
26
26
|
}
|
27
27
|
|
28
|
-
export interface
|
28
|
+
export interface ListActionOptions<T> {
|
29
|
+
customActions?: { label: string; onClick: (item: T) => void; icon?: string }[];
|
29
30
|
details?: { path: string; label: string };
|
30
31
|
edit?: { path: string; label: string };
|
31
32
|
delete?: { label: string; onRemoveItem?: (item: T) => Promise<void> };
|
@@ -34,7 +35,7 @@ export interface ListCellOptions<T> {
|
|
34
35
|
export interface ListOptions<T> {
|
35
36
|
getData: GetDataForList<T>;
|
36
37
|
headers?: ListHeaderOptions;
|
37
|
-
|
38
|
+
actions?: ((item: T) => ListActionOptions<T>) | ListActionOptions<T>;
|
38
39
|
primaryId?: string;
|
39
40
|
key?: string;
|
40
41
|
}
|
package/src/store/store.ts
CHANGED
@@ -0,0 +1,14 @@
|
|
1
|
+
.panel-button {
|
2
|
+
padding: 0.5rem 1rem;
|
3
|
+
border: 1px solid #444444;
|
4
|
+
border-radius: 4px;
|
5
|
+
background-color: cornflowerblue;
|
6
|
+
color: #ffffff;
|
7
|
+
font-size: 0.875rem;
|
8
|
+
font-weight: 500;
|
9
|
+
cursor: pointer;
|
10
|
+
transition: all 0.2s ease;
|
11
|
+
&:hover {
|
12
|
+
transform: scale(1.01);
|
13
|
+
}
|
14
|
+
}
|
package/src/styles/index.scss
CHANGED
package/src/styles/list.scss
CHANGED
@@ -86,14 +86,18 @@ $datagrid-height: calc(100vh - #{$header-height} - #{$footer-height});
|
|
86
86
|
}
|
87
87
|
|
88
88
|
.datagrid-table {
|
89
|
-
width: 100%;
|
89
|
+
min-width: 100%;
|
90
|
+
table-layout: fixed;
|
90
91
|
border-collapse: collapse;
|
92
|
+
position: relative;
|
91
93
|
|
92
94
|
th,
|
93
95
|
td {
|
94
96
|
padding: 12px 16px;
|
95
97
|
text-align: left;
|
96
98
|
border-bottom: 1px solid #444444;
|
99
|
+
text-overflow: ellipsis;
|
100
|
+
white-space: nowrap;
|
97
101
|
}
|
98
102
|
|
99
103
|
th {
|
@@ -265,3 +269,6 @@ $datagrid-height: calc(100vh - #{$header-height} - #{$footer-height});
|
|
265
269
|
}
|
266
270
|
}
|
267
271
|
}
|
272
|
+
.util-cell-link {
|
273
|
+
cursor: pointer;
|
274
|
+
}
|