got publish submission working
This commit is contained in:
parent
70a65a243a
commit
11a954a442
8 changed files with 137 additions and 209 deletions
|
@ -9,103 +9,7 @@ const publishFileFunctions = {
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
},
|
},
|
||||||
createMetadata: function() {
|
|
||||||
const nameInput = document.getElementById('claim-name-input');
|
|
||||||
const titleInput = document.getElementById('publish-title');
|
|
||||||
const descriptionInput = document.getElementById('publish-description');
|
|
||||||
const licenseInput = document.getElementById('publish-license');
|
|
||||||
const nsfwInput = document.getElementById('publish-nsfw');
|
|
||||||
const thumbnailInput = document.getElementById('claim-thumbnail-input');
|
|
||||||
const channelName = this.returnNullOrChannel();
|
|
||||||
let metadata = {
|
|
||||||
name: nameInput.value.trim(),
|
|
||||||
title: titleInput.value.trim(),
|
|
||||||
description: descriptionInput.value.trim(),
|
|
||||||
license: licenseInput.value.trim(),
|
|
||||||
nsfw: nsfwInput.checked,
|
|
||||||
type: stagedFiles[0].type,
|
|
||||||
thumbnail: thumbnailInput.value.trim(),
|
|
||||||
};
|
|
||||||
if (channelName) {
|
|
||||||
metadata['channelName'] = channelName;
|
|
||||||
}
|
|
||||||
return metadata;
|
|
||||||
},
|
|
||||||
appendDataToFormData: function (file, metadata) {
|
|
||||||
var fd = new FormData();
|
|
||||||
fd.append('file', file)
|
|
||||||
for (var key in metadata) {
|
|
||||||
if (metadata.hasOwnProperty(key)) {
|
|
||||||
console.log(key, metadata[key]);
|
|
||||||
fd.append(key, metadata[key]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return fd;
|
|
||||||
},
|
|
||||||
publishFile: function (file, metadata) {
|
|
||||||
var uri = "/api/claim-publish";
|
|
||||||
var xhr = new XMLHttpRequest();
|
|
||||||
var fd = this.appendDataToFormData(file, metadata);
|
|
||||||
var that = this;
|
|
||||||
xhr.upload.addEventListener("loadstart", function(e) {
|
|
||||||
that.showUploadStartedMessage();
|
|
||||||
})
|
|
||||||
xhr.upload.addEventListener("progress", function(e) {
|
|
||||||
if (e.lengthComputable) {
|
|
||||||
var percentage = Math.round((e.loaded * 100) / e.total);
|
|
||||||
console.log('progress:', percentage);
|
|
||||||
that.showUploadProgressMessage(percentage);
|
|
||||||
}
|
|
||||||
}, false);
|
|
||||||
xhr.upload.addEventListener("load", function(e){
|
|
||||||
console.log('loaded 100%');
|
|
||||||
that.showFilePublishUpdate("Your file has been loaded, and is now being published to the blockchain. Sit tight...")
|
|
||||||
}, false);
|
|
||||||
xhr.open("POST", uri, true);
|
|
||||||
xhr.onreadystatechange = function() {
|
|
||||||
if (xhr.readyState == 4) {
|
|
||||||
console.log('publish response:', xhr.response)
|
|
||||||
if (xhr.status == 200) {
|
|
||||||
console.log('publish complete!');
|
|
||||||
that.showFilePublishComplete(JSON.parse(xhr.response).message);
|
|
||||||
} else if (xhr.status == 502){
|
|
||||||
that.showFilePublishFailure('Spee.ch was not able to get a response from the LBRY network.');
|
|
||||||
} else {
|
|
||||||
that.showFilePublishFailure(JSON.parse(xhr.response).message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
// Initiate a multipart/form-data upload
|
|
||||||
xhr.send(fd);
|
|
||||||
},
|
|
||||||
// Validate the publish submission and then trigger upload
|
// Validate the publish submission and then trigger upload
|
||||||
publishStagedFile: function (event) {
|
|
||||||
event.preventDefault(); // prevent default so this script can handle submission
|
|
||||||
const metadata = this.createMetadata();
|
|
||||||
const that = this;
|
|
||||||
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');
|
|
||||||
// validate, submit, and handle response
|
|
||||||
validationFunctions.validateFilePublishSubmission(stagedFiles, metadata)
|
|
||||||
.then( function() {
|
|
||||||
that.publishFile(stagedFiles[0], metadata);
|
|
||||||
})
|
|
||||||
.catch(error => {
|
|
||||||
if (error.name === 'FileError') {
|
|
||||||
validationFunctions.showError(fileSelectionInputError, error.message);
|
|
||||||
} else if (error.name === 'NameError') {
|
|
||||||
validationFunctions.showError(claimNameError, error.message);
|
|
||||||
} else if (error.name === 'ChannelNameError'){
|
|
||||||
console.log(error);
|
|
||||||
validationFunctions.showError(channelSelectError, error.message);
|
|
||||||
} else {
|
|
||||||
validationFunctions.showError(publishSubmitError, error.message);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
})
|
|
||||||
},
|
|
||||||
showUploadStartedMessage: function (){
|
showUploadStartedMessage: function (){
|
||||||
console.log('starting upload');
|
console.log('starting upload');
|
||||||
// hide the publish tool
|
// hide the publish tool
|
||||||
|
|
|
@ -1,53 +1,5 @@
|
||||||
// validation function which checks the proposed file's type, size, and name
|
// validation function which checks the proposed file's type, size, and name
|
||||||
const validationFunctions = {
|
const validationFunctions = {
|
||||||
validateFile: function (file) {
|
|
||||||
if (!file) {
|
|
||||||
console.log('no file found');
|
|
||||||
throw new Error('no file provided');
|
|
||||||
}
|
|
||||||
if (/'/.test(file.name)) {
|
|
||||||
console.log('file name had apostrophe in it');
|
|
||||||
throw new Error('apostrophes are not allowed in the file name');
|
|
||||||
}
|
|
||||||
// validate size and type
|
|
||||||
switch (file.type) {
|
|
||||||
case 'image/jpeg':
|
|
||||||
case 'image/jpg':
|
|
||||||
case 'image/png':
|
|
||||||
if (file.size > 10000000) {
|
|
||||||
console.log('file was too big');
|
|
||||||
throw new Error('Sorry, images are limited to 10 megabytes.');
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'image/gif':
|
|
||||||
if (file.size > 50000000) {
|
|
||||||
console.log('file was too big');
|
|
||||||
throw new Error('Sorry, .gifs are limited to 50 megabytes.');
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'video/mp4':
|
|
||||||
if (file.size > 50000000) {
|
|
||||||
console.log('file was too big');
|
|
||||||
throw new Error('Sorry, videos are limited to 50 megabytes.');
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
console.log('file type is not supported');
|
|
||||||
throw new Error(file.type + ' is not a supported file type. Only, .jpeg, .png, .gif, and .mp4 files are currently supported.')
|
|
||||||
}
|
|
||||||
},
|
|
||||||
// validation function that checks to make sure the claim name is valid
|
|
||||||
validateClaimName: function (name) {
|
|
||||||
// ensure a name was entered
|
|
||||||
if (name.length < 1) {
|
|
||||||
throw new NameError("You must enter a name for your url");
|
|
||||||
}
|
|
||||||
// validate the characters in the 'name' field
|
|
||||||
const invalidCharacters = /[^A-Za-z0-9,-]/g.exec(name);
|
|
||||||
if (invalidCharacters) {
|
|
||||||
throw new NameError('"' + invalidCharacters + '" characters are not allowed');
|
|
||||||
}
|
|
||||||
},
|
|
||||||
validateChannelName: function (name) {
|
validateChannelName: function (name) {
|
||||||
name = name.substring(name.indexOf('@') + 1);
|
name = name.substring(name.indexOf('@') + 1);
|
||||||
// ensure a name was entered
|
// ensure a name was entered
|
||||||
|
@ -117,54 +69,6 @@ const validationFunctions = {
|
||||||
name = `@${name}`;
|
name = `@${name}`;
|
||||||
this.checkAvailability(name, successDisplayElement, errorDisplayElement, this.validateChannelName, 'Sorry, that name is already taken', '/api/channel-is-available/');
|
this.checkAvailability(name, successDisplayElement, errorDisplayElement, this.validateChannelName, 'Sorry, that name is already taken', '/api/channel-is-available/');
|
||||||
},
|
},
|
||||||
// validation function which checks all aspects of the publish submission
|
|
||||||
validateFilePublishSubmission: function (stagedFiles, metadata) {
|
|
||||||
const channelName = metadata.channelName;
|
|
||||||
const claimName = metadata.name;
|
|
||||||
var that = this;
|
|
||||||
return new Promise(function (resolve, reject) {
|
|
||||||
// 1. make sure 1 file was staged
|
|
||||||
if (!stagedFiles) {
|
|
||||||
reject(new FileError("Please select a file"));
|
|
||||||
return;
|
|
||||||
} else if (stagedFiles.length > 1) {
|
|
||||||
reject(new FileError("Only one file is allowed at a time"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// 2. validate the file's name, type, and size
|
|
||||||
try {
|
|
||||||
that.validateFile(stagedFiles[0]);
|
|
||||||
} catch (error) {
|
|
||||||
reject(error);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// 3. validate that a channel was chosen
|
|
||||||
if (channelName === 'new' || channelName === 'login') {
|
|
||||||
reject(new ChannelNameError("Please log in to a channel"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
;
|
|
||||||
// 4. validate the claim name
|
|
||||||
try {
|
|
||||||
that.validateClaimName(claimName);
|
|
||||||
} catch (error) {
|
|
||||||
reject(error);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// if all validation passes, check availability of the name (note: do we need to re-validate channel name vs. credentials as well?)
|
|
||||||
return that.isNameAvailable(claimName, '/api/claim-is-available/')
|
|
||||||
.then(result => {
|
|
||||||
if (result) {
|
|
||||||
resolve();
|
|
||||||
} else {
|
|
||||||
reject(new NameError('Sorry, that ending is already taken'));
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch(error => {
|
|
||||||
reject(error);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
},
|
|
||||||
// validation function which checks all aspects of a new channel submission
|
// validation function which checks all aspects of a new channel submission
|
||||||
validateNewChannelSubmission: function (userName, password) {
|
validateNewChannelSubmission: function (userName, password) {
|
||||||
const channelName = `@${userName}`;
|
const channelName = `@${userName}`;
|
||||||
|
|
|
@ -5,6 +5,7 @@ export const METADATA_UPDATE = 'METADATA_UPDATE';
|
||||||
export const CLAIM_UPDATE = 'CLAIM_UPDATE';
|
export const CLAIM_UPDATE = 'CLAIM_UPDATE';
|
||||||
export const CHANNEL_UPDATE = 'CHANNEL_UPDATE';
|
export const CHANNEL_UPDATE = 'CHANNEL_UPDATE';
|
||||||
export const SET_PUBLISH_IN_CHANNEL = 'SET_PUBLISH_IN_CHANNEL';
|
export const SET_PUBLISH_IN_CHANNEL = 'SET_PUBLISH_IN_CHANNEL';
|
||||||
|
export const PUBLISH_STATUS_UPDATE = 'PUBLISH_STATUS_UPDATE';
|
||||||
|
|
||||||
// export action creators
|
// export action creators
|
||||||
export function selectFile (file) {
|
export function selectFile (file) {
|
||||||
|
@ -44,9 +45,16 @@ export function updateLoggedInChannel (name, shortId, longId) {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export function setPublishInChannel (value) {
|
export function setPublishInChannel (channel) {
|
||||||
return {
|
return {
|
||||||
type: SET_PUBLISH_IN_CHANNEL,
|
type: SET_PUBLISH_IN_CHANNEL,
|
||||||
value,
|
channel,
|
||||||
};
|
};
|
||||||
}
|
};
|
||||||
|
|
||||||
|
export function updatePublishStatus (status) {
|
||||||
|
return {
|
||||||
|
type: PUBLISH_STATUS_UPDATE,
|
||||||
|
status,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
|
@ -18,7 +18,6 @@ class Preview extends React.Component {
|
||||||
this.previewFile(newProps.file);
|
this.previewFile(newProps.file);
|
||||||
}
|
}
|
||||||
previewFile (file) {
|
previewFile (file) {
|
||||||
console.log('previewFile', file)
|
|
||||||
const that = this;
|
const that = this;
|
||||||
if (file.type !== 'video/mp4') {
|
if (file.type !== 'video/mp4') {
|
||||||
const previewReader = new FileReader();
|
const previewReader = new FileReader();
|
||||||
|
|
|
@ -6,18 +6,19 @@ import PublishUrlInput from './PublishUrlInput.jsx';
|
||||||
import PublishThumbnailInput from './PublishThumbnailInput.jsx';
|
import PublishThumbnailInput from './PublishThumbnailInput.jsx';
|
||||||
import PublishMetadataInputs from './PublishMetadataInputs.jsx';
|
import PublishMetadataInputs from './PublishMetadataInputs.jsx';
|
||||||
import AnonymousOrChannelSelect from './AnonymousOrChannelSelect.jsx';
|
import AnonymousOrChannelSelect from './AnonymousOrChannelSelect.jsx';
|
||||||
|
|
||||||
import { selectFile, clearFile, updateLoggedInChannel } from '../actions/index';
|
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { getCookie } from '../utils/cookies.js';
|
import { getCookie } from '../utils/cookies.js';
|
||||||
|
import { selectFile, clearFile, updateLoggedInChannel, updatePublishStatus } from '../actions';
|
||||||
|
|
||||||
class PublishForm extends React.Component {
|
class PublishForm extends React.Component {
|
||||||
constructor (props) {
|
constructor (props) {
|
||||||
super(props);
|
super(props);
|
||||||
// set defaults
|
// set defaults
|
||||||
this.state = {
|
this.state = {
|
||||||
error: null,
|
publishRequestError: null,
|
||||||
};
|
};
|
||||||
|
this.validatePublishRequest = this.validatePublishRequest.bind(this);
|
||||||
|
this.makePublishRequest = this.makePublishRequest.bind(this);
|
||||||
this.publish = this.publish.bind(this);
|
this.publish = this.publish.bind(this);
|
||||||
}
|
}
|
||||||
componentWillMount () {
|
componentWillMount () {
|
||||||
|
@ -28,8 +29,102 @@ class PublishForm extends React.Component {
|
||||||
console.log(`channel cookies found: ${loggedInChannelName} ${loggedInChannelShortId} ${loggedInChannelLongId}`);
|
console.log(`channel cookies found: ${loggedInChannelName} ${loggedInChannelShortId} ${loggedInChannelLongId}`);
|
||||||
this.props.onChannelLogin(loggedInChannelName, loggedInChannelShortId, loggedInChannelLongId);
|
this.props.onChannelLogin(loggedInChannelName, loggedInChannelShortId, loggedInChannelLongId);
|
||||||
}
|
}
|
||||||
|
validatePublishRequest () {
|
||||||
|
// make sure all required data is provided
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
// is there a file?
|
||||||
|
if (!this.props.file) {
|
||||||
|
return reject(new Error('Please choose a file'));
|
||||||
|
}
|
||||||
|
// is there a claim chosen?
|
||||||
|
if (!this.props.claim) {
|
||||||
|
return reject(new Error('Please enter a claim name'));
|
||||||
|
}
|
||||||
|
// if publishInChannel is true, is a channel logged in (or selected)
|
||||||
|
if (this.props.publishInChannel && !this.props.loggedInChannel.name) {
|
||||||
|
return reject(new Error('Select Anonymous or log in to a channel'));
|
||||||
|
}
|
||||||
|
// tbd: is the claim available?
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
makePublishRequest (file, metadata) {
|
||||||
|
const uri = '/api/claim-publish';
|
||||||
|
const xhr = new XMLHttpRequest();
|
||||||
|
const fd = this.appendDataToFormData(file, metadata);
|
||||||
|
const that = this;
|
||||||
|
xhr.upload.addEventListener('loadstart', function () {
|
||||||
|
that.props.onPublishStatusChange('upload started');
|
||||||
|
});
|
||||||
|
xhr.upload.addEventListener('progress', function (e) {
|
||||||
|
if (e.lengthComputable) {
|
||||||
|
const percentage = Math.round((e.loaded * 100) / e.total);
|
||||||
|
that.props.onPublishStatusChange(`upload progress: ${percentage}%`);
|
||||||
|
console.log('progress:', percentage);
|
||||||
|
}
|
||||||
|
}, false);
|
||||||
|
xhr.upload.addEventListener('load', function () {
|
||||||
|
console.log('loaded 100%');
|
||||||
|
that.props.onPublishStatusChange(`Upload complete. Your file is now being published on the blockchain...`);
|
||||||
|
}, false);
|
||||||
|
xhr.open('POST', uri, true);
|
||||||
|
xhr.onreadystatechange = function () {
|
||||||
|
if (xhr.readyState === 4) {
|
||||||
|
console.log('publish response:', xhr.response);
|
||||||
|
if (xhr.status === 200) {
|
||||||
|
console.log('publish complete!');
|
||||||
|
that.props.onPublishStatusChange(JSON.parse(xhr.response).message);
|
||||||
|
} else if (xhr.status === 502) {
|
||||||
|
that.props.onPublishStatusChange('Spee.ch was not able to get a response from the LBRY network.');
|
||||||
|
} else {
|
||||||
|
that.props.onPublishStatusChange(JSON.parse(xhr.response).message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
// Initiate a multipart/form-data upload
|
||||||
|
xhr.send(fd);
|
||||||
|
}
|
||||||
|
createMetadata () {
|
||||||
|
let metadata = {
|
||||||
|
name : this.props.claim,
|
||||||
|
title : this.props.title,
|
||||||
|
description: this.props.description,
|
||||||
|
license : this.props.license,
|
||||||
|
nsfw : this.props.nsfw,
|
||||||
|
type : this.props.file.type,
|
||||||
|
thumbnail : this.props.thumbnail,
|
||||||
|
};
|
||||||
|
if (this.props.publishInChannel) {
|
||||||
|
metadata['channelName'] = this.props.loggedInChannel.name;
|
||||||
|
}
|
||||||
|
return metadata;
|
||||||
|
}
|
||||||
|
appendDataToFormData (file, metadata) {
|
||||||
|
var fd = new FormData();
|
||||||
|
fd.append('file', file);
|
||||||
|
for (var key in metadata) {
|
||||||
|
if (metadata.hasOwnProperty(key)) {
|
||||||
|
console.log(key, metadata[key]);
|
||||||
|
fd.append(key, metadata[key]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return fd;
|
||||||
|
}
|
||||||
publish () {
|
publish () {
|
||||||
// publish the asset
|
// publish the asset
|
||||||
|
const that = this;
|
||||||
|
this.validatePublishRequest()
|
||||||
|
.then(() => {
|
||||||
|
const metadata = that.createMetadata();
|
||||||
|
// publish the claim
|
||||||
|
return that.makePublishRequest(this.props.file, metadata);
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
that.props.onPublishStatusChange('publish request made');
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
that.setState({publishRequestError: error.message});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
render () {
|
render () {
|
||||||
return (
|
return (
|
||||||
|
@ -61,14 +156,18 @@ class PublishForm extends React.Component {
|
||||||
<ChannelSelector />
|
<ChannelSelector />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{ (this.props.fileType === 'video/mp4') && <PublishThumbnailInput /> }
|
{ (this.props.file.type === 'video/mp4') && (
|
||||||
|
<div className="row row--padded row--wide row--no-top">
|
||||||
|
<PublishThumbnailInput />
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
<div className="row row--padded row--no-top row--no-bottom row--wide">
|
<div className="row row--padded row--no-top row--no-bottom row--wide">
|
||||||
<PublishMetadataInputs />
|
<PublishMetadataInputs />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="row row--padded row--wide">
|
<div className="row row--padded row--wide">
|
||||||
<div className="input-error" id="input-error-publish-submit" hidden="true">{this.state.error}</div>
|
<div className="input-error" id="input-error-publish-submit" hidden="true">{this.state.publishRequestError}</div>
|
||||||
<button id="publish-submit" className="button--primary button--large" onClick={this.publish}>Publish</button>
|
<button id="publish-submit" className="button--primary button--large" onClick={this.publish}>Publish</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -89,8 +188,15 @@ class PublishForm extends React.Component {
|
||||||
|
|
||||||
const mapStateToProps = state => {
|
const mapStateToProps = state => {
|
||||||
return {
|
return {
|
||||||
fileType: state.file.type,
|
file : state.file,
|
||||||
claim : state.claim,
|
claim : state.claim,
|
||||||
|
title : state.metadata.title,
|
||||||
|
thumbnail : state.metadata.thumbnail,
|
||||||
|
description : state.metadata.description,
|
||||||
|
license : state.metadata.license,
|
||||||
|
nsfw : state.metadata.nsfw,
|
||||||
|
loggedInChannel : state.loggedInChannel,
|
||||||
|
publishInChannel: state.publishInChannel,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -105,6 +211,9 @@ const mapDispatchToProps = dispatch => {
|
||||||
onChannelLogin: (name, shortId, longId) => {
|
onChannelLogin: (name, shortId, longId) => {
|
||||||
dispatch(updateLoggedInChannel(name, shortId, longId));
|
dispatch(updateLoggedInChannel(name, shortId, longId));
|
||||||
},
|
},
|
||||||
|
onPublishStatusChange: (status) => {
|
||||||
|
dispatch(updatePublishStatus(status));
|
||||||
|
},
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -56,7 +56,7 @@ class ThumbnailInput extends React.Component {
|
||||||
}
|
}
|
||||||
render () {
|
render () {
|
||||||
return (
|
return (
|
||||||
<div className="row row--padded row--wide row--no-top" id="publish-thumbnail">
|
<div>
|
||||||
<div className="column column--3 column--sml-10">
|
<div className="column column--3 column--sml-10">
|
||||||
<label className="label">Thumbnail:</label>
|
<label className="label">Thumbnail:</label>
|
||||||
</div><div className="column column--6 column--sml-10">
|
</div><div className="column column--6 column--sml-10">
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import {
|
import {
|
||||||
CHANNEL_UPDATE, CLAIM_UPDATE, FILE_CLEAR, FILE_SELECTED, METADATA_UPDATE,
|
CHANNEL_UPDATE, CLAIM_UPDATE, FILE_CLEAR, FILE_SELECTED, METADATA_UPDATE, PUBLISH_STATUS_UPDATE,
|
||||||
SET_PUBLISH_IN_CHANNEL,
|
SET_PUBLISH_IN_CHANNEL,
|
||||||
} from '../actions';
|
} from '../actions';
|
||||||
|
|
||||||
|
@ -55,8 +55,12 @@ export default function (state = initialState, action) {
|
||||||
});
|
});
|
||||||
case SET_PUBLISH_IN_CHANNEL:
|
case SET_PUBLISH_IN_CHANNEL:
|
||||||
return Object.assign({}, state, {
|
return Object.assign({}, state, {
|
||||||
publishInChannel: action.value,
|
publishInChannel: action.channel,
|
||||||
});
|
});
|
||||||
|
case PUBLISH_STATUS_UPDATE:
|
||||||
|
return Object.assign({}, state, {
|
||||||
|
publishStatus: action.status,
|
||||||
|
})
|
||||||
default:
|
default:
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,8 +24,8 @@
|
||||||
<span class="nav-bar-tagline">Open-source, decentralized image and video sharing.</span>
|
<span class="nav-bar-tagline">Open-source, decentralized image and video sharing.</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="nav-bar--right">
|
<div class="nav-bar--right">
|
||||||
<a class="nav-bar-link link--nav" href="/">Upload</a>
|
<a class="nav-bar-link link--nav" href="/">Publish</a>
|
||||||
<a class="nav-bar-link link--nav" href="/popular">Popular</a>
|
<!--<a class="nav-bar-link link--nav" href="/popular">Popular</a>-->
|
||||||
<a class="nav-bar-link link--nav" href="/about">About</a>
|
<a class="nav-bar-link link--nav" href="/about">About</a>
|
||||||
<select type="text" id="nav-bar-channel-select" class="select select--arrow link--nav" onchange="toggleNavBarSelection(event.target.selectedOptions[0].value)" {{#unless user}}style="display:none"{{/unless}}>
|
<select type="text" id="nav-bar-channel-select" class="select select--arrow link--nav" onchange="toggleNavBarSelection(event.target.selectedOptions[0].value)" {{#unless user}}style="display:none"{{/unless}}>
|
||||||
<option id="nav-bar-channel-select-channel-option">@{{user.userName}}</option>
|
<option id="nav-bar-channel-select-channel-option">@{{user.userName}}</option>
|
||||||
|
@ -48,4 +48,4 @@
|
||||||
link.setAttribute('class', 'select select--arrow link--nav-active');
|
link.setAttribute('class', 'select select--arrow link--nav-active');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
Loading…
Reference in a new issue