set up basic AssetDisplay functionality and removed unnecessary handlebars/js
This commit is contained in:
parent
bfa623ec17
commit
97a6254370
21 changed files with 238 additions and 651 deletions
|
@ -1,139 +0,0 @@
|
||||||
const Asset = function () {
|
|
||||||
this.data = {};
|
|
||||||
this.addPlayPauseToVideo = function () {
|
|
||||||
const that = this;
|
|
||||||
const video = document.getElementById('video-asset');
|
|
||||||
if (video) {
|
|
||||||
// add event listener for click
|
|
||||||
video.addEventListener('click', ()=> {
|
|
||||||
that.playOrPause(video);
|
|
||||||
});
|
|
||||||
// add event listener for space bar
|
|
||||||
document.body.onkeyup = (event) => {
|
|
||||||
if (event.keyCode == 32) {
|
|
||||||
that.playOrPause(video);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
this.playOrPause = function(video){
|
|
||||||
if (video.paused == true) {
|
|
||||||
video.play();
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
video.pause();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
this.showAsset = function () {
|
|
||||||
this.hideAssetStatus();
|
|
||||||
this.showAssetHolder();
|
|
||||||
if (!this.data.src) {
|
|
||||||
return console.log('error: src is not set')
|
|
||||||
}
|
|
||||||
if (!this.data.contentType) {
|
|
||||||
return console.log('error: contentType is not set')
|
|
||||||
}
|
|
||||||
if (this.data.contentType === 'video/mp4') {
|
|
||||||
this.showVideo();
|
|
||||||
} else {
|
|
||||||
this.showImage();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
this.showVideo = function () {
|
|
||||||
console.log('showing video', this.data.src);
|
|
||||||
const video = document.getElementById('video-asset');
|
|
||||||
const source = document.createElement('source');
|
|
||||||
source.setAttribute('src', this.data.src);
|
|
||||||
video.appendChild(source);
|
|
||||||
video.play();
|
|
||||||
};
|
|
||||||
this.showImage = function () {
|
|
||||||
console.log('showing image', this.data.src);
|
|
||||||
const asset = document.getElementById('image-asset');
|
|
||||||
asset.setAttribute('src', this.data.src);
|
|
||||||
};
|
|
||||||
this.hideAssetStatus = function () {
|
|
||||||
const assetStatus = document.getElementById('asset-status');
|
|
||||||
assetStatus.hidden = true;
|
|
||||||
};
|
|
||||||
this.showAssetHolder =function () {
|
|
||||||
const assetHolder = document.getElementById('asset-holder');
|
|
||||||
assetHolder.hidden = false;
|
|
||||||
};
|
|
||||||
this.showSearchMessage = function () {
|
|
||||||
const searchMessage = document.getElementById('searching-message');
|
|
||||||
searchMessage.hidden = false;
|
|
||||||
};
|
|
||||||
this.showFailureMessage = function (msg) {
|
|
||||||
console.log(msg);
|
|
||||||
const searchMessage = document.getElementById('searching-message');
|
|
||||||
const failureMessage = document.getElementById('failure-message');
|
|
||||||
const errorMessage = document.getElementById('error-message');
|
|
||||||
searchMessage.hidden = true;
|
|
||||||
failureMessage.hidden = false;
|
|
||||||
errorMessage.innerText = msg;
|
|
||||||
};
|
|
||||||
this.checkFileAndRenderAsset = function () {
|
|
||||||
const that = this;
|
|
||||||
this.isFileAvailable()
|
|
||||||
.then(isAvailable => {
|
|
||||||
if (!isAvailable) {
|
|
||||||
console.log('file is not yet available');
|
|
||||||
that.showSearchMessage();
|
|
||||||
return that.getAssetOnSpeech();
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.then(() => {
|
|
||||||
that.showAsset();
|
|
||||||
})
|
|
||||||
.catch(error => {
|
|
||||||
that.showFailureMessage(error);
|
|
||||||
})
|
|
||||||
};
|
|
||||||
this.isFileAvailable = function () {
|
|
||||||
console.log(`checking if file is available for ${this.data.claimName}#${this.data.claimId}`)
|
|
||||||
const uri = `/api/file-is-available/${this.data.claimName}/${this.data.claimId}`;
|
|
||||||
const xhr = new XMLHttpRequest();
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
xhr.open("GET", uri, true);
|
|
||||||
xhr.onreadystatechange = function() {
|
|
||||||
if (xhr.readyState == 4) {
|
|
||||||
const response = JSON.parse(xhr.response);
|
|
||||||
if (xhr.status == 200) {
|
|
||||||
console.log('isFileAvailable succeeded:', response);
|
|
||||||
if (response.message === true) {
|
|
||||||
resolve(true);
|
|
||||||
} else {
|
|
||||||
resolve(false);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
console.log('isFileAvailable failed:', response);
|
|
||||||
reject('Well this sucks, but we can\'t seem to phone home');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
xhr.send();
|
|
||||||
})
|
|
||||||
};
|
|
||||||
this.getAssetOnSpeech = function() {
|
|
||||||
console.log(`getting claim for ${this.data.claimName}#${this.data.claimId}`)
|
|
||||||
const uri = `/api/claim-get/${this.data.claimName}/${this.data.claimId}`;
|
|
||||||
const xhr = new XMLHttpRequest();
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
xhr.open("GET", uri, true);
|
|
||||||
xhr.onreadystatechange = function() {
|
|
||||||
if (xhr.readyState == 4) {
|
|
||||||
const response = JSON.parse(xhr.response);
|
|
||||||
if (xhr.status == 200) {
|
|
||||||
console.log('getAssetOnSpeech succeeded:', response)
|
|
||||||
resolve(true);
|
|
||||||
} else {
|
|
||||||
console.log('getAssetOnSpeech failed:', response);
|
|
||||||
reject(response.message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
xhr.send();
|
|
||||||
})
|
|
||||||
};
|
|
||||||
};
|
|
|
@ -1,65 +0,0 @@
|
||||||
// display the content that shows channel creation has started
|
|
||||||
function showChannelCreateInProgressDisplay () {
|
|
||||||
const publishChannelForm = document.getElementById('publish-channel-form');
|
|
||||||
const inProgress = document.getElementById('channel-publish-in-progress');
|
|
||||||
publishChannelForm.hidden = true;
|
|
||||||
inProgress.hidden = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// display the content that shows channel creation is done
|
|
||||||
function showChannelCreateDoneDisplay() {
|
|
||||||
const inProgress = document.getElementById('channel-publish-in-progress');
|
|
||||||
inProgress.hidden=true;
|
|
||||||
const done = document.getElementById('channel-publish-done');
|
|
||||||
done.hidden = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
function showChannelCreationError(msg) {
|
|
||||||
const inProgress = document.getElementById('channel-publish-in-progress');
|
|
||||||
inProgress.innerText = msg;
|
|
||||||
}
|
|
||||||
|
|
||||||
function publishNewChannel (event) {
|
|
||||||
const username = document.getElementById('new-channel-name').value;
|
|
||||||
const password = document.getElementById('new-channel-password').value;
|
|
||||||
// prevent default so this script can handle submission
|
|
||||||
event.preventDefault();
|
|
||||||
// validate submission
|
|
||||||
validationFunctions.validateNewChannelSubmission(username, password)
|
|
||||||
.then(() => {
|
|
||||||
showChannelCreateInProgressDisplay();
|
|
||||||
// return sendAuthRequest(userName, password, '/signup') // post the request
|
|
||||||
return fetch('/signup', {
|
|
||||||
method: 'POST',
|
|
||||||
body: JSON.stringify({username, password}),
|
|
||||||
headers: new Headers({
|
|
||||||
'Content-Type': 'application/json'
|
|
||||||
}),
|
|
||||||
credentials: 'include',
|
|
||||||
})
|
|
||||||
.then(function(response) {
|
|
||||||
if (response.ok){
|
|
||||||
return response.json();
|
|
||||||
} else {
|
|
||||||
throw response;
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch(function(error) {
|
|
||||||
throw error;
|
|
||||||
})
|
|
||||||
})
|
|
||||||
.then(signupResult => {
|
|
||||||
console.log('signup success:', signupResult);
|
|
||||||
showChannelCreateDoneDisplay();
|
|
||||||
window.location = '/';
|
|
||||||
})
|
|
||||||
.catch(error => {
|
|
||||||
if (error.name === 'ChannelNameError' || error.name === 'ChannelPasswordError'){
|
|
||||||
const channelNameErrorDisplayElement = document.getElementById('input-error-channel-name');
|
|
||||||
validationFunctions.showError(channelNameErrorDisplayElement, error.message);
|
|
||||||
} else {
|
|
||||||
console.log('signup failure:', error);
|
|
||||||
showChannelCreationError('Unfortunately, we encountered an error while creating your channel. Please let us know in slack!', error);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
|
@ -1,44 +0,0 @@
|
||||||
function loginToChannel (event) {
|
|
||||||
const username = document.getElementById('channel-login-name-input').value;
|
|
||||||
const password = document.getElementById('channel-login-password-input').value;
|
|
||||||
// prevent default
|
|
||||||
event.preventDefault()
|
|
||||||
validationFunctions.validateNewChannelLogin(username, password)
|
|
||||||
.then(() => {
|
|
||||||
return fetch('/login', {
|
|
||||||
method: 'POST',
|
|
||||||
body: JSON.stringify({username, password}),
|
|
||||||
headers: new Headers({
|
|
||||||
'Content-Type': 'application/json'
|
|
||||||
}),
|
|
||||||
credentials: 'include',
|
|
||||||
})
|
|
||||||
.then(function(response) {
|
|
||||||
console.log(response);
|
|
||||||
if (response.ok){
|
|
||||||
return response.json();
|
|
||||||
} else {
|
|
||||||
throw response;
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch(function(error) {
|
|
||||||
throw error;
|
|
||||||
})
|
|
||||||
})
|
|
||||||
.then(function({success, message}) {
|
|
||||||
if (success) {
|
|
||||||
window.location = '/';
|
|
||||||
} else {
|
|
||||||
throw new Error(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
})
|
|
||||||
.catch(error => {
|
|
||||||
const loginErrorDisplayElement = document.getElementById('login-error-display-element');
|
|
||||||
if (error.message){
|
|
||||||
validationFunctions.showError(loginErrorDisplayElement, error.message);
|
|
||||||
} else {
|
|
||||||
validationFunctions.showError(loginErrorDisplayElement, 'There was an error logging into your channel');
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
|
@ -1,45 +0,0 @@
|
||||||
const ProgressBar = function() {
|
|
||||||
this.data = {
|
|
||||||
x: 0,
|
|
||||||
adder: 1,
|
|
||||||
bars: [],
|
|
||||||
};
|
|
||||||
this.barHolder = document.getElementById('bar-holder');
|
|
||||||
this.createProgressBar = function (size) {
|
|
||||||
this.data['size'] = size;
|
|
||||||
for (var i = 0; i < size; i++) {
|
|
||||||
const bar = document.createElement('span');
|
|
||||||
bar.innerText = '| ';
|
|
||||||
bar.setAttribute('class', 'progress-bar progress-bar--inactive');
|
|
||||||
this.barHolder.appendChild(bar);
|
|
||||||
this.data.bars.push(bar);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
this.startProgressBar = function () {
|
|
||||||
this.updateInterval = setInterval(this.updateProgressBar.bind(this), 300);
|
|
||||||
};
|
|
||||||
this.updateProgressBar = function () {
|
|
||||||
const x = this.data.x;
|
|
||||||
const adder = this.data.adder;
|
|
||||||
const size = this.data.size;
|
|
||||||
// update the appropriate bar
|
|
||||||
if (x > -1 && x < size){
|
|
||||||
if (adder === 1){
|
|
||||||
this.data.bars[x].setAttribute('class', 'progress-bar progress-bar--active');
|
|
||||||
} else {
|
|
||||||
this.data.bars[x].setAttribute('class', 'progress-bar progress-bar--inactive');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// update adder
|
|
||||||
if (x === size){
|
|
||||||
this.data['adder'] = -1;
|
|
||||||
} else if ( x === -1){
|
|
||||||
this.data['adder'] = 1;
|
|
||||||
}
|
|
||||||
// update x
|
|
||||||
this.data['x'] = x + adder;
|
|
||||||
};
|
|
||||||
this.stopProgressBar = function () {
|
|
||||||
clearInterval(this.updateInterval);
|
|
||||||
};
|
|
||||||
};
|
|
|
@ -1,132 +0,0 @@
|
||||||
// validation function which checks the proposed file's type, size, and name
|
|
||||||
const validationFunctions = {
|
|
||||||
validateChannelName: function (name) {
|
|
||||||
name = name.substring(name.indexOf('@') + 1);
|
|
||||||
// ensure a name was entered
|
|
||||||
if (name.length < 1) {
|
|
||||||
throw new ChannelNameError("You must enter a name for your channel");
|
|
||||||
}
|
|
||||||
// validate the characters in the 'name' field
|
|
||||||
const invalidCharacters = /[^A-Za-z0-9,-,@]/g.exec(name);
|
|
||||||
if (invalidCharacters) {
|
|
||||||
throw new ChannelNameError('"' + invalidCharacters + '" characters are not allowed');
|
|
||||||
}
|
|
||||||
},
|
|
||||||
validatePassword: function (password) {
|
|
||||||
if (password.length < 1) {
|
|
||||||
throw new ChannelPasswordError("You must enter a password for you channel");
|
|
||||||
}
|
|
||||||
},
|
|
||||||
// validation functions to check claim & channel name eligibility as the inputs change
|
|
||||||
isChannelNameAvailable: function (name) {
|
|
||||||
return this.isNameAvailable(name, '/api/channel-is-available/');
|
|
||||||
},
|
|
||||||
isNameAvailable: function (name, apiUrl) {
|
|
||||||
console.log('isNameAvailable?', name);
|
|
||||||
const url = apiUrl + name;
|
|
||||||
return fetch(url)
|
|
||||||
.then(function (response) {
|
|
||||||
return response.json();
|
|
||||||
})
|
|
||||||
.catch(error => {
|
|
||||||
console.log('isNameAvailable error', error);
|
|
||||||
throw error;
|
|
||||||
})
|
|
||||||
},
|
|
||||||
showError: function (errorDisplay, errorMsg) {
|
|
||||||
errorDisplay.hidden = false;
|
|
||||||
errorDisplay.innerText = errorMsg;
|
|
||||||
},
|
|
||||||
hideError: function (errorDisplay) {
|
|
||||||
errorDisplay.hidden = true;
|
|
||||||
errorDisplay.innerText = '';
|
|
||||||
},
|
|
||||||
showSuccess: function (successElement) {
|
|
||||||
successElement.hidden = false;
|
|
||||||
successElement.innerHTML = "✔";
|
|
||||||
},
|
|
||||||
hideSuccess: function (successElement) {
|
|
||||||
successElement.hidden = true;
|
|
||||||
successElement.innerHTML = "";
|
|
||||||
},
|
|
||||||
checkChannelName: function (name) {
|
|
||||||
var successDisplayElement = document.getElementById('input-success-channel-name');
|
|
||||||
var errorDisplayElement = document.getElementById('input-error-channel-name');
|
|
||||||
var channelName = `@${name}`;
|
|
||||||
var that = this;
|
|
||||||
try {
|
|
||||||
// check to make sure the characters are valid
|
|
||||||
that.validateChannelName(channelName);
|
|
||||||
// check to make sure it is available
|
|
||||||
that.isChannelNameAvailable(channelName)
|
|
||||||
.then(function(isAvailable){
|
|
||||||
console.log('isChannelNameAvailable:', isAvailable);
|
|
||||||
if (isAvailable) {
|
|
||||||
that.hideError(errorDisplayElement);
|
|
||||||
that.showSuccess(successDisplayElement)
|
|
||||||
} else {
|
|
||||||
that.hideSuccess(successDisplayElement);
|
|
||||||
that.showError(errorDisplayElement, 'Sorry, that name is already taken');
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch(error => {
|
|
||||||
that.hideSuccess(successDisplayElement);
|
|
||||||
that.showError(errorDisplayElement, error.message);
|
|
||||||
});
|
|
||||||
} catch (error) {
|
|
||||||
that.hideSuccess(successDisplayElement);
|
|
||||||
that.showError(errorDisplayElement, error.message);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
// validation function which checks all aspects of a new channel submission
|
|
||||||
validateNewChannelSubmission: function (userName, password) {
|
|
||||||
const channelName = `@${userName}`;
|
|
||||||
var that = this;
|
|
||||||
return new Promise(function (resolve, reject) {
|
|
||||||
// 1. validate name
|
|
||||||
try {
|
|
||||||
that.validateChannelName(channelName);
|
|
||||||
} catch (error) {
|
|
||||||
return reject(error);
|
|
||||||
}
|
|
||||||
// 2. validate password
|
|
||||||
try {
|
|
||||||
that.validatePassword(password);
|
|
||||||
} catch (error) {
|
|
||||||
return reject(error);
|
|
||||||
}
|
|
||||||
// 3. if all validation passes, check availability of the name
|
|
||||||
that.isChannelNameAvailable(channelName)
|
|
||||||
.then(function(isAvailable) {
|
|
||||||
if (isAvailable) {
|
|
||||||
resolve();
|
|
||||||
} else {
|
|
||||||
reject(new ChannelNameError('Sorry, that name is already taken'));
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch(function(error) {
|
|
||||||
reject(error);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
},
|
|
||||||
// validation function which checks all aspects of a new channel login
|
|
||||||
validateNewChannelLogin: function (userName, password) {
|
|
||||||
const channelName = `@${userName}`;
|
|
||||||
var that = this;
|
|
||||||
return new Promise(function (resolve, reject) {
|
|
||||||
// 1. validate name
|
|
||||||
try {
|
|
||||||
that.validateChannelName(channelName);
|
|
||||||
} catch (error) {
|
|
||||||
return reject(error);
|
|
||||||
}
|
|
||||||
// 2. validate password
|
|
||||||
try {
|
|
||||||
that.validatePassword(password);
|
|
||||||
} catch (error) {
|
|
||||||
return reject(error);
|
|
||||||
}
|
|
||||||
resolve();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
|
@ -1,11 +1,153 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import ProgressBar from 'components/ProgressBar';
|
||||||
|
import Request from 'utils/request';
|
||||||
|
|
||||||
const AssetDisplay = ({ name, claimId }) => {
|
const LOCAL_CHECK = 'LOCAL_CHECK';
|
||||||
|
const SEARCHING = 'SEARCHING';
|
||||||
|
const UNAVAILABLE = 'UNAVAILABLE';
|
||||||
|
const AVAILABLE = 'AVAILABLE';
|
||||||
|
|
||||||
|
class AssetDisplay extends React.Component {
|
||||||
|
constructor (props) {
|
||||||
|
super(props);
|
||||||
|
this.state = {
|
||||||
|
error : null,
|
||||||
|
status : LOCAL_CHECK,
|
||||||
|
thumbnail : this.props.thumbnail,
|
||||||
|
src : `/${this.props.claimId}}/${this.props.name}.${this.props.fileExt}`,
|
||||||
|
name : this.props.name,
|
||||||
|
claimId : this.props.claimId,
|
||||||
|
fileExt : this.props.fileExt,
|
||||||
|
contentType: this.props.contentType,
|
||||||
|
};
|
||||||
|
this.checkIfLocalFileAvailable = this.checkIfLocalFileAvailable.bind(this);
|
||||||
|
this.triggerGetAssetOnSpeech = this.triggerGetAssetOnSpeech.bind(this);
|
||||||
|
}
|
||||||
|
componentDidMount () {
|
||||||
|
const that = this;
|
||||||
|
this.checkIfLocalFileAvailable()
|
||||||
|
.then(isAvailable => {
|
||||||
|
if (!isAvailable) {
|
||||||
|
console.log('file is not yet available');
|
||||||
|
that.setState({status: SEARCHING});
|
||||||
|
return that.triggerGetAssetOnSpeech();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
that.setState({status: AVAILABLE});
|
||||||
|
that.addPlayPauseToVideoToBody();
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
that.setState({
|
||||||
|
status: UNAVAILABLE,
|
||||||
|
error : error.message,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
checkIfLocalFileAvailable () {
|
||||||
|
console.log(`checking if file is available for ${this.props.name}#${this.props.claimId}`);
|
||||||
|
const url = `/api/file-is-available/${this.props.name}/${this.props.claimId}`;
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
Request(url)
|
||||||
|
.then(isAvailable => {
|
||||||
|
console.log('/api/file-is-available response:', isAvailable);
|
||||||
|
resolve(isAvailable);
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
reject(error);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
triggerGetAssetOnSpeech () {
|
||||||
|
console.log(`getting claim for ${this.props.name}#${this.props.claimId}`)
|
||||||
|
const url = `/api/claim-get/${this.props.name}/${this.props.claimId}`;
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
Request(url)
|
||||||
|
.then(response => {
|
||||||
|
console.log('/api/claim-get response:', response);
|
||||||
|
resolve(true);
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
reject(error);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
addPlayPauseToVideoToBody () {
|
||||||
|
const that = this;
|
||||||
|
const video = document.getElementById('video');
|
||||||
|
if (video) {
|
||||||
|
// add event listener for click
|
||||||
|
video.addEventListener('click', () => {
|
||||||
|
that.playOrPause(video);
|
||||||
|
});
|
||||||
|
// add event listener for space bar
|
||||||
|
document.body.onkeyup = (event) => {
|
||||||
|
if (event.keyCode === 32) {
|
||||||
|
that.playOrPause(video);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
playOrPause (video) {
|
||||||
|
if (video.paused === true) {
|
||||||
|
video.play();
|
||||||
|
} else {
|
||||||
|
video.pause();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
render () {
|
||||||
return (
|
return (
|
||||||
|
<div id="asset-display-component">
|
||||||
|
{(this.state.status === SEARCHING) &&
|
||||||
<div>
|
<div>
|
||||||
<p>display {name}#{claimId} here</p>
|
<p>Sit tight, we're searching the LBRY blockchain for your asset!</p>
|
||||||
|
<ProgressBar size={12}/>
|
||||||
|
<p>Curious what magic is happening here? <a className="link--primary" target="blank" href="https://lbry.io/faq/what-is-lbry">Learn more.</a></p>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
{(this.state.status === UNAVAILABLE) &&
|
||||||
|
<div>
|
||||||
|
<p>Unfortunately, we couldn't download your asset from LBRY. You can help us out by sharing the below error message in the <a className="link--primary" href="https://discord.gg/YjYbwhS" target="_blank">LBRY discord</a>.</p>
|
||||||
|
<i><p id="error-message">{this.state.error}</p></i>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
{(this.state.status === AVAILABLE) &&
|
||||||
|
(() => {
|
||||||
|
switch (this.state.contentType) {
|
||||||
|
case 'image/jpeg':
|
||||||
|
case 'image/jpg':
|
||||||
|
case 'image/png':
|
||||||
|
return (
|
||||||
|
<img className="asset" src={this.state.src} alt={this.state.name}/>
|
||||||
|
);
|
||||||
|
case 'image/gif':
|
||||||
|
return (
|
||||||
|
<img className="asset" src={this.state.src} alt={this.state.name}/>
|
||||||
|
);
|
||||||
|
case 'video/mp4':
|
||||||
|
return (
|
||||||
|
<video id="video" className="asset" controls poster={this.state.thumbnail}>
|
||||||
|
<source src={this.state.src}/>
|
||||||
|
<p>Your browser does not support the <code>video</code> element.</p>
|
||||||
|
</video>
|
||||||
|
);
|
||||||
|
default:
|
||||||
|
return (
|
||||||
|
<p>unsupported file type</p>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
})()
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// required props
|
||||||
|
// name
|
||||||
|
// claimId
|
||||||
|
// thumbnail
|
||||||
|
// contentType
|
||||||
|
// file extension
|
||||||
|
|
||||||
export default AssetDisplay;
|
export default AssetDisplay;
|
||||||
|
|
|
@ -3,23 +3,17 @@ import React from 'react';
|
||||||
class AssetInfo extends React.Component {
|
class AssetInfo extends React.Component {
|
||||||
constructor (props) {
|
constructor (props) {
|
||||||
super(props);
|
super(props);
|
||||||
this.toggleSection = this.toggleSection.bind(this);
|
this.state = {
|
||||||
|
showDetails: false,
|
||||||
|
}
|
||||||
|
this.toggleDetails = this.toggleDetails.bind(this);
|
||||||
this.copyToClipboard = this.copyToClipboard.bind(this);
|
this.copyToClipboard = this.copyToClipboard.bind(this);
|
||||||
}
|
}
|
||||||
toggleSection (event) {
|
toggleDetails () {
|
||||||
var dataSet = event.target.dataset;
|
if (this.state.showDetails) {
|
||||||
var status = dataSet.status;
|
return this.setState({showDetails: false});
|
||||||
var toggle = document.getElementById('show-details-toggle');
|
|
||||||
var details = document.getElementById('show-details');
|
|
||||||
if (status === 'closed') {
|
|
||||||
details.hidden = false;
|
|
||||||
toggle.innerText = '[less]';
|
|
||||||
toggle.dataset.status = 'open';
|
|
||||||
} else {
|
|
||||||
details.hidden = true;
|
|
||||||
toggle.innerText = '[more]';
|
|
||||||
toggle.dataset.status = 'closed';
|
|
||||||
}
|
}
|
||||||
|
this.setState({showDetails: true});
|
||||||
}
|
}
|
||||||
copyToClipboard (event) {
|
copyToClipboard (event) {
|
||||||
var elementToCopy = event.target.dataset.elementtocopy;
|
var elementToCopy = event.target.dataset.elementtocopy;
|
||||||
|
@ -126,41 +120,40 @@ class AssetInfo extends React.Component {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="show-details" className="row--padded row--wide row--no-top" hidden="true">
|
{ this.state.showDetails &&
|
||||||
<div id="show-claim-name">
|
<div>
|
||||||
|
<div className="row--padded row--wide row--no-top">
|
||||||
|
<div>
|
||||||
<div className="column column--2 column--med-10">
|
<div className="column column--2 column--med-10">
|
||||||
<span className="text">Claim Name:</span>
|
<span className="text">Claim Name:</span>
|
||||||
</div>
|
</div><div className="column column--8 column--med-10">
|
||||||
<div className="column column--8 column--med-10">
|
|
||||||
{this.props.name}
|
{this.props.name}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="show-claim-id">
|
<div>
|
||||||
<div className="column column--2 column--med-10">
|
<div className="column column--2 column--med-10">
|
||||||
<span className="text">Claim Id:</span>
|
<span className="text">Claim Id:</span>
|
||||||
</div>
|
</div><div className="column column--8 column--med-10">
|
||||||
<div className="column column--8 column--med-10">
|
|
||||||
{this.props.claimId}
|
{this.props.claimId}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="show-claim-id">
|
<div>
|
||||||
<div className="column column--2 column--med-10">
|
<div className="column column--2 column--med-10">
|
||||||
<span className="text">File Type:</span>
|
<span className="text">File Type:</span>
|
||||||
</div>
|
</div><div className="column column--8 column--med-10">
|
||||||
<div className="column column--8 column--med-10">
|
|
||||||
{this.props.contentType ? `${this.props.contentType}` : 'unknown'}
|
{this.props.contentType ? `${this.props.contentType}` : 'unknown'}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="show-claim-id">
|
</div>
|
||||||
|
<div className="row--padded row--wide row--no-top">
|
||||||
<div className="column column--10">
|
<div className="column column--10">
|
||||||
<a target="_blank" href="https://lbry.io/dmca">Report</a>
|
<a target="_blank" href="https://lbry.io/dmca">Report</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
}
|
||||||
<div className="row row--wide">
|
<div className="row row--wide">
|
||||||
<a className="text link--primary" id="show-details-toggle" href="#" onClick={this.toggleSection}
|
<a className="text link--primary" id="show-details-toggle" href="#" onClick={this.toggleDetails}>{this.state.showDetails ? '[less]' : '[more]'}</a>
|
||||||
data-status="closed">[more]</a>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -50,7 +50,6 @@ class ChannelClaimsDisplay extends React.Component {
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div className="row row--tall">
|
<div className="row row--tall">
|
||||||
<p># of claims in channel: {this.state.totalResults >= 0 ? this.state.totalResults : 'loading...' }</p>
|
|
||||||
{this.state.claims && this.state.claims.map((claim, index) => <AssetPreview
|
{this.state.claims && this.state.claims.map((claim, index) => <AssetPreview
|
||||||
name={claim.name}
|
name={claim.name}
|
||||||
claimId={claim.claimId}
|
claimId={claim.claimId}
|
||||||
|
|
|
@ -27,6 +27,9 @@ class ShowDetails extends React.Component {
|
||||||
<AssetDisplay
|
<AssetDisplay
|
||||||
name={this.props.claimData.name}
|
name={this.props.claimData.name}
|
||||||
claimId={this.props.claimData.claimId}
|
claimId={this.props.claimData.claimId}
|
||||||
|
thumbnail={this.props.claimData.thumbnail}
|
||||||
|
contentType={this.props.claimData.contentType}
|
||||||
|
fileExt={this.props.claimData.fileExt}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div><div className="column column--5 column--sml-10 align-content-top">
|
</div><div className="column column--5 column--sml-10 align-content-top">
|
||||||
|
|
|
@ -6,6 +6,6 @@ module.exports = app => {
|
||||||
// a catch-all route if someone visits a page that does not exist
|
// a catch-all route if someone visits a page that does not exist
|
||||||
app.use('*', ({ originalUrl, ip }, res) => {
|
app.use('*', ({ originalUrl, ip }, res) => {
|
||||||
// send response
|
// send response
|
||||||
res.status(404).render('index');
|
res.status(404).render('404');
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
{{> navBar}}
|
<div class="row row--tall flex-container--column flex-container--center-center">
|
||||||
<div class="row row--padded">
|
|
||||||
<h3>404: Not Found</h3>
|
<h3>404: Not Found</h3>
|
||||||
<p>That page does not exist. Return <a class="link--primary" href="/">home</a>.</p>
|
<p>That page does not exist. Return <a class="link--primary" href="/">home</a>.</p>
|
||||||
</div>
|
</div>
|
|
@ -1,55 +0,0 @@
|
||||||
{{> navBar}}
|
|
||||||
<div class="row row--padded">
|
|
||||||
<div class="row">
|
|
||||||
{{#ifConditional this.totalPages '===' 0}}
|
|
||||||
<p>There is no content in {{this.channelName}}:{{this.longChannelClaimId}} yet. Upload some!</p>
|
|
||||||
{{/ifConditional}}
|
|
||||||
{{#ifConditional this.totalPages '>=' 1}}
|
|
||||||
<p>Below are the contents for {{this.channelName}}:{{this.longChannelClaimId}}</p>
|
|
||||||
<div class="grid">
|
|
||||||
{{#each this.claims}}
|
|
||||||
{{> gridItem}}
|
|
||||||
{{/each}}
|
|
||||||
</div>
|
|
||||||
{{/ifConditional}}
|
|
||||||
{{#ifConditional this.totalPages '>' 1}}
|
|
||||||
<div class="row">
|
|
||||||
<div class="column column--3 align-content--left">
|
|
||||||
<a class="link--primary" href="/{{this.channelName}}:{{this.longChannelClaimId}}?p=1">First [1]</a>
|
|
||||||
</div><div class="column column--4 align-content-center">
|
|
||||||
{{#if this.previousPage}}
|
|
||||||
<a class="link--primary" href="/{{this.channelName}}:{{this.longChannelClaimId}}?p={{this.previousPage}}">Previous</a>
|
|
||||||
{{else}}
|
|
||||||
<a disabled>Previous</a>
|
|
||||||
{{/if}}
|
|
||||||
|
|
|
||||||
{{#if this.nextPage}}
|
|
||||||
<a class="link--primary" href="/{{this.channelName}}:{{this.longChannelClaimId}}?p={{this.nextPage}}">Next</a>
|
|
||||||
{{else}}
|
|
||||||
<a disabled>Next</a>
|
|
||||||
{{/if}}
|
|
||||||
</div><div class="column column--3 align-content-right">
|
|
||||||
<a class="link--primary" href="/{{this.channelName}}:{{this.longChannelClaimId}}?p={{this.totalPages}}">Last [{{this.totalPages}}]</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{{/ifConditional}}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<script src="/assets/vendors/masonry/masonry.pkgd.min.js"></script>
|
|
||||||
<script src="/assets/vendors/imagesloaded/imagesloaded.pkgd.min.js"></script>
|
|
||||||
<script>
|
|
||||||
// init masonry with element
|
|
||||||
var grid = document.querySelector('.grid');
|
|
||||||
var msnry;
|
|
||||||
|
|
||||||
imagesLoaded( grid, function() {
|
|
||||||
msnry = new Masonry( grid, {
|
|
||||||
itemSelector: '.grid-item',
|
|
||||||
columnWidth: 3,
|
|
||||||
percentPosition: true
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
</script>
|
|
|
@ -1,22 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en" prefix="og: http://ogp.me/ns# fb: http://ogp.me/ns/fb#">
|
|
||||||
<head>
|
|
||||||
{{ placeCommonHeaderTags }}
|
|
||||||
<meta name="twitter:card" content="summary" />
|
|
||||||
<meta name="twitter:site" content="@spee_ch" />
|
|
||||||
<meta property="og:title" content="{{this.channelName}} on Spee.ch" />
|
|
||||||
<meta property="og:site_name" content="Spee.ch" />
|
|
||||||
<meta property="og:type" content="website" />
|
|
||||||
<meta property="og:image" content="https://spee.ch/assets/img/Speech_Logo_Main@OG-02.jpg" />
|
|
||||||
<meta property="og:url" content="http://spee.ch/{{this.channelName}}:{{this.longChannelId}}" />
|
|
||||||
<meta property="og:description" content="View images and videos from {{this.channelName}}" />
|
|
||||||
<!--google font-->
|
|
||||||
<link href="https://fonts.googleapis.com/css?family=Roboto:300" rel="stylesheet">
|
|
||||||
<!-- google analytics -->
|
|
||||||
{{ googleAnalytics }}
|
|
||||||
</head>
|
|
||||||
<body id="channel-body">
|
|
||||||
<script src="/assets/js/generalFunctions.js"></script>
|
|
||||||
{{{ body }}}
|
|
||||||
</body>
|
|
||||||
</html>
|
|
|
@ -16,8 +16,6 @@
|
||||||
{{ googleAnalytics }}
|
{{ googleAnalytics }}
|
||||||
</head>
|
</head>
|
||||||
<body id="main-body">
|
<body id="main-body">
|
||||||
<script src="/assets/js/generalFunctions.js"></script>
|
|
||||||
<script src="/assets/js/validationFunctions.js"></script>
|
|
||||||
{{{ body }}}
|
{{{ body }}}
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -1,21 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en" prefix="og: http://ogp.me/ns# fb: http://ogp.me/ns/fb# article: http://ogp.me/ns/article#">
|
|
||||||
<head>
|
|
||||||
{{ placeCommonHeaderTags }}
|
|
||||||
<meta property="fb:app_id" content="1371961932852223">
|
|
||||||
{{#unless claimInfo.nsfw}}
|
|
||||||
{{{addTwitterCard claimInfo }}}
|
|
||||||
{{{addOpenGraph claimInfo }}}
|
|
||||||
{{/unless}}
|
|
||||||
<!--google font-->
|
|
||||||
<link href="https://fonts.googleapis.com/css?family=Roboto:300" rel="stylesheet">
|
|
||||||
<!-- google analytics -->
|
|
||||||
{{ googleAnalytics }}
|
|
||||||
</head>
|
|
||||||
<body id="show-body">
|
|
||||||
<script src="/assets/js/generalFunctions.js"></script>
|
|
||||||
<script src="/assets/js/assetConstructor.js"></script>
|
|
||||||
{{{ body }}}
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
|
|
|
@ -1,6 +0,0 @@
|
||||||
{{> navBar}}
|
|
||||||
<div class="row row--padded">
|
|
||||||
<h3>No Channel</h3>
|
|
||||||
<p>There are no published channels matching your url</p>
|
|
||||||
<p>If you think this message is an error, contact us in the <a class="link--primary" href="https://discord.gg/YjYbwhS" target="_blank">LBRY Discord!</a></p>
|
|
||||||
</div>
|
|
|
@ -1,6 +0,0 @@
|
||||||
{{> navBar}}
|
|
||||||
<div class="row row--padded">
|
|
||||||
<h3>No Claims</h3>
|
|
||||||
<p>There are no free assets at that claim. You should publish one at <a class="link--primary" href="/">spee.ch</a>.</p>
|
|
||||||
<p>NOTE: it is possible your claim was published, but it is still being processed by the blockchain</p>
|
|
||||||
</div>
|
|
|
@ -1,7 +1,52 @@
|
||||||
<p id="bar-holder"></p>
|
<p id="bar-holder"></p>
|
||||||
|
|
||||||
<script src="/assets/js/progressBarConstructor.js"></script>
|
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
|
const ProgressBar = function() {
|
||||||
|
this.data = {
|
||||||
|
x: 0,
|
||||||
|
adder: 1,
|
||||||
|
bars: [],
|
||||||
|
};
|
||||||
|
this.barHolder = document.getElementById('bar-holder');
|
||||||
|
this.createProgressBar = function (size) {
|
||||||
|
this.data['size'] = size;
|
||||||
|
for (var i = 0; i < size; i++) {
|
||||||
|
const bar = document.createElement('span');
|
||||||
|
bar.innerText = '| ';
|
||||||
|
bar.setAttribute('class', 'progress-bar progress-bar--inactive');
|
||||||
|
this.barHolder.appendChild(bar);
|
||||||
|
this.data.bars.push(bar);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
this.startProgressBar = function () {
|
||||||
|
this.updateInterval = setInterval(this.updateProgressBar.bind(this), 300);
|
||||||
|
};
|
||||||
|
this.updateProgressBar = function () {
|
||||||
|
const x = this.data.x;
|
||||||
|
const adder = this.data.adder;
|
||||||
|
const size = this.data.size;
|
||||||
|
// update the appropriate bar
|
||||||
|
if (x > -1 && x < size){
|
||||||
|
if (adder === 1){
|
||||||
|
this.data.bars[x].setAttribute('class', 'progress-bar progress-bar--active');
|
||||||
|
} else {
|
||||||
|
this.data.bars[x].setAttribute('class', 'progress-bar progress-bar--inactive');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// update adder
|
||||||
|
if (x === size){
|
||||||
|
this.data['adder'] = -1;
|
||||||
|
} else if ( x === -1){
|
||||||
|
this.data['adder'] = 1;
|
||||||
|
}
|
||||||
|
// update x
|
||||||
|
this.data['x'] = x + adder;
|
||||||
|
};
|
||||||
|
this.stopProgressBar = function () {
|
||||||
|
clearInterval(this.updateInterval);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
const progressBar = new ProgressBar();
|
const progressBar = new ProgressBar();
|
||||||
progressBar.createProgressBar(10);
|
progressBar.createProgressBar(10);
|
||||||
progressBar.startProgressBar();
|
progressBar.startProgressBar();
|
||||||
|
|
|
@ -1,7 +0,0 @@
|
||||||
{{> navBar}}
|
|
||||||
<div class="row row--padded">
|
|
||||||
<h3>Error</h3>
|
|
||||||
<p>Unfortnately, Spee.ch encountered an error. You can help us out, by reporting the below error message in the #speech channel on <a class="link--primary" href="https://discord.gg/YjYbwhS" target="_blank">LBRY Discord</a>!</p>
|
|
||||||
<p>status: {{status}}</p>
|
|
||||||
<p>message: {{message}}</p>
|
|
||||||
</div>
|
|
|
@ -1,18 +0,0 @@
|
||||||
{{> navBar}}
|
|
||||||
<div class="row row--tall row--padded">
|
|
||||||
<div class="column column--10">
|
|
||||||
<!-- title -->
|
|
||||||
<span class="text--large">{{claimInfo.title}}</span>
|
|
||||||
</div>
|
|
||||||
<div class="column column--5 column--sml-10 align-content-top">
|
|
||||||
<!-- asset -->
|
|
||||||
<div class="row row--padded">
|
|
||||||
{{> asset}}
|
|
||||||
</div>
|
|
||||||
</div><div class="column column--5 column--sml-10 align-content-top">
|
|
||||||
<!-- details -->
|
|
||||||
<div class="row row--padded">
|
|
||||||
{{> assetInfo}}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
|
@ -1,32 +0,0 @@
|
||||||
<div>
|
|
||||||
<h3>Site Statistics</h3>
|
|
||||||
<p>Serve: {{ totals.totalServe }}</p>
|
|
||||||
<p>Publish: {{ totals.totalPublish }}</p>
|
|
||||||
<p>Show: {{ totals.totalShow }}</p>
|
|
||||||
<p>Percent Success: {{ percentSuccess}}%</p>
|
|
||||||
<table>
|
|
||||||
<tr>
|
|
||||||
<th>action</th>
|
|
||||||
<th >url</th>
|
|
||||||
<th class="">count</th>
|
|
||||||
<th class="">success</th>
|
|
||||||
<th class="">failure</th>
|
|
||||||
</tr>
|
|
||||||
{{#each records}}
|
|
||||||
<tr>
|
|
||||||
<td>{{ this.action }}</td>
|
|
||||||
<td class="stats-table-url">{{ this.url }}</td>
|
|
||||||
<td class="">{{ this.count }}</td>
|
|
||||||
<td class="">{{ this.success }}</td>
|
|
||||||
<td class="">{{ this.failure }}</td>
|
|
||||||
</tr>
|
|
||||||
{{/each}}
|
|
||||||
<tr>
|
|
||||||
<td></td>
|
|
||||||
<td></td>
|
|
||||||
<td class="">{{ totals.totalCount }}</td>
|
|
||||||
<td class="">{{ totals.totalSuccess }}</td>
|
|
||||||
<td class="">{{ totals.totalFailure }}</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
Loading…
Reference in a new issue