added input for video thumbnail link

This commit is contained in:
bill bittner 2017-10-09 18:29:40 -07:00
parent 58bece6efc
commit 1b37ef91a4
15 changed files with 98 additions and 51 deletions

View file

@ -44,6 +44,7 @@ spee.ch is a single-serving site that reads and publishes images and videos to a
* license (string, optional)
* title (string, optional)
* description (string, optional)
* thumbnail (string, optional) (for .mp4 uploads only)
* channelName(string, optional)
* channelPassword (string, optional)

View file

@ -16,6 +16,7 @@ module.exports = {
return db.Channel.findOne({where: {channelName: publishParams.channel_name}});
})
.then(user => {
logger.debug('user:', user);
let certificateId;
if (user) {
certificateId = user.channelClaimId;

View file

@ -2,14 +2,14 @@ const axios = require('axios');
const logger = require('winston');
function handleResponse ({ data }, resolve, reject) {
logger.debug('handling lbry api response');
logger.debug('handling lbry api response...');
if (data.result) {
// check for an error
if (data.result.error) {
reject(data.result.error);
return;
};
logger.debug('data.result', data.result);
// logger.debug('data.result', data.result);
resolve(data.result);
return;
}

View file

@ -111,7 +111,7 @@ module.exports = {
}
throw new Error('NSFW must be set to either true or false');
},
createPublishParams (filePath, name, title, description, license, nsfw, channelName) {
createPublishParams (filePath, name, title, description, license, nsfw, thumbnail, channelName) {
logger.debug(`Creating Publish Parameters`);
// provide defaults for title
if (title === null || title.trim() === '') {
@ -140,6 +140,10 @@ module.exports = {
},
claim_address: config.get('WalletConfig.LbryClaimAddress'),
};
// add thumbnail to channel if video
if (thumbnail !== null) {
publishParams['metadata']['thumbnail'] = thumbnail;
}
// add channel to params, if applicable
if (channelName) {
publishParams['channel_name'] = channelName;

View file

@ -268,20 +268,20 @@ option {
/* modifiers */
.input-text--primary, .select--primary, .textarea--primary {
border-bottom: 1px solid dodgerblue;
border-bottom: 1px solid grey;
}
.input-text--primary:focus, .select--primary:focus, .textarea--primary:focus {
border-bottom: 1px solid dodgerblue;
border-bottom: 1px solid lightgrey;
}
.input-text--large, .select--large, .textarea--large {
font-size: 1.5rem;
border-left: 1px solid dodgerblue;
border-left: 1px solid grey;
}
.input-text--large:focus, .select--large:focus, .textarea--large:focus {
border-left: 1px solid dodgerblue;
border-left: 1px solid lightgrey;
}
.input-text--full-width, .textarea--full-width {

View file

@ -84,7 +84,7 @@
width: 100%;
}
#publish-active-area > .row, #details-detail > .row, #channel-login-form > .row, #publish-channel-form > .row {
#publish-active-area > .row, #publish-details > .row, #channel-login-form > .row, #publish-channel-form > .row {
padding: 1em 0px 1em 0px;
}
}

View file

@ -12,14 +12,16 @@ function previewAndStageFile(selectedFile){
const primaryDropzone = document.getElementById('primary-dropzone-wrapper');
const previewReader = new FileReader();
const nameInput = document.getElementById('claim-name-input');
const fileSelectionError = document.getElementById('input-error-file-selection');
const fileSelectionInputError = document.getElementById('input-error-file-selection');
const thumbnailSelectionTool = document.getElementById('publish-thumbnail');
const thumbnailSelectionInput = document.getElementById('claim-thumbnail-input');
// validate the file's name, type, and size
try {
console.log('validating file');
validateFile(selectedFile);
} catch (error) {
console.log('file validation failed with error:', error);
showError(fileSelectionError, error.message);
showError(fileSelectionInputError, error.message);
return;
}
// set the image preview, if an image was provided
@ -32,8 +34,14 @@ function previewAndStageFile(selectedFile){
previewReader.onloadend = function () {
assetPreview.innerHTML = '<img id="asset-preview" src="' + previewReader.result + '" alt="image preview"/>';
};
// clear & hide the thumbnail selection input
thumbnailSelectionInput.value = '';
thumbnailSelectionTool.hidden = true;
} else {
assetPreview.innerHTML = `<img id="asset-preview" src="/assets/img/black_video_play.jpg"/>`
assetPreview.innerHTML = `<img id="asset-preview" src="/assets/img/black_video_play.jpg"/>`;
// clear & show the thumbnail selection input
thumbnailSelectionInput.value = '';
thumbnailSelectionTool.hidden = false;
}
// hide the drop zone
primaryDropzone.hidden = true;
@ -55,12 +63,12 @@ function publishStagedFile(event) {
// declare variables
const claimName = document.getElementById('claim-name-input').value;
let channelName = document.getElementById('channel-name-select').value;
const fileSelectionError = document.getElementById('input-error-file-selection');
const fileSelectionInputError = document.getElementById('input-error-file-selection');
const claimNameError = document.getElementById('input-error-claim-name');
const channelSelectError = document.getElementById('input-error-channel-select');
const publishSubmitError = document.getElementById('input-error-publish-submit');
let anonymousOrInChannel;
// replace channelName with 'anonymous' if needed
// replace channelName with 'anonymous' if appropriate
const radios = document.getElementsByName('anonymous-or-channel');
for (let i = 0; i < radios.length; i++) {
if (radios[i].checked) {
@ -70,7 +78,9 @@ function publishStagedFile(event) {
break;
}
}
if (anonymousOrInChannel === 'anonymous') {channelName = 'anonymous'};
if (anonymousOrInChannel === 'anonymous') {
channelName = null;
};
console.log('channel name:', channelName);
// validate, submit, and handle response
validateFilePublishSubmission(stagedFiles, claimName, channelName)
@ -79,7 +89,7 @@ function publishStagedFile(event) {
})
.catch(error => {
if (error.name === 'FileError') {
showError(fileSelectionError, error.message);
showError(fileSelectionInputError, error.message);
} else if (error.name === 'NameError') {
showError(claimNameError, error.message);
} else if (error.name === 'ChannelNameError'){

View file

@ -25,7 +25,7 @@ module.exports = (app) => {
});
});
// route to check whether spee.ch has published to a claim
app.get('/api/isClaimAvailable/:name', ({ ip, originalUrl, params }, res) => {
app.get('/api/isClaimAvailable/:name', ({ params }, res) => {
// send response
checkClaimNameAvailability(params.name)
.then(result => {
@ -72,7 +72,8 @@ module.exports = (app) => {
});
// route to run a publish request on the daemon
app.post('/api/publish', multipartMiddleware, (req, res) => {
logger.debug(req);
logger.debug('req:', req);
// validate that mandatory parts of the request are present
const body = req.body;
const files = req.files;
try {
@ -82,16 +83,14 @@ module.exports = (app) => {
res.status(400).json({success: false, message: error.message});
return;
}
// required inputs
// validate file, name, license, and nsfw
const file = files.file;
const fileName = file.name;
const filePath = file.path;
const fileType = file.type;
const name = body.name;
let nsfw = body.nsfw;
// cleanse nsfw
nsfw = cleanseNSFW(nsfw);
// validate file, name, license, and nsfw
nsfw = cleanseNSFW(nsfw); // cleanse nsfw
try {
validatePublishSubmission(file, name, nsfw);
} catch (error) {
@ -104,6 +103,7 @@ module.exports = (app) => {
const license = body.license || null;
const title = body.title || null;
const description = body.description || null;
const thumbnail = body.thumbnail || null;
let channelName = body.channelName || null;
channelName = cleanseChannelName(channelName);
const channelPassword = body.channelPassword || null;
@ -122,7 +122,7 @@ module.exports = (app) => {
throw new Error('That name is already in use by spee.ch.');
}
// create publish parameters object
return createPublishParams(filePath, name, title, description, license, nsfw, channelName);
return createPublishParams(filePath, name, title, description, license, nsfw, thumbnail, channelName);
})
.then(publishParams => {
logger.debug('publishParams:', publishParams);

View file

@ -9,7 +9,7 @@ module.exports = (app) => {
});
// route for log in
app.post('/login', passport.authenticate('local-login'), (req, res) => {
logger.debug(req.user);
logger.debug('req.user:', req.user);
logger.debug('successful login');
res.status(200).json({
success : true,

View file

@ -35,16 +35,25 @@ module.exports = (app, siofu, hostedContentPath) => {
if (file.success) {
logger.debug(`Client successfully uploaded ${file.name}`);
socket.emit('publish-status', 'File upload successfully completed. Your image is being published to LBRY (this might take a second)...');
/*
NOTE: need to validate that client has the credentials to the channel they chose
otherwise they could circumvent security client side.
*/
let channelName = file.meta.channel;
if (channelName === 'none') channelName = null;
// /*
// NOTE: need to validate that client has the credentials to the channel they chose
// otherwise they could circumvent security.
// */
let thumbnail;
if (file.meta.thumbnail) {
thumbnail = file.meta.thumbnail;
} else {
thumbnail = null;
}
let channelName;
if (file.meta.channel) {
channelName = file.meta.channel;
} else {
channelName = null;
}
// prepare the publish parameters
const publishParams = createPublishParams(file.pathName, file.meta.name, file.meta.title, file.meta.description, file.meta.license, file.meta.nsfw, channelName);
logger.debug(publishParams);
const publishParams = createPublishParams(file.pathName, file.meta.name, file.meta.title, file.meta.description, file.meta.license, file.meta.nsfw, thumbnail, channelName);
logger.debug('publish parameters:', publishParams);
// publish the file
publish(publishParams, file.name, file.meta.type)
.then(result => {

View file

@ -34,7 +34,7 @@ app.use(bodyParser.urlencoded({ extended: true })); // 'body parser' for parsing
app.use(siofu.router); // 'socketio-file-upload' router for uploading with socket.io
app.use((req, res, next) => { // custom logging middleware to log all incoming http requests
logger.verbose(`Request on ${req.originalUrl} from ${req.ip}`);
logger.debug(req.body);
logger.debug('req.body:', req.body);
next();
});

View file

@ -48,6 +48,7 @@
<div id="publish-active-area">
{{> publishForm-Channel}}
{{> publishForm-Url}}
{{> publishForm-Thumbnail}}
{{> publishForm-Details}}
{{> publishForm-Submit}}
</div>
@ -107,19 +108,29 @@
document.getElementById('publish-status').innerHTML = msg;
}
uploader.addEventListener('start', function(event){
var name = document.getElementById('claim-name-input').value;
var title = document.getElementById('publish-title').value;
var description = document.getElementById('publish-description').value;
var license = document.getElementById('publish-license').value;
var nsfw = document.getElementById('publish-nsfw').checked;
var channel = document.getElementById('channel-name-select').value;
console.log('starting upload');
const name = document.getElementById('claim-name-input').value;
const title = document.getElementById('publish-title').value;
const description = document.getElementById('publish-description').value;
const license = document.getElementById('publish-license').value;
const nsfw = document.getElementById('publish-nsfw').checked;
const anonymous = document.getElementById('anonymous-select').checked;
console.log('anonymous?', anonymous);
const channel = document.getElementById('channel-name-select').value;
console.log('channel:', channel);
const thumbnail = document.getElementById('claim-thumbnail-input').value;
event.file.meta.name = name;
event.file.meta.title = title;
event.file.meta.description = description;
event.file.meta.license = license;
event.file.meta.nsfw = nsfw;
event.file.meta.type = stagedFiles[0].type;
if (!anonymous) {
event.file.meta.channel = channel;
}
if (thumbnail && (thumbnail.trim !== '')){
event.file.meta.thumbnail = thumbnail;
}
// hide the submit area
document.getElementById('publish-active-area').hidden = true;
// show the progress status and animation
@ -146,6 +157,7 @@
document.getElementById('publish-progress-bar').hidden = true;
});
socket.on('publish-complete', function(msg){
console.log(msg);
var showUrl = msg.result.claim_id + "/" + msg.name;
// update status
updatePublishStatus('<p>Your publish is complete! You are being redirected to it now.</p><p><a target="_blank" href="' + showUrl + '">If you do not get redirected, click here.</a></p>');

View file

@ -1,4 +1,4 @@
<div id="details-detail" hidden="true">
<div id="publish-details" hidden="true">
<div class="row row--short">
<div class="column column--3 column--sml-10">
@ -22,7 +22,7 @@
<div class="row">
<div class="column column--10">
<a class="label" id="details-toggle" href="#" onclick="toggleSection(event)" data-open="false" data-openlabel="[less]" data-closedlabel="[more]" data-slaveelementid="details-detail">[more]</a>
<a class="label" id="details-toggle" href="#" onclick="toggleSection(event)" data-open="false" data-openlabel="[less]" data-closedlabel="[more]" data-slaveelementid="publish-details">[more]</a>
</div>
</div>

View file

@ -0,0 +1,10 @@
<div class="row" id="publish-thumbnail" hidden="true">
<div class="column column--3 column--sml-10">
<label class="label">Thumbnail:</label>
</div><div class="column column--6 column--sml-10">
<div class="input-text--primary">
<input type="text" id="claim-thumbnail-input" class="input-text input-text--full-width" placeholder="https://spee.ch/xyz/example.jpg" value="">
</div>
</div>
</div>

View file

@ -6,15 +6,15 @@
<a class="nav-bar-link" href="/">Upload</a>
<a class="nav-bar-link" href="/popular">Popular</a>
<a class="nav-bar-link" href="/about">About</a>
<!--{{#if user}}-->
<!--<select type="text" class="select select--no-arrow nav-bar-link" onchange="toggleLogin(event)">-->
<!--<option value="{{user.channelName}}:{{user.channelClaimId}}">@{{user.userName}}</option>-->
<!--<option value="view">View</option>-->
<!--<option value="logout">Logout</option>-->
<!--</select>-->
<!--{{else}}-->
<!--<a class="nav-bar-link" href="/login">Login</a>-->
<!--{{/if}}-->
{{#if user}}
<select type="text" class="select select--no-arrow nav-bar-link" onchange="toggleLogin(event)">
<option value="{{user.channelName}}:{{user.channelClaimId}}">@{{user.userName}}</option>
<option value="view">View</option>
<option value="logout">Logout</option>
</select>
{{else}}
<a class="nav-bar-link" href="/login">Login</a>
{{/if}}
</div>
</div>