commit
928d240bfc
177 changed files with 11432 additions and 430 deletions
|
@ -1,3 +1,4 @@
|
|||
node_modules/
|
||||
public/
|
||||
public/bundle
|
||||
index.js
|
||||
test
|
||||
|
|
19
.gitignore
vendored
19
.gitignore
vendored
|
@ -1,7 +1,12 @@
|
|||
node_modules
|
||||
.idea
|
||||
config/sequelizeCliConfig.js
|
||||
config/speechConfig.js
|
||||
public/bundle
|
||||
server.js
|
||||
webpack.config.js
|
||||
node_modules/
|
||||
.idea/
|
||||
config/lbryConfig.js
|
||||
config/loggerConfig.js
|
||||
config/mysqlConfig.js
|
||||
config/siteConfig.js
|
||||
devConfig/slackConfig.js
|
||||
devConfig/sequelizeCliConfig.js
|
||||
devConfig/testingConfig.js
|
||||
|
||||
public/bundle/
|
||||
index.js
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
const path = require('path');
|
||||
|
||||
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 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
|
||||
* install mysql
|
||||
* 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
|
||||
* clone this repo
|
||||
* run `npm install`
|
||||
* create your `speechConfig.js` file
|
||||
* copy `speechConfig.js.example` and name it `speechConfig.js`
|
||||
* create your own config files in `/config`
|
||||
* copy `example.js.example` and name it `example.js`
|
||||
* 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`
|
||||
* visit [localhost:3000](http://localhost:3000)
|
||||
* 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
|
||||
* example: `curl -F 'name=MyPictureName' -F 'file=@/path/to/myPicture.jpeg' https://spee.ch/api/claim/publish`
|
||||
* Parameters:
|
||||
* `name`
|
||||
* `file` (must be type .mp4, .jpeg, .jpg, .gif, or .png)
|
||||
* `name` (required)
|
||||
* `file` (required) (must be type .mp4, .jpeg, .jpg, .gif, or .png)
|
||||
* `nsfw` (optional)
|
||||
* `license` (optional)
|
||||
* `title` (optional)
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
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 = {};
|
||||
// create request params
|
||||
if (modifier) {
|
||||
|
@ -24,12 +23,12 @@ export function getLongClaimId (name, modifier) {
|
|||
return Request(url, params);
|
||||
};
|
||||
|
||||
export function getShortId (name, claimId) {
|
||||
export function getShortId (host, name, claimId) {
|
||||
const url = `${host}/api/claim/short-id/${claimId}/${name}`;
|
||||
return Request(url);
|
||||
};
|
||||
|
||||
export function getClaimData (name, claimId) {
|
||||
export function getClaimData (host, name, claimId) {
|
||||
const url = `${host}/api/claim/data/${name}/${claimId}`;
|
||||
return Request(url);
|
||||
};
|
|
@ -1,13 +1,12 @@
|
|||
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';
|
||||
const url = `${host}/api/channel/data/${name}/${id}`;
|
||||
return Request(url);
|
||||
};
|
||||
|
||||
export function getChannelClaims (name, longId, page) {
|
||||
export function getChannelClaims (host, longId, name, page) {
|
||||
if (!page) page = 1;
|
||||
const url = `${host}/api/channel/claims/${name}/${longId}/${page}`;
|
||||
return Request(url);
|
|
@ -1,12 +1,11 @@
|
|||
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}`;
|
||||
return Request(url);
|
||||
}
|
||||
|
||||
export function triggerClaimGet (name, claimId) {
|
||||
export function triggerClaimGet (claimId, host, name) {
|
||||
const url = `${host}/api/claim/get/${name}/${claimId}`;
|
||||
return Request(url);
|
||||
}
|
|
@ -1,10 +1,10 @@
|
|||
import React from 'react';
|
||||
import { Route, Switch } from 'react-router-dom';
|
||||
import HomePage from 'components/HomePage';
|
||||
import AboutPage from 'components/AboutPage';
|
||||
import LoginPage from 'containers/LoginPage';
|
||||
import ShowPage from 'containers/ShowPage';
|
||||
import FourOhFourPage from 'components/FourOhFourPage';
|
||||
import HomePage from 'pages/HomePage'; // or use the provided local homepage
|
||||
import AboutPage from 'pages/AboutPage';
|
||||
import LoginPage from 'pages/LoginPage';
|
||||
import ShowPage from 'pages/ShowPage';
|
||||
import FourOhFourPage from 'containers/FourOhFourPage';
|
||||
|
||||
const App = () => {
|
||||
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 { 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 showUrlLink = `/${claimId}/${name}`;
|
||||
return (
|
|
@ -1,10 +1,9 @@
|
|||
import React from 'react';
|
||||
import GoogleAnalytics from 'react-ga';
|
||||
import { withRouter } from 'react-router-dom';
|
||||
const config = require('../../../config/speechConfig.js');
|
||||
const googleApiKey = config.analytics.googleId;
|
||||
const { analytics: { googleId } } = require('../../../config/siteConfig.js');
|
||||
|
||||
GoogleAnalytics.initialize(googleApiKey);
|
||||
GoogleAnalytics.initialize(googleId);
|
||||
|
||||
class GAListener extends React.Component {
|
||||
componentDidMount () {
|
|
@ -1,7 +1,7 @@
|
|||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
class Preview extends React.Component {
|
||||
class PublishPreview extends React.Component {
|
||||
constructor (props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
|
@ -53,10 +53,10 @@ class Preview extends React.Component {
|
|||
}
|
||||
};
|
||||
|
||||
Preview.propTypes = {
|
||||
PublishPreview.propTypes = {
|
||||
dimPreview: PropTypes.bool.isRequired,
|
||||
file : PropTypes.object.isRequired,
|
||||
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 {
|
||||
render () {
|
||||
let { pageTitle, asset, channel, pageUri } = this.props;
|
||||
pageTitle = createPageTitle(pageTitle);
|
||||
const metaTags = createMetaTags(asset, channel);
|
||||
const canonicalLink = createCanonicalLink(asset, channel, pageUri);
|
||||
// props from state
|
||||
const { defaultDescription, defaultThumbnail, siteDescription, siteHost, siteTitle, siteTwitter } = this.props;
|
||||
// props from parent
|
||||
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 (
|
||||
<Helmet
|
||||
title={pageTitle}
|
|
@ -1,6 +1,6 @@
|
|||
import React from 'react';
|
||||
import { validateFile } from 'utils/file';
|
||||
import Preview from 'components/Preview';
|
||||
import PublishPreview from 'components/PublishPreview';
|
||||
|
||||
class Dropzone extends React.Component {
|
||||
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}>
|
||||
{this.props.file ? (
|
||||
<div>
|
||||
<Preview
|
||||
<PublishPreview
|
||||
dimPreview={this.state.dimPreview}
|
||||
file={this.props.file}
|
||||
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 NavBar from 'containers/NavBar';
|
||||
import Helmet from 'react-helmet';
|
||||
const { site: { title, host } } = require('../../../config/speechConfig.js');
|
||||
|
||||
class FourOhForPage extends React.Component {
|
||||
render () {
|
||||
const {title, host} = this.props;
|
||||
return (
|
||||
<div>
|
||||
<Helmet>
|
|
@ -1,13 +1,14 @@
|
|||
import { connect } from 'react-redux';
|
||||
import { updateLoggedInChannel } from 'actions/channel';
|
||||
import {updateSelectedChannel} from 'actions/publish';
|
||||
import View from './view';
|
||||
import {updateSelectedChannel} from '../../actions/publish';
|
||||
|
||||
const mapStateToProps = ({ channel }) => {
|
||||
const mapStateToProps = ({ channel, site }) => {
|
||||
return {
|
||||
channelName : channel.loggedInChannel.name,
|
||||
channelShortId: channel.loggedInChannel.shortId,
|
||||
channelLongId : channel.loggedInChannel.longId,
|
||||
siteDescription: site.description,
|
||||
};
|
||||
};
|
||||
|
|
@ -53,12 +53,13 @@ class NavBar extends React.Component {
|
|||
}
|
||||
}
|
||||
render () {
|
||||
const { siteDescription } = this.props;
|
||||
return (
|
||||
<div className='row row--wide nav-bar'>
|
||||
<div className='row row--padded row--short flex-container--row flex-container--space-between-center'>
|
||||
<Logo />
|
||||
<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 className='nav-bar--right'>
|
||||
<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 SEO from 'components/SEO';
|
||||
import NavBar from 'containers/NavBar';
|
||||
import ErrorPage from 'components/ErrorPage';
|
||||
import ErrorPage from 'pages/ErrorPage';
|
||||
import AssetTitle from 'containers/AssetTitle';
|
||||
import AssetDisplay from 'containers/AssetDisplay';
|
||||
import AssetInfo from 'containers/AssetInfo';
|
|
@ -1,6 +1,6 @@
|
|||
import React from 'react';
|
||||
import SEO from 'components/SEO';
|
||||
import ErrorPage from 'components/ErrorPage';
|
||||
import ErrorPage from 'pages/ErrorPage';
|
||||
import NavBar from 'containers/NavBar';
|
||||
import ChannelClaimsDisplay from 'containers/ChannelClaimsDisplay';
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
import React from 'react';
|
||||
import ErrorPage from 'components/ErrorPage';
|
||||
import ErrorPage from 'pages/ErrorPage';
|
||||
import ShowAssetLite from 'containers/ShowAssetLite';
|
||||
import ShowAssetDetails from 'containers/ShowAssetDetails';
|
||||
import ShowChannel from 'containers/ShowChannel';
|
|
@ -1,9 +1,10 @@
|
|||
import * as actions from 'constants/publish_action_types';
|
||||
import { LOGIN } from 'constants/publish_channel_select_states';
|
||||
const { publish } = require('../../config/speechConfig.js');
|
||||
const { publishing } = require('../../config/siteConfig.js');
|
||||
|
||||
const initialState = {
|
||||
disabled : publish.disabled,
|
||||
disabled : publishing.disabled,
|
||||
disabledMessage : publishing.disabledMessage,
|
||||
publishInChannel : false,
|
||||
selectedChannel : LOGIN,
|
||||
showMetadataInputs: false,
|
||||
|
@ -25,8 +26,6 @@ const initialState = {
|
|||
license : '',
|
||||
nsfw : false,
|
||||
},
|
||||
thumbnailChannel : publish.thumbnailChannel,
|
||||
thumbnailChannelId: publish.thumbnailChannelId,
|
||||
thumbnail: null,
|
||||
};
|
||||
|
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 { updateFileAvailability, updateDisplayAssetError } from 'actions/show';
|
||||
import { UNAVAILABLE, AVAILABLE } from 'constants/asset_display_states';
|
||||
import { checkFileAvailability, triggerClaimGet } from 'api/fileApi';
|
||||
import { selectSiteHost } from 'selectors/site';
|
||||
|
||||
function * retrieveFile (action) {
|
||||
const name = action.data.name;
|
||||
const claimId = action.data.claimId;
|
||||
const host = yield select(selectSiteHost);
|
||||
// see if the file is available
|
||||
let isAvailable;
|
||||
try {
|
||||
({ data: isAvailable } = yield call(checkFileAvailability, name, claimId));
|
||||
({ data: isAvailable } = yield call(checkFileAvailability, claimId, host, name));
|
||||
} catch (error) {
|
||||
return yield put(updateDisplayAssetError(error.message));
|
||||
};
|
||||
|
@ -21,7 +23,7 @@ function * retrieveFile (action) {
|
|||
yield put(updateFileAvailability(UNAVAILABLE));
|
||||
// initiate get request for the file
|
||||
try {
|
||||
yield call(triggerClaimGet, name, claimId);
|
||||
yield call(triggerClaimGet, claimId, host, name);
|
||||
} catch (error) {
|
||||
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 { getLongClaimId, getShortId, getClaimData } from 'api/assetApi';
|
||||
import { selectShowState } from 'selectors/show';
|
||||
import { selectSiteHost } from 'selectors/site';
|
||||
|
||||
export function * newAssetRequest (action) {
|
||||
const { requestType, requestId, name, modifier } = action.data;
|
||||
|
@ -11,13 +12,14 @@ export function * newAssetRequest (action) {
|
|||
// is this an existing request?
|
||||
// If this uri is in the request list, it's already been fetched
|
||||
const state = yield select(selectShowState);
|
||||
const host = yield select(selectSiteHost);
|
||||
if (state.requestList[requestId]) {
|
||||
return null;
|
||||
}
|
||||
// get long id && add request to request list
|
||||
let longId;
|
||||
try {
|
||||
({data: longId} = yield call(getLongClaimId, name, modifier));
|
||||
({data: longId} = yield call(getLongClaimId, host, name, modifier));
|
||||
} catch (error) {
|
||||
return yield put(onRequestError(error.message));
|
||||
}
|
||||
|
@ -31,14 +33,14 @@ export function * newAssetRequest (action) {
|
|||
// get short Id
|
||||
let shortId;
|
||||
try {
|
||||
({data: shortId} = yield call(getShortId, name, longId));
|
||||
({data: shortId} = yield call(getShortId, host, name, longId));
|
||||
} catch (error) {
|
||||
return yield put(onRequestError(error.message));
|
||||
}
|
||||
// get asset claim data
|
||||
let claimData;
|
||||
try {
|
||||
({data: claimData} = yield call(getClaimData, name, longId));
|
||||
({data: claimData} = yield call(getClaimData, host, name, longId));
|
||||
} catch (error) {
|
||||
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 { getChannelClaims, getChannelData } from 'api/channelApi';
|
||||
import { selectShowState } from 'selectors/show';
|
||||
import { selectSiteHost } from 'selectors/site';
|
||||
|
||||
export function * newChannelRequest (action) {
|
||||
const { requestType, requestId, channelName, channelId } = action.data;
|
||||
|
@ -11,13 +12,14 @@ export function * newChannelRequest (action) {
|
|||
// is this an existing request?
|
||||
// If this uri is in the request list, it's already been fetched
|
||||
const state = yield select(selectShowState);
|
||||
const host = yield select(selectSiteHost);
|
||||
if (state.requestList[requestId]) {
|
||||
return null;
|
||||
}
|
||||
// get channel long id
|
||||
let longId, shortId;
|
||||
try {
|
||||
({ data: {longChannelClaimId: longId, shortChannelClaimId: shortId} } = yield call(getChannelData, channelName, channelId));
|
||||
({ data: {longChannelClaimId: longId, shortChannelClaimId: shortId} } = yield call(getChannelData, host, channelName, channelId));
|
||||
} catch (error) {
|
||||
return yield put(onRequestError(error.message));
|
||||
}
|
||||
|
@ -32,7 +34,7 @@ export function * newChannelRequest (action) {
|
|||
// get channel claims data
|
||||
let claimsData;
|
||||
try {
|
||||
({ data: claimsData } = yield call(getChannelClaims, channelName, longId, 1));
|
||||
({ data: claimsData } = yield call(getChannelClaims, host, longId, channelName, 1));
|
||||
} catch (error) {
|
||||
return yield put(onRequestError(error.message));
|
||||
}
|
||||
|
@ -48,9 +50,10 @@ export function * watchNewChannelRequest () {
|
|||
|
||||
function * getNewClaimsAndUpdateChannel (action) {
|
||||
const { channelKey, name, longId, page } = action.data;
|
||||
const host = yield select(selectSiteHost);
|
||||
let claimsData;
|
||||
try {
|
||||
({ data: claimsData } = yield call(getChannelClaims, name, longId, page));
|
||||
({ data: claimsData } = yield call(getChannelClaims, host, longId, name, page));
|
||||
} catch (error) {
|
||||
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