Grégoire Delattre 9a37677d52
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing
Update redux state management
Use immer with native javascript objects instead of immutablejs.
2020-04-07 18:08:47 +02:00

119 lines
3.0 KiB
JavaScript

import React, { useState } from "react";
import PropTypes from "prop-types";
import { useDispatch, useSelector } from "react-redux";
import { prettySize } from "../../utils";
import { addTorrent, removeTorrent } from "../../actions/torrents";
export const TorrentList = () => {
return (
<div className="row">
<div className="col-12">
<AddTorrent />
<Torrents />
</div>
</div>
);
};
const AddTorrent = () => {
const dispatch = useDispatch();
const [url, setUrl] = useState("");
const handleSubmit = (e) => {
e.preventDefault();
if (url === "") {
return;
}
dispatch(addTorrent(url));
setUrl("");
};
return (
<form onSubmit={(e) => handleSubmit(e)}>
<input
type="text"
className="form-control mb-3 w-100"
placeholder="Add torrent URL"
onSubmit={handleSubmit}
value={url}
onChange={(e) => setUrl(e.target.value)}
/>
</form>
);
};
const Torrents = () => {
const torrents = useSelector((state) => state.torrents.torrents);
if (torrents.length === 0) {
return (
<div className="jumbotron">
<h2>No torrents</h2>
</div>
);
}
return (
<div className="d-flex flex-wrap">
{torrents.map((torrent, index) => (
<Torrent key={index} torrent={torrent} />
))}
</div>
);
};
const Torrent = ({ torrent }) => {
const dispatch = useDispatch();
var progressStyle = torrent.is_finished
? "success"
: "info progress-bar-striped progress-bar-animated";
const progressBarClass = "progress-bar bg-" + progressStyle;
var percentDone = torrent.percent_done;
const started = percentDone !== 0;
if (started) {
percentDone = Number(percentDone).toFixed(1) + "%";
}
// Pretty sizes
const downloadedSize = prettySize(torrent.downloaded_size);
const totalSize = prettySize(torrent.total_size);
const downloadRate = prettySize(torrent.download_rate) + "/s";
return (
<div className="card w-100 mb-3">
<h5 className="card-header">
<span className="text text-break">{torrent.name}</span>
<span
className="fa fa-trash clickable pull-right"
onClick={() => dispatch(removeTorrent(torrent.id))}
></span>
</h5>
<div className="card-body pb-0">
{started && (
<React.Fragment>
<div className="progress bg-light">
<div
className={progressBarClass}
style={{ width: percentDone }}
role="progressbar"
aria-valuenow={percentDone}
aria-valuemin="0"
aria-valuemax="100"
></div>
</div>
<p>
{downloadedSize} / {totalSize} - {percentDone} - {downloadRate}
</p>
</React.Fragment>
)}
{!started && <p>Download not yet started</p>}
</div>
</div>
);
};
Torrent.propTypes = {
torrent: PropTypes.object.isRequired,
};