upload mode (wip)

This commit is contained in:
Brandon Thomas committed 2021-05-21 06:04:20 -04:00
1 parent 5ab974f346
commit 04d59933e5
7 files changed
+298 -6

No files matched your search

+29 -3
View File
@@ -1855,6 +1855,11 @@
}
}
},
"@types/uuid": {
"version": "8.3.0",
"resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-8.3.0.tgz",
"integrity": "sha512-eQ9qFW/fhfGJF8WKHGEHZEyVWfZxrT+6CLIJGBcZPfxUh/+BnEj+UCGYMlr9qZuX/2AltsvwrGqp0LhEW8D0zQ=="
},
"@types/yargs": {
"version": "13.0.9",
"resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-13.0.9.tgz",
@@ -11522,6 +11527,13 @@
"tough-cookie": "~2.5.0",
"tunnel-agent": "^0.6.0",
"uuid": "^3.3.2"
},
"dependencies": {
"uuid": {
"version": "3.4.0",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
"integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A=="
}
}
},
"request-promise-core": {
@@ -12272,6 +12284,13 @@
"requires": {
"faye-websocket": "^0.10.0",
"uuid": "^3.0.1"
},
"dependencies": {
"uuid": {
"version": "3.4.0",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
"integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A=="
}
}
},
"sockjs-client": {
@@ -13468,9 +13487,9 @@
"integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM="
},
"uuid": {
"version": "3.4.0",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
"integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A=="
"version": "8.3.2",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
"integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg=="
},
"v8-compile-cache": {
"version": "2.1.1",
@@ -14159,6 +14178,13 @@
"requires": {
"ansi-colors": "^3.0.0",
"uuid": "^3.3.2"
},
"dependencies": {
"uuid": {
"version": "3.4.0",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
"integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A=="
}
}
},
"webpack-manifest-plugin": {
+3 -1
View File
@@ -14,6 +14,7 @@
"@types/node": "^12.12.47",
"@types/react": "^16.9.36",
"@types/react-dom": "^16.9.8",
"@types/uuid": "^8.3.0",
"axios": "^0.21.0",
"bulma": "^0.9.0",
"howler": "^2.2.0",
@@ -21,7 +22,8 @@
"react": "^16.13.1",
"react-dom": "^16.13.1",
"react-scripts": "3.4.1",
"typescript": "^3.7.5"
"typescript": "^3.7.5",
"uuid": "^8.3.2"
},
"scripts": {
"start": "BROWSER=none react-scripts start",
+8
View File
@@ -22,6 +22,7 @@ import { SignupComponent } from './modes/signup/SignupComponent';
import { ApiConfig } from './api/ApiConfig';
import { SessionStateResponse } from './api/SessionState';
import { LoginComponent } from './modes/login/LoginComponent';
import { UploadComponent } from './modes/upload/UploadComponent';
interface Props {
// Certan browsers (iPhone) have pitiful support for drawing APIs. Worse yet,
@@ -432,6 +433,13 @@ class App extends React.Component<Props, State> {
switchModeCallback={this.switchMode}
/>
break;
case Mode.UPLOAD_MODE:
component = <UploadComponent
loggedIn={this.state.loggedIn}
querySessionCallback={this.querySession}
switchModeCallback={this.switchMode}
/>
break;
}
return (
<div id="main" className="mainwrap">
+1 -1
View File
@@ -13,7 +13,7 @@ enum Mode {
COMMUNITY_TTS_MODE,
COMMUNITY_VIDEO_MODE,
UPLOAD,
UPLOAD_MODE,
MY_DATA_MODE,
}
+8
View File
@@ -37,6 +37,14 @@ class ApiConfig {
return `${this.getScheme()}://${this.getNewApiHost()}/session`;
}
uploadTts() : string {
return `${this.getScheme()}://${this.getNewApiHost()}/tts/upload`;
}
uploadW2l() : string {
return `${this.getScheme()}://${this.getNewApiHost()}/w2l/upload`;
}
private getScheme() : string {
return this.isLocalDev ? "http" : "https";
}
@@ -0,0 +1,248 @@
import React from 'react';
import { ApiConfig } from '../../api/ApiConfig';
import { Mode } from '../../AppMode';
import { v4 } from 'uuid';
enum UploadType {
TTS_MODEL,
W2L_TEMPLATE,
}
enum FieldTriState {
EMPTY_FALSE,
FALSE,
TRUE,
}
interface Props {
loggedIn: boolean,
querySessionCallback : () => void,
switchModeCallback: (mode: Mode) => void,
}
interface State {
uploadType: UploadType,
title: string,
titleValid: FieldTriState,
titleInvalidReason: string,
downloadUrl: string,
downloadUrlValid: FieldTriState,
downloadUrlInvalidReason: string,
idempotencyToken: string,
}
class UploadComponent extends React.Component<Props, State> {
constructor(props: Props) {
super(props);
this.state = {
uploadType: UploadType.TTS_MODEL,
title: "",
titleValid: FieldTriState.EMPTY_FALSE,
titleInvalidReason: "",
downloadUrl: "",
downloadUrlValid: FieldTriState.EMPTY_FALSE,
downloadUrlInvalidReason: "",
idempotencyToken: "",
};
}
handleTitleChange = (ev: React.FormEvent<HTMLInputElement>) => {
ev.preventDefault();
const title = (ev.target as HTMLInputElement).value;
this.setState({
title: title,
});
return false;
}
handleDownloadUrlChange = (ev: React.FormEvent<HTMLInputElement>) => {
ev.preventDefault();
const downloadUrl = (ev.target as HTMLInputElement).value;
this.setState({
downloadUrl: downloadUrl,
});
return false;
}
handleFormSubmit = (ev: React.FormEvent<HTMLFormElement>) : boolean => {
ev.preventDefault();
const api = new ApiConfig();
let endpointUrl = "";
switch (this.state.uploadType) {
case UploadType.TTS_MODEL:
endpointUrl = api.uploadTts();
break;
case UploadType.W2L_TEMPLATE:
endpointUrl = api.uploadW2l();
break;
}
let idempotency_token = this.state.idempotencyToken;
idempotency_token = v4();
const request = {
idempotency_token: idempotency_token,
title: this.state.title,
download_url: this.state.downloadUrl,
}
fetch(endpointUrl, {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
credentials: 'include',
body: JSON.stringify(request),
})
.then(res => res.json())
.then(res => {
console.log('upload response', res)
if (res.success) {
this.props.switchModeCallback(Mode.SPEAK_MODE);
return;
}
})
.catch(e => {
//this.props.onSpeakErrorCallback();
});
return false;
}
setTts = () => {
this.setState({
uploadType: UploadType.TTS_MODEL,
})
}
setW2l = () => {
this.setState({
uploadType: UploadType.W2L_TEMPLATE,
})
}
public render() {
if (!this.props.loggedIn) {
return (
<div>
<h1>You must be logged in to upload!</h1>
Invalid view for logged out users.
</div>
);
}
let extra = <div />;
if (this.state.uploadType === UploadType.TTS_MODEL) {
extra = (
<div className="notification is-warning">
<strong>Over $500 in prizes!</strong>
<p>You can help vo.codes grow by uploading Tacotron2 models.
The person that uploads the most models will get $100,
the person that uploads the most popular model will get $100,
and a number of other lucky winners will be chosen at random to
recieve cash prizes.</p>
</div>
);
}
let title = "";
let ttsClasses = "";
let w2lClasses = "";
switch (this.state.uploadType) {
case UploadType.TTS_MODEL:
title = "Upload Tacotron 2 Model";
ttsClasses = "button is-primary is-large is-light";
w2lClasses = "button is-primary is-large";
break;
case UploadType.W2L_TEMPLATE:
title = "Upload W2L Video or Image Template";
ttsClasses = "button is-primary is-large";
w2lClasses = "button is-primary is-large is-light";
break;
}
return (
<div>
<h2> {title} </h2>
<div className="columns">
<div className="column">
<button
className={ttsClasses}
title="Upload TTS"
onClick={this.setTts}
>Upload TTS Model</button>
</div>
<div className="column">
<button
className={w2lClasses}
title="Upload W2L"
onClick={this.setW2l}
>Upload Video Template</button>
</div>
</div>
{extra}
<form onSubmit={this.handleFormSubmit}>
<div className="field">
<label className="label">Title</label>
<div className="control has-icons-left has-icons-right">
<input className="input" type="text" placeholder="Title" value={this.state.title} onChange={this.handleTitleChange} />
<span className="icon is-small is-left">
<i className="fas fa-user"></i>
</span>
<span className="icon is-small is-right">
<i className="fas fa-check"></i>
</span>
</div>
<p className="help">{this.state.titleInvalidReason}</p>
</div>
<div className="field">
<label className="label">Download URL</label>
<div className="control has-icons-left has-icons-right">
<input className="input" type="password" placeholder="Download URL" value={this.state.downloadUrl} onChange={this.handleDownloadUrlChange} />
<span className="icon is-small is-left">
<i className="fas fa-envelope"></i>
</span>
<span className="icon is-small is-right">
<i className="fas fa-exclamation-triangle"></i>
</span>
</div>
<p className="help">{this.state.downloadUrlInvalidReason}</p>
</div>
<br />
<div className="field is-grouped">
<div className="control">
<button className="button is-link is-large">Upload</button>
</div>
</div>
</form>
</div>
)
}
}
export { UploadComponent };
+1 -1
View File
@@ -65,7 +65,7 @@ function TopNav(props: Props) {
<br />
<a href="#community_tts" onClick={() => props.switchModeCallback(Mode.COMMUNITY_TTS_MODE)}>TTS</a>
<a href="#community_video" onClick={() => props.switchModeCallback(Mode.COMMUNITY_VIDEO_MODE)}>Video</a>
<a href="#upload" onClick={() => props.switchModeCallback(Mode.UPLOAD)}>Upload</a>
<a href="#upload" onClick={() => props.switchModeCallback(Mode.UPLOAD_MODE)}>Upload</a>
<a href="#my_data" onClick={() => props.switchModeCallback(Mode.MY_DATA_MODE)}>My Data</a>
</div>
);