@elice/material-exercise 1.221109.0 → 1.221129.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.
@@ -20,7 +20,23 @@ var styled__default = /*#__PURE__*/_interopDefaultLegacy(styled);
20
20
  //
21
21
  //
22
22
 
23
- const ROW_PER_PAGE_LIST = [10, 25, 50]; //
23
+ const OPTIONS_PER_PAGE = [10, 25, 50];
24
+ const OPTIONS_DELIMITER = [{
25
+ char: ',',
26
+ label: 'Comma [,]'
27
+ }, {
28
+ char: '\t',
29
+ label: 'Tab [\\t]'
30
+ }, {
31
+ char: '/',
32
+ label: 'Regular Bar [/]'
33
+ }, {
34
+ char: '\\',
35
+ label: 'Inverted Bar [\\]'
36
+ }, {
37
+ char: '|',
38
+ label: 'Vertical Bar [|]'
39
+ }]; //
24
40
  //
25
41
  //
26
42
 
@@ -30,28 +46,36 @@ const StyledViewer = styled__default["default"].div.withConfig({
30
46
  const StyledViewerTableWrap = styled__default["default"].div.withConfig({
31
47
  componentId: "sc-pyv7uu-1"
32
48
  })(["flex:1;overflow:auto;"]);
33
- const StyledViewerFooter = styled__default["default"].div.withConfig({
49
+ const StyledViewerTable = styled__default["default"].table.withConfig({
34
50
  componentId: "sc-pyv7uu-2"
51
+ })(["border:none;border-collapse:collapse;color:", ";font-family:'Elice Digital Coding',monospace,fixed-width;th,td{border:1px solid ", ";padding:0.5rem;white-space:pre;&:first-of-type{color:", ";border-left:none;}&:last-of-type{border-right:none;}}tbody{tr:nth-child(odd){background:", ";}tr:hover{background:", ";}}"], designTokens.base.color.white, designTokens.base.color.navy5, designTokens.base.color.gray5, designTokens.base.color.navy8, designTokens.base.color.navy6);
52
+ const StyledViewerFooter = styled__default["default"].div.withConfig({
53
+ componentId: "sc-pyv7uu-3"
35
54
  })(["flex:0 0 auto;display:flex;justify-content:space-between;align-items:center;padding:0.5rem;"]);
36
55
  const StyledViewerFooterSelect = styled__default["default"].select.withConfig({
37
- componentId: "sc-pyv7uu-3"
38
- })(["width:3rem;border-radius:0.25rem;"]);
39
- const StyledViewerTable = styled__default["default"].table.withConfig({
40
56
  componentId: "sc-pyv7uu-4"
41
- })(["border:1px solid ", ";border-collapse:collapse;color:", ";font-family:'Elice Digital Coding',monospace,fixed-width;th,td{border:1px solid ", ";padding:0.5rem;white-space:pre;&:nth-child(1){color:", ";}}tbody{tr:nth-child(odd){background:", ";}tr:hover{background:", ";}}"], designTokens.base.color.navy5, designTokens.base.color.white, designTokens.base.color.navy5, designTokens.base.color.gray5, designTokens.base.color.navy8, designTokens.base.color.navy6);
57
+ })(["width:", "rem;border-radius:0.25rem;"], props => props.width);
58
+ const StyledViewerFooterHr = styled__default["default"](blocks.Hr).withConfig({
59
+ componentId: "sc-pyv7uu-5"
60
+ })(["height:1rem;"]); //
61
+ //
62
+ //
42
63
 
43
64
  const FileViewerCsv = ({
44
65
  fileurl
45
66
  }) => {
67
+ const [csv, setCsv] = React__default["default"].useState('');
46
68
  const [csvHeader, setCsvHeader] = React__default["default"].useState(null);
47
69
  const [csvRecords, setCsvRecords] = React__default["default"].useState([]);
48
70
  const [csvStatus, setCsvStatus] = React__default["default"].useState('idle');
49
71
  const [page, setPage] = React__default["default"].useState(1);
50
- const [perPage, setPerPage] = React__default["default"].useState(ROW_PER_PAGE_LIST[0]);
51
- const maxPage = Math.ceil(csvRecords.length / perPage);
72
+ const [perPage, setPerPage] = React__default["default"].useState(OPTIONS_PER_PAGE[0]);
73
+ const [delimiter, setDelimiter] = React__default["default"].useState(OPTIONS_DELIMITER[0].char);
52
74
  const [isUsingHeader, setUsingHeader] = React__default["default"].useState(true);
75
+ const csvRecordCount = csvRecords.length + (csvHeader ? -1 : 0);
76
+ const maxPage = Math.ceil(csvRecordCount / perPage);
53
77
  const tableWrapElRef = React__default["default"].useRef(null); //
54
- // fetch csv file and parse it
78
+ // Fetch csv file
55
79
  //
56
80
 
57
81
  React__default["default"].useEffect(() => {
@@ -64,7 +88,7 @@ const FileViewerCsv = ({
64
88
  setCsvStatus('pending');
65
89
  fetch(fileurl, {
66
90
  signal: abortCtrl.signal
67
- }).then(res => res.text()).then(data => data.split('\n').map(row => row.split(','))).then(setCsvRecords).then(() => setCsvStatus('resolved')).catch(err => {
91
+ }).then(res => res.text()).then(setCsv).then(() => setCsvStatus('resolved')).catch(err => {
68
92
  if (err.name === 'AbortError') {
69
93
  return;
70
94
  }
@@ -76,11 +100,15 @@ const FileViewerCsv = ({
76
100
  abortCtrl.abort();
77
101
  };
78
102
  }, [fileurl]); //
103
+ // Parse csv file and save as records
104
+ //
105
+
106
+ React__default["default"].useEffect(() => setCsvRecords(csv.split('\n').filter(Boolean).map(row => row.split(delimiter))), [csv, delimiter]); //
79
107
  // Set CSV header.
80
108
  //
81
109
 
82
110
  React__default["default"].useEffect(() => setCsvHeader(isUsingHeader ? csvRecords[0] : null), [csvRecords, isUsingHeader]); //
83
- // Set CSV header.
111
+ // Scroll to top when page changes.
84
112
  //
85
113
 
86
114
  React__default["default"].useEffect(() => {
@@ -110,7 +138,7 @@ const FileViewerCsv = ({
110
138
  const renderViewerTableTbody = () => {
111
139
  const start = (page - 1) * perPage;
112
140
  const end = page * perPage;
113
- const records = csvRecords.slice(isUsingHeader ? 1 : 0).slice(start, end);
141
+ const records = csvRecords.slice(csvHeader ? 1 : 0).slice(start, end);
114
142
  return React__default["default"].createElement("tbody", null, records.map((row, rowIdx) => {
115
143
  const curRecordNo = start + rowIdx + 1;
116
144
  const curRow = [curRecordNo, ...row];
@@ -147,14 +175,22 @@ const FileViewerCsv = ({
147
175
  }, React__default["default"].createElement(blocks.Text, {
148
176
  role: "gray1",
149
177
  size: "small"
150
- }, csvRecords.length, " records"), React__default["default"].createElement(blocks.Hr, {
178
+ }, csvRecordCount, " records"), React__default["default"].createElement(StyledViewerFooterHr, {
151
179
  vertical: true,
152
180
  color: designTokens.base.color.navy5
153
181
  }), React__default["default"].createElement(blocks.Flex, {
154
182
  align: "center"
155
183
  }, React__default["default"].createElement(blocks.IconButton, {
156
- icon: icons.eilArrowLeftwardsBasic,
157
- role: "gray5",
184
+ icon: icons.eilArrowLeftwardsDouble,
185
+ role: "navy3",
186
+ size: "nano",
187
+ disabled: page <= 1,
188
+ onClick: () => setPage(1)
189
+ }), React__default["default"].createElement(blocks.Hspace, {
190
+ width: 0.25
191
+ }), React__default["default"].createElement(blocks.IconButton, {
192
+ icon: icons.eilArrowLeftwardsSingle,
193
+ role: "navy3",
158
194
  size: "nano",
159
195
  disabled: page <= 1,
160
196
  onClick: () => setPage(prevPage => prevPage - 1)
@@ -166,11 +202,19 @@ const FileViewerCsv = ({
166
202
  }, page, " / ", maxPage), React__default["default"].createElement(blocks.Hspace, {
167
203
  width: 0.5
168
204
  }), React__default["default"].createElement(blocks.IconButton, {
169
- icon: icons.eilArrowRightwardsBasic,
170
- role: "gray5",
205
+ icon: icons.eilArrowRightwardsSingle,
206
+ role: "navy3",
171
207
  size: "nano",
172
208
  disabled: page >= maxPage,
173
209
  onClick: () => setPage(prevPage => prevPage + 1)
210
+ }), React__default["default"].createElement(blocks.Hspace, {
211
+ width: 0.25
212
+ }), React__default["default"].createElement(blocks.IconButton, {
213
+ icon: icons.eilArrowRightwardsDouble,
214
+ role: "navy3",
215
+ size: "nano",
216
+ disabled: page >= maxPage,
217
+ onClick: () => setPage(maxPage)
174
218
  })));
175
219
  };
176
220
  /**
@@ -194,7 +238,28 @@ const FileViewerCsv = ({
194
238
  size: "small",
195
239
  checked: isUsingHeader,
196
240
  onChange: setUsingHeader
197
- })), React__default["default"].createElement(blocks.Hr, {
241
+ })), React__default["default"].createElement(StyledViewerFooterHr, {
242
+ vertical: true,
243
+ color: designTokens.base.color.navy5
244
+ }), React__default["default"].createElement(blocks.Flex, {
245
+ align: "center"
246
+ }, React__default["default"].createElement(blocks.Text, {
247
+ role: "gray1",
248
+ size: "small"
249
+ }, React__default["default"].createElement(reactIntl.FormattedMessage, {
250
+ id: "\uAD6C\uBD84\uC790:"
251
+ })), React__default["default"].createElement(blocks.Hspace, {
252
+ width: 0.5
253
+ }), React__default["default"].createElement(StyledViewerFooterSelect, {
254
+ width: 7.5,
255
+ value: delimiter,
256
+ onChange: e => setDelimiter(e.target.value)
257
+ }, OPTIONS_DELIMITER.map(({
258
+ char,
259
+ label
260
+ }) => React__default["default"].createElement("option", {
261
+ value: char
262
+ }, label)))), React__default["default"].createElement(StyledViewerFooterHr, {
198
263
  vertical: true,
199
264
  color: designTokens.base.color.navy5
200
265
  }), React__default["default"].createElement(blocks.Flex, {
@@ -207,9 +272,10 @@ const FileViewerCsv = ({
207
272
  })), React__default["default"].createElement(blocks.Hspace, {
208
273
  width: 0.5
209
274
  }), React__default["default"].createElement(StyledViewerFooterSelect, {
275
+ width: 3,
210
276
  value: perPage,
211
277
  onChange: e => setPerPage(Number(e.target.value))
212
- }, ROW_PER_PAGE_LIST.map(perPage => React__default["default"].createElement("option", {
278
+ }, OPTIONS_PER_PAGE.map(perPage => React__default["default"].createElement("option", {
213
279
  value: perPage
214
280
  }, perPage)))));
215
281
  };
@@ -1,8 +1,8 @@
1
1
  import React from 'react';
2
2
  import { FormattedMessage } from 'react-intl';
3
- import { Flex, Text, Hr, IconButton, Hspace, AntSwitch } from '@elice/blocks';
3
+ import { Hr, Flex, Text, IconButton, Hspace, AntSwitch } from '@elice/blocks';
4
4
  import { base } from '@elice/design-tokens';
5
- import { eilArrowLeftwardsBasic, eilArrowRightwardsBasic } from '@elice/icons';
5
+ import { eilArrowLeftwardsDouble, eilArrowLeftwardsSingle, eilArrowRightwardsSingle, eilArrowRightwardsDouble } from '@elice/icons';
6
6
  import styled from 'styled-components';
7
7
  import ExerciseFileShimmer from '../exercise-shimmer/ExerciseFileShimmer.js';
8
8
  import '../exercise-shimmer/ExerciseFileTabsShimmer.js';
@@ -13,7 +13,23 @@ import '../exercise-shimmer/ExerciseFileTreeListItemShimmer.js';
13
13
  //
14
14
  //
15
15
 
16
- const ROW_PER_PAGE_LIST = [10, 25, 50]; //
16
+ const OPTIONS_PER_PAGE = [10, 25, 50];
17
+ const OPTIONS_DELIMITER = [{
18
+ char: ',',
19
+ label: 'Comma [,]'
20
+ }, {
21
+ char: '\t',
22
+ label: 'Tab [\\t]'
23
+ }, {
24
+ char: '/',
25
+ label: 'Regular Bar [/]'
26
+ }, {
27
+ char: '\\',
28
+ label: 'Inverted Bar [\\]'
29
+ }, {
30
+ char: '|',
31
+ label: 'Vertical Bar [|]'
32
+ }]; //
17
33
  //
18
34
  //
19
35
 
@@ -23,28 +39,36 @@ const StyledViewer = styled.div.withConfig({
23
39
  const StyledViewerTableWrap = styled.div.withConfig({
24
40
  componentId: "sc-pyv7uu-1"
25
41
  })(["flex:1;overflow:auto;"]);
26
- const StyledViewerFooter = styled.div.withConfig({
42
+ const StyledViewerTable = styled.table.withConfig({
27
43
  componentId: "sc-pyv7uu-2"
44
+ })(["border:none;border-collapse:collapse;color:", ";font-family:'Elice Digital Coding',monospace,fixed-width;th,td{border:1px solid ", ";padding:0.5rem;white-space:pre;&:first-of-type{color:", ";border-left:none;}&:last-of-type{border-right:none;}}tbody{tr:nth-child(odd){background:", ";}tr:hover{background:", ";}}"], base.color.white, base.color.navy5, base.color.gray5, base.color.navy8, base.color.navy6);
45
+ const StyledViewerFooter = styled.div.withConfig({
46
+ componentId: "sc-pyv7uu-3"
28
47
  })(["flex:0 0 auto;display:flex;justify-content:space-between;align-items:center;padding:0.5rem;"]);
29
48
  const StyledViewerFooterSelect = styled.select.withConfig({
30
- componentId: "sc-pyv7uu-3"
31
- })(["width:3rem;border-radius:0.25rem;"]);
32
- const StyledViewerTable = styled.table.withConfig({
33
49
  componentId: "sc-pyv7uu-4"
34
- })(["border:1px solid ", ";border-collapse:collapse;color:", ";font-family:'Elice Digital Coding',monospace,fixed-width;th,td{border:1px solid ", ";padding:0.5rem;white-space:pre;&:nth-child(1){color:", ";}}tbody{tr:nth-child(odd){background:", ";}tr:hover{background:", ";}}"], base.color.navy5, base.color.white, base.color.navy5, base.color.gray5, base.color.navy8, base.color.navy6);
50
+ })(["width:", "rem;border-radius:0.25rem;"], props => props.width);
51
+ const StyledViewerFooterHr = styled(Hr).withConfig({
52
+ componentId: "sc-pyv7uu-5"
53
+ })(["height:1rem;"]); //
54
+ //
55
+ //
35
56
 
36
57
  const FileViewerCsv = ({
37
58
  fileurl
38
59
  }) => {
60
+ const [csv, setCsv] = React.useState('');
39
61
  const [csvHeader, setCsvHeader] = React.useState(null);
40
62
  const [csvRecords, setCsvRecords] = React.useState([]);
41
63
  const [csvStatus, setCsvStatus] = React.useState('idle');
42
64
  const [page, setPage] = React.useState(1);
43
- const [perPage, setPerPage] = React.useState(ROW_PER_PAGE_LIST[0]);
44
- const maxPage = Math.ceil(csvRecords.length / perPage);
65
+ const [perPage, setPerPage] = React.useState(OPTIONS_PER_PAGE[0]);
66
+ const [delimiter, setDelimiter] = React.useState(OPTIONS_DELIMITER[0].char);
45
67
  const [isUsingHeader, setUsingHeader] = React.useState(true);
68
+ const csvRecordCount = csvRecords.length + (csvHeader ? -1 : 0);
69
+ const maxPage = Math.ceil(csvRecordCount / perPage);
46
70
  const tableWrapElRef = React.useRef(null); //
47
- // fetch csv file and parse it
71
+ // Fetch csv file
48
72
  //
49
73
 
50
74
  React.useEffect(() => {
@@ -57,7 +81,7 @@ const FileViewerCsv = ({
57
81
  setCsvStatus('pending');
58
82
  fetch(fileurl, {
59
83
  signal: abortCtrl.signal
60
- }).then(res => res.text()).then(data => data.split('\n').map(row => row.split(','))).then(setCsvRecords).then(() => setCsvStatus('resolved')).catch(err => {
84
+ }).then(res => res.text()).then(setCsv).then(() => setCsvStatus('resolved')).catch(err => {
61
85
  if (err.name === 'AbortError') {
62
86
  return;
63
87
  }
@@ -69,11 +93,15 @@ const FileViewerCsv = ({
69
93
  abortCtrl.abort();
70
94
  };
71
95
  }, [fileurl]); //
96
+ // Parse csv file and save as records
97
+ //
98
+
99
+ React.useEffect(() => setCsvRecords(csv.split('\n').filter(Boolean).map(row => row.split(delimiter))), [csv, delimiter]); //
72
100
  // Set CSV header.
73
101
  //
74
102
 
75
103
  React.useEffect(() => setCsvHeader(isUsingHeader ? csvRecords[0] : null), [csvRecords, isUsingHeader]); //
76
- // Set CSV header.
104
+ // Scroll to top when page changes.
77
105
  //
78
106
 
79
107
  React.useEffect(() => {
@@ -103,7 +131,7 @@ const FileViewerCsv = ({
103
131
  const renderViewerTableTbody = () => {
104
132
  const start = (page - 1) * perPage;
105
133
  const end = page * perPage;
106
- const records = csvRecords.slice(isUsingHeader ? 1 : 0).slice(start, end);
134
+ const records = csvRecords.slice(csvHeader ? 1 : 0).slice(start, end);
107
135
  return React.createElement("tbody", null, records.map((row, rowIdx) => {
108
136
  const curRecordNo = start + rowIdx + 1;
109
137
  const curRow = [curRecordNo, ...row];
@@ -140,14 +168,22 @@ const FileViewerCsv = ({
140
168
  }, React.createElement(Text, {
141
169
  role: "gray1",
142
170
  size: "small"
143
- }, csvRecords.length, " records"), React.createElement(Hr, {
171
+ }, csvRecordCount, " records"), React.createElement(StyledViewerFooterHr, {
144
172
  vertical: true,
145
173
  color: base.color.navy5
146
174
  }), React.createElement(Flex, {
147
175
  align: "center"
148
176
  }, React.createElement(IconButton, {
149
- icon: eilArrowLeftwardsBasic,
150
- role: "gray5",
177
+ icon: eilArrowLeftwardsDouble,
178
+ role: "navy3",
179
+ size: "nano",
180
+ disabled: page <= 1,
181
+ onClick: () => setPage(1)
182
+ }), React.createElement(Hspace, {
183
+ width: 0.25
184
+ }), React.createElement(IconButton, {
185
+ icon: eilArrowLeftwardsSingle,
186
+ role: "navy3",
151
187
  size: "nano",
152
188
  disabled: page <= 1,
153
189
  onClick: () => setPage(prevPage => prevPage - 1)
@@ -159,11 +195,19 @@ const FileViewerCsv = ({
159
195
  }, page, " / ", maxPage), React.createElement(Hspace, {
160
196
  width: 0.5
161
197
  }), React.createElement(IconButton, {
162
- icon: eilArrowRightwardsBasic,
163
- role: "gray5",
198
+ icon: eilArrowRightwardsSingle,
199
+ role: "navy3",
164
200
  size: "nano",
165
201
  disabled: page >= maxPage,
166
202
  onClick: () => setPage(prevPage => prevPage + 1)
203
+ }), React.createElement(Hspace, {
204
+ width: 0.25
205
+ }), React.createElement(IconButton, {
206
+ icon: eilArrowRightwardsDouble,
207
+ role: "navy3",
208
+ size: "nano",
209
+ disabled: page >= maxPage,
210
+ onClick: () => setPage(maxPage)
167
211
  })));
168
212
  };
169
213
  /**
@@ -187,7 +231,28 @@ const FileViewerCsv = ({
187
231
  size: "small",
188
232
  checked: isUsingHeader,
189
233
  onChange: setUsingHeader
190
- })), React.createElement(Hr, {
234
+ })), React.createElement(StyledViewerFooterHr, {
235
+ vertical: true,
236
+ color: base.color.navy5
237
+ }), React.createElement(Flex, {
238
+ align: "center"
239
+ }, React.createElement(Text, {
240
+ role: "gray1",
241
+ size: "small"
242
+ }, React.createElement(FormattedMessage, {
243
+ id: "\uAD6C\uBD84\uC790:"
244
+ })), React.createElement(Hspace, {
245
+ width: 0.5
246
+ }), React.createElement(StyledViewerFooterSelect, {
247
+ width: 7.5,
248
+ value: delimiter,
249
+ onChange: e => setDelimiter(e.target.value)
250
+ }, OPTIONS_DELIMITER.map(({
251
+ char,
252
+ label
253
+ }) => React.createElement("option", {
254
+ value: char
255
+ }, label)))), React.createElement(StyledViewerFooterHr, {
191
256
  vertical: true,
192
257
  color: base.color.navy5
193
258
  }), React.createElement(Flex, {
@@ -200,9 +265,10 @@ const FileViewerCsv = ({
200
265
  })), React.createElement(Hspace, {
201
266
  width: 0.5
202
267
  }), React.createElement(StyledViewerFooterSelect, {
268
+ width: 3,
203
269
  value: perPage,
204
270
  onChange: e => setPerPage(Number(e.target.value))
205
- }, ROW_PER_PAGE_LIST.map(perPage => React.createElement("option", {
271
+ }, OPTIONS_PER_PAGE.map(perPage => React.createElement("option", {
206
272
  value: perPage
207
273
  }, perPage)))));
208
274
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@elice/material-exercise",
3
- "version": "1.221109.0",
3
+ "version": "1.221129.0",
4
4
  "description": "User view and editing components of Elice material exercise",
5
5
  "repository": "https://git.elicer.io/elice/frontend/library/elice-material",
6
6
  "license": "UNLICENSED",
@@ -81,7 +81,6 @@
81
81
  "ot-text-unicode": "^4.0.0",
82
82
  "prettier": "~2.7.1",
83
83
  "random-words": "^1.1.2",
84
- "react-csv-to-table": "^0.0.4",
85
84
  "react-hook-form": "~7.12.0",
86
85
  "react-transition-group": "^4.3.0",
87
86
  "rxjs": "^7.5.6",
@@ -116,8 +115,8 @@
116
115
  "@elice/design-tokens": "^1.220803.0",
117
116
  "@elice/icons": "^1.220803.0",
118
117
  "@elice/markdown": "^1.220803.0",
119
- "@elice/material-shared-types": "1.221109.0",
120
- "@elice/material-shared-utils": "1.221109.0",
118
+ "@elice/material-shared-types": "1.221129.0",
119
+ "@elice/material-shared-utils": "1.221129.0",
121
120
  "@elice/types": "^1.221027.0",
122
121
  "@elice/websocket": "^1.220803.0",
123
122
  "@types/classnames": "^2.3.1",
@@ -139,5 +138,5 @@
139
138
  "recoil": "^0.6.1",
140
139
  "styled-components": "^5.2.0"
141
140
  },
142
- "gitHead": "bd17b325b12a0b7b2b1e663180666dc45bb90b27"
141
+ "gitHead": "2f7b7c14476949931e7dfe508a6a192d454f3d75"
143
142
  }