Add YouTube frontend (#5)

* Add youtube frontend

* Add production build of frontend
This commit is contained in:
Adam Svystun 2018-10-01 23:29:29 +02:00 committed by Maciej Pęśko
parent 939d017850
commit d5ae415ce1
7 changed files with 689 additions and 322 deletions

View file

@ -8,7 +8,8 @@ import { css } from "react-emotion";
import {
COMIXIFY_API,
MAX_FILE_SIZE,
PERMITTED_VIDEO_EXTENSIONS
PERMITTED_VIDEO_EXTENSIONS,
FROM_YOUTUBE_API
} from "./constants";
class App extends React.Component {
@ -19,6 +20,7 @@ class App extends React.Component {
UPLOAD_ERROR: 3,
DROP_ERROR: 4
};
ytInput = React.createRef();
constructor(props) {
super(props);
this.state = {
@ -27,6 +29,8 @@ class App extends React.Component {
result_comics: null
};
this.onVideoDrop = this.onVideoDrop.bind(this);
this.handleResponse = this.handleResponse.bind(this);
this.onYouTubeSubmit = this.onYouTubeSubmit.bind(this);
this.onVideoUploadProgress = this.onVideoUploadProgress.bind(this);
}
onVideoUploadProgress(progressEvent) {
@ -35,6 +39,18 @@ class App extends React.Component {
);
console.log(percentCompleted);
}
handleResponse(res) {
if (res.data["status_message"] === "ok") {
this.setState({
state: App.appStates.FINISHED,
result_comics: res.data["comic"]
});
} else {
this.setState({
state: App.appStates.UPLOAD_ERROR
});
}
}
processVideo(video) {
let data = new FormData();
data.append("file", video);
@ -42,18 +58,7 @@ class App extends React.Component {
headers: { "content-type": "multipart/form-data" },
onUploadProgress: this.onVideoUploadProgress
})
.then(res => {
if (res.data["status_message"] === "ok") {
this.setState({
state: App.appStates.FINISHED,
result_comics: res.data["comic"]
});
} else {
this.setState({
state: App.appStates.UPLOAD_ERROR
});
}
})
.then(this.handleResponse)
.catch(err => {
console.error(err);
this.setState({
@ -75,10 +80,25 @@ class App extends React.Component {
}
this.processVideo(files[0]);
}
onYouTubeSubmit() {
let ytLink = this.ytInput.current.value;
post(FROM_YOUTUBE_API, {
url: ytLink
})
.then(this.handleResponse)
.catch(err => {
console.error(err);
this.setState({
state: App.appStates.UPLOAD_ERROR
});
});
this.setState({
state: App.appStates.PROCESSING
});
}
render() {
let { state, drop_errors, result_comics } = this.state;
let showDropzone = [
let showUsage = [
App.appStates.INITIAL,
App.appStates.UPLOAD_ERROR,
App.appStates.DROP_ERROR,
@ -95,7 +115,7 @@ class App extends React.Component {
{state === App.appStates.UPLOAD_ERROR && (
<p>Server Error: Please try again later.</p>
)}
{showDropzone && (
{showUsage && (
<Dropzone
onDrop={this.onVideoDrop}
accept={PERMITTED_VIDEO_EXTENSIONS}
@ -105,9 +125,16 @@ class App extends React.Component {
rejectClassName="dropzone--rejected"
multiple={false} // Only one video at the time
>
<p>Drop files here, or click to select manually</p>
<p>Drop video here, or click to select manually</p>
</Dropzone>
)}
{showUsage && (
<div>
<label htmlFor="yt-link" className="yt-label">Or use YouTube link:</label>
<input type="url" id="yt-link" ref={this.ytInput}/>
<button onClick={this.onYouTubeSubmit}>Run</button>
</div>
)}
{state === App.appStates.PROCESSING && (
<BarLoader
color={"rgb(54, 215, 183)"}

View file

@ -1,3 +1,4 @@
export const COMIXIFY_API = "/comixify/";
export const FROM_YOUTUBE_API = "/comixify/from_yt/";
export const MAX_FILE_SIZE = 50000000;
export const PERMITTED_VIDEO_EXTENSIONS = "video/*";

View file

@ -1,51 +1,54 @@
const webpack = require("webpack");
const merge = require("webpack-merge");
const UglifyJsPlugin = require("uglifyjs-webpack-plugin");
module.exports = env => {
const merge = require("webpack-merge");
const UglifyJsPlugin = require("uglifyjs-webpack-plugin");
const webpack = require("webpack");
let common = {
entry: {
app: __dirname + "/App.js"
},
output: {
path: __dirname + "/../static/frontend/js",
filename: "[name].client.js"
},
externals: {
cheerio: "window",
"react/lib/ExecutionEnvironment": true,
"react/lib/ReactContext": true
},
module: {
rules: [
{
test: /\.jsx?$/,
exclude: /(node_modules|bower_components)/,
loader: "babel-loader",
query: {
presets: ["react", "stage-0", "flow"],
plugins: ["emotion"]
let common = {
entry: {
app: __dirname + "/App.js"
},
output: {
path: __dirname + "/../static/frontend/js",
filename: "[name].client.js"
},
externals: {
cheerio: "window",
"react/lib/ExecutionEnvironment": true,
"react/lib/ReactContext": true
},
module: {
rules: [
{
test: /\.jsx?$/,
exclude: /(node_modules|bower_components)/,
loader: "babel-loader",
query: {
presets: ["react", "stage-0", "flow"],
plugins: ["emotion"]
}
},
{
test: /\.css$/,
use: ["style-loader", "css-loader"]
}
},
{
test: /\.css$/,
use: ["style-loader", "css-loader"]
}
]
}
};
]
}
};
if (process.env.NODE_ENV === "production") {
module.exports = merge(common, {
plugins: [
new webpack.DefinePlugin({
"process.env.NODE_ENV": JSON.stringify("production")
}),
new UglifyJsPlugin()
],
mode: "production"
});
} else {
module.exports = merge(common, {
mode: "development"
});
if (env.production) {
return merge(common, {
plugins: [
new webpack.DefinePlugin({
"process.env.NODE_ENV": JSON.stringify("production")
}),
new UglifyJsPlugin()
],
mode: "production"
});
} else {
return merge(common, {
mode: "development"
});
}
}

View file

@ -61,6 +61,56 @@ img {
background-color: #eee;
}
.yt-label {
margin: 10px 0 10px 20px;
display: block;
}
#yt-link {
height: 30px;
margin-right: 5px;
padding: 6px 10px;
background-color: #fff;
border: 1px solid #D1D1D1;
border-radius: 3px;
box-shadow: none;
box-sizing: border-box;
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
}
#yt-link:focus {
border: 1px solid #33C3F0;
outline: 0;
}
button {
display: inline-block;
height: 30px;
padding: 0 30px;
color: #555;
text-align: center;
font-size: 11px;
font-weight: 600;
line-height: 30px;
text-transform: uppercase;
text-decoration: none;
white-space: nowrap;
background-color: transparent;
border-radius: 3px;
border: 1px solid #bbb;
cursor: pointer;
box-sizing: border-box;
}
button:hover,
button:focus {
color: #333;
border-color: #888;
outline: 0;
}
@media all and (max-width: 700px) {
.wrap {
margin-top: 0;

File diff suppressed because one or more lines are too long

782
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -7,7 +7,7 @@
"test": "echo \"Error: no test specified\" && exit 1",
"build": "webpack --config ./frontend/client/webpack.config.js",
"build:watch": "webpack --config ./frontend/client/webpack.config.js --watch",
"build:prod": "NODE_ENV=production webpack --config ./frontend/client/webpack.config.js"
"build:prod": "webpack --env.production --config ./frontend/client/webpack.config.js"
},
"repository": {
"type": "git",
@ -35,11 +35,11 @@
"react-dropzone": "^5.0.1",
"react-spinners": "^0.4.5",
"style-loader": "^0.23.0",
"uglifyjs-webpack-plugin": "^1.2.5",
"webpack": "^4.17.1",
"webpack-merge": "^4.1.1"
"uglifyjs-webpack-plugin": "^1.2.5"
},
"devDependencies": {
"webpack-cli": "^3.1.0"
"webpack": "^4.20.2",
"webpack-cli": "^3.1.0",
"webpack-merge": "^4.1.4"
}
}