Git Product home page Git Product logo

boxcar's People

Contributors

chrisgbaker avatar dependabot[bot] avatar dkniffin avatar ludwigmuench avatar

Stargazers

 avatar  avatar

Watchers

 avatar  avatar

Forkers

dkniffin

boxcar's Issues

Add logging solution for both front and back end

Motivation

I think this would be great for monitoring apps and finding / understanding bugs throughout the full stack on a live production server.

Requested Feature

It would be useful if we could log errors and other events from both the front and the back end.

Example (frontend):

    try {
      foo()
    } catch (e) {
      // handle error
      logger.log({
        error: e,
        description: 'something something failed when something',
        //...
       })
    }

The logger on the frontend would have to send logged events to the back end with http requests. On the back end all logged events would have to be persisted.

Now even though the error was handled, we could use the logging solution to show us all logged events (of both the front and back end) during a specified time frame and filter for certain keywords.

Monitoring Solutions

Solution Pros Cons
custom solution good labs project?
rails-client-logger ? not maintained
Elastic APM we've used it before can be a lot of work to set up ELK
Prometheus
Airbrake React Integration we've used it before (Rails only)

User model

We'll want to set this up in a way that doesn't tie the project to a certain authentication strategy.

Here's some of the strategies we might want to support

  • No authentication
  • Devise session auth?
  • devise_token_auth
  • JWT
  • Oauth
  • SAML

erb-lint

Right now, our erb code does not get linted at all, because rubocop does not handle that. We've tried the erb-lint gem and liked it, so we should pull it in here

Tweaks to monorepo setup

  • Update yarn build to something like cd frontend && npm run build && cd .. && rm -rf public && mkdir -p public && mv frontend/build/* public && mv public/index.html public/frontend.html
  • Add docs describing the monorepo setup
  • Add links to that doc from app/assets and app/javascript

SPIKE: Investigate formik for our form handling Logic

Some reference
https://redux.js.org/faq/organizing-state#should-i-put-form-state-or-other-ui-state-in-my-store
Basically, redux says you probably don't need your form state in redux. So, I agree ๐Ÿ˜„
Their first recommendation: just write it yourself
Their second recommendation: https://goshakkk.name/on-forms-react/
The third, and probably best (?) option, Formik https://github.com/jaredpalmer/formik

Whoever pulls this story should read the above articles, play around with at least the second and third options (we've all done the first in some capacity), and document what they found, and their recommendations moving forward. I can see this getting pulled into an Allhands potentially.

Authentication

We'll want to set this up in a way that doesn't tie the project to a certain authentication strategy.

Here's some of the strategies we might want to support

  • No authentication
  • Devise session auth?
  • devise_token_auth
  • JWT
  • Oauth
  • SAML

This will more than likely be worked in tandem with #45

TODOs

  • Set up auth on the backend, with a User model
  • Seed a user object
  • Connect frontend to backend auth, as an example of how to use redux and save tokens

Setup Husky/Prettier

Admittedly, I don't use prettier or husky, and the 15 minutes I spent to set them up didn't seem to work.

TODOS:

  • install husky and any needed dependencies
  • set up the rules we all agree upon to get husky doing the right things pre-commit.
  • update the Readme.md to explain what husky is and what we are using it for.

Add Redux/React-Redux to the app

Currently we are trying to define what it means to use redux in a standard manner for our apps going forward. However, as a first pass, I recommend we see the structure/patterns used in Koru, and follow those for now.

While they are not 100% ideal as far as the boilerplate created, I believe this approach makes it very clear what an action is doing, and leverages strongly typed actions as well.

TODOs:

  • Add in the following libraries: redux, react-redux, redux-thunk, redux-devtools-extension
  • Follow the patterns in the configureStore.ts file to connect all of the reducers.
  • Add in a blank reducer, auth, which just returns the initial state it was passed.
  • Add in a unit test around this reducer, and any actions included.

Rolify

This is blocked by #14 because we need a user model in order to add roles to it.

SPIKE: Typescript api generator?

I've used these in the past, basing the generation off of a swaggerdoc, but we have also been a discussion of moving to graphQL. This is more a braindump to see if anyone has any knowledge around this, and how to move forward if so. graphql-code-generator could be a helpful tool, but i don't know much about it.

Standard issue format

Much like our PR template, we should create a standard Issues template, so they all follow a similar format.

Documentation!

Pieces that have already been included in the first commit that have not been well-documented

  • find and replace any references to boxcar
  • what to replace in the /frontend/public folder when bootstrapping a new app
  • notes on how to run vscode debuggers
  • documenting what linting rules we change and why. Currently we don't change any.
  • If the app is react, delete react native and vice versa (note this will only be valid if we create a RN app inside boxcar as well)
  • how to use the bundle analyzer command
  • how to use react-intl

rswag

rswag is a gem for creating swagger docs from request specs. The specs have to be formatted in a certain way, but in my opinion, this can completely replace the way we currently do request specs.

Here's what a spec looks like:

require "swagger_helper"

describe "Gopher API", type: :request do
  path "/api/v1/orders/{id}/flag" do
    post "Creates a new flag" do
      tags "Orders"
      consumes "application/json"
      produces "application/json"
      security [access_token: [], token_type: [], client: [], expiry: [], uid: []]

      parameter name: :id, in: :path, type: :integer
      parameter name: :params, in: :body, schema: {
        type: :object,
        properties: {
          reason: { type: :string },
          description: { type: :string }
        }
      }

      let!(:order) { create(:order) }
      let(:reason) { Flag.reasons.keys.sample }
      let(:description) { Faker::Lorem.sentence }

      let(:id) { order.id }
      let(:params) { { reason: reason, description: description } }

      before { @flag_count_before = Flag.count }

      response "200", "Valid Credentials, Valid Params" do
        let(:current_user) { create(:user, :gopher) }
        include_context "when auth headers are included"

        schema type: :object,
               properties: {
                 id: { type: :integer },
                 reason: { type: :string },
                 description: { type: :string },
                 order_id: { type: :integer },
                 user_id: { type: :integer },
                 created_at: { type: :string, format: :date },
                 updated_at: { type: :string, format: :date }
               }

        run_test! do |response|
          json_response = JSON.parse(response.body)
          expect(Flag.count).to eq(@flag_count_before + 1)
          created_flag = Flag.find(json_response["id"])
          expect(created_flag.reason).to eq(reason)
          expect(created_flag.description).to eq(description)
        end
      end

      response "403", "Unauthorized" do
        let(:current_user) { create(:user, :requestor) }
        include_context "when auth headers are included"

        description "This probably means you're not signed in as a gopher"

        examples "application/json" => {
          "meta" => {
            "success" => false,
            "message" => "Unauthorized."
          },
          "errors" => [
            "Unauthorized."
          ]
        }

        run_test! do
          expect(Flag.count).to eq(@flag_count_before)
        end
      end
    end
  end
end

and here's what it looks like in swagger:
screencapture-localhost-5100-api-docs-index-html-2019-05-01-16_41_40

Decide on a network layer for the frontend

Native fetch?
Axois?

Whatever we implement, we need to standardize the way a base api/api controller is instantiated, and the way in which to send network requests, deal with failures, manipulate/handle headers, etc.

Add React-Router

Pretty Self Explanatory

TODOS:

  • Add react-router
  • Add in a dummy route that links to a new component, showing how we define routes at the root level
  • potentially tests around the new app, or updating a dummy component for testing that is wrapped in the appropriate provider
  • Update the Readme.md to reflect that we use this library, and links to any pertinent documentation
  • Add a generic 404 page. This is important because with the monorepo setup, all 404s will be sent to the frontend

Add in Redux-Persist

A standard library we can use to persist data to local storage.

TODOS:

  • add in redux-persist and follow the docs to get it wired up.
  • Add either a whitelist or a blacklist, so it is clear how those work
  • Update the Readme.md to reflect on how to use redux-persist, even if this is just a link out to official docs, and links in the repo to any relevant files.

Add a DEPLOYMENT.md file template

Ideally, each of our repos should have instructions for how to deploy, in some standard place. A DEPLOYMENT.md is one place we could put that.

Pundit

This should probably wait until after #14

Absolute imports

Since create-react-app v3 you can configure your app to use absolute imports (= relative to a top-level folder, e.g. src). I think this would make imports easier to write and more readable.

Example:

// tsconfig.json
{
  "compilerOptions": {
    "baseUrl": "src"
  },
  "include": ["src"]
}
โ€‹
// before
import Button from '../../Button/Button'
โ€‹
// after
import Button from 'components/Button/Button'

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.