techsbcn-storybook 0.11.2 → 0.12.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.
@@ -0,0 +1,57 @@
1
+ import React from 'react';
2
+ import { ObjectKey } from '../../../interfaces';
3
+ import './SimpleTableComponent.scss';
4
+ interface SimpleTableComponentProps {
5
+ rows: any[];
6
+ values: ObjectKey;
7
+ className?: string;
8
+ columns: ColumnProps[];
9
+ rowsColorColumn?: {
10
+ columnName: string;
11
+ columnValue: string;
12
+ };
13
+ loading?: boolean;
14
+ onClickRow?: (id: number) => void;
15
+ isCheckTable?: {
16
+ rowsChecked?: number[];
17
+ onCheckedAction?: (ids: number[]) => void;
18
+ onCheckedSingleAction?: (id: number) => void;
19
+ };
20
+ }
21
+ interface ColumnProps {
22
+ id?: string;
23
+ label?: string;
24
+ minWidth?: number;
25
+ maxWidth?: number;
26
+ align?: 'inherit' | 'left' | 'center' | 'right' | 'justify';
27
+ alignCell?: 'inherit' | 'left' | 'center' | 'right' | 'justify';
28
+ action?: ActionProps[];
29
+ isUnique?: boolean;
30
+ isDate?: boolean;
31
+ enumColumn?: {
32
+ isEnum?: boolean;
33
+ enumType?: any;
34
+ hasColor?: boolean;
35
+ };
36
+ isCheck?: boolean;
37
+ isPrice?: boolean;
38
+ isImage?: {
39
+ isUrl?: boolean;
40
+ isGuid?: {
41
+ guid: boolean;
42
+ action: (guid: string) => string;
43
+ };
44
+ };
45
+ isActiveFunction?: {
46
+ activeIcon: any;
47
+ disabledIcon: any;
48
+ onClickId: (id: number) => void;
49
+ };
50
+ }
51
+ interface ActionProps {
52
+ children: React.ReactNode;
53
+ onClick?: (row: any) => void;
54
+ onClickId?: (id: number) => void;
55
+ }
56
+ export declare const SimpleTableComponent: React.FunctionComponent<SimpleTableComponentProps>;
57
+ export {};
@@ -1,4 +1,5 @@
1
1
  import { Meta, Story } from '@storybook/react';
2
2
  declare const meta: Meta;
3
3
  export default meta;
4
- export declare const TableSimple: Story;
4
+ export declare const Table: Story;
5
+ export declare const SimpleTable: Story;
package/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "0.11.2",
2
+ "version": "0.12.0",
3
3
  "license": "MIT",
4
4
  "main": "dist/index.js",
5
5
  "typings": "dist/index.d.ts",
@@ -0,0 +1,131 @@
1
+ .table-simple-component{
2
+ .paper-container{
3
+ box-shadow: none;
4
+ background-color: transparent!important;
5
+ .checkbox-cell{
6
+ .MuiCheckbox-root{
7
+ padding:0 !important;
8
+ &:hover{
9
+ background-color:transparent !important;
10
+ }
11
+ }
12
+ .Mui-checked {
13
+ color: rgba(0,0,0,0.54) !important;
14
+ }
15
+ .MuiCheckbox-indeterminate {
16
+ color: #212529 !important;
17
+ }
18
+ }
19
+ .table-container{
20
+ max-height: 68vh;
21
+ border-bottom: 1px solid black;
22
+ .table-column:first-child{
23
+ border-radius: 5px 0 0 5px;
24
+ }
25
+ .table-column:last-child{
26
+ border-right: none!important;
27
+ border-radius: 0 5px 5px 0;
28
+ }
29
+ .table-column{
30
+ font-weight: bold;
31
+ font-size: 1rem !important;
32
+ padding: 10px !important;
33
+ border-top: 1px solid rgba(224, 224, 224, 1);
34
+ border-right: 1px solid rgba(224, 224, 224, 1);
35
+ border-bottom: 2px solid rgba(224, 224, 224, 1);
36
+ .table-header-cell{
37
+ color: black;
38
+ padding: 0px 10px 0px 10px !important;
39
+ }
40
+ }
41
+ .table-rows{
42
+ &.row-click{
43
+ cursor: pointer;
44
+ &:hover{
45
+ background-color:rgba(0, 0, 0, 0.04);
46
+ }
47
+ }
48
+ .Mui-selected {
49
+ background-color: transparent !important;
50
+ }
51
+ .MuiTableCell-root {
52
+ padding: 6px !important;
53
+ overflow: hidden;
54
+ }
55
+ .img-table{
56
+ width: 100%;
57
+ height: 110px;
58
+ img{
59
+ object-fit: contain;
60
+ }
61
+ }
62
+ .actions{
63
+ float: right;
64
+ }
65
+ .btn-action {
66
+ color:rgba(0,0,0,0.54);
67
+ display: inline-block;
68
+ text-decoration: none;
69
+ font-size: 1.6em !important;
70
+ padding: 0px 7px;
71
+ cursor: pointer;
72
+ }
73
+ }
74
+ }
75
+
76
+ .MuiTable-root.loading {
77
+ opacity: 0.5;
78
+ .MuiCircularProgress-root{
79
+ width: 80px !important;
80
+ height: 80px !important;
81
+ position: absolute;
82
+ left: 0;
83
+ right: 0;
84
+ top: 5px;
85
+ margin: auto;
86
+ color:grey;
87
+ }
88
+ }
89
+
90
+ }
91
+ @media (max-width: 992px ) {
92
+ .paper-container{
93
+ .table-container{
94
+ max-height: 60vh;
95
+ border-top: 1px solid #cccccc;
96
+ .MuiTable-root{
97
+ border-collapse: collapse!important;
98
+ }
99
+ .MuiTableHead-root{
100
+ display:none!important;
101
+ }
102
+ .table-rows{
103
+ border-bottom: 2px solid #cccccc;
104
+ .MuiTableCell-root {
105
+ width:100%;
106
+ border-bottom: none!important;
107
+ .label-cell{
108
+ font-size: 1rem;
109
+ vertical-align: top;
110
+ width: 50%;
111
+ height: auto;
112
+ }
113
+ .label-cell + div{
114
+ display: inline-block;
115
+ }
116
+ }
117
+ .table-cell{
118
+ display: inline-block!important;
119
+ }
120
+ .format-value{
121
+ text-overflow: ellipsis;
122
+ white-space: nowrap;
123
+ overflow: hidden;
124
+ width: 50%;
125
+ max-width: 300px;
126
+ }
127
+ }
128
+ }
129
+ }
130
+ }
131
+ }
@@ -0,0 +1,368 @@
1
+ import React from 'react';
2
+ import {
3
+ Table,
4
+ TableCell,
5
+ Paper,
6
+ TableContainer,
7
+ TableHead,
8
+ TableRow,
9
+ TableBody,
10
+ Checkbox,
11
+ CircularProgress,
12
+ Box,
13
+ Hidden,
14
+ Avatar,
15
+ } from '@mui/material/';
16
+ import { ObjectKey } from '../../../interfaces';
17
+ import './SimpleTableComponent.scss';
18
+
19
+ interface SimpleTableComponentProps {
20
+ rows: any[];
21
+ values: ObjectKey;
22
+ className?: string;
23
+ columns: ColumnProps[];
24
+ rowsColorColumn?: { columnName: string; columnValue: string };
25
+ loading?: boolean;
26
+ onClickRow?: (id: number) => void;
27
+ isCheckTable?: {
28
+ rowsChecked?: number[];
29
+ onCheckedAction?: (ids: number[]) => void;
30
+ onCheckedSingleAction?: (id: number) => void;
31
+ };
32
+ }
33
+
34
+ interface ColumnProps {
35
+ id?: string;
36
+ label?: string;
37
+ minWidth?: number;
38
+ maxWidth?: number;
39
+ align?: 'inherit' | 'left' | 'center' | 'right' | 'justify';
40
+ alignCell?: 'inherit' | 'left' | 'center' | 'right' | 'justify';
41
+ action?: ActionProps[];
42
+ isUnique?: boolean;
43
+ isDate?: boolean;
44
+ enumColumn?: {
45
+ isEnum?: boolean;
46
+ enumType?: any;
47
+ hasColor?: boolean;
48
+ };
49
+ isCheck?: boolean;
50
+ isPrice?: boolean;
51
+ isImage?: {
52
+ isUrl?: boolean;
53
+ isGuid?: {
54
+ guid: boolean;
55
+ action: (guid: string) => string;
56
+ };
57
+ };
58
+ isActiveFunction?: {
59
+ activeIcon: any;
60
+ disabledIcon: any;
61
+ onClickId: (id: number) => void;
62
+ };
63
+ }
64
+ interface ActionProps {
65
+ children: React.ReactNode;
66
+ onClick?: (row: any) => void;
67
+ onClickId?: (id: number) => void;
68
+ }
69
+ export const SimpleTableComponent: React.FunctionComponent<SimpleTableComponentProps> = (props) => {
70
+ const isSelected = (id: number) => JSON.parse(JSON.stringify(props.isCheckTable?.rowsChecked)).indexOf(id) !== -1;
71
+
72
+ const handleRowClick = (id: number) => {
73
+ if (props.onClickRow) props.onClickRow(id);
74
+ };
75
+
76
+ const onCheckAction = (event: React.ChangeEvent<HTMLInputElement>, id: number) => {
77
+ const checks = JSON.parse(JSON.stringify(props.isCheckTable?.rowsChecked || []));
78
+ const index = checks.indexOf(id);
79
+ if (event.target.checked) checks.push(id);
80
+ else checks.splice(index, 1);
81
+ props.isCheckTable?.onCheckedAction && props.isCheckTable?.onCheckedAction(checks);
82
+ };
83
+
84
+ const onCheckSingleAction = (event: React.ChangeEvent<HTMLInputElement>, id: number) => {
85
+ let checks = JSON.parse(JSON.stringify(props.isCheckTable?.rowsChecked || []));
86
+ const index = checks.indexOf(id);
87
+
88
+ if (event.target.checked) {
89
+ checks.push(id);
90
+ if (checks.length > 1) {
91
+ checks = checks.splice(-1);
92
+ }
93
+ } else checks.splice(index, 1);
94
+ props.isCheckTable?.onCheckedSingleAction && props.isCheckTable?.onCheckedSingleAction(checks[0]);
95
+ };
96
+
97
+ const handleSelectAllClick = (event: React.ChangeEvent<HTMLInputElement>) => {
98
+ let newSelecteds: any = [];
99
+ if (event.target.checked) {
100
+ newSelecteds = props.rows.map((n) => n.id);
101
+ }
102
+ props.isCheckTable?.onCheckedAction && props.isCheckTable?.onCheckedAction(newSelecteds);
103
+ };
104
+
105
+ const formatValue = (value: string, column: ColumnProps) => {
106
+ if (column.enumColumn?.isEnum) {
107
+ if (column.enumColumn?.enumType) {
108
+ const result: string[] = [];
109
+ if (value === null) {
110
+ return value;
111
+ } else if (value.split(',').length > 1) {
112
+ value.split(',').forEach((v) => {
113
+ result.push(props.values[column.enumColumn?.enumType[v.replace(/ /g, '')].toUpperCase()]);
114
+ });
115
+ return result.join();
116
+ } else if (Array.isArray(value)) {
117
+ const split: string[] = value.toString().split(',');
118
+ split.forEach((v) => {
119
+ if (!isNaN(parseInt(v)))
120
+ result.push(props.values[column.enumColumn?.enumType[v.replace(/ /g, '')].toUpperCase()]);
121
+ else result.push(props.values[v.toUpperCase()]);
122
+ });
123
+ return result.join();
124
+ } else return props.values[column.enumColumn?.enumType[value].toUpperCase()];
125
+ } else return props.values[value.toUpperCase()];
126
+ }
127
+ if (column.isDate && value) return new Date(value).toLocaleDateString('es-ES');
128
+
129
+ if (column.isPrice) {
130
+ if (value !== null) return `${value.toLocaleString()} ${props.values.SYMBOL_EURO}`;
131
+ }
132
+
133
+ if (column.isImage) {
134
+ if (column.isImage.isUrl) {
135
+ return <Avatar alt="-" src={value} className="img-table" variant="square" />;
136
+ }
137
+ }
138
+ if (Array.isArray(value)) {
139
+ return value.join(', ');
140
+ }
141
+ return value;
142
+ };
143
+
144
+ const ObjectbyString = (o: any, s: string) => {
145
+ s = s.replace(/\[(\w+)\]/g, '.$1');
146
+ const a = s.split('.');
147
+ for (let i = 0, n = a.length; i < n; ++i) {
148
+ const k = a[i];
149
+ try {
150
+ if (k in o) {
151
+ o = o[k];
152
+ } else {
153
+ return undefined;
154
+ }
155
+ } catch (_error) {
156
+ return undefined;
157
+ }
158
+ }
159
+ return o;
160
+ };
161
+
162
+ return (
163
+ <Box className="table-simple-component">
164
+ <Paper className="paper-container">
165
+ {props.isCheckTable && (
166
+ <Hidden mdUp>
167
+ <Box display="block" className="checkbox-cell">
168
+ <Checkbox
169
+ indeterminate={
170
+ props.rows &&
171
+ JSON.parse(JSON.stringify(props.isCheckTable?.rowsChecked)).length > 0 &&
172
+ JSON.parse(JSON.stringify(props.isCheckTable?.rowsChecked)).length < props.rows.length
173
+ }
174
+ checked={
175
+ props.rows &&
176
+ props.rows.length > 0 &&
177
+ JSON.parse(JSON.stringify(props.isCheckTable?.rowsChecked)).length === props.rows.length
178
+ }
179
+ onChange={handleSelectAllClick}
180
+ />
181
+ </Box>
182
+ </Hidden>
183
+ )}
184
+ <TableContainer className="table-container">
185
+ <Table
186
+ stickyHeader={true}
187
+ aria-label="sticky table"
188
+ className={props.loading ? 'loading' : props.className ? props.className : ''}
189
+ >
190
+ <Hidden smDown>
191
+ <TableHead>
192
+ <TableRow>
193
+ {props.columns.map((column) => {
194
+ if (column.id) {
195
+ return (
196
+ <TableCell
197
+ className="table-column"
198
+ key={column.isUnique ? `${column.id}-unique` : column.id}
199
+ align={column.align ? column.align : 'center'}
200
+ style={{ minWidth: column.minWidth, maxWidth: column.maxWidth }}
201
+ >
202
+ {column.isCheck ? (
203
+ <Box className="checkbox-cell">
204
+ <Checkbox
205
+ indeterminate={
206
+ props.rows &&
207
+ JSON.parse(JSON.stringify(props.isCheckTable?.rowsChecked)).length > 0 &&
208
+ JSON.parse(JSON.stringify(props.isCheckTable?.rowsChecked)).length < props.rows.length
209
+ }
210
+ checked={
211
+ props.rows &&
212
+ props.rows.length > 0 &&
213
+ JSON.parse(JSON.stringify(props.isCheckTable?.rowsChecked)).length ===
214
+ props.rows.length
215
+ }
216
+ onChange={handleSelectAllClick}
217
+ />
218
+ </Box>
219
+ ) : (
220
+ <Box className="table-header-cell">{column.label}</Box>
221
+ )}
222
+ </TableCell>
223
+ );
224
+ } else return null;
225
+ })}
226
+ </TableRow>
227
+ </TableHead>
228
+ </Hidden>
229
+ <TableBody>
230
+ {props.loading && (
231
+ <TableRow className="table-rows">
232
+ <TableCell
233
+ colSpan={props.columns.length}
234
+ sx={{
235
+ position: 'relative',
236
+ overflow: 'inherit !important',
237
+ height: props.rows.length > 0 ? 'auto' : '80px',
238
+ }}
239
+ >
240
+ <CircularProgress className="circular-progress-main-color" />
241
+ </TableCell>
242
+ </TableRow>
243
+ )}
244
+ {props.rows && props.rows.length > 0 ? (
245
+ props.rows.map((row, index) => {
246
+ const key = props.rows[index + 1] && props.rows[index + 1].id === row.id ? index : row.id;
247
+ const rowColor =
248
+ props.rowsColorColumn &&
249
+ ObjectbyString(row, props.rowsColorColumn.columnName) === props.rowsColorColumn.columnValue
250
+ ? `row-color-${props.rowsColorColumn.columnValue}`
251
+ : '';
252
+ const isRowSelected = props.isCheckTable?.rowsChecked && isSelected(row.id);
253
+ return (
254
+ <TableRow
255
+ className={`table-rows ${rowColor} ${props.onClickRow ? 'row-click' : ''}`}
256
+ role="checkbox"
257
+ tabIndex={-1}
258
+ selected={isRowSelected}
259
+ aria-checked={isRowSelected}
260
+ key={key || index}
261
+ >
262
+ {props.columns.map((column) => {
263
+ if (column.id) {
264
+ const value = ObjectbyString(row, column.id);
265
+ const isItemSelected = column.isCheck && isSelected(row.id);
266
+ return (
267
+ <TableCell
268
+ className="table-cell"
269
+ key={column.isUnique ? `${column.id}-unique` : column.id}
270
+ sx={{
271
+ textAlign: {
272
+ xs: 'left',
273
+ md: column.alignCell ? column.alignCell : column.align ? column.align : 'center',
274
+ },
275
+ }}
276
+ onClick={() =>
277
+ !column.action && !column.isCheck && !column.isActiveFunction
278
+ ? handleRowClick(row.id)
279
+ : ''
280
+ }
281
+ >
282
+ <Hidden mdUp>
283
+ {column.label !== '-' && (
284
+ <Box display="inline-block" className="label-cell">
285
+ {column.label}
286
+ </Box>
287
+ )}
288
+ </Hidden>
289
+ {column.action ? (
290
+ <Box>
291
+ <Box display="flex" className="actions">
292
+ {column.action &&
293
+ column.action.map((action, i) => (
294
+ <Box key={i}>
295
+ {action.onClick && (
296
+ <Box
297
+ className="btn-action main-color-hover"
298
+ onClick={() => action.onClick && action.onClick(row)}
299
+ >
300
+ {action.children}
301
+ </Box>
302
+ )}
303
+ {action.onClickId && (
304
+ <Box
305
+ className="btn-action main-color-hover"
306
+ onClick={() => action.onClickId && action.onClickId(row.id)}
307
+ >
308
+ {action.children}
309
+ </Box>
310
+ )}
311
+ {!action.onClick && !action.onClickId && (
312
+ <Box className="btn-action">{action.children}</Box>
313
+ )}
314
+ </Box>
315
+ ))}
316
+ </Box>
317
+ </Box>
318
+ ) : column.isActiveFunction ? (
319
+ <Box
320
+ className="btn-action main-color-hover"
321
+ onClick={() => column.isActiveFunction && column.isActiveFunction.onClickId(row.id)}
322
+ >
323
+ {value ? column.isActiveFunction.activeIcon : column.isActiveFunction.disabledIcon}
324
+ </Box>
325
+ ) : column.isCheck ? (
326
+ <Box className="checkbox-cell">
327
+ <Checkbox
328
+ checked={isItemSelected}
329
+ inputProps={{ 'aria-labelledby': row.id }}
330
+ onChange={(event: React.ChangeEvent<HTMLInputElement>) =>
331
+ props.isCheckTable?.onCheckedAction
332
+ ? onCheckAction(event, row.id)
333
+ : onCheckSingleAction(event, row.id)
334
+ }
335
+ />
336
+ </Box>
337
+ ) : (
338
+ <Box
339
+ className={`${
340
+ column.enumColumn?.hasColor ? `${value.toLowerCase()}-type-color` : ''
341
+ } format-value`}
342
+ >
343
+ {formatValue(value, column)}
344
+ </Box>
345
+ )}
346
+ </TableCell>
347
+ );
348
+ } else return null;
349
+ })}
350
+ </TableRow>
351
+ );
352
+ })
353
+ ) : !props.loading ? (
354
+ <TableRow>
355
+ <TableCell colSpan={props.columns.length}>
356
+ <Box>{props.values.NO_RESULTS_FOUND}</Box>
357
+ </TableCell>
358
+ </TableRow>
359
+ ) : (
360
+ <TableRow />
361
+ )}
362
+ </TableBody>
363
+ </Table>
364
+ </TableContainer>
365
+ </Paper>
366
+ </Box>
367
+ );
368
+ };
@@ -8,6 +8,7 @@ import { UserList, Values } from '../../data';
8
8
  import { Search } from '@mui/icons-material';
9
9
  import { ButtonComponent } from '../../components/fields/ButtonComponent/ButtonComponent';
10
10
  import { TableComponent } from '../../components/tables/TableComponent/TableComponent';
11
+ import { SimpleTableComponent } from '../../components/tables/SimpleTableComponent/SimpleTableComponent';
11
12
  import { SearchFilters } from '../../interfaces';
12
13
  import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
13
14
  import { faTrashAlt, faEdit } from '@fortawesome/free-solid-svg-icons';
@@ -29,7 +30,7 @@ const defaultFilters: SearchFilters = {
29
30
  orderAsc: true,
30
31
  };
31
32
 
32
- export const TableSimple: Story = () => {
33
+ export const Table: Story = () => {
33
34
  const [filters] = React.useState(defaultFilters);
34
35
  return (
35
36
  <MainLayoutSimple
@@ -116,3 +117,69 @@ export const TableSimple: Story = () => {
116
117
  />
117
118
  );
118
119
  };
120
+
121
+ export const SimpleTable: Story = () => {
122
+ return (
123
+ <MainLayoutSimple
124
+ headerComponent={
125
+ <AppHeader handleDrawerOpen={() => console.log('e')}>
126
+ <Box m={'auto'}>
127
+ <img src={logo} className="header-logo" alt="logo" />
128
+ </Box>
129
+ </AppHeader>
130
+ }
131
+ mainComponent={
132
+ <Box py={2}>
133
+ <MainWrapperComponent
134
+ headerProps={{
135
+ title: 'Table',
136
+ }}
137
+ >
138
+ <SimpleTableComponent
139
+ rows={UserList}
140
+ columns={[
141
+ { id: 'id', label: 'Id', minWidth: 55, maxWidth: 55 },
142
+ { id: 'name', label: Values.NAME, minWidth: 100, maxWidth: 100 },
143
+ {
144
+ id: 'image',
145
+ label: Values.IMAGE,
146
+ minWidth: 100,
147
+ isImage: { isUrl: true },
148
+ },
149
+ { id: 'extraInfo.name', label: Values.USER, minWidth: 100, maxWidth: 100 },
150
+ { id: 'skills', label: Values.SKILLS, minWidth: 100, maxWidth: 100 },
151
+ { id: 'information', label: Values.INFORMATION, minWidth: 100, maxWidth: 100 },
152
+ { id: 'email', label: Values.EMAIL, minWidth: 100 },
153
+ { id: 'charge', label: Values.PRICE, minWidth: 100, isPrice: true },
154
+ {
155
+ id: 'actions',
156
+ label: '',
157
+ minWidth: 10,
158
+ action: [
159
+ {
160
+ children: <FontAwesomeIcon icon={faEdit} />,
161
+ onClick: (row: any) => {
162
+ console.log(row);
163
+ },
164
+ },
165
+ {
166
+ children: <FontAwesomeIcon icon={faTrashAlt} />,
167
+ onClickId: (id: number) => {
168
+ console.log(id);
169
+ },
170
+ },
171
+ ],
172
+ },
173
+ ]}
174
+ rowsColorColumn={{ columnName: 'extraInfo.name', columnValue: 'Juan' }}
175
+ values={Values}
176
+ onClickRow={(id: number) => {
177
+ console.log(id);
178
+ }}
179
+ />
180
+ </MainWrapperComponent>
181
+ </Box>
182
+ }
183
+ />
184
+ );
185
+ };