added input for video thumbnail link
This commit is contained in:
parent
58bece6efc
commit
1b37ef91a4
15 changed files with 98 additions and 51 deletions
|
@ -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)
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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'){
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 => {
|
||||
|
|
|
@ -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();
|
||||
});
|
||||
|
||||
|
|
|
@ -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>');
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
|
10
views/partials/publishForm-Thumbnail.handlebars
Normal file
10
views/partials/publishForm-Thumbnail.handlebars
Normal 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>
|
|
@ -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>
|
||||
|
||||
|
|
Loading…
Reference in a new issue