commit
928d240bfc
177 changed files with 11432 additions and 430 deletions
|
@ -1,3 +1,4 @@
|
||||||
node_modules/
|
node_modules/
|
||||||
public/
|
public/bundle
|
||||||
|
index.js
|
||||||
test
|
test
|
||||||
|
|
19
.gitignore
vendored
19
.gitignore
vendored
|
@ -1,7 +1,12 @@
|
||||||
node_modules
|
node_modules/
|
||||||
.idea
|
.idea/
|
||||||
config/sequelizeCliConfig.js
|
config/lbryConfig.js
|
||||||
config/speechConfig.js
|
config/loggerConfig.js
|
||||||
public/bundle
|
config/mysqlConfig.js
|
||||||
server.js
|
config/siteConfig.js
|
||||||
webpack.config.js
|
devConfig/slackConfig.js
|
||||||
|
devConfig/sequelizeCliConfig.js
|
||||||
|
devConfig/testingConfig.js
|
||||||
|
|
||||||
|
public/bundle/
|
||||||
|
index.js
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
'config': path.resolve('config', 'sequelizeCliConfig.js'),
|
'config': path.resolve('devConfig', 'sequelizeCliConfig.js'),
|
||||||
}
|
}
|
||||||
|
|
15
README.md
15
README.md
|
@ -1,7 +1,7 @@
|
||||||
# Spee.ch
|
# Spee.ch
|
||||||
Spee.ch is a web app that reads and publishes images and videos to and from the [LBRY](https://lbry.io/) blockchain.
|
Spee.ch is a web app that reads and publishes images and videos to and from the [LBRY](https://lbry.io/) blockchain.
|
||||||
|
|
||||||
## How to run this repository locally
|
##Installation
|
||||||
* start mysql
|
* start mysql
|
||||||
* install mysql
|
* install mysql
|
||||||
* create a database called `lbry`
|
* create a database called `lbry`
|
||||||
|
@ -12,10 +12,13 @@ Spee.ch is a web app that reads and publishes images and videos to and from the
|
||||||
* start spee.ch
|
* start spee.ch
|
||||||
* clone this repo
|
* clone this repo
|
||||||
* run `npm install`
|
* run `npm install`
|
||||||
* create your `speechConfig.js` file
|
* create your own config files in `/config`
|
||||||
* copy `speechConfig.js.example` and name it `speechConfig.js`
|
* copy `example.js.example` and name it `example.js`
|
||||||
* replace the `null` values in the config file with the appropriate values for your environment
|
* replace the `null` values in the config file with the appropriate values for your environment
|
||||||
* build the app by running `npm run build-prod`
|
* create your own config files in `/devConfig`
|
||||||
|
* copy `example.js.example` and name it `example.js`
|
||||||
|
* note: you must create these files, but the default values are sufficient if you do not want to update them.
|
||||||
|
* build the app by running `npm run build`
|
||||||
* to start the server, run `npm run start`
|
* to start the server, run `npm run start`
|
||||||
* visit [localhost:3000](http://localhost:3000)
|
* visit [localhost:3000](http://localhost:3000)
|
||||||
* start spee.ch-sync (optional, recommended)
|
* start spee.ch-sync (optional, recommended)
|
||||||
|
@ -45,8 +48,8 @@ Spee.ch is a web app that reads and publishes images and videos to and from the
|
||||||
* /api/claim/publish
|
* /api/claim/publish
|
||||||
* example: `curl -F 'name=MyPictureName' -F 'file=@/path/to/myPicture.jpeg' https://spee.ch/api/claim/publish`
|
* example: `curl -F 'name=MyPictureName' -F 'file=@/path/to/myPicture.jpeg' https://spee.ch/api/claim/publish`
|
||||||
* Parameters:
|
* Parameters:
|
||||||
* `name`
|
* `name` (required)
|
||||||
* `file` (must be type .mp4, .jpeg, .jpg, .gif, or .png)
|
* `file` (required) (must be type .mp4, .jpeg, .jpg, .gif, or .png)
|
||||||
* `nsfw` (optional)
|
* `nsfw` (optional)
|
||||||
* `license` (optional)
|
* `license` (optional)
|
||||||
* `title` (optional)
|
* `title` (optional)
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import Request from 'utils/request';
|
import Request from 'utils/request';
|
||||||
const { site: { host } } = require('../../config/speechConfig.js');
|
|
||||||
|
|
||||||
export function getLongClaimId (name, modifier) {
|
export function getLongClaimId (host, name, modifier) {
|
||||||
let body = {};
|
let body = {};
|
||||||
// create request params
|
// create request params
|
||||||
if (modifier) {
|
if (modifier) {
|
||||||
|
@ -24,12 +23,12 @@ export function getLongClaimId (name, modifier) {
|
||||||
return Request(url, params);
|
return Request(url, params);
|
||||||
};
|
};
|
||||||
|
|
||||||
export function getShortId (name, claimId) {
|
export function getShortId (host, name, claimId) {
|
||||||
const url = `${host}/api/claim/short-id/${claimId}/${name}`;
|
const url = `${host}/api/claim/short-id/${claimId}/${name}`;
|
||||||
return Request(url);
|
return Request(url);
|
||||||
};
|
};
|
||||||
|
|
||||||
export function getClaimData (name, claimId) {
|
export function getClaimData (host, name, claimId) {
|
||||||
const url = `${host}/api/claim/data/${name}/${claimId}`;
|
const url = `${host}/api/claim/data/${name}/${claimId}`;
|
||||||
return Request(url);
|
return Request(url);
|
||||||
};
|
};
|
|
@ -1,13 +1,12 @@
|
||||||
import Request from 'utils/request';
|
import Request from 'utils/request';
|
||||||
const { site: { host } } = require('../../config/speechConfig.js');
|
|
||||||
|
|
||||||
export function getChannelData (name, id) {
|
export function getChannelData (host, id, name) {
|
||||||
if (!id) id = 'none';
|
if (!id) id = 'none';
|
||||||
const url = `${host}/api/channel/data/${name}/${id}`;
|
const url = `${host}/api/channel/data/${name}/${id}`;
|
||||||
return Request(url);
|
return Request(url);
|
||||||
};
|
};
|
||||||
|
|
||||||
export function getChannelClaims (name, longId, page) {
|
export function getChannelClaims (host, longId, name, page) {
|
||||||
if (!page) page = 1;
|
if (!page) page = 1;
|
||||||
const url = `${host}/api/channel/claims/${name}/${longId}/${page}`;
|
const url = `${host}/api/channel/claims/${name}/${longId}/${page}`;
|
||||||
return Request(url);
|
return Request(url);
|
|
@ -1,12 +1,11 @@
|
||||||
import Request from 'utils/request';
|
import Request from 'utils/request';
|
||||||
const { site: { host } } = require('../../config/speechConfig.js');
|
|
||||||
|
|
||||||
export function checkFileAvailability (name, claimId) {
|
export function checkFileAvailability (claimId, host, name) {
|
||||||
const url = `${host}/api/file/availability/${name}/${claimId}`;
|
const url = `${host}/api/file/availability/${name}/${claimId}`;
|
||||||
return Request(url);
|
return Request(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function triggerClaimGet (name, claimId) {
|
export function triggerClaimGet (claimId, host, name) {
|
||||||
const url = `${host}/api/claim/get/${name}/${claimId}`;
|
const url = `${host}/api/claim/get/${name}/${claimId}`;
|
||||||
return Request(url);
|
return Request(url);
|
||||||
}
|
}
|
|
@ -1,10 +1,10 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Route, Switch } from 'react-router-dom';
|
import { Route, Switch } from 'react-router-dom';
|
||||||
import HomePage from 'components/HomePage';
|
import HomePage from 'pages/HomePage'; // or use the provided local homepage
|
||||||
import AboutPage from 'components/AboutPage';
|
import AboutPage from 'pages/AboutPage';
|
||||||
import LoginPage from 'containers/LoginPage';
|
import LoginPage from 'pages/LoginPage';
|
||||||
import ShowPage from 'containers/ShowPage';
|
import ShowPage from 'pages/ShowPage';
|
||||||
import FourOhFourPage from 'components/FourOhFourPage';
|
import FourOhFourPage from 'containers/FourOhFourPage';
|
||||||
|
|
||||||
const App = () => {
|
const App = () => {
|
||||||
return (
|
return (
|
10
client/components/AssetPreview/index.js
Normal file
10
client/components/AssetPreview/index.js
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
import { connect } from 'react-redux';
|
||||||
|
import View from './view';
|
||||||
|
|
||||||
|
const mapStateToProps = ({site: {defaults: { defaultThumbnail }}}) => {
|
||||||
|
return {
|
||||||
|
defaultThumbnail,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export default connect(mapStateToProps, null)(View);
|
|
@ -1,8 +1,7 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
const { claim: { defaultThumbnail } } = require('../../../config/speechConfig.js');
|
|
||||||
|
|
||||||
const AssetPreview = ({ claimData: { name, claimId, fileExt, contentType, thumbnail } }) => {
|
const AssetPreview = ({ defaultThumbnail, claimData: { name, claimId, fileExt, contentType, thumbnail } }) => {
|
||||||
const directSourceLink = `${claimId}/${name}.${fileExt}`;
|
const directSourceLink = `${claimId}/${name}.${fileExt}`;
|
||||||
const showUrlLink = `/${claimId}/${name}`;
|
const showUrlLink = `/${claimId}/${name}`;
|
||||||
return (
|
return (
|
|
@ -1,10 +1,9 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import GoogleAnalytics from 'react-ga';
|
import GoogleAnalytics from 'react-ga';
|
||||||
import { withRouter } from 'react-router-dom';
|
import { withRouter } from 'react-router-dom';
|
||||||
const config = require('../../../config/speechConfig.js');
|
const { analytics: { googleId } } = require('../../../config/siteConfig.js');
|
||||||
const googleApiKey = config.analytics.googleId;
|
|
||||||
|
|
||||||
GoogleAnalytics.initialize(googleApiKey);
|
GoogleAnalytics.initialize(googleId);
|
||||||
|
|
||||||
class GAListener extends React.Component {
|
class GAListener extends React.Component {
|
||||||
componentDidMount () {
|
componentDidMount () {
|
|
@ -1,7 +1,7 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
class Preview extends React.Component {
|
class PublishPreview extends React.Component {
|
||||||
constructor (props) {
|
constructor (props) {
|
||||||
super(props);
|
super(props);
|
||||||
this.state = {
|
this.state = {
|
||||||
|
@ -53,10 +53,10 @@ class Preview extends React.Component {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Preview.propTypes = {
|
PublishPreview.propTypes = {
|
||||||
dimPreview: PropTypes.bool.isRequired,
|
dimPreview: PropTypes.bool.isRequired,
|
||||||
file : PropTypes.object.isRequired,
|
file : PropTypes.object.isRequired,
|
||||||
thumbnail : PropTypes.object,
|
thumbnail : PropTypes.object,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default Preview;
|
export default PublishPreview;
|
16
client/components/SEO/index.js
Normal file
16
client/components/SEO/index.js
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
import { connect } from 'react-redux';
|
||||||
|
import View from './view';
|
||||||
|
|
||||||
|
const mapStateToProps = ({ site }) => {
|
||||||
|
const { defaultDescription, defaultThumbnail, description: siteDescription, host: siteHost, title: siteTitle, twitter: siteTwitter } = site;
|
||||||
|
return {
|
||||||
|
defaultDescription,
|
||||||
|
defaultThumbnail,
|
||||||
|
siteDescription,
|
||||||
|
siteHost,
|
||||||
|
siteTitle,
|
||||||
|
siteTwitter,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export default connect(mapStateToProps, null)(View);
|
|
@ -8,10 +8,16 @@ import { createCanonicalLink } from 'utils/canonicalLink';
|
||||||
|
|
||||||
class SEO extends React.Component {
|
class SEO extends React.Component {
|
||||||
render () {
|
render () {
|
||||||
let { pageTitle, asset, channel, pageUri } = this.props;
|
// props from state
|
||||||
pageTitle = createPageTitle(pageTitle);
|
const { defaultDescription, defaultThumbnail, siteDescription, siteHost, siteTitle, siteTwitter } = this.props;
|
||||||
const metaTags = createMetaTags(asset, channel);
|
// props from parent
|
||||||
const canonicalLink = createCanonicalLink(asset, channel, pageUri);
|
const { asset, channel, pageUri } = this.props;
|
||||||
|
let { pageTitle } = this.props;
|
||||||
|
// create page title, tags, and canonical link
|
||||||
|
pageTitle = createPageTitle(siteTitle, pageTitle);
|
||||||
|
const metaTags = createMetaTags(siteDescription, siteHost, siteTitle, siteTwitter, asset, channel, defaultDescription, defaultThumbnail);
|
||||||
|
const canonicalLink = createCanonicalLink(asset, channel, pageUri, siteHost);
|
||||||
|
// render results
|
||||||
return (
|
return (
|
||||||
<Helmet
|
<Helmet
|
||||||
title={pageTitle}
|
title={pageTitle}
|
|
@ -1,6 +1,6 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { validateFile } from 'utils/file';
|
import { validateFile } from 'utils/file';
|
||||||
import Preview from 'components/Preview';
|
import PublishPreview from 'components/PublishPreview';
|
||||||
|
|
||||||
class Dropzone extends React.Component {
|
class Dropzone extends React.Component {
|
||||||
constructor (props) {
|
constructor (props) {
|
||||||
|
@ -87,7 +87,7 @@ class Dropzone extends React.Component {
|
||||||
<div id='preview-dropzone' className={'row row--padded row--tall dropzone' + (this.state.dragOver ? ' dropzone--drag-over' : '')} onDrop={this.handleDrop} onDragOver={this.handleDragOver} onDragEnd={this.handleDragEnd} onDragEnter={this.handleDragEnter} onDragLeave={this.handleDragLeave} onMouseEnter={this.handleMouseEnter} onMouseLeave={this.handleMouseLeave} onClick={this.handleClick}>
|
<div id='preview-dropzone' className={'row row--padded row--tall dropzone' + (this.state.dragOver ? ' dropzone--drag-over' : '')} onDrop={this.handleDrop} onDragOver={this.handleDragOver} onDragEnd={this.handleDragEnd} onDragEnter={this.handleDragEnter} onDragLeave={this.handleDragLeave} onMouseEnter={this.handleMouseEnter} onMouseLeave={this.handleMouseLeave} onClick={this.handleClick}>
|
||||||
{this.props.file ? (
|
{this.props.file ? (
|
||||||
<div>
|
<div>
|
||||||
<Preview
|
<PublishPreview
|
||||||
dimPreview={this.state.dimPreview}
|
dimPreview={this.state.dimPreview}
|
||||||
file={this.props.file}
|
file={this.props.file}
|
||||||
thumbnail={this.props.thumbnail}
|
thumbnail={this.props.thumbnail}
|
11
client/containers/FourOhFourPage/index.jsx
Normal file
11
client/containers/FourOhFourPage/index.jsx
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
import { connect } from 'react-redux';
|
||||||
|
import View from './view';
|
||||||
|
|
||||||
|
const mapStateToProps = ({ site: { host, title } }) => {
|
||||||
|
return {
|
||||||
|
host,
|
||||||
|
title,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export default connect(mapStateToProps, null)(View);
|
|
@ -1,10 +1,10 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import NavBar from 'containers/NavBar';
|
import NavBar from 'containers/NavBar';
|
||||||
import Helmet from 'react-helmet';
|
import Helmet from 'react-helmet';
|
||||||
const { site: { title, host } } = require('../../../config/speechConfig.js');
|
|
||||||
|
|
||||||
class FourOhForPage extends React.Component {
|
class FourOhForPage extends React.Component {
|
||||||
render () {
|
render () {
|
||||||
|
const {title, host} = this.props;
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<Helmet>
|
<Helmet>
|
|
@ -1,13 +1,14 @@
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { updateLoggedInChannel } from 'actions/channel';
|
import { updateLoggedInChannel } from 'actions/channel';
|
||||||
|
import {updateSelectedChannel} from 'actions/publish';
|
||||||
import View from './view';
|
import View from './view';
|
||||||
import {updateSelectedChannel} from '../../actions/publish';
|
|
||||||
|
|
||||||
const mapStateToProps = ({ channel }) => {
|
const mapStateToProps = ({ channel, site }) => {
|
||||||
return {
|
return {
|
||||||
channelName : channel.loggedInChannel.name,
|
channelName : channel.loggedInChannel.name,
|
||||||
channelShortId: channel.loggedInChannel.shortId,
|
channelShortId: channel.loggedInChannel.shortId,
|
||||||
channelLongId : channel.loggedInChannel.longId,
|
channelLongId : channel.loggedInChannel.longId,
|
||||||
|
siteDescription: site.description,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -53,12 +53,13 @@ class NavBar extends React.Component {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
render () {
|
render () {
|
||||||
|
const { siteDescription } = this.props;
|
||||||
return (
|
return (
|
||||||
<div className='row row--wide nav-bar'>
|
<div className='row row--wide nav-bar'>
|
||||||
<div className='row row--padded row--short flex-container--row flex-container--space-between-center'>
|
<div className='row row--padded row--short flex-container--row flex-container--space-between-center'>
|
||||||
<Logo />
|
<Logo />
|
||||||
<div className='nav-bar--center'>
|
<div className='nav-bar--center'>
|
||||||
<span className='nav-bar-tagline'>Open-source, decentralized image and video sharing.</span>
|
<span className='nav-bar-tagline'>{siteDescription}</span>
|
||||||
</div>
|
</div>
|
||||||
<div className='nav-bar--right'>
|
<div className='nav-bar--right'>
|
||||||
<NavLink className='nav-bar-link link--nav' activeClassName='link--nav-active' to='/' exact>Publish</NavLink>
|
<NavLink className='nav-bar-link link--nav' activeClassName='link--nav-active' to='/' exact>Publish</NavLink>
|
10
client/containers/PublishDisabledMessage/index.js
Normal file
10
client/containers/PublishDisabledMessage/index.js
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
import {connect} from 'react-redux';
|
||||||
|
import View from './view';
|
||||||
|
|
||||||
|
const mapStateToProps = ({ publish }) => {
|
||||||
|
return {
|
||||||
|
message: publish.disabledMessage,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export default connect(mapStateToProps, null)(View);
|
16
client/containers/PublishDisabledMessage/view.jsx
Normal file
16
client/containers/PublishDisabledMessage/view.jsx
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
class PublishDisabledMessage extends React.Component {
|
||||||
|
render () {
|
||||||
|
const message = this.props.message;
|
||||||
|
console.log('this.props.message:', message);
|
||||||
|
return (
|
||||||
|
<div className='row dropzone--disabled row--tall flex-container--column flex-container--center-center'>
|
||||||
|
<p className='text--disabled'>Publishing is currently disabled.</p>
|
||||||
|
<p className='text--disabled'>{message}</p>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default PublishDisabledMessage;
|
30
client/containers/PublishTool/view.jsx
Normal file
30
client/containers/PublishTool/view.jsx
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
import React from 'react';
|
||||||
|
import Dropzone from 'containers/Dropzone';
|
||||||
|
import PublishDetails from 'containers/PublishDetails';
|
||||||
|
import PublishStatus from 'containers/PublishStatus';
|
||||||
|
import PublishDisabledMessage from 'containers/PublishDisabledMessage';
|
||||||
|
|
||||||
|
class PublishTool extends React.Component {
|
||||||
|
render () {
|
||||||
|
if (this.props.disabled) {
|
||||||
|
console.log('publish is disabled');
|
||||||
|
return (
|
||||||
|
<PublishDisabledMessage />
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
console.log('publish is not disabled');
|
||||||
|
if (this.props.file) {
|
||||||
|
if (this.props.status) {
|
||||||
|
return (
|
||||||
|
<PublishStatus />
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return <PublishDetails />;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return <Dropzone />;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default PublishTool;
|
|
@ -1,7 +1,7 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import SEO from 'components/SEO';
|
import SEO from 'components/SEO';
|
||||||
import NavBar from 'containers/NavBar';
|
import NavBar from 'containers/NavBar';
|
||||||
import ErrorPage from 'components/ErrorPage';
|
import ErrorPage from 'pages/ErrorPage';
|
||||||
import AssetTitle from 'containers/AssetTitle';
|
import AssetTitle from 'containers/AssetTitle';
|
||||||
import AssetDisplay from 'containers/AssetDisplay';
|
import AssetDisplay from 'containers/AssetDisplay';
|
||||||
import AssetInfo from 'containers/AssetInfo';
|
import AssetInfo from 'containers/AssetInfo';
|
|
@ -1,6 +1,6 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import SEO from 'components/SEO';
|
import SEO from 'components/SEO';
|
||||||
import ErrorPage from 'components/ErrorPage';
|
import ErrorPage from 'pages/ErrorPage';
|
||||||
import NavBar from 'containers/NavBar';
|
import NavBar from 'containers/NavBar';
|
||||||
import ChannelClaimsDisplay from 'containers/ChannelClaimsDisplay';
|
import ChannelClaimsDisplay from 'containers/ChannelClaimsDisplay';
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import ErrorPage from 'components/ErrorPage';
|
import ErrorPage from 'pages/ErrorPage';
|
||||||
import ShowAssetLite from 'containers/ShowAssetLite';
|
import ShowAssetLite from 'containers/ShowAssetLite';
|
||||||
import ShowAssetDetails from 'containers/ShowAssetDetails';
|
import ShowAssetDetails from 'containers/ShowAssetDetails';
|
||||||
import ShowChannel from 'containers/ShowChannel';
|
import ShowChannel from 'containers/ShowChannel';
|
|
@ -1,9 +1,10 @@
|
||||||
import * as actions from 'constants/publish_action_types';
|
import * as actions from 'constants/publish_action_types';
|
||||||
import { LOGIN } from 'constants/publish_channel_select_states';
|
import { LOGIN } from 'constants/publish_channel_select_states';
|
||||||
const { publish } = require('../../config/speechConfig.js');
|
const { publishing } = require('../../config/siteConfig.js');
|
||||||
|
|
||||||
const initialState = {
|
const initialState = {
|
||||||
disabled : publish.disabled,
|
disabled : publishing.disabled,
|
||||||
|
disabledMessage : publishing.disabledMessage,
|
||||||
publishInChannel : false,
|
publishInChannel : false,
|
||||||
selectedChannel : LOGIN,
|
selectedChannel : LOGIN,
|
||||||
showMetadataInputs: false,
|
showMetadataInputs: false,
|
||||||
|
@ -25,9 +26,7 @@ const initialState = {
|
||||||
license : '',
|
license : '',
|
||||||
nsfw : false,
|
nsfw : false,
|
||||||
},
|
},
|
||||||
thumbnailChannel : publish.thumbnailChannel,
|
thumbnail: null,
|
||||||
thumbnailChannelId: publish.thumbnailChannelId,
|
|
||||||
thumbnail : null,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function (state = initialState, action) {
|
export default function (state = initialState, action) {
|
34
client/reducers/site.js
Normal file
34
client/reducers/site.js
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
const siteConfig = require('../../config/siteConfig.js');
|
||||||
|
|
||||||
|
const {
|
||||||
|
analytics: {
|
||||||
|
googleId: googleAnalyticsId,
|
||||||
|
},
|
||||||
|
assetDefaults: {
|
||||||
|
thumbnail: defaultThumbnail,
|
||||||
|
description: defaultDescription,
|
||||||
|
},
|
||||||
|
details: {
|
||||||
|
description,
|
||||||
|
host,
|
||||||
|
title,
|
||||||
|
twitter,
|
||||||
|
},
|
||||||
|
} = siteConfig;
|
||||||
|
|
||||||
|
const initialState = {
|
||||||
|
description,
|
||||||
|
googleAnalyticsId,
|
||||||
|
host,
|
||||||
|
title,
|
||||||
|
twitter,
|
||||||
|
defaultDescription,
|
||||||
|
defaultThumbnail,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function (state = initialState, action) {
|
||||||
|
switch (action.type) {
|
||||||
|
default:
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,16 +1,18 @@
|
||||||
import { call, put, takeLatest } from 'redux-saga/effects';
|
import {call, put, select, takeLatest} from 'redux-saga/effects';
|
||||||
import * as actions from 'constants/show_action_types';
|
import * as actions from 'constants/show_action_types';
|
||||||
import { updateFileAvailability, updateDisplayAssetError } from 'actions/show';
|
import { updateFileAvailability, updateDisplayAssetError } from 'actions/show';
|
||||||
import { UNAVAILABLE, AVAILABLE } from 'constants/asset_display_states';
|
import { UNAVAILABLE, AVAILABLE } from 'constants/asset_display_states';
|
||||||
import { checkFileAvailability, triggerClaimGet } from 'api/fileApi';
|
import { checkFileAvailability, triggerClaimGet } from 'api/fileApi';
|
||||||
|
import { selectSiteHost } from 'selectors/site';
|
||||||
|
|
||||||
function * retrieveFile (action) {
|
function * retrieveFile (action) {
|
||||||
const name = action.data.name;
|
const name = action.data.name;
|
||||||
const claimId = action.data.claimId;
|
const claimId = action.data.claimId;
|
||||||
|
const host = yield select(selectSiteHost);
|
||||||
// see if the file is available
|
// see if the file is available
|
||||||
let isAvailable;
|
let isAvailable;
|
||||||
try {
|
try {
|
||||||
({ data: isAvailable } = yield call(checkFileAvailability, name, claimId));
|
({ data: isAvailable } = yield call(checkFileAvailability, claimId, host, name));
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return yield put(updateDisplayAssetError(error.message));
|
return yield put(updateDisplayAssetError(error.message));
|
||||||
};
|
};
|
||||||
|
@ -21,7 +23,7 @@ function * retrieveFile (action) {
|
||||||
yield put(updateFileAvailability(UNAVAILABLE));
|
yield put(updateFileAvailability(UNAVAILABLE));
|
||||||
// initiate get request for the file
|
// initiate get request for the file
|
||||||
try {
|
try {
|
||||||
yield call(triggerClaimGet, name, claimId);
|
yield call(triggerClaimGet, claimId, host, name);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return yield put(updateDisplayAssetError(error.message));
|
return yield put(updateDisplayAssetError(error.message));
|
||||||
};
|
};
|
|
@ -3,6 +3,7 @@ import * as actions from 'constants/show_action_types';
|
||||||
import { addRequestToRequestList, onRequestError, onRequestUpdate, addAssetToAssetList } from 'actions/show';
|
import { addRequestToRequestList, onRequestError, onRequestUpdate, addAssetToAssetList } from 'actions/show';
|
||||||
import { getLongClaimId, getShortId, getClaimData } from 'api/assetApi';
|
import { getLongClaimId, getShortId, getClaimData } from 'api/assetApi';
|
||||||
import { selectShowState } from 'selectors/show';
|
import { selectShowState } from 'selectors/show';
|
||||||
|
import { selectSiteHost } from 'selectors/site';
|
||||||
|
|
||||||
export function * newAssetRequest (action) {
|
export function * newAssetRequest (action) {
|
||||||
const { requestType, requestId, name, modifier } = action.data;
|
const { requestType, requestId, name, modifier } = action.data;
|
||||||
|
@ -11,13 +12,14 @@ export function * newAssetRequest (action) {
|
||||||
// is this an existing request?
|
// is this an existing request?
|
||||||
// If this uri is in the request list, it's already been fetched
|
// If this uri is in the request list, it's already been fetched
|
||||||
const state = yield select(selectShowState);
|
const state = yield select(selectShowState);
|
||||||
|
const host = yield select(selectSiteHost);
|
||||||
if (state.requestList[requestId]) {
|
if (state.requestList[requestId]) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
// get long id && add request to request list
|
// get long id && add request to request list
|
||||||
let longId;
|
let longId;
|
||||||
try {
|
try {
|
||||||
({data: longId} = yield call(getLongClaimId, name, modifier));
|
({data: longId} = yield call(getLongClaimId, host, name, modifier));
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return yield put(onRequestError(error.message));
|
return yield put(onRequestError(error.message));
|
||||||
}
|
}
|
||||||
|
@ -31,14 +33,14 @@ export function * newAssetRequest (action) {
|
||||||
// get short Id
|
// get short Id
|
||||||
let shortId;
|
let shortId;
|
||||||
try {
|
try {
|
||||||
({data: shortId} = yield call(getShortId, name, longId));
|
({data: shortId} = yield call(getShortId, host, name, longId));
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return yield put(onRequestError(error.message));
|
return yield put(onRequestError(error.message));
|
||||||
}
|
}
|
||||||
// get asset claim data
|
// get asset claim data
|
||||||
let claimData;
|
let claimData;
|
||||||
try {
|
try {
|
||||||
({data: claimData} = yield call(getClaimData, name, longId));
|
({data: claimData} = yield call(getClaimData, host, name, longId));
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return yield put(onRequestError(error.message));
|
return yield put(onRequestError(error.message));
|
||||||
}
|
}
|
|
@ -3,6 +3,7 @@ import * as actions from 'constants/show_action_types';
|
||||||
import { addNewChannelToChannelList, addRequestToRequestList, onRequestError, onRequestUpdate, updateChannelClaims } from 'actions/show';
|
import { addNewChannelToChannelList, addRequestToRequestList, onRequestError, onRequestUpdate, updateChannelClaims } from 'actions/show';
|
||||||
import { getChannelClaims, getChannelData } from 'api/channelApi';
|
import { getChannelClaims, getChannelData } from 'api/channelApi';
|
||||||
import { selectShowState } from 'selectors/show';
|
import { selectShowState } from 'selectors/show';
|
||||||
|
import { selectSiteHost } from 'selectors/site';
|
||||||
|
|
||||||
export function * newChannelRequest (action) {
|
export function * newChannelRequest (action) {
|
||||||
const { requestType, requestId, channelName, channelId } = action.data;
|
const { requestType, requestId, channelName, channelId } = action.data;
|
||||||
|
@ -11,13 +12,14 @@ export function * newChannelRequest (action) {
|
||||||
// is this an existing request?
|
// is this an existing request?
|
||||||
// If this uri is in the request list, it's already been fetched
|
// If this uri is in the request list, it's already been fetched
|
||||||
const state = yield select(selectShowState);
|
const state = yield select(selectShowState);
|
||||||
|
const host = yield select(selectSiteHost);
|
||||||
if (state.requestList[requestId]) {
|
if (state.requestList[requestId]) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
// get channel long id
|
// get channel long id
|
||||||
let longId, shortId;
|
let longId, shortId;
|
||||||
try {
|
try {
|
||||||
({ data: {longChannelClaimId: longId, shortChannelClaimId: shortId} } = yield call(getChannelData, channelName, channelId));
|
({ data: {longChannelClaimId: longId, shortChannelClaimId: shortId} } = yield call(getChannelData, host, channelName, channelId));
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return yield put(onRequestError(error.message));
|
return yield put(onRequestError(error.message));
|
||||||
}
|
}
|
||||||
|
@ -32,7 +34,7 @@ export function * newChannelRequest (action) {
|
||||||
// get channel claims data
|
// get channel claims data
|
||||||
let claimsData;
|
let claimsData;
|
||||||
try {
|
try {
|
||||||
({ data: claimsData } = yield call(getChannelClaims, channelName, longId, 1));
|
({ data: claimsData } = yield call(getChannelClaims, host, longId, channelName, 1));
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return yield put(onRequestError(error.message));
|
return yield put(onRequestError(error.message));
|
||||||
}
|
}
|
||||||
|
@ -48,9 +50,10 @@ export function * watchNewChannelRequest () {
|
||||||
|
|
||||||
function * getNewClaimsAndUpdateChannel (action) {
|
function * getNewClaimsAndUpdateChannel (action) {
|
||||||
const { channelKey, name, longId, page } = action.data;
|
const { channelKey, name, longId, page } = action.data;
|
||||||
|
const host = yield select(selectSiteHost);
|
||||||
let claimsData;
|
let claimsData;
|
||||||
try {
|
try {
|
||||||
({ data: claimsData } = yield call(getChannelClaims, name, longId, page));
|
({ data: claimsData } = yield call(getChannelClaims, host, longId, name, page));
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return yield put(onRequestError(error.message));
|
return yield put(onRequestError(error.message));
|
||||||
}
|
}
|
7
client/selectors/site.js
Normal file
7
client/selectors/site.js
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
export const selectSiteState = (state) => {
|
||||||
|
return state.site;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const selectSiteHost = (state) => {
|
||||||
|
return state.site.host;
|
||||||
|
};
|
29
client/utils/canonicalLink.js
Normal file
29
client/utils/canonicalLink.js
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
const createBasicCanonicalLink = (page, siteHost) => {
|
||||||
|
return `${siteHost}/${page}`;
|
||||||
|
};
|
||||||
|
|
||||||
|
const createAssetCanonicalLink = (asset, siteHost) => {
|
||||||
|
let channelName, certificateId, name, claimId;
|
||||||
|
if (asset.claimData) {
|
||||||
|
({ channelName, certificateId, name, claimId } = asset.claimData);
|
||||||
|
};
|
||||||
|
if (channelName) {
|
||||||
|
return `${siteHost}/${channelName}:${certificateId}/${name}`;
|
||||||
|
};
|
||||||
|
return `${siteHost}/${claimId}/${name}`;
|
||||||
|
};
|
||||||
|
|
||||||
|
const createChannelCanonicalLink = (channel, siteHost) => {
|
||||||
|
const { name, longId } = channel;
|
||||||
|
return `${siteHost}/${name}:${longId}`;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const createCanonicalLink = (asset, channel, page, siteHost) => {
|
||||||
|
if (asset) {
|
||||||
|
return createAssetCanonicalLink(asset, siteHost);
|
||||||
|
}
|
||||||
|
if (channel) {
|
||||||
|
return createChannelCanonicalLink(channel, siteHost);
|
||||||
|
}
|
||||||
|
return createBasicCanonicalLink(page, siteHost);
|
||||||
|
};
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue