Guest User

Untitled

a guest
Mar 31st, 2021
9
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 4.94 KB | None | 0 0
  1. import React, { useEffect, useState } from 'react';
  2. import {
  3. Button, Jumbotron, Toast, ToastHeader, ToastBody, Form, Label, FormGroup,
  4. } from 'reactstrap';
  5. import styled from 'styled-components';
  6. import readXlsxFile from 'read-excel-file';
  7. import Papa from 'papaparse';
  8. import csvToJsonUtil from '../../../application/csvToJsonUtil';
  9. import backendApi from '../../../api/backend-api';
  10.  
  11. interface Props {
  12. getAccessToken: Function;
  13. }
  14.  
  15. interface Courses {
  16. courses: {
  17. id: string;
  18. name: string,
  19. }[],
  20. }
  21.  
  22. const FormWrapper = styled.div`
  23. margin: 12px 0px 0px;
  24. `;
  25.  
  26. const SelectInput = styled.select`
  27. margin: 12px;
  28. `;
  29.  
  30. const FileInputWrapper = styled.div`
  31. margin: 12px;
  32. `;
  33.  
  34. const schema = {
  35. 'Полное имя': {
  36. prop: 'fullName',
  37. type: String,
  38. required: true,
  39. },
  40. 'Действие пользователя': {
  41. prop: 'userAction',
  42. type: String,
  43. required: true,
  44. },
  45. 'Метка времени': {
  46. prop: 'timestamp',
  47. type: String,
  48. required: true,
  49. },
  50. };
  51.  
  52. export default ({ getAccessToken }: Props) => {
  53. const [selectedFile, setSelectedFile] = useState({
  54. file: '',
  55. fileExtension: '',
  56. });
  57.  
  58. const [courseOptions, setCourseOptions] = useState<Courses>();
  59. const [courseId, setCourseId] = useState('1');
  60. const [errorOnSavingFile, setErrorOnSavingFile] = useState(false);
  61. const [successOnSavingFile, setSuccessOnSavingFile] = useState(false);
  62.  
  63. useEffect(() => {
  64. if (!courseOptions) {
  65. setCourseOptionsFromBackend();
  66. }
  67. setTimeout(() => {
  68. setErrorOnSavingFile(false);
  69. setSuccessOnSavingFile(false);
  70. }, 6000);
  71. });
  72.  
  73. return (
  74. <div>
  75. {(errorOnSavingFile || successOnSavingFile)
  76. && (
  77. <div className={`p-3 my-2 rounded ${(errorOnSavingFile && 'bg-danger') || (successOnSavingFile && 'bg-success')}`}>
  78. <Toast>
  79. <ToastHeader>
  80. {errorOnSavingFile && 'Error'}
  81. {successOnSavingFile && 'Ok'}
  82. </ToastHeader>
  83. <ToastBody>
  84. {errorOnSavingFile && `Error on saving student attendance.
  85. Try to amend file and try again. Maybe, there is no such student!`}
  86. {successOnSavingFile && 'Successfully completed operation!'}
  87. </ToastBody>
  88. </Toast>
  89. </div>
  90. )}
  91. <Jumbotron>
  92. <div>Register student providing files from Teams</div>
  93. <FormWrapper>
  94. <Form>
  95. {courseOptions
  96. && (
  97. <FormGroup>
  98. <Label for="course">Select course</Label>
  99. <SelectInput name="course" onChange={(event) => setCourseId(event.target.value)}>
  100. <option value={-1}>Please, select some option</option>
  101. {courseOptions.courses.map(
  102. ({ id, name }) => <option key={id} value={id}>{name}</option>,
  103. )}
  104. </SelectInput>
  105. </FormGroup>
  106. )}
  107. <FormGroup>
  108. <Label for="fileInput">Select attendance file</Label>
  109. <FileInputWrapper>
  110. <input name="fileInput" type="file" onChange={fileInputChangeHandler} required accept=".xls,.xlsx,.csv" />
  111. </FileInputWrapper>
  112. </FormGroup>
  113. <Button color="primary" onClick={() => handleSubmission()}>Upload student attendance file</Button>
  114. </Form>
  115. </FormWrapper>
  116. </Jumbotron>
  117. </div>
  118. );
  119.  
  120. function fileInputChangeHandler(event) {
  121. const file = event.target.files[0];
  122. setSelectedFile({ file, fileExtension: file?.name.split('.').pop() ?? '' });
  123. }
  124.  
  125. function handleSubmission() {
  126. ({
  127. csv: () => saveCsv(),
  128. xlsx: () => saveXlsx(),
  129. }[selectedFile.fileExtension] || (() => setErrorOnSavingFile(true)))();
  130. }
  131.  
  132. function saveCsv() {
  133. Papa.parse(selectedFile.file, {
  134. async complete(results) {
  135. await saveStudentsAttendanceFile(csvToJsonUtil(results.data.slice(1)));
  136. },
  137. });
  138. }
  139.  
  140. function saveXlsx() {
  141. readXlsxFile(selectedFile.file, { schema }).then(async ({ rows }) => {
  142. await saveStudentsAttendanceFile(rows);
  143. });
  144. }
  145.  
  146. async function saveStudentsAttendanceFile(rows) {
  147. const accessToken = await getAccessToken();
  148. return backendApi.saveStudentsAttendanceFile({
  149. attendances: rows,
  150. courseId,
  151. registeredTimestamp: Date.now(),
  152. })(accessToken).then((response) => {
  153. if (response.ok) {
  154. setSuccessOnSavingFile(true);
  155. setErrorOnSavingFile(false);
  156. } else {
  157. setErrorOnSavingFile(true);
  158. }
  159. }).catch(() => setErrorOnSavingFile(true));
  160. }
  161.  
  162. async function setCourseOptionsFromBackend() {
  163. const accessToken = await getAccessToken();
  164. const courses = await backendApi.fetchCourses(accessToken);
  165. setCourseOptions(courses);
  166. setCourseId(courses[0] && courses[0].id);
  167. }
  168. };
  169.  
Advertisement
Add Comment
Please, Sign In to add comment