2016-07-26 12:09:09 +02:00
|
|
|
var publishNumberStyle = {
|
2016-07-15 14:04:47 +02:00
|
|
|
width: '50px',
|
2016-07-20 08:25:22 +02:00
|
|
|
}, publishFieldLabelStyle = {
|
|
|
|
display: 'inline-block',
|
|
|
|
width: '118px',
|
|
|
|
textAlign: 'right',
|
|
|
|
verticalAlign: 'top',
|
|
|
|
}, publishFieldStyle = {
|
|
|
|
width: '330px',
|
2016-07-15 14:04:47 +02:00
|
|
|
};
|
|
|
|
|
2016-05-23 17:14:21 +02:00
|
|
|
var PublishPage = React.createClass({
|
2016-07-26 12:09:09 +02:00
|
|
|
_requiredFields: ['name', 'file', 'meta_title', 'meta_author', 'meta_license', 'meta_description'],
|
|
|
|
|
|
|
|
handleSubmit: function() {
|
2016-07-21 08:58:06 +02:00
|
|
|
this.setState({
|
|
|
|
submitting: true,
|
|
|
|
});
|
|
|
|
|
2016-07-26 12:09:09 +02:00
|
|
|
var missingFieldFound = false;
|
|
|
|
for (let fieldName of this._requiredFields) {
|
|
|
|
var field = this.refs[fieldName];
|
|
|
|
if (field.getValue() == '') {
|
|
|
|
field.warnRequired();
|
|
|
|
if (!missingFieldFound) {
|
|
|
|
field.focus();
|
|
|
|
missingFieldFound = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (missingFieldFound) {
|
|
|
|
this.setState({
|
|
|
|
submitting: false,
|
|
|
|
});
|
2016-07-27 13:46:48 +02:00
|
|
|
return;
|
2016-07-26 12:09:09 +02:00
|
|
|
}
|
2016-07-20 08:25:22 +02:00
|
|
|
|
2016-07-26 12:09:09 +02:00
|
|
|
var metadata = {};
|
|
|
|
for (let metaField of ['meta_title', 'meta_author', 'meta_description', 'meta_thumbnail',
|
|
|
|
'meta_language']) {
|
|
|
|
var value = this.refs[metaField].getValue();
|
|
|
|
if (value != '') {
|
|
|
|
metadata[metaField] = value;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
metadata.license = {};
|
|
|
|
metadata.license.name = this.refs.meta_license.getValue();
|
|
|
|
|
|
|
|
var licenseUrl = this.refs.meta_license_url.getValue();
|
|
|
|
if (licenseUrl != '') {
|
2016-07-26 14:30:46 +02:00
|
|
|
metadata.license.url = licenseUrl;
|
2016-07-20 08:25:22 +02:00
|
|
|
}
|
|
|
|
|
2016-07-21 08:58:06 +02:00
|
|
|
var doPublish = () => {
|
|
|
|
lbry.publish({
|
|
|
|
name: this.state.name,
|
|
|
|
file_path: this._tempFilePath,
|
|
|
|
bid: parseFloat(this.state.bid),
|
|
|
|
metadata: metadata,
|
|
|
|
}, (message) => {
|
2016-07-26 12:09:09 +02:00
|
|
|
this.handlePublishSuccess();
|
2016-07-21 08:58:06 +02:00
|
|
|
this.setState({
|
|
|
|
submitting: false,
|
|
|
|
});
|
|
|
|
}, (error) => {
|
|
|
|
this.handlePublishError(error);
|
|
|
|
this.setState({
|
|
|
|
submitting: false,
|
|
|
|
});
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
2016-07-20 08:25:22 +02:00
|
|
|
if (this.state.isFee) {
|
2016-07-21 08:58:06 +02:00
|
|
|
lbry.getNewAddress((address) => {
|
|
|
|
metadata.fee = {
|
|
|
|
'LBC': {
|
|
|
|
amount: parseFloat(this.state.fee),
|
|
|
|
address: address,
|
|
|
|
},
|
|
|
|
};
|
2016-07-20 08:25:22 +02:00
|
|
|
|
2016-07-21 08:58:06 +02:00
|
|
|
doPublish();
|
|
|
|
});
|
|
|
|
} else {
|
|
|
|
doPublish();
|
|
|
|
}
|
2016-05-23 17:14:21 +02:00
|
|
|
},
|
2016-07-15 14:04:47 +02:00
|
|
|
getInitialState: function() {
|
2016-07-20 08:25:22 +02:00
|
|
|
this._tempFilePath = null;
|
|
|
|
|
2016-07-15 14:04:47 +02:00
|
|
|
return {
|
|
|
|
name: '',
|
|
|
|
bid: '',
|
2016-07-20 08:25:22 +02:00
|
|
|
nameResolved: false,
|
|
|
|
claimValue: 0.0,
|
|
|
|
fileInfo: null,
|
|
|
|
uploadProgress: 0.0,
|
|
|
|
uploaded: false,
|
|
|
|
tempFileReady: false,
|
2016-07-21 08:58:06 +02:00
|
|
|
submitting: false,
|
2016-07-15 14:04:47 +02:00
|
|
|
};
|
|
|
|
},
|
2016-07-26 12:09:09 +02:00
|
|
|
handlePublishSuccess: function() {
|
|
|
|
alert(`Your file ${this.refs.meta_title.value} has been published to LBRY at the address lbry://${this.state.name}!\n\n` +
|
2016-07-21 08:58:06 +02:00
|
|
|
`You will now be taken to your My Files page, where your newly published file should appear within a few minutes.`);
|
2016-07-25 07:38:56 +02:00
|
|
|
window.location = "?files";
|
2016-07-21 08:58:06 +02:00
|
|
|
},
|
|
|
|
handlePublishError: function(error) {
|
|
|
|
alert(`The following error occurred when attempting to publish your file:\n\n` +
|
|
|
|
error.message);
|
|
|
|
},
|
2016-07-15 14:04:47 +02:00
|
|
|
handleNameChange: function(event) {
|
|
|
|
var name = event.target.value;
|
|
|
|
|
|
|
|
if (!name) {
|
|
|
|
this.setState({
|
|
|
|
name: '',
|
|
|
|
nameResolved: false,
|
2016-07-20 08:25:22 +02:00
|
|
|
});
|
2016-07-15 14:04:47 +02:00
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
lbry.resolveName(name, (info) => {
|
|
|
|
if (!info) {
|
|
|
|
this.setState({
|
|
|
|
name: name,
|
2016-07-20 08:25:22 +02:00
|
|
|
nameResolved: false,
|
2016-07-15 14:04:47 +02:00
|
|
|
});
|
|
|
|
} else {
|
|
|
|
lbry.search(name, (results) => {
|
|
|
|
var claimValue = results[0].value;
|
|
|
|
|
|
|
|
this.setState({
|
|
|
|
name: name,
|
|
|
|
nameResolved: true,
|
|
|
|
claimValue: parseFloat(claimValue),
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
});
|
|
|
|
},
|
2016-07-20 08:25:22 +02:00
|
|
|
handleBidChange: function(event) {
|
2016-07-15 14:04:47 +02:00
|
|
|
this.setState({
|
2016-07-20 08:25:22 +02:00
|
|
|
bid: event.target.value,
|
2016-07-15 14:04:47 +02:00
|
|
|
});
|
|
|
|
},
|
2016-07-20 08:25:22 +02:00
|
|
|
handleFeeChange: function(event) {
|
2016-07-15 14:04:47 +02:00
|
|
|
this.setState({
|
2016-07-20 08:25:22 +02:00
|
|
|
fee: event.target.value,
|
|
|
|
});
|
|
|
|
},
|
|
|
|
handleFileChange: function(event) {
|
|
|
|
event.preventDefault();
|
|
|
|
|
|
|
|
var fileInput = event.target;
|
|
|
|
|
|
|
|
this._tempFilePath = null;
|
|
|
|
if (fileInput.files.length == 0) {
|
|
|
|
// File was removed
|
|
|
|
this.setState({
|
|
|
|
fileInfo: null,
|
|
|
|
uploadProgress: 0.0,
|
|
|
|
uploaded: false,
|
|
|
|
tempFileReady: false,
|
|
|
|
});
|
|
|
|
} else {
|
|
|
|
var file = fileInput.files[0];
|
|
|
|
this.setState({
|
|
|
|
fileInfo: {
|
|
|
|
name: file.name,
|
|
|
|
size: file.size,
|
|
|
|
},
|
|
|
|
uploadProgress: 0.0,
|
|
|
|
uploaded: false,
|
|
|
|
tempFileReady: false,
|
|
|
|
});
|
|
|
|
|
|
|
|
var xhr = new XMLHttpRequest();
|
|
|
|
xhr.upload.addEventListener('progress', (event) => {
|
|
|
|
this.setState({
|
|
|
|
uploadProgress: (event.loaded / event.total),
|
|
|
|
});
|
|
|
|
});
|
|
|
|
xhr.upload.addEventListener('load', (event) => {
|
|
|
|
this.setState({
|
|
|
|
uploaded: true,
|
|
|
|
});
|
|
|
|
});
|
|
|
|
xhr.addEventListener('load', (event) => {
|
|
|
|
this._tempFilePath = JSON.parse(xhr.responseText);
|
|
|
|
this.setState({
|
|
|
|
tempFileReady: true,
|
|
|
|
});
|
|
|
|
})
|
|
|
|
|
|
|
|
xhr.open('POST', '/upload', true);
|
|
|
|
xhr.send(new FormData(fileInput.form));
|
|
|
|
}
|
|
|
|
},
|
|
|
|
handleFeePrefChange: function(feeEnabled) {
|
|
|
|
this.setState({
|
|
|
|
isFee: feeEnabled
|
2016-07-15 14:04:47 +02:00
|
|
|
});
|
|
|
|
},
|
|
|
|
readyToPublish: function() {
|
2016-07-20 08:25:22 +02:00
|
|
|
var bidFloat = parseFloat(this.state.bid);
|
|
|
|
return (this.state.name && this.state.fileInfo && !isNaN(bidFloat) && (!this.state.claimValue || bidFloat > this.state.claimValue));
|
2016-07-15 14:04:47 +02:00
|
|
|
},
|
2016-05-23 17:14:21 +02:00
|
|
|
render: function() {
|
2016-07-20 08:25:22 +02:00
|
|
|
if (this.state.fileInfo && !this.state.tempFileReady) {
|
|
|
|
// A file was chosen but the daemon hasn't finished processing it yet, i.e. it's loading, so
|
|
|
|
// we need a value for the progress bar.
|
|
|
|
|
|
|
|
if (!this.state.uploaded) {
|
|
|
|
// Still uploading
|
|
|
|
var progressOpts = {
|
|
|
|
value: this.state.uploadProgress,
|
|
|
|
};
|
|
|
|
} else {
|
|
|
|
// Fully uploaded and waiting for server to finish processing, so set progress bar to "indeterminite"
|
|
|
|
var progressOpts = {};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-05-23 17:14:21 +02:00
|
|
|
return (
|
2016-07-26 12:09:09 +02:00
|
|
|
<main className="page" ref="page">
|
2016-05-23 17:14:21 +02:00
|
|
|
<SubPageLogo />
|
2016-07-15 14:04:47 +02:00
|
|
|
<h1>Publish Content</h1>
|
2016-07-22 17:29:43 +02:00
|
|
|
<section className="section-block">
|
|
|
|
<h4>LBRY Name</h4>
|
2016-07-26 12:09:09 +02:00
|
|
|
lbry://<FormField type="text" ref="name" onChange={this.handleNameChange} />
|
2016-07-15 14:04:47 +02:00
|
|
|
{
|
|
|
|
(!this.state.name ? '' :
|
|
|
|
(this.state.nameResolved ? <em> This name is currently claimed for <strong>{lbry.formatCredits(this.state.claimValue)}</strong> credits</em>
|
|
|
|
: <em> This name is available</em>))
|
|
|
|
}
|
2016-07-22 17:29:43 +02:00
|
|
|
<div className="help">What LBRY name would you like to claim for this file?</div>
|
2016-05-23 17:14:21 +02:00
|
|
|
</section>
|
|
|
|
|
2016-07-22 17:29:43 +02:00
|
|
|
<section className="section-block">
|
|
|
|
<h4>Choose File</h4>
|
2016-07-20 08:25:22 +02:00
|
|
|
<form>
|
2016-07-26 12:09:09 +02:00
|
|
|
<FormField name="file" ref="file" type="file" onChange={this.handleFileChange} />
|
2016-07-20 08:25:22 +02:00
|
|
|
{ !this.state.fileInfo ? '' :
|
|
|
|
(!this.state.tempFileReady ? <div>
|
|
|
|
<progress {...progressOpts}></progress>
|
|
|
|
{!this.state.uploaded ? <span> Importing file into LBRY...</span> : <span> Processing file...</span>}
|
|
|
|
</div>
|
|
|
|
: <div>File ready for publishing!</div>) }
|
|
|
|
</form>
|
2016-05-23 17:14:21 +02:00
|
|
|
</section>
|
|
|
|
|
2016-07-22 17:29:43 +02:00
|
|
|
<section className="section-block">
|
|
|
|
<h4>Bid Amount</h4>
|
2016-07-26 12:09:09 +02:00
|
|
|
Credits <FormField style={publishNumberStyle} type="text" onChange={this.handleBidChange} value={this.state.bid} placeholder={this.state.nameResolved ? lbry.formatCredits(this.state.claimValue + 10) : 100} />
|
2016-07-20 08:25:22 +02:00
|
|
|
{this.state.bid && isNaN(this.state.bid) ? <span className="warning"> Must be a number</span> : ''}
|
2016-07-22 17:29:43 +02:00
|
|
|
<div className="help">How much would you like to bid for this name?
|
|
|
|
{ !this.state.nameResolved ? <span> Since this name is not currently resolved, you may bid as low as you want, but higher bids help prevent others from claiming your name.</span>
|
|
|
|
: <span> You must bid over <strong>{lbry.formatCredits(this.state.claimValue)}</strong> credits to claim this name.</span> }
|
|
|
|
</div>
|
2016-07-20 08:25:22 +02:00
|
|
|
</section>
|
|
|
|
|
2016-07-22 17:29:43 +02:00
|
|
|
<section className="section-block">
|
2016-07-20 08:25:22 +02:00
|
|
|
<h4>Fee</h4>
|
2016-07-22 17:29:43 +02:00
|
|
|
<div className="spacer-bottom--sm">
|
|
|
|
<label>
|
2016-07-26 12:09:09 +02:00
|
|
|
<FormField type="radio" onChange={ () => { this.handleFeePrefChange(false) } } checked={!this.state.isFee} /> No fee
|
2016-07-22 17:29:43 +02:00
|
|
|
</label>
|
|
|
|
<label>
|
2016-07-26 12:09:09 +02:00
|
|
|
<FormField type="radio" onChange={ () => { this.handleFeePrefChange(true) } } checked={this.state.isFee} /> { !this.state.isFee ? 'Choose fee...' : 'Fee (in LBRY credits) ' }
|
|
|
|
<FormField type="text" hidden={!this.state.isFee} onChange={this.handleFeeChange} placeholder="5.5" style={publishNumberStyle} />
|
2016-07-22 17:29:43 +02:00
|
|
|
{this.state.fee && isNaN(this.state.fee) ? <span className="warning"> Must be a number</span> : ''}
|
|
|
|
</label>
|
|
|
|
</div>
|
|
|
|
<div className="help">How much would you like to charge for this file? </div>
|
2016-05-23 17:14:21 +02:00
|
|
|
</section>
|
|
|
|
|
2016-07-20 08:25:22 +02:00
|
|
|
|
2016-07-22 17:29:43 +02:00
|
|
|
<section className="section-block">
|
|
|
|
<h4>Your Content</h4>
|
2016-07-20 08:25:22 +02:00
|
|
|
|
2016-07-26 12:09:09 +02:00
|
|
|
<label htmlFor="title">Title</label><FormField type="text" ref="meta_title" name="title" placeholder="My Show, Episode 1" style={publishFieldStyle} />
|
|
|
|
<label htmlFor="author">Author</label><FormField type="text" ref="meta_author" name="author" placeholder="My Company, Inc." style={publishFieldStyle} />
|
|
|
|
<label htmlFor="license">License info</label><FormField type="text" ref="meta_license" name="license" defaultValue="Creative Commons Attribution 3.0 United States" style={publishFieldStyle} />
|
|
|
|
<label htmlFor="language">Language</label> <FormField type="select" ref="meta_language" name="language">
|
2016-07-20 08:25:22 +02:00
|
|
|
<option value="en" selected>English</option>
|
|
|
|
<option value="zh">Chinese</option>
|
|
|
|
<option value="fr">French</option>
|
|
|
|
<option value="de">German</option>
|
|
|
|
<option value="jp">Japanese</option>
|
|
|
|
<option value="ru">Russian</option>
|
|
|
|
<option value="es">Spanish</option>
|
2016-07-26 12:09:09 +02:00
|
|
|
</FormField>
|
2016-07-20 08:25:22 +02:00
|
|
|
|
2016-07-26 12:09:09 +02:00
|
|
|
<label htmlFor="description">Description</label> <FormField type="textarea" ref="meta_description" name="description" placeholder="Description of your content" style={publishFieldStyle} />
|
2016-07-20 08:25:22 +02:00
|
|
|
</section>
|
|
|
|
|
2016-07-22 17:29:43 +02:00
|
|
|
|
2016-07-20 08:25:22 +02:00
|
|
|
|
2016-07-26 12:09:09 +02:00
|
|
|
<section className="section-block">
|
|
|
|
<h4>Additional Content Information (Optional)</h4>
|
|
|
|
<label htmlFor="meta_thumbnail">Thumbnail URL</label> <FormField type="text" ref="meta_thumbnail" name="thumbnail" placeholder="http://mycompany.com/images/ep_1.jpg" style={publishFieldStyle} />
|
|
|
|
<label htmlFor="meta_license_url">License URL</label> <FormField type="text" ref="meta_license_url" name="license_url" defaultValue="https://creativecommons.org/licenses/by/3.0/us/legalcode" style={publishFieldStyle} />
|
|
|
|
</section>
|
2016-05-23 17:14:21 +02:00
|
|
|
|
2016-07-22 17:29:43 +02:00
|
|
|
<div className="footer-buttons">
|
|
|
|
<Link button="alt" href="/" label="Cancel"/>
|
2016-07-26 12:09:09 +02:00
|
|
|
<Link button="primary" label="Publish" onClick={this.handleSubmit} disabled={this.state.submitting} />
|
2016-07-22 17:29:43 +02:00
|
|
|
</div>
|
2016-05-23 17:14:21 +02:00
|
|
|
</main>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
});
|