Merge pull request #726 from lbryio/master

cut master to staging
This commit is contained in:
Travis Eden 2018-11-12 12:42:38 -05:00 committed by GitHub
commit 93ef9c69bf
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
121 changed files with 1378 additions and 881 deletions

4
.gitignore vendored
View file

@ -17,3 +17,7 @@ public/bundle/Lekton-*
public/bundle/style.css
uploads
config/
deployment-config.json

109
README.md
View file

@ -1,21 +1,97 @@
# Spee.ch
Spee.ch is a web app that reads and publishes images and videos to and from the [LBRY](https://lbry.io/) blockchain. You are encouraged to contribute to the shared code base, or fork it and make it your own.
Spee.ch is a web app that reads and publishes images and videos to and from the [LBRY](https://lbry.io/) blockchain. We encourage you to contribute to the shared code base, or fork it and make it your own.
You can create your own custom version of spee.ch by installing this code base and then creating your own custom components and styles to override the defaults. (More details/guide on how to do that coming soon.)
## Quickstart
## Technology Overview
Spee.ch is a react web app that depends on MySQL for local content, and on two other lbry technologies:
* [chainquery](https://github.com/lbryio/chainquery) - a normalized database of the blockchain data. We've provided credentials to use a public chainquery service. You can also install it on your own server to avoid being affected by the commons.
* [lbrynet](https://github.com/lbryio/lbry) - a daemon that handles your wallet and transactions.
### Ubuntu
[Ubuntu VPS Setup](./docs/ubuntu16vpspersonal.md)
## Installation
_Note: This is our new setup. For our old setup see the [fullstart guide](./fullstart.md)._
### Ubuntu Step by Step
[Ubuntu Install Guide](./docs/ubuntuinstall.md)
#### System Dependencies:
* [node](https://nodejs.org)
### Quickstart Overview
#### Get some information ready:
* mysqlusername
* mysqlpassword
* domainname or 'http://localhost'
* speechport = 3000
#### Install and Set Up System Dependencies:
* [NodeJS](https://nodejs.org)
* [MySQL](https://dev.mysql.com/doc/refman/8.0/en/installing.html)
* [`lbry`](https://github.com/lbryio/lbry) daemon
* note: retrieve an address from the daemon and send your wallet a few credits (or join us in the [#speech discord channel](https://discord.gg/YjYbwhS) and we will send you a few)
* localhost port 3306
* mysqlusername or root
* mysqlpassword
* You may need
```
mysql> `ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'yourpassword';`
```
* [lbrynet](https://github.com/lbryio/lbry) daemon
* run this as a service exposing ports 3333 and 4444
* _note_: once the daemon is running, issue commands in another terminal session (tmux) to retrieve an address for your wallet to recieve 5+ LBC credits (or join us in the [#speech discord channel](https://discord.gg/YjYbwhS) and we will send you a few)
* `./lbrynet commands` gets a list of commands
* `./lbrynet account_balance` gets your balance (initially 0.0)
* `./lbrynet address_list` gets addresses you can use to recieve LBC
* [FFmpeg](https://www.ffmpeg.org/download.html)
* [Spee.ch] (below)
* [pm2] (optional) process manager such as pm2 to run speech server.js
* [http proxy server] caddy, nginx, traefik, etc to forward 443 to speech port 3000
#### Clone this repo
* release version for stable production
```
$ git clone -b release https://github.com/lbryio/spee.ch.git
```
* master version for development
```
$ git clone https://github.com/lbryio/spee.ch.git
```
* your own fork for customization
#### Change directory into your project
```
$ cd spee.ch
```
#### Install node dependencies
```
$ npm install
```
#### Create the config files using the built-in CLI
_note: make sure lbrynet is running in the background before proceeding_
```
$ npm run configure
```
* _note: At the moment, you will have to copy chainqueryConfig.json from:_
```
~/spee.ch/docs/setup/conf/speech/chainqueryConfig.json
```
_to:_
```
~/spee.ch/site/config/chainqueryConfig.json
```
* _note: The domain name in this part must be prefixed with http:// or https://_
#### Build & start the app
_note: make sure lbrynet is running in the background before proceeding_
```
$ npm run start
```
#### View in browser
* Visit [http://localhost:3000](http://localhost:3000) in your browser
#### Customize your app
@ -23,12 +99,11 @@ Check out the [customization guide](https://github.com/lbryio/spee.ch/blob/readm
#### (optional) add custom components and update the styles
* Create custom components by creating React components in `src/views/` (further instructions coming soon)
* Update the CSS by changing the files in `public/assets/css/` (further instructions and refactor coming soon)
* Create custom components by creating React components in `site/custom/src/` (further instructions coming soon)
* Update the CSS by changing the files in `site/custom/scss` (further instructions and refactor coming soon)
#### (optional) Syncing the full blockchain
* Start the `spee.ch-sync` tool available at [billbitt/spee.ch-sync](https://github.com/billbitt/spee.ch-sync)
* This is not necessary, but highly recommended. It will decode the blocks of the `LBRY` blockchain and add the claims information to your database's tables
#### (optional) install your own chainquery
Instructions are coming at [lbry-docker] to install your own chainquery instance using docker-compose. This will require 50GB of preferably SSD space and at least 10 minutes to download, possibly much longer.
## API
#### /api/claim/publish
@ -112,7 +187,7 @@ Spee.ch also runs a sync tool, which decodes blocks from the `LBRY` blockchain a
### Architecture
* `cli/` contains the code for the CLI tool. Running the tool will create `.json` config files and place them in the `config/` folder
* `cli/` contains the code for the CLI tool. Running the tool will create `.json` config files and place them in the `site/config/` folder
* `configure.js` is the entry point for the CLI tool
* `cli/defaults/` holds default config files
* `cli/questions/` holds the questions that the CLI tool asks to build the config files
@ -128,9 +203,9 @@ Spee.ch also runs a sync tool, which decodes blocks from the `LBRY` blockchain a
* `client/scss/` contains the CSS for the project
*
* `config/custom` is a folder which can be used to override the default components in `client/`
* `site/custom` is a folder which can be used to override the default components in `client/`
* The folder structure mimics that of the `client/` folder
* to customize spee.ch, place your own components and scss in the `config/custom/src/` and `config/custom/scss` folders.
* to customize spee.ch, place your own components and scss in the `site/custom/src/` and `site/custom/scss` folders.
* `server/` contains all of the server code
* `index.js` is the entry point for the server. It creates the [express app](https://expressjs.com/), requires the routes, syncs the database, and starts the server listening on the `PORT` designated in the config files.

View file

@ -67,6 +67,13 @@ try {
slackConfig = require('./defaults/slackConfig.json');
}
let chainqueryConfig;
try {
chainqueryConfig = require('../site/config/chainqueryConfig.json');
} catch (error) {
chainqueryConfig = require('./defaults/chainqueryConfig.json');
}
// ask user questions and create config files
inquirer
.prompt(mysqlQuestions(mysqlDatabase, mysqlUsername, mysqlPassword))
@ -196,6 +203,7 @@ inquirer
createConfigFile('lbryConfig.json', lbryConfig);
createConfigFile('loggerConfig.json', loggerConfig);
createConfigFile('slackConfig.json', slackConfig);
createConfigFile('chainqueryConfig.json', chainqueryConfig);
})
.then(() => {
console.log('\nYou\'re all done!');

View file

@ -1,8 +1,8 @@
{
"host": "localhost",
"host": "public.chainquery.lbry.io",
"port": "3306",
"timeout": 30,
"database": "chainquery",
"username": "lbry",
"password": "root"
"username": "speechpublic",
"password": "7uITJLwZRvHBZYS3JZDykD1-7hLVkVA1jDWfcgqi6QnC"
}

View file

@ -0,0 +1,129 @@
.asset-main {
height: 75vh;
display: flex;
flex-direction: column;
align-items: center;
}
.asset-display {
display: flex;
min-height: 50vh
}
.asset-title {
padding-bottom: $thin-padding;
text-align: center;
@media (min-width: $break-point-mobile) {
padding-top: $secondary-padding;
}
}
.asset-image, .asset-video {
max-height: 100%;
max-width: 100%;
margin-left: auto;
margin-right: auto;
object-fit: contain;
object-position: center;
}
/*below must die if this is intended to be shareable component! it also probably doesn't need to be*/
.visible-content {
margin: 0;
padding-bottom: 30px;
position: relative;
width: 100%;
&.closed {
box-shadow: none;
&:after {
box-shadow: none;
}
}
&:after {
box-shadow: 0px 2px 3px 2px $shadow-color;
content: '';
height: 0;
position: absolute;
top: 100%;
width: 100%;
z-index: 100;
}
}
.vertical-split, .visible-content {
flex : 1 0 auto;
display : flex;
flex-direction : column;
justify-content: space-between;
align-items : center;
};
.collapse-content {
flex-grow: 0;
@media (max-width: $break-point-tablet) {
max-width: 100%;
width: 100%;
}
}
.collapse-content.closed{
display: none;
}
.collapse-button {
background: none;
border: none;
display: block;
margin: 15px auto 0;
width: 25px;
height: 25px;
text-align: center;
padding: 0px;
@media (max-width: $break-point-tablet) {
padding: 0;
}
svg {
stroke: $primary-color;
&.plus-icon {
transform: rotate(0);
transition: all 0.4s ease;
}
}
&:hover {
.plus-icon {
transform: rotate(-180deg);
}
}
}
.asset-info {
$asset-info-width: 1000px;
max-width: $asset-info-width;
margin: $primary-padding;
max-width: 100%;
@media (max-width: $break-point-tablet) {
margin: $primary-padding $secondary-padding;
}
@media (max-width: $break-point-mobile) {
margin: $primary-padding 0;
}
}
.asset-footer {
border-top: 1px solid $grey-border;
padding-top: $primary-padding;
margin-top: $primary-padding;
color: $grey;
}

View file

@ -1,10 +1,10 @@
body {
margin: 0;
padding: 0;
height: 100%;
min-height: 100%;
word-wrap: break-word;
display: -webkit-flex;
display: flex;
-webkit-flex-direction: column;
flex-direction: column;
}
}

View file

@ -0,0 +1,16 @@
.button--primary, .button--primary:focus, .button--primary:active {
border-color: $primary-color;
color: $primary-color;
background-color: $background-color;
}
.button--primary:hover {
color: $background-color;
background-color: $primary-color;
}
.button--primary:active {
$color: darken($primary-color, 10%);
border-color: $color;
background-color: $color;
}

View file

@ -0,0 +1,11 @@
.button--secondary, .button--secondary:focus, .button--secondary:active {
border-bottom-color: $secondary-color;
color: $secondary-color;
background-color: $background-color;
}
.button--secondary:active {
$color: darken($secondary-color, 10%);
color: $color;
border-bottom-color: $color;
}

21
client/scss/_button.scss Normal file
View file

@ -0,0 +1,21 @@
button {
cursor: pointer;
&:active
{
outline: 0;
}
}
.button--primary, .button--secondary
{
border-width: $button-border-width;
border-style: $button-border-strength;
border-color: transparent;
padding: $thin-padding;
}
.button--jumbo, .button--jumbo:focus, .button--jumbo:active {
width: $button-full-width;
font-size: x-large;
}

View file

@ -0,0 +1,33 @@
.click-to-copy-wrap {
display: flex;
width: 100%;
justify-content: space-between;
align-items: center;
cursor: pointer;
border: 1px solid $grey-border;
border-radius: 6px;
.click-to-copy {
border: none;
padding: 0.36em 0.5em;
margin: 0;
background-color: transparent;
width: calc(100% - 1em - 2px);
font-size: 14px;
letter-spacing: -0.6px;
line-height: 20px;
letter-spacing: 0;
font-family: monospace;
border-right: 1px solid $grey-border;
}
.icon-wrap {
width: 30px;
height: 30px;
line-height: 34px;
text-align: center;
svg {
stroke: $primary-color;
width: 16px;
height: 16px;
}
}
}

View file

@ -16,6 +16,7 @@
flex-direction: column;
justify-content: center;
align-items: center;
user-select: none;
}
.dropzone:hover, .dropzone--active {
@ -28,6 +29,11 @@
text-align: center;
}
.dropzone-dropit-display
{
color: $primary-color;
}
.dropzone-preview-wrapper {
position: relative;
width: 100%;
@ -49,3 +55,7 @@
padding: 1em;
width: calc(100% - 2em);
}
.dropzone-instructions-display__chooser-label {
text-decoration: underline;
}

7
client/scss/_form.scss Normal file
View file

@ -0,0 +1,7 @@
.form-group {
padding-bottom: $secondary-padding;
}
.form-title {
padding-bottom: $secondary-padding;
}

View file

@ -0,0 +1,62 @@
.horizontal-split {
max-width: $width-content-constrained;
width: 100%;
margin-left: auto;
margin-right: auto;
display : flex;
flex-direction : row;
justify-content: space-between;
&.horizontal-split--mobile-collapse {
@media (max-width: $break-point-mobile) {
flex-direction: column;
.horizontal-split__column {
width: 100%;
}
.horizontal-split__column--right {
padding-left: 0;
padding-top: $secondary-padding;
}
}
}
};
.horizontal-split__column {
width: 50%;
flex: 1 0 auto;
box-sizing: border-box;
}
.horizontal-split__column--left {
padding-right: $primary-padding;
@media (max-width: $break-point-mobile) {
padding-right: $thin-padding;
}
}
.horizontal-split__column--right {
padding-left: $primary-padding;
@media (max-width: $break-point-mobile) {
padding-left: $thin-padding;
}
}
@media (max-width: $break-point-tablet) {
.horizontal-split__column {
display : flex;
flex-direction : column;
justify-content: space-between;
};
.column {
width: 100%;
padding-left: 0;
padding-right: 0;
padding-bottom: $secondary-padding;
}
}

View file

@ -4,17 +4,12 @@ input:-webkit-autofill {
input {
margin: 0;
outline: none;
padding: $input-padding;
border: 0;
background-color: $background-color;
display: inline-block;
}
.input-text {
}
.input-slider {
width: 100%
}
@ -43,6 +38,10 @@ input {
border-bottom: 1px solid $secondary-color;
}
.form-group {
padding-bottom: $secondary-padding;
}
// modifiers
.input--full-width {

View file

@ -2,6 +2,7 @@
padding-top: $thin-padding;
padding-bottom: $thin-padding;
display: inline-block;
font-size: 12px;
}
.label-radio {
@ -10,7 +11,7 @@
cursor: pointer;
}
@media (max-width: $break-point-medium ) {
@media (max-width: $break-point-tablet ) {
// note: bolding break point lines up with row-label break point
.label, .label-radio {

21
client/scss/_link.scss Normal file
View file

@ -0,0 +1,21 @@
a, a:visited {
text-decoration: none;
}
.link--primary, .link--primary:visited {
color: $primary-color;
&:hover { text-decoration: underline; }
}
.link--nav {
color: $text-color;
border-bottom: 2px solid white;
&:hover {
color: $primary-color;
}
}
.link--nav-active {
border-bottom: 2px solid $primary-color;
}

View file

@ -0,0 +1,7 @@
@media (max-width: $break-point-x-large) {
// hide site description in nav bar
.site-description {
display: none;
}
}

View file

@ -1,31 +1,37 @@
.nav-bar {
padding-left: $primary-padding;
padding-right: $primary-padding;
border-bottom: 0.5px solid $tertiary-color;
.select--arrow {
padding: 0 1.5em 0 $input-padding;
margin-top: $thin-padding;
margin-left: $primary-padding;
margin-right: $primary-padding;
@media (max-width: $break-point-mobile) {
margin-left: 15px;
margin-right: 15px;
}
}
.nav-bar-link {
padding: calc(1em - 2px);
display: inline-block;
font-size: $text-medium;
letter-spacing: 0.4px;
text-transform: uppercase;
}
.nav-bar-logo {
cursor: pointer;
}
@media (max-width: $break-point-medium ) {
@media (max-width: $break-point-tablet ) {
.nav-bar-link {
padding-top: calc(1em - 2px);
padding-right: 1em;
padding-bottom: calc(1em - 2px);
padding-left: 1em;
}
}
@media (max-width: $break-point-small ) {
@media (max-width: $break-point-mobile ) {
.nav-bar-link {
padding-top: calc(0.5em - 2px);
padding-right: 0.5em;

View file

@ -0,0 +1,27 @@
.page-layout {
flex: 1 0 auto;
display: flex;
flex-direction: column;
.content {
flex: 1 0 auto;
display: flex;
-webkit-flex-direction: column;
flex-direction: column;
margin: $secondary-padding;
}
}
@media (max-width: $break-point-tablet) {
.page-layout .content { margin: $tertiary-padding; }
}
@media (max-width: $break-point-mobile) {
max-width: calc(100% - 30px);
}
//below should take some styles from _text.scss and probably elsewhere and become "markdown" or "rich" styles
.page-layout {
p {
margin-bottom: $tertiary-padding;
}
}

View file

@ -0,0 +1,12 @@
.progress-bar__wrapper {
display: flex;
align-items: center;
justify-content: center;
}
.progress-bar--inactive {
color: $grey;
}
.progress-bar--active {
color: $primary-color;
}

View file

@ -0,0 +1,13 @@
.publish-form__title {
max-width: $width-content-constrained;
margin-left: auto;
margin-right: auto;
@media (max-width: $break-point-mobile) {
font-size: .8em;
}
}
.publish-preview-dim {
opacity: 0.2;
}

View file

@ -17,5 +17,5 @@
.publish-url-text {
margin: 0;
padding: 0;
color: $secondary-color;
color: $help-color;
}

4
client/scss/_reset.scss Normal file
View file

@ -0,0 +1,4 @@
button, input, textarea, label, select, option {
font-family: inherit;
font-size: inherit;
}

View file

@ -1,5 +1,5 @@
.row {
padding-bottom: 2em;
margin-bottom: 1.2em;
}
.row-labeled {
@ -7,29 +7,28 @@
flex-direction: row;
flex-wrap: nowrap;
justify-content: flex-start;
padding-bottom: $tertiary-padding;
}
.row-labeled-label {
align-self: flex-start;
width: 30%;
display: flex;
align-items: center;
flex: 1;
}
.row-labeled-content {
align-self: center;
width: 70%;
}
@media (max-width: $break-point-medium ) {
@media (max-width: $break-point-tablet ) {
.row-labeled {
flex-direction: column;
}
.row-labeled-label {
width: 100%;
}
.row-labeled-content {
width: 100%;
}
}

4
client/scss/_select.scss Normal file
View file

@ -0,0 +1,4 @@
select {
margin: 0;
display: inline-block;
}

View file

@ -0,0 +1,51 @@
.share-buttons {
display: flex;
align-items: center;
a {
display: block;
width: 30px;
height: 30px;
margin: 0 7px;
border-radius: 100%;
line-height: 30px;
text-align: center;
transition: all 0.2s ease;
&.twitter {
background:#4DC2FE;
img {
margin-top: 8px;
margin-left: 2px;
}
}
&.facebook {
background: #5487DE;
img {
margin-top: 6px;
}
}
&.tumblr {
background: #274061;
img {
margin-top: 7px;
}
}
&.reddit {
background: #FF4500;
img {
margin-top: 7px;
}
}
&:first-child{
margin-left: 0px;
}
&:hover {
background: $primary-color;
}
}
}

View file

@ -7,5 +7,4 @@
.social-share-link > a{
padding-right:0.5em;
padding-left:0.5em;
padding-bottom:0.3em;
}

59
client/scss/_text.scss Normal file
View file

@ -0,0 +1,59 @@
// set defaults
h1, h2, h3, h4, p {
margin: 0;
}
body {
color: $text-color;
font-family: 'Circular', serif;
font-size: 16px;
}
h1 {
font-size: $text-xx-large;
}
h2 {
font-size: $text-x-large;
}
h3 {
font-size: $text-large;
}
.text--extra-large {
font-size: $text-xx-large;
}
.text--large {
font-size: $text-large;
}
.text--medium {
font-size: $text-medium;
}
.text--small {
font-size: $text-small;
}
.text--extra-small {
font-size: $text-x-small;
}
.text--secondary {
color: $help-color;
}
.text--interactive {
color: $primary-color;
}
.text--failure {
color: $failure-color;
}
.text--success {
color: $success-color;
}

View file

@ -0,0 +1,6 @@
textarea {
margin: 0;
padding: $input-padding;
display: inline-block;
width: $input-full-width;
}

View file

@ -1,10 +1,12 @@
$base-color: white;
$primary-color: black;
$secondary-color: #9b9b9b;
$tertiary-color: #ccccc0;
$interactive-color: blue;
$primary-color: #005da0;
$secondary-color: $primary-color;
$success-color: green;
$failure-color: red;
$grey: #9095A5;
$help-color: $grey;
$grey-border: #DDDFE4;
$shadow-color: rgba(169, 173, 186, 0.2);
$primary-padding: 3em;
$secondary-padding: 2em;
@ -12,8 +14,10 @@ $tertiary-padding: 1em;
$thin-padding: 0.3em;
$full-width-thin-padding: calc(100% - 0.6em);
$width-content-constrained: 1000px;
$background-color: $base-color;
$font-color: $primary-color;
$text-color: #333;
$button-border-width: 1px;
$button-border-strength: solid;
@ -23,16 +27,14 @@ $input-padding: 0.3em;
$input-full-width: calc(100% - 0.6em);
$text-xx-large: 2.5em;
$text-x-large: xx-large;
$text-large: x-large;
$text-medium: large;
$text-small: medium;
$text-x-small: small;
$text-x-large: 2.0em;
$text-large: 1.5em;
$text-medium: 1.0em;
$text-small: 0.9em;
$text-x-small: 0.8em;
$break-point-xx-large: 1400px;
$break-point-x-large: 1290px;
$break-point-large: 1000px;
$break-point-medium: 800px;
$break-point-small: 500px;
$break-point-x-small: 400px;
$break-point-tablet: 800px;
$break-point-mobile: 500px;

View file

@ -1,48 +1,44 @@
@import '~variables/_variables';
@import '~reset/_reset';
@import '~font/_font';
@import '~html/_html';
@import '~body/_body';
@import '~react-app/_react-app';
@import '~text/_text';
@import '_variables';
@import '_reset';
@import 'font/_font.scss';
@import '_html';
@import '_body';
@import '_react-app';
@import '_text';
@import '~link/_link';
@import '~input/_input';
@import '~select/_select';
@import '~textarea/_textarea';
@import '~video/_video';
@import '_link';
@import '_input';
@import '_select';
@import '_textarea';
@import '_video';
@import '_form';
@import '~asset-display/_asset-display';
@import '~asset-preview/_asset-preview';
@import '~button/_button';
@import '~button-primary/_button-primary';
@import '~button-secondary/_button-secondary';
@import '~button-tertiary/_button-tertiary';
@import '~click-to-copy/_click-to-copy';
@import '~column/_column';
@import '~form-feedback/_form-feedback';
@import '~horizontal-quad-split/_horizontal-quad-split';
@import '~horizontal-split/_horizontal-split';
@import '~label/_label';
@import '~nav-bar/_nav-bar';
@import '~page-layout/_page-layout';
@import '~page-layout-show-lite/_page-layout-show-lite';
@import '~page-content/_page-content';
@import '~progress-bar/_progress-bar';
@import '~publish-preview/_publish-preview';
@import '~space-between/_space-between';
@import '~space-around/_space-around';
@import '~row/_row';
@import '~vertical-split/_vertical-split';
@import '~tooltip/_tooltip';
@import '~social-share-link/_social-share-link';
@import '~channel-claims-display/_channel-claims-display';
@import '~dropzone/_dropzone';
@import '~publish-url-input/_publish-url-input';
@import '~publish-status/_publish-status';
@import '~publish-disabled-message/_publish-disabled-message';
@import '~media-queries/_media-queries';
@import '_asset-display';
@import '_asset-preview';
@import '_button';
@import '_button-primary';
@import '_button-secondary';
@import '_click-to-copy';
@import '_form-feedback';
@import '_horizontal-split';
@import '_label';
@import '_nav-bar';
@import '_page-layout';
@import '_page-layout-show-lite';
@import '_page-content';
@import '_progress-bar';
@import '_publish-preview';
@import '_share-buttons';
@import '_space-between';
@import '_space-around';
@import '_row';
@import '_tooltip';
@import '_social-share-link';
@import '_channel-claims-display';
@import '_dropzone';
@import '_publish-url-input';
@import '_publish-status';
@import '_publish-disabled-message';
@import '_media-queries';

View file

@ -1,22 +0,0 @@
.asset-display {
display: flex;
flex: 1 0 auto;
flex-direction: column;
justify-content: center;
}
.asset-image, .asset-video {
margin : 0;
max-width: 100%;
max-height: 100%;
object-fit: contain;
object-position: center;
}
.asset-video {
border: 1px solid #d0d0d0;
margin: 16px;
padding: 6px;
}
.vertical-split .asset-display {
height: 90vh;
}

View file

@ -1,34 +0,0 @@
.button-primary, .button-primary:focus, .button-primary:active {
border: $button-border-width $button-border-strength $primary-color;
margin-top: $thin-padding;
margin-bottom: $thin-padding;
padding: $thin-padding;
color: $primary-color;
background-color: $background-color;
outline: 0;
}
.button-primary:focus {
border-color: $secondary-color;
background-color: $tertiary-color;
}
.button-primary:hover {
border-color: $interactive-color;
color: $background-color;
background-color: $interactive-color;
}
.button-primary:active{
border-color: $background-color;
color: $secondary-color;
background-color: $tertiary-color;
}
.button-primary--jumbo, .button-primary--jumbo:focus, .button-primary--jumbo:active {
width: $button-full-width;
padding-top: $secondary-padding;
padding-bottom: $secondary-padding;
font-size: x-large;
}

View file

@ -1,21 +0,0 @@
.button--secondary, .button--secondary:focus {
border: 0;
border-bottom: $button-border-width $button-border-strength $primary-color;
padding: 0.5em;
color: $primary-color;
background-color: $background-color;
outline: 0;
}
.button--secondary:focus{
border-color: $secondary-color;
background-color: $tertiary-color;
}
.button--secondary:hover {
color: $interactive-color;
}
.button--secondary:active {
color: $background-color;
}

View file

@ -1,14 +0,0 @@
.button--tertiary, .button--tertiary:focus, .button--tertiary:active {
border: 0;
color: $secondary-color;
background-color: $background-color;
}
.button--tertiary:hover {
color: $primary-color;
}
.button--tertiary:active, .button--tertiary:focus {
color: $secondary-color;
background-color: $tertiary-color;
}

View file

@ -1,3 +0,0 @@
button {
cursor: pointer;
}

View file

@ -1,9 +0,0 @@
.click-to-copy {
cursor: pointer;
border: 1px solid black;
padding: 0.5em;
margin: 0;
color: black;
background-color: white;
width: calc(100% - 1em - 2px);
}

View file

@ -1,4 +0,0 @@
.column {
padding-left: $primary-padding;
padding-right: $primary-padding;
}

Binary file not shown.

Binary file not shown.

View file

@ -16,3 +16,16 @@
font-weight: normal;
font-style: italic;
}
@font-face {
font-family: 'Circular';
src: url('./font/Circular/CircularStd-Book.ttf');
font-weight: normal;
}
@font-face {
font-family: 'Circular';
src: url('./font/Circular/CircularStd-Bold.ttf');
font-weight: bold;
}

View file

@ -1,53 +0,0 @@
.horizontal-quad-split {
display : flex;
flex-direction : row;
justify-content: space-between;
align-items : flex-start;
.left-side, .right-side {
width : 50%;
display : flex;
flex-direction : row;
justify-content: space-between;
align-items : flex-start;
.column-a, .column-b, .column-c, .column-d {
width: 50%;
};
.column-a, .column-b, .column-c {
padding-right: $secondary-padding;
};
};
};
@media (max-width: $break-point-large ) {
.horizontal-quad-split {
flex-direction : column;
.left-side, .right-side {
width : 100%;
.column-a, .column-b, .column-c, .column-d {
width: 50%;
};
.column-b {
padding-right: 0;
}
}
};
}
@media (max-width: $break-point-medium ) {
.horizontal-quad-split {
flex-direction : column;
.left-side, .right-side {
flex-direction : column;
.column-a, .column-b, .column-c, .column-d {
width: 100%;
padding: 0;
};
}
};
}

View file

@ -1,28 +0,0 @@
.horizontal-split {
display : flex;
flex-direction : row;
justify-content: space-between;
align-items : flex-start;
.column {
width: 50%;
}
};
@media (max-width: $break-point-large ) {
.horizontal-split {
display : flex;
flex-direction : column;
justify-content: space-between;
align-items : flex-start;
.column {
width: 100%;
padding-left: 0;
padding-right: 0;
padding-bottom: $secondary-padding;
}
};
}

View file

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="14px" height="8px" viewBox="0 0 14 8" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 52.2 (67145) - http://www.bohemiancoding.com/sketch -->
<title>chevron-down</title>
<desc>Created with Sketch.</desc>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" stroke-linecap="round">
<polyline id="chevron-down" stroke="#000000" stroke-width="1.2" fill-rule="nonzero" points="13 1 7 7 1 1"></polyline>
</g>
</svg>

After

Width:  |  Height:  |  Size: 582 B

View file

@ -1,27 +0,0 @@
a, a:visited {
text-decoration: none;
}
.link--primary, .link--primary:visited {
color: $interactive-color;
}
.link--secondary, .link--secondary:visited {
margin: 0px;
padding: 0.3em;
color: $secondary-color;
}
.link--nav {
color: $primary-color;
border-bottom: 2px solid white;
}
.link--nav:hover {
color: $interactive-color;
}
.link--nav-active {
color: $interactive-color;
border-bottom: 2px solid $interactive-color;
}

View file

@ -1,24 +0,0 @@
@media (max-width: $break-point-x-large) {
// hide site description in nav bar
.site-description {
display: none;
}
}
@media (max-width: $break-point-large ) {
}
@media (max-width: $break-point-medium) {
}
@media (max-width: $break-point-small) {
}
@media (max-width: $break-point-x-small ) {
}

View file

@ -1,12 +0,0 @@
.page-layout {
flex: 1 0 auto;
display: flex;
flex-direction: column;
.content {
flex: 1 0 auto;
display: flex;
-webkit-flex-direction: column;
flex-direction: column;
margin: $primary-padding;
}
}

View file

@ -1,7 +0,0 @@
.progress-bar--inactive {
color: $secondary-color;
}
.progress-bar--active {
color: $primary-color;
}

View file

@ -1,3 +0,0 @@
.publish-preview-dim {
opacity: 0.2;
}

View file

@ -1,17 +0,0 @@
select {
margin: 0;
outline: none;
padding: $input-padding;
border: 0;
background-color: $background-color;
display: inline-block;
}
.select--arrow {
-moz-appearance:none;
-webkit-appearance: none;
background: url('./icon/downArrow.svg') no-repeat right;
cursor: pointer;
padding-right: 1.5em;
padding-left: $input-padding
}

View file

@ -1,165 +0,0 @@
// set defaults
h1, h2, h3, h4, p {
margin: 0;
}
h1 {
font-size: $text-xx-large;
}
h2 {
font-size: $text-x-large;
}
h3 {
font-size: $text-large;
font-weight: bold;
}
p, body, button, input, textarea, label, select, option {
font-family: 'Lekton', monospace;
font-size: $text-large;
}
.text--extra-large {
font-size: $text-xx-large;
}
.text--large {
font-size: $text-large;
}
.text--medium {
font-size: $text-medium;
}
.text--small {
font-size: $text-small;
}
.text--extra-small {
font-size: $text-x-small;
}
.text--underline {
text-decoration: underline;
}
.text--primary {
color: $primary-color;
}
.text--secondary {
color: $secondary-color;
}
.text--tertiary {
color: $tertiary-color;
}
.text--interactive {
color: $interactive-color;
}
.text--failure {
color: $failure-color;
}
.text--success {
color: $success-color;
}
@media (max-width: $break-point-x-large ) {
h1 {
font-size: $text-x-large;
}
h2 {
font-size: $text-large;
}
h3 {
font-size: $text-medium;
}
p, body, button, input, textarea, label, select, option {
font-size: $text-medium;
}
.text--extra-large {
font-size: $text-x-large;
}
.text--large {
font-size: $text-medium;
}
.text--medium {
font-size: $text-small;
}
}
@media (max-width: $break-point-medium) {
h1 {
font-size: $text-large;
}
h2 {
font-size: $text-medium;
}
h3 {
font-size: $text-small;
}
p, body, button, input, textarea, label, select, option {
font-size: $text-small;
}
.text--extra-large {
font-size: $text-large;
}
.text--large {
font-size: $text-medium;
}
.text--small {
font-size: $text-x-small;
}
}
@media (max-width: $break-point-x-small) {
h1 {
font-size: $text-medium;
font-weight: bold;
}
h2 {
font-size: $text-small;
}
p, body, button, input, textarea, label, select, option {
font-size: $text-x-small;
}
.text--extra-large {
font-size: $text-x-small;
font-weight: bold;
}
.text--large {
font-size: $text-x-small;
}
.text--medium {
font-size: $text-x-small;
}
}

View file

@ -1,10 +0,0 @@
textarea {
margin: 0;
outline: none;
padding: $input-padding;
border: 0;
border-bottom: 1px solid $secondary-color;
background-color: $background-color;
display: inline-block;
width: $input-full-width;
}

View file

@ -1,7 +0,0 @@
.vertical-split {
flex : 1 0 auto;
display : flex;
flex-direction : column;
justify-content: space-between;
align-items : center;
};

View file

@ -7,9 +7,9 @@ const AboutSpeechDetails = () => {
<div>
<Row>
<p className={'text--large'}>
<Link to='/tos'>Terms of Service</Link>
<Link className={'link--primary'} to='/tos'>Terms of Service</Link>
<br />
<Link to='/faq'>Frequently Asked Questions</Link>
<Link className={'link--primary'} to='/faq'>Frequently Asked Questions</Link>
</p>
</Row>
<Row>

View file

@ -8,18 +8,12 @@ const AboutSpeechOverview = () => {
<p className={'text--extra-large'}>Spee.ch is an open-source project. Please contribute to the existing site, or fork it and make your own.</p>
</Row>
<Row>
<p className={'text--large'}>
<a className='link--primary' target='_blank' href='https://twitter.com/spee_ch'>TWITTER</a>
</p>
<p className={'text--large'}>
<a className='link--primary' target='_blank' href='https://github.com/lbryio/spee.ch'>GITHUB</a>
</p>
<p className={'text--large'}>
<a className='link--primary' target='_blank' href='https://discord.gg/YjYbwhS'>DISCORD CHANNEL</a>
</p>
<p className={'text--large'}>
<a className='link--primary' target='_blank' href='https://github.com/lbryio/spee.ch/blob/master/README.md'>DOCUMENTATION</a>
</p>
<div className={'text--large'}>
<a className='link--primary' target='_blank' href='https://twitter.com/spee_ch'>TWITTER</a><br/>
<a className='link--primary' target='_blank' href='https://github.com/lbryio/spee.ch'>GITHUB</a><br/>
<a className='link--primary' target='_blank' href='https://discord.gg/YjYbwhS'>DISCORD CHANNEL</a><br/>
<a className='link--primary' target='_blank' href='https://github.com/lbryio/spee.ch/blob/master/README.md'>DOCUMENTATION</a><br/>
</div>
</Row>
</div>
);

View file

@ -0,0 +1,14 @@
import React from 'react';
import Row from '@components/Row';
const AssetInfoFooter = ({ assetUrl, name }) => {
return (
<div className='asset-footer'>
<p>
Hosted via the <a className={'link--primary'} href={'https://lbry.io/get'} target={'_blank'}>LBRY</a> blockchain
</p>
</div>
);
};
export default AssetInfoFooter;

View file

@ -5,49 +5,53 @@ const AssetShareButtons = ({ assetUrl, name }) => {
return (
<SocialShareLink >
<a
className='link--primary'
className='link--primary twitter'
target='_blank'
href={`https://twitter.com/intent/tweet?text=${assetUrl}`}
>
twitter
<img src='/assets/img/icn_twitter.svg' />
</a>
<a
className='link--primary'
className='link--primary facebook'
target='_blank'
href={`https://www.facebook.com/sharer/sharer.php?u=${assetUrl}`}
>
facebook
<img src='/assets/img/icn_facebook.svg' />
</a>
<a
className='link--primary'
className='link--primary tumblr'
target='_blank'
href={`https://tumblr.com/widgets/share/tool?canonicalUrl=${assetUrl}`}
>
tumblr
<img src='/assets/img/icn_tumblr.svg' />
</a>
<a
className='link--primary'
className='link--primary reddit'
target='_blank'
href={`https://www.reddit.com/submit?url=${assetUrl}&title=${name}`}
>
reddit
</a>
<a
className='link--primary'
target='_blank'
href={`https://sharetomastodon.github.io/?title=${name}&url=${assetUrl}`}
>
mastodon
</a>
<a
className='link--primary'
target='_blank'
href={`https://share.diasporafoundation.org/?title=${name}&url=${assetUrl}`}
>
diaspora
<img src='/assets/img/icn_reddit.svg' />
</a>
</SocialShareLink>
);
};
//
// Additional icons disabled. If you want to add additional icons, you have to solve
// https://github.com/lbryio/spee.ch/issues/687
//
// <a
// className='link--primary'
// target='_blank'
// href={`https://sharetomastodon.github.io/?title=${name}&url=${assetUrl}`}
// >
// mastodon
// </a>
// <a
// className='link--primary'
// target='_blank'
// href={`https://share.diasporafoundation.org/?title=${name}&url=${assetUrl}`}
// >
// diaspora
// </a>
export default AssetShareButtons;

View file

@ -4,7 +4,7 @@ const ButtonPrimary = ({ value, onClickHandler, type = 'button' }) => {
return (
<button
type={type}
className={'button button-primary'}
className={'button button--primary'}
onClick={onClickHandler}
>
{value}

View file

@ -3,7 +3,7 @@ import React from 'react';
const ButtonPrimaryJumbo = ({ value, onClickHandler }) => {
return (
<button
className={'button button-primary button-primary--jumbo'}
className={'button button--primary button--jumbo'}
onClick={onClickHandler}
>
{value}

View file

@ -1,14 +0,0 @@
import React from 'react';
const ButtonTertiary = ({ value, onClickHandler }) => {
return (
<button
className={'button button--tertiary'}
onClick={onClickHandler}
>
{value}
</button>
);
};
export default ButtonTertiary;

View file

@ -2,8 +2,9 @@ import React from 'react';
const ChannelAbout = () => {
return (
<div>
<p className={'text--large'}>Channels allow you to publish and group content under an identity. You can create a channel for yourself, or share one with like-minded friends. You can create 1 channel, or 100, so whether you're <a className='link--primary' target='_blank' href='/@catalonia2017:43dcf47163caa21d8404d9fe9b30f78ef3e146a8'>documenting important events</a>, or making a public repository for <a className='link--primary' target='_blank' href='/@catGifs'>cat gifs</a> (password: '1234'), try creating a channel for it!</p>
<div className={'text--large'}>
<p>Channels allow you to publish and group content under an identity. You can create a channel for yourself, or share one with like-minded friends.</p>
<p>You can create 1 channel, or 100, so whether you're <a className='link--primary' target='_blank' href='/@catalonia2017:43dcf47163caa21d8404d9fe9b30f78ef3e146a8'>documenting important events</a>, or making a public repository for <a className='link--primary' target='_blank' href='/@catGifs'>cat gifs</a> (password: '1234'), try creating a channel for it!</p>
</div>
);
};

View file

@ -5,7 +5,6 @@ const ChannelSelectDropdown = ({ selectedChannel, handleSelection, loggedInChann
return (
<select
id='channel-name-select'
className='select select--arrow'
value={selectedChannel}
onChange={handleSelection}>
{ loggedInChannelName && (

View file

@ -1,13 +1,15 @@
import React from 'react';
import * as Icon from 'react-feather';
class ClickToCopy extends React.Component {
constructor (props) {
super(props);
this.copyToClipboard = this.copyToClipboard.bind(this);
}
copyToClipboard (event) {
const elementToCopy = event.target.id;
copyToClipboard () {
const elementToCopy = this.props.id;
const element = document.getElementById(elementToCopy);
console.log(elementToCopy);
element.select();
try {
document.execCommand('copy');
@ -18,15 +20,22 @@ class ClickToCopy extends React.Component {
render () {
const {id, value} = this.props;
return (
<input
id={id}
value={value}
<div
className='click-to-copy-wrap'
onClick={this.copyToClipboard}
type='text'
className='click-to-copy'
readOnly
spellCheck='false'
/>
>
<input
id={id}
value={value}
type='text'
className='click-to-copy'
readOnly
spellCheck='false'
/>
<div className='icon-wrap'>
<Icon.Copy />
</div>
</div>
);
}
}

View file

@ -1,13 +0,0 @@
import React from 'react';
class Column extends React.Component {
render () {
return (
<div className={'column'}>
{this.props.children}
</div>
);
}
}
export default Column;

View file

@ -3,7 +3,7 @@ import React from 'react';
const DropzoneDropItDisplay = () => {
return (
<div className={'dropzone-dropit-display'}>
<p className={'text--interactive'}>Drop it.</p>
Drop it.
</div>
);
}

View file

@ -9,15 +9,15 @@ const DropzoneInstructionsDisplay = ({fileError, message}) => {
return (
<div className={'dropzone-instructions-display'}>
<Row>
<p className={'text--large'}>{message}</p>
<span className={'text--large'}>{message}</span>
</Row>
<Row>
<p className={'text--small'}>OR</p>
<span className={'text--small text--secondary'}>OR</span>
</Row>
{ fileError ? (
<div>
<Row>
<p className={'text--large text--underline'}>CHOOSE FILE</p>
<span className={'text--large dropzone-instructions-display__chooser-label'}>CHOOSE FILE</span>
</Row>
<FormFeedbackDisplay
errorMessage={fileError}
@ -25,7 +25,7 @@ const DropzoneInstructionsDisplay = ({fileError, message}) => {
/>
</div>
) : (
<p className={'text--large text--underline'}>CHOOSE FILE</p>
<span className={'text--large dropzone-instructions-display__chooser-label'}>CHOOSE FILE</span>
)}
</div>
);

View file

@ -1,21 +1,21 @@
import React from 'react';
const FormFeedbackDisplay = ({ errorMessage, defaultMessage }) => {
return (
return (errorMessage || defaultMessage) ? (
<div className={'form-feedback'}>
{ errorMessage ? (
<p className={'text--small text--failure'}>{errorMessage}</p>
<span className={'text--small text--failure'}>{errorMessage}</span>
) : (
<div>
{ defaultMessage ? (
<p className={'text--small text--secondary'}>{defaultMessage}</p>
<span className={'text--small text--secondary'}>{defaultMessage}</span>
) : (
<p className={'text--small'}>&nbsp;</p>
<span className={'text--small'}>&nbsp;</span>
)}
</div>
)}
</div>
);
) : null;
};
export default FormFeedbackDisplay;

View file

@ -1,37 +0,0 @@
import React from 'react';
import Row from '@components/Row';
class HorizontalTriSplit extends React.Component {
render () {
return (
<div className={'horizontal-quad-split'}>
<div className={'left-side'}>
<div className={'column-a'}>
<Row>
{this.props.columnA}
</Row>
</div>
<div className={'column-b'}>
<Row>
{this.props.columnB}
</Row>
</div>
</div>
<div className={'right-side'}>
<div className={'column-c'}>
<Row>
{this.props.columnC}
</Row>
</div>
<div className={'column-d'}>
<Row>
{this.props.columnD}
</Row>
</div>
</div>
</div>
);
}
}
export default HorizontalTriSplit;

View file

@ -2,13 +2,26 @@ import React from 'react';
class HorizontalSplit extends React.Component {
render () {
const { leftSide, rightSide, collapseOnMobile } = this.props;
let className = 'horizontal-split';
if (collapseOnMobile) {
className += " horizontal-split--mobile-collapse";
}
// If there is no left side, move the right side to the left
// This is mostly for content with no description
// It doesn't need to be on the right side with nothing next to it.
const leftComponent = leftSide || rightSide;
const rightComponent = leftSide ? rightSide : null;
return (
<div className={'horizontal-split'}>
<div className={'column'}>
{this.props.leftSide}
<div className={className}>
<div className={'horizontal-split__column horizontal-split__column--left'}>
{leftComponent}
</div>
<div className={'column'}>
{this.props.rightSide}
<div className={'horizontal-split__column horizontal-split__column--right'}>
{rightComponent}
</div>
</div>
);

View file

@ -10,7 +10,6 @@ class NavBar extends React.Component {
<div className={'nav-bar'}>
<SpaceBetween >
<Logo />
<SiteDescription />
<NavigationLinks />
</SpaceBetween>
</div>

View file

@ -6,7 +6,6 @@ function NavBarChannelDropdown ({ channelName, handleSelection, defaultSelection
<select
type='text'
id='nav-bar-channel-select'
className='select select--arrow'
onChange={handleSelection}
value={defaultSelection}
>

View file

@ -62,7 +62,7 @@ class ProgressBar extends React.Component {
};
render () {
return (
<div>
<div className="progress-bar__wrapper">
{this.state.bars.map((bar, index) => bar.isActive ? <ActiveStatusBar key={index} /> : <InactiveStatusBar key={index}/>)}
</div>
);

View file

@ -13,7 +13,6 @@ const PublishLicenseInput = ({ handleSelect }) => {
type='text'
name='license'
id='publish-license'
className='select select--primary'
onChange={handleSelect}
>
<option value=''>Unspecified</option>

View file

@ -5,16 +5,21 @@ import PublishDetails from '@containers/PublishDetails';
import PublishTitleInput from '@containers/PublishTitleInput';
import Row from '@components/Row';
// this class seems more like PublishForm and should probably be renamed
class PublishPreview extends React.Component {
render () {
const { isUpdate, uri } = this.props;
return (
<div>
<Row>
{isUpdate && uri && (<p className='text--extra-small'>{`Editing ${uri}`}</p>)}
<PublishTitleInput />
</Row>
<div className={'publish-form'}>
<div className={'publish-form__title'}>
<Row>
{isUpdate && uri && (<p className='text--secondary'>{`Editing ${uri}`}</p>)}
<PublishTitleInput />
</Row>
</div>
<HorizontalSplit
collapseOnMobile
leftSide={<Dropzone />}
rightSide={<PublishDetails />}
/>

View file

@ -79,12 +79,12 @@ class AssetDisplay extends React.Component {
</div>
}
{(status === AVAILABLE) &&
<AvailableContent
contentType={contentType}
sourceUrl={sourceUrl}
name={name}
thumbnail={thumbnail}
/>
<AvailableContent
contentType={contentType}
sourceUrl={sourceUrl}
name={name}
thumbnail={thumbnail}
/>
}
</div>
);

View file

@ -6,10 +6,12 @@ import Row from '@components/Row';
import SpaceBetween from '@components/SpaceBetween';
import AssetShareButtons from '@components/AssetShareButtons';
import ClickToCopy from '@components/ClickToCopy';
import HorizontalSplit from '@components/HorizontalSplit';
import siteConfig from '@config/siteConfig.json';
const { details: { host } } = siteConfig;
import createCanonicalLink from '../../../../utils/createCanonicalLink';
import AssetInfoFooter from '../../components/AssetInfoFooter/index';
class AssetInfo extends React.Component {
render () {
@ -29,137 +31,119 @@ class AssetInfo extends React.Component {
channelCanonicalUrl = `${createCanonicalLink({channel})}`;
}
return (
<div>
{editable && (
<Row>
<RowLabeled
label={<Label value={'Edit:'} />}
content={<Link to={`/edit${canonicalUrl}`}>{name}</Link>}
/>
</Row>
)}
<div className='asset-info'>
<HorizontalSplit
leftSide={
description && (
<p className='asset-info__description'>{description}</p>
)
}
rightSide={
<div>
{editable && (
<RowLabeled
label={<Label value={'Edit:'} />}
content={<Link to={`/edit${canonicalUrl}`}>{name}</Link>}
/>
)}
{channelName && (
<RowLabeled
label={
<Label value={'Channel'} />
}
content={
<span className='text'>
<Link className='link--primary' to={channelCanonicalUrl}>{channelName}</Link>
</span>
}
/>
)}
{claimViews ? (
<RowLabeled
label={
<Label value={'Views'} />
}
content={
<span className='text'>
{claimViews}
</span>
}
/>
) : null}
{channelName && (
<Row>
<RowLabeled
label={
<Label value={'Channel:'} />
}
content={
<span className='text'>
<Link to={channelCanonicalUrl}>{channelName}</Link>
</span>
}
/>
</Row>
)}
{claimViews ? (
<Row>
<RowLabeled
label={
<Label value={'Views:'} />
}
content={
<span className='text'>
{claimViews}
</span>
}
/>
</Row>
) : null}
<Row>
<RowLabeled
label={
<Label value={'Share:'} />
}
content={
<AssetShareButtons
name={name}
assetUrl={assetCanonicalUrl}
/>
}
/>
</Row>
<Row>
<RowLabeled
label={
<Label value={'Link:'} />
}
content={
<ClickToCopy
id={'short-link'}
value={assetCanonicalUrl}
/>
}
/>
</Row>
<Row>
<RowLabeled
label={
<Label value={'Embed:'} />
}
content={
<div>
{(contentType === 'video/mp4') ? (
<ClickToCopy
id={'embed-text-video'}
value={`<iframe src="${host}/video-embed${canonicalUrl}" allowfullscreen="true" style="border:0" /></iframe>`}
<RowLabeled
label={
<Label value={'Share'} />
}
content={
<AssetShareButtons
name={name}
assetUrl={assetCanonicalUrl}
/>
) : (
}
/>
<RowLabeled
label={
<Label value={'Link'} />
}
content={
<ClickToCopy
id={'embed-text-image'}
value={`<img src="${assetCanonicalUrl}.${fileExt}"/>`}
id={'short-link'}
value={assetCanonicalUrl}
/>
)}
</div>
}
/>
</Row>
}
/>
<Row>
<SpaceBetween>
<a
className='link--primary'
href={`${assetCanonicalUrl}.${fileExt}`}
>
Direct Link
</a>
<a
className={'link--primary'}
href={`${assetCanonicalUrl}.${fileExt}`}
download={name}
>
Download
</a>
<a
className={'link--primary'}
target='_blank'
href='https://lbry.io/dmca'
>
Report
</a>
</SpaceBetween>
</Row>
{description && (
<Row>
<p>{description}</p>
</Row>
)}
<Row>
<p>
Hosted via the <a className={'link--primary'} href={'https://lbry.io/get'} target={'_blank'}>LBRY</a> blockchain
</p>
</Row>
<RowLabeled
label={
<Label value={'Embed'} />
}
content={
<div>
{(contentType === 'video/mp4') ? (
<ClickToCopy
id={'embed-text-video'}
value={`<iframe src="${host}/video-embed${canonicalUrl}" allowfullscreen="true" style="border:0" /></iframe>`}
/>
) : (
<ClickToCopy
id={'embed-text-image'}
value={`<img src="${assetCanonicalUrl}.${fileExt}"/>`}
/>
)}
</div>
}
/>
<SpaceBetween>
<a
className='link--primary'
href={`${assetCanonicalUrl}.${fileExt}`}
>
Direct Link
</a>
<a
className={'link--primary'}
href={`${assetCanonicalUrl}.${fileExt}`}
download={name}
>
Download
</a>
<a
className={'link--primary'}
target='_blank'
href='https://lbry.io/dmca'
>
Report
</a>
</SpaceBetween>
</div>
} />
<AssetInfoFooter/>
</div>
);
}
};
export default AssetInfo;
export default AssetInfo;

View file

@ -1,12 +1,8 @@
import React from 'react';
import { Link } from 'react-router-dom';
import Row from '@components/Row';
const AssetTitle = ({ title }) => {
return (
<Row>
<h3>{title}</h3>
</Row>
<h1 className='asset-title'>{title}</h1>
);
};

View file

@ -59,7 +59,7 @@ class ChannelCreateForm extends React.Component {
return (
<div>
{ !status ? (
<form onSubmit={this.handleSubmit}>
<form className="form-group" onSubmit={this.handleSubmit}>
<ChannelCreateNameInput
value={name.value}
error={name.error}
@ -69,10 +69,7 @@ class ChannelCreateForm extends React.Component {
value={password.value}
handlePasswordInput={this.handlePasswordInput}
/>
<FormFeedbackDisplay
errorMessage={formError}
defaultMessage={'Choose a name and password for your channel'}
/>
<FormFeedbackDisplay errorMessage={formError} />
<ButtonPrimary
type={'submit'}
value={'Create Channel'}
@ -81,7 +78,7 @@ class ChannelCreateForm extends React.Component {
</form>
) : (
<div>
<p className={'text--small text--secondary'}>{status}</p>
<span className={'text--small text--secondary'}>{status}</span>
<ProgressBar size={12} />
</div>
)}

View file

@ -49,7 +49,7 @@ class ChannelLoginForm extends React.Component {
}
render () {
return (
<form onSubmit={this.loginToChannel}>
<form className="form-group" onSubmit={this.loginToChannel}>
<ChannelLoginNameInput
channelName={this.state.channelName}
handleInput={this.handleInput}
@ -58,10 +58,7 @@ class ChannelLoginForm extends React.Component {
channelPassword={this.state.channelPassword}
handleInput={this.handleInput}
/>
<FormFeedbackDisplay
errorMessage={this.state.error}
defaultMessage={'Enter the name and password for your channel'}
/>
<FormFeedbackDisplay errorMessage={this.state.error} />
<ButtonPrimary
type={'submit'}
value={'Authenticate'}

View file

@ -40,16 +40,16 @@ class ChannelSelect extends React.Component {
const { publishInChannel, channelError, selectedChannel, loggedInChannelName, publishOnlyApproved } = this.props;
if (publishOnlyApproved) {
return (
<div>
<React.Fragment>
<RowLabeled
label={<Label value={'Channel:'} />}
content={<span>{loggedInChannelName}</span>}
/>
</div>
</React.Fragment>
);
}
return (
<div>
<React.Fragment>
<RowLabeled
label={
<ChooseAnonymousPublishRadio
@ -87,7 +87,7 @@ class ChannelSelect extends React.Component {
{ (selectedChannel === CREATE) && <ChannelCreateForm /> }
</div>
)}
</div>
</React.Fragment>
);
}
}

View file

@ -7,14 +7,14 @@ class ChannelTools extends React.Component {
render () {
return (
<div>
<Row>
<h3>Log in to an existing channel:</h3>
<ChannelLoginForm />
</Row>
{!this.props.closedRegistration && (<Row>
<h3>Create a brand new channel:</h3>
<ChannelCreateForm />
</Row>)}
<h3 className="form-title">Log in to existing channel</h3>
<ChannelLoginForm />
{!this.props.closedRegistration && (
<React.Fragment>
<h3 className="form-title">Create new channel</h3>
<ChannelCreateForm />
</React.Fragment>
)}
</div>
);
}

View file

@ -84,7 +84,7 @@ class Dropzone extends React.Component {
const { dragOver, mouseOver, dimPreview } = this.state;
const { file, thumbnail, fileError, isUpdate, sourceUrl, fileExt } = this.props;
return (
<div className="dropzone-wrapper">
<React.Fragment>
{isUpdate && fileExt === 'mp4' ? (
<p>Video updates are currently disabled. This feature will be available soon. You can edit metadata.</p>
) : (
@ -145,7 +145,7 @@ class Dropzone extends React.Component {
</div>
</div>
)}
</div>
</React.Fragment>
);
}
};

View file

@ -8,7 +8,6 @@ import Row from '@components/Row';
import Label from '@components/Label';
import RowLabeled from '@components/RowLabeled';
import ButtonPrimaryJumbo from '@components/ButtonPrimaryJumbo';
import ButtonTertiary from '@components/ButtonTertiary';
import ButtonSecondary from '@components/ButtonSecondary';
import SpaceAround from '@components/SpaceAround';
import PublishFinePrint from '@components/PublishFinePrint';
@ -46,7 +45,7 @@ class PublishDetails extends React.Component {
return (
<div>
{isUpdate ? (asset && (
<Row>
<React.Fragment>
<RowLabeled
label={
<Label value={'Channel:'} />
@ -57,16 +56,14 @@ class PublishDetails extends React.Component {
</span>
}
/>
</Row>
</React.Fragment>
)) : (
<React.Fragment>
<Row>
<PublishUrlInput />
</Row>
<Row>
<ChannelSelect />
</Row>
<ChannelSelect />
</React.Fragment>
)}
@ -100,7 +97,7 @@ class PublishDetails extends React.Component {
<Row>
<SpaceAround>
<ButtonTertiary
<ButtonSecondary
value={'Cancel'}
onClickHandler={this.onCancel}
/>

View file

@ -3,6 +3,7 @@ import PublishDescriptionInput from '@components/PublishDescriptionInput';
import PublishLicenseInput from '@components/PublishLicenseInput';
import PublishNsfwInput from '@components/PublishNsfwInput';
import ButtonSecondary from '@components/ButtonSecondary';
import Row from '@components/Row';
class PublishMetadataInputs extends React.Component {
constructor (props) {
@ -29,20 +30,20 @@ class PublishMetadataInputs extends React.Component {
const { showMetadataInputs, description, isUpdate, nsfw } = this.props;
return (
<div>
{(showMetadataInputs || isUpdate) && (
<div>
{(showMetadataInputs || isUpdate) && (
<React.Fragment>
<PublishDescriptionInput
description={description}
description={this.props.description}
handleInput={this.handleInput}
/>
<PublishLicenseInput
handleSelect={this.handleSelect}
/>
<PublishNsfwInput
nsfw={nsfw}
nsfw={this.props.nsfw}
handleInput={this.handleInput}
/>
</div>
</React.Fragment>
)}
{!isUpdate && (
<ButtonSecondary

View file

@ -126,7 +126,7 @@ class PublishThumbnailInput extends React.Component {
</div>
</div>
) : (
<p className={'text--small text--secondary'}>loading... </p>
<span className={'text--small text--secondary'}>loading... </span>
)
}
<FormFeedbackDisplay

View file

@ -13,6 +13,7 @@ class AboutPage extends React.Component {
pageUri={'about'}
>
<HorizontalSplit
collapseOnMobile
leftSide={<AboutSpeechOverview />}
rightSide={<AboutSpeechDetails />}
/>

Some files were not shown because too many files have changed in this diff Show more