import React, { Component } from "react";
import '../../css/Form.css';
/**
* A form to submit a new course rss which is converted into json data and
* submitted to the server.
*/
class NewCourse extends Component {
state = {
rss: {
value: "",
error: "",
},
loading: false,
success: false
};
/**
* Updates the value of a input as the user types inside it
* @param {String} type Which input to update
*/
handleChange = type => event => {
this.setState({
[type]: { value: event.target.value }
});
};
/**
* Handles form submission.
*/
submit = () => event => {
event.preventDefault();
const rss = this.state.rss.value;
if (!rss) {
this.setState({
rss: { error: "Please provide the RSS feed content" }
})
return;
}
const course = this.parseRss(rss);
if(!course) {
this.setState({ rss: { error: "Invalid RSS feed"} });
return;
}
/*
console.log("Submitting form...");
this.setState({ loading: true });
this.submitRSS({ feed: course })
.then(data => {
console.log(JSON.stringify(data));
// Redirect user to verify account
return (
<div>It worked</div>
)
})
TODO: Process errors
.catch(error => {
console.error(error);
this.setState({ loading: false })
});
*/
}
/**
* Parses the rss feed to a json object.
* @param {String} rss The rss feed
* @returns {json} A json object container the course name, course link and
* lectures
*/
parseRss = (rss) => {
const parser = new DOMParser();
const parsedRss = parser.parseFromString(rss, "text/xml");
// Check valid rss
if (parsedRss.getElementsByTagName("title").length === 0 &&
parsedRss.getElementsByTagName("link").length === 0) {
return null;
}
// Gets the title and link of the course
let course = {
name: parsedRss.getElementsByTagName("title")[0].childNodes[0].nodeValue,
url: parsedRss.getElementsByTagName("link")[0].childNodes[0].nodeValue
}
// Gets the amount of lectures
const lectureCount = parsedRss.getElementsByTagName("item").length;
// Gets all the lectures
const parsedLectures = parsedRss.getElementsByTagName("item");
// Gets all the lectures name
let lectures = [];
for (let i = 0; i < lectureCount; i++) {
// Create the lecture object
const lecture = {
name: parsedLectures[i].getElementsByTagName("title")[0].childNodes[0].nodeValue,
author: parsedLectures[i].getElementsByTagName("itunes:author")[0].childNodes[0].nodeValue,
summary: parsedLectures[i].getElementsByTagName("itunes:summary")[0].childNodes[0].nodeValue,
url: parsedLectures[i].getElementsByTagName("guid")[0].childNodes[0].nodeValue,
published: parsedLectures[i].getElementsByTagName("pubDate")[0].childNodes[0].nodeValue,
duration: parsedLectures[i].getElementsByTagName("itunes:duration")[0].childNodes[0].nodeValue
}
// Add the lecture to the lectures array
lectures = [...lectures, lecture];
}
course = { ...course, lectures };
this.setState({
course
})
return course;
}
/**
* Uploads the rss feed to the database
* @param {object} data The data to be uploaded
* @returns {promise} Returns a promise from the request
*/
submitRSS = (data = {}) => {
return fetch("", {
method: "POST",
mode: "cors",
cache: "no-cache",
credentials: "same-origin",
headers: {
"Content-Type": "application/json; charset=utf-8",
},
redirect: "follow",
referrer: "no-referrer",
body: JSON.stringify(data),
}).then(response => response.json());
}
/**
* Changes the time from seconds to a human friendly time
* @param {String} duration The duration in seconds
* @returns {String} A human readable time hh:mm:ss
*/
humanTime = (duration) => {
let humanTime = new Date(null);
humanTime.setSeconds(duration);
return humanTime.toISOString().substr(11, 8);
}
render() {
const { rss, course, loading } = this.state;
return (
<div className="row">
<div className="
col-sm-12 col-md-8 col-lg-6 col-md-offset-2 col-lg-offset-3
">
<form onSubmit={this.submit()} autoComplete="on">
<legend><h1 className="form-header">Register a course</h1></legend>
<div className="input-group vertical">
<label htmlFor="rss">
RSS feed
{ rss.error && (
<mark className="secondary">{rss.error}</mark>
)}
</label>
<textarea
onChange={this.handleChange("rss")}
value={rss.value || ''}
type="text"
id="rss"
name="rss"
disabled={loading}
autoFocus
/>
</div>
<div className="btn-container">
{ loading && (
<div className="loading">
<div className="spinner primary"></div>
</div>
)}
<div className="button-group btn-group">
<button
className="primary shadowed btn-1"
type="submit"
disabled={loading}
>
Register course
</button>
</div>
</div>
</form>
</div>
<div className="col-sm-12">
{ course && (
<table className="striped">
<caption>
<h4>
{course.name}
<small>Found {course.lectures.length} lectures</small>
</h4>
</caption>
<thead>
<tr>
<th>Name</th>
<th>Author</th>
<th>Published</th>
<th>Duration</th>
</tr>
</thead>
<tbody>
{course.lectures.map(lecture => (
<tr key={lecture.url}>
<td data-label="name">{lecture.name}</td>
<td data-label="author">{lecture.author}</td>
<td data-label="author">{lecture.published}</td>
<td data-label="author">{
this.humanTime(lecture.duration)
}</td>
</tr>
))}
</tbody>
</table>
)}
</div>
</div>
)
}
}
export default NewCourse;