Skip to content
This repository has been archived by the owner on Apr 5, 2024. It is now read-only.

Upgrade to Create React App 2.0 #72

Merged
merged 18 commits into from
Dec 19, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions .babelrc

This file was deleted.

35 changes: 2 additions & 33 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ version: 2
jobs:
test:
docker:
- image: node:9.3.0
- image: node:11

steps:
- checkout
Expand Down Expand Up @@ -36,7 +36,7 @@ jobs:

- run:
name: Code Style Lint
command: yarn check-style
command: yarn check-fmt

- run:
name: Run Tests
Expand Down Expand Up @@ -69,37 +69,6 @@ jobs:
FOLDER_NAME=$([ -z "$CIRCLE_TAG" ] && echo "$CIRCLE_BRANCH" || echo "$CIRCLE_TAG")
aws s3 cp ./forte-web.tar.gz "s3://forte-web-artifacts/${FOLDER_NAME}/forte-web.tar.gz"

deploy_surge:
docker:
- image: node:9.3.0

steps:
- checkout

- restore_cache:
keys:
- dependencies-{{ checksum "package.json" }}
# fallback to using the latest cache if no exact match is found
- dependencies-

- run:
name: Install Deps
command: yarn install

- run:
name: Build
environment:
REACT_APP_MOCK_RESOLVER: true
command: yarn build

- run:
name: Copy Index File
command: cp build/index.html build/200.html

- run:
name: Deploy to Surge
command: yarn surge --project ./build --domain forte.surge.sh

workflows:
version: 2
test:
Expand Down
File renamed without changes.
56 changes: 56 additions & 0 deletions .storybook/config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import React from 'react';
import { configure, addDecorator } from '@storybook/react';
import { RootThemeProvider } from '../src/components/App/RootThemeProvider';
import './styles.css';

const themeDecorator = story => (
<RootThemeProvider>{story()}</RootThemeProvider>
);
addDecorator(themeDecorator);

// This condition actually should detect if it's an Node environment
// https://stackoverflow.com/questions/38332094/how-can-i-mock-webpacks-require-context-in-jest/42191018#42191018
if (typeof require.context === 'undefined') {
const fs = require('fs');
const path = require('path');

require.context = (
base = '.',
scanSubDirectories = false,
regularExpression = /\.js$/
) => {
const files = {};

function readDirectory(directory) {
fs.readdirSync(directory).forEach(file => {
const fullPath = path.resolve(directory, file);

if (fs.statSync(fullPath).isDirectory()) {
if (scanSubDirectories) readDirectory(fullPath);

return;
}

if (!regularExpression.test(fullPath)) return;

files[fullPath] = true;
});
}

readDirectory(path.resolve(__dirname, base));

function Module(file) {
return require(file);
}

Module.keys = () => Object.keys(files);

return Module;
};
}

const req = require.context('../src', true, /\.stories\.tsx$/);

configure(() => {
req.keys().forEach(filename => req(filename));
}, module);
File renamed without changes.
61 changes: 47 additions & 14 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -1,58 +1,91 @@
# Contributing to forte-music/web

Thanks for taking the time to contribute to forte. Here are some guidelines to follow when contributing.
Thanks for taking the time to contribute to forte. Here are some guidelines
to follow when contributing.

Some of the code in this project hasn't been refactored to follow these guidelines yet.
Some of the code in this project hasn't been refactored to follow these
guidelines yet.

## CSS

For the most part, CSS is written using [styled-components]. Currently, they are scattered near the presentational components they are used in, in `src/components/styled` and in `src/components`. Going forward, mixins should be placed in `src/styled-mixins`, shared styled components in `src/components/styled`, and unshared styled components, near where they are used.
For the most part, CSS is written using [styled-components]. Currently, they
are scattered near the presentational components they are used in, in
`src/components/styled` and in `src/components`. Going forward, mixins should
be placed in `src/styled-mixins`, shared styled components in
`src/components/styled`, and unshared styled components, near where they are
used.

Avoid using theming unless needed. It adds un-needed complexity for most use cases. If you are using the same component with slightly different styles in two different places, then use themeing.
Avoid using theming unless needed. It adds un-needed complexity for most use
cases. If you are using the same component with slightly different styles in
two different places, then use themeing.

## Redux
The [render-props] pattern is used to decouple data providing components with components consuming data. We use a wrapper around `connect` (a Higher Order Component from `react-redux`) to use the render props pattern with redux. This wrapper is called `createReduxComponent` and can be found in `src/redux/render.tsx`.

The [render-props] pattern is used to decouple data providing components with
components consuming data. We use a wrapper around `connect` (a Higher Order
Component from `react-redux`) to use the render props pattern with redux.
This wrapper is called `createReduxComponent` and can be found in
`src/redux/render.tsx`.

## Component Folder Structure

There are a few different types of components.

* Presentational Components

Stateless components which are primarily concerned with how things look. State and actions are passed as props and prop callbacks respectively. These are usually functional components. Usually placed in `src/components/`.
Stateless components which are primarily concerned with how things look.
State and actions are passed as props and prop callbacks respectively. These
are usually functional components. Usually placed in `src/components/`.

* Enhancer Components

Often handle data fetching and state storage concerns. Usually stored next to the container component they are used in (for example `src/components/AlbumsContainer/enhancers/redux.ts`).
Often handle data fetching and state storage concerns. Usually stored next to the container
component they are used in (for example
`src/components/AlbumsContainer/enhancers/redux.ts`).

* Container Components

Made up by composing many enhancers and on or more presentational components. Found in folders ending with `Container` (for example `src/components/AlbumsContainer/index.tsx`).
Made up by composing many enhancers and on or more presentational
components. Found in folders ending with `Container` (for example
`src/components/AlbumsContainer/index.tsx`).

[Here is some more information about the presentational and container component pattern.][container-component]

## Code Style

[Prettier] is used to keep our code formatted consistently. Run `yarn fix-style` to reformat code to follow adhere to Prettier's style. Run `yarn check-style` to see which files don't adhere to Prettier's style.
[Prettier] is used to keep our code formatted consistently. Code is formatted
in a precommit hook. Run `yarn fmt` to reformat code manually.

## Storybook

[Storybook] is used for testing react components outside of the complete application. Run `yarn storybook` to start it with mock data. Files ending with `.stories.tsx` are picked up storybook. A test ensures that all stories render without crashing.
[Storybook] is used for testing react components outside of the complete
application. Run `yarn storybook` to start it with mock data. Files ending
with `.stories.tsx` are picked up storybook. A test ensures that all stories
render without crashing.

## Tests

Tests are run using [Jest]. Run `yarn test` to start jest. Tests should placed in files ending with `.test.ts` or `.test.tsx`.
Tests are run using [Jest]. Run `yarn test` to start jest. Tests should
placed in files ending with `.test.ts` or `.test.tsx`.

## Lints

[TSLint] is used for linting code. Run `yarn tslint` to run tslint on this project.
[TSLint] is used for linting code. Run `yarn tslint` to run tslint on this
project.

## CircleCI Build

CircleCI does a number of [tasks] after your code is pushed. Make sure your code passes before submitting a PR. Many of the same tests run in CircleCI can be run with `yarn check-all`.
CircleCI does a number of [tasks] after your code is pushed. Make sure your
code passes before submitting a PR. Many of the same tests run in CircleCI
can be run with `yarn check-all`.

## Contributor Agreement

By contributing code to our project in any form, including sending a pull request via Github, a code fragment or patch via private email or public discussion groups, you agree to release your code under the terms of the license that you can find in the LICENSE.md file included in the forte-music/web source distribution.
By contributing code to our project in any form, including sending a pull
request via Github, a code fragment or patch via private email or public
discussion groups, you agree to release your code under the terms of the
license that you can find in the LICENSE.md file included in the
forte-music/web source distribution.

[jest]: https://jestjs.io/
[prettier]: https://prettier.io/
Expand Down
49 changes: 21 additions & 28 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,47 +1,40 @@
# web

[![Build Status][build-status-image]][build-status]
A web interface for streaming music from forte.

[Check out the demo site!][demo-site]
[![Build Status][build-status-image]][build-status]

## Quickstart

yarn query-codegen && yarn start-mock

## Build Configuration

This project was bootstrapped with [create-react-app]. We've since ejected, but still use many of its features.

## Generated Files

[GraphQL] is used to talk to the backend. Given a schema and a graphql request string, we can compute the response type and provide it to typescript so typechecking code around API calls works.

To generate typing information for responses which typescript understands, use `yarn query-codegen`. Re-run this command every time a query or the schema changes and after pulling new versions from the remote. These files are stored in a sibling folder named `__generated__` to the file the query is defined in. The files in `__generated__` are ignored by git.

The `query-codegen` script is run before the `build` and `check-all` scripts.

## Mock Backend

A few things change when the application is run in an environment with the `REACT_APP_MOCK_RESOLVER` variable set to a truthy value.

First, a mock [GraphQL] resolver is used instead of a resolver which queries a remote endpoint. The graphql resolver is provided by the [`@forte-music/mock`][forte-music/mock] npm package with data from the [`@forte-music/schema`][forte-music/schema] npm package. [The mock data can be found in the toml files here.][mock]

Second, instead of fetching audio files from the remote server, a fixed set of audio files is used instead. Each song in the mock data maps to an audio file based on the identifier of the mock song's identifier. Multiple songs may share the same underlying audio file.
[GraphQL] is used to talk to the backend. Given a schema and a graphql
request string, we can compute the response type and provide it to typescript
so typechecking code around API calls works.

These features allow developing the frontend independently of the backend.
To generate typing information for responses which typescript understands,
use `yarn query-codegen`. Re-run this command every time a query or the
schema changes and after pulling new versions from the remote. Generated
files are stored in a sibling folder named `__generated__` to the file the
query is defined in. Files in `__generated__` are ignored by git.

The `start-mock` and `storybook` scripts enable mock behavior for their corresponding actions.
## Backend

## External Server
By default (`yarn start`) this application connects to a backend hosted at
`localhost:8080`. Configure this by changing the proxy key of `package.json`.
See the [create react app proxy guide][proxy-guide] for more.

To use an external graphql resolver, run `yarn start` instead of `yarn start-mock` and configure the [Create React App Proxy][proxy-guide] to proxy requests to your server.
There's a mock backend which can be enabled by using `yarn start-mock`. When
enabled, a mock graphql resolver will run inside the dev server. A playground
can be found at `localhost:3000/graphql`. The mock resolver is provided by
[`@forte-music/mock`][forte-music/mock]. The mock backend even configures the
app to use a set of royalty free tracks so features around playback can be
tested.

[graphql]: https://graphql.org/
[demo-site]: https://forte.surge.sh/
[proxy-guide]: https://github.com/facebook/create-react-app/blob/cb1608b3e02e0eef5fd350f6e4cf5ce32bdfc215/packages/react-scripts/template/README.md#proxying-api-requests-in-development
[proxy-guide]: https://facebook.github.io/create-react-app/docs/proxying-api-requests-in-development
[build-status-image]: https://img.shields.io/circleci/project/github/forte-music/web/master.svg
[build-status]: https://circleci.com/gh/forte-music/web
[forte-music/mock]: https://github.com/forte-music/schema/tree/master/packages/mock
[forte-music/schema]: https://github.com/forte-music/schema/tree/master/packages/schema
[mock]: https://github.com/forte-music/schema/tree/master/packages/schema/fixtures
[create-react-app]: https://github.com/facebook/create-react-app
5 changes: 0 additions & 5 deletions config/aliases.js

This file was deleted.

90 changes: 0 additions & 90 deletions config/env.js

This file was deleted.

Loading