├── log └── .keep ├── tmp └── .keep ├── vendor └── .keep ├── lib ├── assets │ └── .keep └── tasks │ └── .keep ├── public ├── favicon.ico ├── apple-touch-icon.png ├── apple-touch-icon-precomposed.png ├── robots.txt ├── 500.html ├── 422.html └── 404.html ├── test ├── helpers │ └── .keep ├── mailers │ └── .keep ├── models │ ├── .keep │ └── todo_test.rb ├── system │ ├── .keep │ └── todos_test.rb ├── controllers │ ├── .keep │ └── todos_controller_test.rb ├── fixtures │ ├── .keep │ ├── files │ │ └── .keep │ └── todos.yml ├── integration │ └── .keep ├── application_system_test_case.rb └── test_helper.rb ├── app ├── assets │ ├── images │ │ ├── .keep │ │ ├── square-o.svg │ │ ├── check-square-o.svg │ │ ├── rails.svg │ │ └── react.svg │ ├── packs │ │ ├── todos.ts │ │ └── app.ts │ ├── javascripts │ │ ├── todos │ │ │ ├── components │ │ │ │ ├── App │ │ │ │ │ ├── styles.module.scss │ │ │ │ │ ├── index.ts │ │ │ │ │ └── render.tsx │ │ │ │ ├── TodoList │ │ │ │ │ ├── index.ts │ │ │ │ │ └── render.tsx │ │ │ │ ├── EditButton │ │ │ │ │ ├── index.ts │ │ │ │ │ └── render.tsx │ │ │ │ ├── __test__ │ │ │ │ │ ├── setup.ts │ │ │ │ │ ├── TodoAddForm.spec.tsx │ │ │ │ │ └── TodoItem.spec.tsx │ │ │ │ ├── TodoItem │ │ │ │ │ ├── styles.module.scss │ │ │ │ │ ├── index.ts │ │ │ │ │ └── render.tsx │ │ │ │ ├── __stories__ │ │ │ │ │ ├── EditButton.stories.tsx │ │ │ │ │ ├── TodoConditions.stories.tsx │ │ │ │ │ ├── TodoAddForm.stories.tsx │ │ │ │ │ └── TodoItem.stories.tsx │ │ │ │ ├── TodoAddForm │ │ │ │ │ ├── styles.module.scss │ │ │ │ │ ├── index.ts │ │ │ │ │ └── render.tsx │ │ │ │ └── TodoConditions │ │ │ │ │ ├── index.ts │ │ │ │ │ └── render.tsx │ │ │ ├── reducers │ │ │ │ ├── index.ts │ │ │ │ ├── __test__ │ │ │ │ │ ├── app.spec.ts │ │ │ │ │ └── todo.spec.ts │ │ │ │ ├── todos.ts │ │ │ │ └── app.ts │ │ │ ├── types │ │ │ │ └── index.ts │ │ │ ├── store │ │ │ │ └── index.ts │ │ │ ├── index.tsx │ │ │ ├── webApi │ │ │ │ └── index.ts │ │ │ ├── sagas │ │ │ │ └── index.ts │ │ │ └── actions │ │ │ │ └── index.ts │ │ ├── application.ts │ │ ├── types │ │ │ ├── rails-ujs.d.ts │ │ │ ├── ignore-styles.d.ts │ │ │ └── assets.d.ts │ │ ├── lib │ │ │ └── case-util.ts │ │ └── change-query.ts │ ├── config │ │ └── manifest.js │ └── stylesheets │ │ ├── todos.scss │ │ ├── application.scss │ │ ├── scaffold.scss │ │ └── react-datetime.scss ├── models │ ├── concerns │ │ └── .keep │ ├── todo.rb │ └── application_record.rb ├── controllers │ ├── concerns │ │ └── .keep │ ├── pages_controller.rb │ ├── application_controller.rb │ ├── react_todos_controller.rb │ └── todos_controller.rb ├── views │ ├── layouts │ │ ├── mailer.text.erb │ │ ├── mailer.html.erb │ │ └── application.html.erb │ ├── todos │ │ ├── show.json.jbuilder │ │ ├── index.json.jbuilder │ │ ├── _todo.json.jbuilder │ │ ├── new.html.erb │ │ ├── edit.html.erb │ │ ├── show.html.erb │ │ ├── _form.html.erb │ │ └── index.html.erb │ ├── pages │ │ └── home.html.erb │ └── react_todos │ │ └── index.html.erb ├── helpers │ ├── todos_helper.rb │ └── application_helper.rb ├── jobs │ └── application_job.rb ├── channels │ └── application_cable │ │ ├── channel.rb │ │ └── connection.rb └── mailers │ └── application_mailer.rb ├── .postcssrc.yml ├── .rubocop.yml ├── .editorconfig ├── Procfile ├── bin ├── rake ├── bundle ├── rails ├── yarn ├── webpack ├── webpack-dev-server ├── spring ├── update └── setup ├── config ├── webpack │ ├── test.js │ ├── production.js │ ├── development.js │ └── environment.js ├── spring.rb ├── routes.rb ├── environment.rb ├── initializers │ ├── mime_types.rb │ ├── filter_parameter_logging.rb │ ├── application_controller_renderer.rb │ ├── cookies_serializer.rb │ ├── backtrace_silencers.rb │ ├── wrap_parameters.rb │ ├── inflections.rb │ ├── content_security_policy.rb │ └── new_framework_defaults_5_2.rb ├── boot.rb ├── cable.yml ├── database.yml ├── locales │ └── en.yml ├── application.rb ├── storage.yml ├── espower-typescript.js ├── secrets.yml ├── puma.rb ├── webpacker.yml └── environments │ ├── test.rb │ ├── development.rb │ └── production.rb ├── tsconfig.test.json ├── config.ru ├── Rakefile ├── .storybook ├── config.js └── webpack.config.js ├── db ├── migrate │ └── 20170617154903_create_todos.rb ├── seeds.rb └── schema.rb ├── tsconfig.json ├── .babelrc ├── tslint.json ├── .gitignore ├── Gemfile ├── README.md ├── package.json └── Gemfile.lock /log/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tmp/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /vendor/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /lib/assets/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /lib/tasks/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/helpers/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/mailers/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/models/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/system/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/assets/images/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/controllers/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/fixtures/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/integration/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/models/concerns/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/apple-touch-icon.png: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/fixtures/files/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/controllers/concerns/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/apple-touch-icon-precomposed.png: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.postcssrc.yml: -------------------------------------------------------------------------------- 1 | plugins: 2 | autoprefixer: {} 3 | -------------------------------------------------------------------------------- /.rubocop.yml: -------------------------------------------------------------------------------- 1 | Documentation: 2 | Enabled: false 3 | -------------------------------------------------------------------------------- /app/views/layouts/mailer.text.erb: -------------------------------------------------------------------------------- 1 | <%= yield %> 2 | -------------------------------------------------------------------------------- /app/assets/packs/todos.ts: -------------------------------------------------------------------------------- 1 | import 'javascripts/todos' 2 | -------------------------------------------------------------------------------- /app/helpers/todos_helper.rb: -------------------------------------------------------------------------------- 1 | module TodosHelper 2 | end 3 | -------------------------------------------------------------------------------- /app/models/todo.rb: -------------------------------------------------------------------------------- 1 | class Todo < ApplicationRecord 2 | end 3 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | [*] 2 | indent_style = space 3 | indent_size = 2 4 | -------------------------------------------------------------------------------- /app/helpers/application_helper.rb: -------------------------------------------------------------------------------- 1 | module ApplicationHelper 2 | end 3 | -------------------------------------------------------------------------------- /app/jobs/application_job.rb: -------------------------------------------------------------------------------- 1 | class ApplicationJob < ActiveJob::Base 2 | end 3 | -------------------------------------------------------------------------------- /app/views/todos/show.json.jbuilder: -------------------------------------------------------------------------------- 1 | json.partial! 'todos/todo', todo: @todo 2 | -------------------------------------------------------------------------------- /Procfile: -------------------------------------------------------------------------------- 1 | web: PORT=3000 bundle exec rails s 2 | webpacker: ./bin/webpack-dev-server 3 | -------------------------------------------------------------------------------- /app/views/todos/index.json.jbuilder: -------------------------------------------------------------------------------- 1 | json.array! @todos, partial: 'todos/todo', as: :todo 2 | -------------------------------------------------------------------------------- /app/assets/javascripts/todos/components/App/styles.module.scss: -------------------------------------------------------------------------------- 1 | .logo { 2 | width: 100px; 3 | } 4 | -------------------------------------------------------------------------------- /app/controllers/pages_controller.rb: -------------------------------------------------------------------------------- 1 | class PagesController < ApplicationController 2 | def home; end 3 | end 4 | -------------------------------------------------------------------------------- /bin/rake: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require_relative '../config/boot' 3 | require 'rake' 4 | Rake.application.run 5 | -------------------------------------------------------------------------------- /app/assets/javascripts/todos/components/TodoList/index.ts: -------------------------------------------------------------------------------- 1 | import TodoList from './render' 2 | export default TodoList 3 | -------------------------------------------------------------------------------- /app/models/application_record.rb: -------------------------------------------------------------------------------- 1 | class ApplicationRecord < ActiveRecord::Base 2 | self.abstract_class = true 3 | end 4 | -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | # See http://www.robotstxt.org/robotstxt.html for documentation on how to use the robots.txt file 2 | -------------------------------------------------------------------------------- /app/assets/javascripts/todos/components/EditButton/index.ts: -------------------------------------------------------------------------------- 1 | import EditButton from './render' 2 | export default EditButton 3 | -------------------------------------------------------------------------------- /config/webpack/test.js: -------------------------------------------------------------------------------- 1 | const environment = require('./environment') 2 | 3 | module.exports = environment.toWebpackConfig() 4 | -------------------------------------------------------------------------------- /tsconfig.test.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "jsx": "react" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /config/webpack/production.js: -------------------------------------------------------------------------------- 1 | const environment = require('./environment') 2 | 3 | module.exports = environment.toWebpackConfig() 4 | -------------------------------------------------------------------------------- /app/channels/application_cable/channel.rb: -------------------------------------------------------------------------------- 1 | module ApplicationCable 2 | class Channel < ActionCable::Channel::Base 3 | end 4 | end 5 | -------------------------------------------------------------------------------- /config/webpack/development.js: -------------------------------------------------------------------------------- 1 | const environment = require('./environment') 2 | 3 | module.exports = environment.toWebpackConfig() 4 | -------------------------------------------------------------------------------- /app/assets/config/manifest.js: -------------------------------------------------------------------------------- 1 | // = link_tree ../images 2 | // = link_directory ../javascripts .js 3 | // = link_directory ../stylesheets .css 4 | -------------------------------------------------------------------------------- /app/channels/application_cable/connection.rb: -------------------------------------------------------------------------------- 1 | module ApplicationCable 2 | class Connection < ActionCable::Connection::Base 3 | end 4 | end 5 | -------------------------------------------------------------------------------- /bin/bundle: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__) 3 | load Gem.bin_path('bundler', 'bundle') 4 | -------------------------------------------------------------------------------- /app/controllers/application_controller.rb: -------------------------------------------------------------------------------- 1 | class ApplicationController < ActionController::Base 2 | protect_from_forgery with: :exception 3 | end 4 | -------------------------------------------------------------------------------- /app/mailers/application_mailer.rb: -------------------------------------------------------------------------------- 1 | class ApplicationMailer < ActionMailer::Base 2 | default from: 'from@example.com' 3 | layout 'mailer' 4 | end 5 | -------------------------------------------------------------------------------- /config/spring.rb: -------------------------------------------------------------------------------- 1 | %w[ 2 | .ruby-version 3 | .rbenv-vars 4 | tmp/restart.txt 5 | tmp/caching-dev.txt 6 | ].each { |path| Spring.watch(path) } 7 | -------------------------------------------------------------------------------- /app/assets/packs/app.ts: -------------------------------------------------------------------------------- 1 | import 'javascripts/application' 2 | import 'stylesheets/application' 3 | require.context('images', true, /\.(png|jpg|jpeg|svg)$/) 4 | -------------------------------------------------------------------------------- /app/controllers/react_todos_controller.rb: -------------------------------------------------------------------------------- 1 | class ReactTodosController < ApplicationController 2 | def index 3 | @todos = Todo.all 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /app/views/todos/_todo.json.jbuilder: -------------------------------------------------------------------------------- 1 | json.extract! todo, :id, :content, :due_date, :done, :created_at, :updated_at 2 | json.url todo_url(todo, format: :json) 3 | -------------------------------------------------------------------------------- /config.ru: -------------------------------------------------------------------------------- 1 | # This file is used by Rack-based servers to start the application. 2 | 3 | require_relative 'config/environment' 4 | 5 | run Rails.application 6 | -------------------------------------------------------------------------------- /config/routes.rb: -------------------------------------------------------------------------------- 1 | Rails.application.routes.draw do 2 | root to: 'pages#home' 3 | resources :todos 4 | get 'react/todos', to: 'react_todos#index' 5 | end 6 | -------------------------------------------------------------------------------- /app/assets/javascripts/application.ts: -------------------------------------------------------------------------------- 1 | import 'babel-polyfill' 2 | import 'javascripts/change-query' 3 | import * as Rails from 'rails-ujs' 4 | 5 | Rails.start() 6 | -------------------------------------------------------------------------------- /app/views/todos/new.html.erb: -------------------------------------------------------------------------------- 1 |

New Todo

2 | 3 | <%= render 'form', todo: @todo %> 4 | 5 | <%= link_to 'Back', todos_path, class: 'btn btn-secondary' %> 6 | -------------------------------------------------------------------------------- /bin/rails: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | APP_PATH = File.expand_path('../config/application', __dir__) 3 | require_relative '../config/boot' 4 | require 'rails/commands' 5 | -------------------------------------------------------------------------------- /config/environment.rb: -------------------------------------------------------------------------------- 1 | # Load the Rails application. 2 | require_relative 'application' 3 | 4 | # Initialize the Rails application. 5 | Rails.application.initialize! 6 | -------------------------------------------------------------------------------- /test/models/todo_test.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class TodoTest < ActiveSupport::TestCase 4 | # test "the truth" do 5 | # assert true 6 | # end 7 | end 8 | -------------------------------------------------------------------------------- /app/assets/stylesheets/todos.scss: -------------------------------------------------------------------------------- 1 | /* 2 | Place all the styles related to the matching controller here. 3 | They will automatically be included in application.css. 4 | */ 5 | -------------------------------------------------------------------------------- /app/assets/javascripts/todos/components/__test__/setup.ts: -------------------------------------------------------------------------------- 1 | import { configure } from 'enzyme' 2 | import * as Adapter from 'enzyme-adapter-react-16' 3 | 4 | configure({ adapter: new Adapter() }) 5 | -------------------------------------------------------------------------------- /app/assets/javascripts/types/rails-ujs.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'rails-ujs' { 2 | const Rails: { 3 | start(): void 4 | csrfToken(): string | undefined 5 | } 6 | 7 | export = Rails 8 | } 9 | -------------------------------------------------------------------------------- /app/views/pages/home.html.erb: -------------------------------------------------------------------------------- 1 | 5 | -------------------------------------------------------------------------------- /config/initializers/mime_types.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Add new mime types for use in respond_to blocks: 4 | # Mime::Type.register "text/richtext", :rtf 5 | -------------------------------------------------------------------------------- /test/application_system_test_case.rb: -------------------------------------------------------------------------------- 1 | require 'test_helper' 2 | 3 | class ApplicationSystemTestCase < ActionDispatch::SystemTestCase 4 | driven_by :selenium, using: :chrome, screen_size: [1400, 1400] 5 | end 6 | -------------------------------------------------------------------------------- /app/views/todos/edit.html.erb: -------------------------------------------------------------------------------- 1 |

Editing Todo

2 | 3 | <%= render 'form', todo: @todo %> 4 | 5 | <%= link_to 'Show', @todo, class: 'btn btn-secondary' %> | 6 | <%= link_to 'Back', todos_path, class: 'btn btn-secondary' %> 7 | -------------------------------------------------------------------------------- /config/boot.rb: -------------------------------------------------------------------------------- 1 | ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__) 2 | 3 | require 'bundler/setup' # Set up gems listed in the Gemfile. 4 | require 'bootsnap/setup' # Speed up boot time by caching expensive operations. 5 | -------------------------------------------------------------------------------- /config/initializers/filter_parameter_logging.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Configure sensitive parameters which will be filtered from the log file. 4 | Rails.application.config.filter_parameters += [:password] 5 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | # Add your own tasks in files placed in lib/tasks ending in .rake, 2 | # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake. 3 | 4 | require_relative 'config/application' 5 | 6 | Rails.application.load_tasks 7 | -------------------------------------------------------------------------------- /test/system/todos_test.rb: -------------------------------------------------------------------------------- 1 | require 'application_system_test_case' 2 | 3 | class TodosTest < ApplicationSystemTestCase 4 | # test "visiting the index" do 5 | # visit todos_url 6 | # 7 | # assert_selector "h1", text: "Todo" 8 | # end 9 | end 10 | -------------------------------------------------------------------------------- /config/cable.yml: -------------------------------------------------------------------------------- 1 | development: 2 | adapter: async 3 | 4 | test: 5 | adapter: async 6 | 7 | production: 8 | adapter: redis 9 | url: <%= ENV.fetch("REDIS_URL") { "redis://localhost:6379/1" } %> 10 | channel_prefix: webpacker_react_example_production 11 | -------------------------------------------------------------------------------- /config/initializers/application_controller_renderer.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # ActiveSupport::Reloader.to_prepare do 4 | # ApplicationController.renderer.defaults.merge!( 5 | # http_host: 'example.org', 6 | # https: false 7 | # ) 8 | # end 9 | -------------------------------------------------------------------------------- /config/initializers/cookies_serializer.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Specify a serializer for the signed and encrypted cookie jars. 4 | # Valid options are :json, :marshal, and :hybrid. 5 | Rails.application.config.action_dispatch.cookies_serializer = :json 6 | -------------------------------------------------------------------------------- /test/fixtures/todos.yml: -------------------------------------------------------------------------------- 1 | # Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html 2 | 3 | one: 4 | content: MyString 5 | due_date: 2017-06-18 00:49:03 6 | done: false 7 | 8 | two: 9 | content: MyString 10 | due_date: 2017-06-18 00:49:03 11 | done: false 12 | -------------------------------------------------------------------------------- /app/views/layouts/mailer.html.erb: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 8 | 9 | 10 | 11 | <%= yield %> 12 | 13 | 14 | -------------------------------------------------------------------------------- /.storybook/config.js: -------------------------------------------------------------------------------- 1 | import { configure } from '@storybook/react' 2 | import 'stylesheets/application.scss' 3 | 4 | const req = require.context('javascripts', true, /\.stories\.tsx$/) 5 | 6 | function loadStories() { 7 | req.keys().forEach((filename) => req(filename)) 8 | } 9 | 10 | configure(loadStories, module) 11 | -------------------------------------------------------------------------------- /app/views/react_todos/index.html.erb: -------------------------------------------------------------------------------- 1 | <% content_for :head do %> 2 | <%= javascript_pack_tag 'todos' %> 3 | <%= stylesheet_pack_tag 'todos' %> 4 | <% end %> 5 | 6 | <%= content_tag :div, 7 | id: 'todos-data', 8 | data: { 9 | todos: @todos 10 | }.to_json do %> 11 | <% end %> 12 |
13 | -------------------------------------------------------------------------------- /db/migrate/20170617154903_create_todos.rb: -------------------------------------------------------------------------------- 1 | class CreateTodos < ActiveRecord::Migration[5.1] 2 | def change 3 | create_table :todos do |t| 4 | t.string :content, null: false 5 | t.datetime :due_date, null: false 6 | t.boolean :done, null: false 7 | 8 | t.timestamps 9 | end 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /app/assets/javascripts/todos/components/TodoItem/styles.module.scss: -------------------------------------------------------------------------------- 1 | .contentCol { 2 | width: 20em; 3 | } 4 | 5 | .contentLabel { 6 | display: inline; 7 | font-weight: normal; 8 | } 9 | 10 | .editButton { 11 | margin-left: 1rem; 12 | } 13 | 14 | .dueDateCol { 15 | width: 25em; 16 | } 17 | 18 | .error { 19 | color: red; 20 | } 21 | -------------------------------------------------------------------------------- /bin/yarn: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | APP_ROOT = File.expand_path('..', __dir__) 3 | Dir.chdir(APP_ROOT) do 4 | begin 5 | exec "yarnpkg", *ARGV 6 | rescue Errno::ENOENT 7 | $stderr.puts "Yarn executable was not detected in the system." 8 | $stderr.puts "Download Yarn at https://yarnpkg.com/en/docs/install" 9 | exit 1 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /app/assets/stylesheets/application.scss: -------------------------------------------------------------------------------- 1 | @import '~bootstrap/scss/bootstrap'; 2 | @import '~@fortawesome/fontawesome-free/scss/fontawesome'; 3 | @import '~@fortawesome/fontawesome-free/scss/regular'; 4 | @import '~stylesheets/scaffold'; 5 | @import '~stylesheets/react-datetime'; 6 | 7 | .check { 8 | width: 1em; 9 | } 10 | 11 | .logo { 12 | width: 100px; 13 | } 14 | -------------------------------------------------------------------------------- /test/test_helper.rb: -------------------------------------------------------------------------------- 1 | require File.expand_path('../config/environment', __dir__) 2 | require 'rails/test_help' 3 | 4 | module ActiveSupport 5 | class TestCase 6 | # Setup all fixtures in test/fixtures/*.yml for all tests in alphabetical 7 | # order. 8 | fixtures :all 9 | 10 | # Add more helper methods to be used by all tests here... 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /app/views/layouts/application.html.erb: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | WebpackerReactExample 5 | <%= csrf_meta_tags %> 6 | 7 | <%= javascript_pack_tag 'app' %> 8 | <%= stylesheet_pack_tag 'app' %> 9 | <%= yield :head %> 10 | 11 | 12 | 13 |
14 | <%= yield %> 15 |
16 | 17 | 18 | -------------------------------------------------------------------------------- /app/assets/images/square-o.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /app/assets/javascripts/todos/reducers/index.ts: -------------------------------------------------------------------------------- 1 | import { combineReducers, Reducer } from 'redux' 2 | import app, { AppState } from './app' 3 | import todos, { TodosState } from './todos' 4 | 5 | export interface StoreState { 6 | readonly todos: TodosState 7 | readonly app: AppState 8 | } 9 | 10 | export * from './todos' 11 | export * from './app' 12 | export default combineReducers({ todos, app }) 13 | -------------------------------------------------------------------------------- /bin/webpack: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | ENV["RAILS_ENV"] ||= ENV["RACK_ENV"] || "development" 4 | ENV["NODE_ENV"] ||= "development" 5 | 6 | require "pathname" 7 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", 8 | Pathname.new(__FILE__).realpath) 9 | 10 | require "rubygems" 11 | require "bundler/setup" 12 | 13 | require "webpacker" 14 | require "webpacker/webpack_runner" 15 | Webpacker::WebpackRunner.run(ARGV) 16 | -------------------------------------------------------------------------------- /app/assets/javascripts/todos/components/__stories__/EditButton.stories.tsx: -------------------------------------------------------------------------------- 1 | import { action } from '@storybook/addon-actions' 2 | import { storiesOf } from '@storybook/react' 3 | import * as React from 'react' 4 | import EditButton from '../EditButton/render' 5 | 6 | storiesOf('EditButton', module) 7 | .add('typical', () => ) 8 | .add('disabled', () => ) 9 | -------------------------------------------------------------------------------- /db/seeds.rb: -------------------------------------------------------------------------------- 1 | # This file should contain all the record creation needed to seed the database 2 | # with its default values. The data can then be loaded with the rails db:seed 3 | # command (or created alongside the database with db:setup). 4 | # 5 | # Examples: 6 | # 7 | # movies = Movie.create([ 8 | # { name: 'Star Wars' }, 9 | # { name: 'Lord of the Rings' } 10 | # ]) 11 | # Character.create(name: 'Luke', movie: movies.first) 12 | -------------------------------------------------------------------------------- /app/assets/javascripts/todos/components/TodoAddForm/styles.module.scss: -------------------------------------------------------------------------------- 1 | .content { 2 | font-weight: normal; 3 | } 4 | 5 | .dueDate { 6 | display: inline-block; 7 | font-weight: normal; 8 | 9 | :global(.form-control) { 10 | line-height: inherit; 11 | height: inherit; 12 | padding: 2px; 13 | border-radius: 0; 14 | } 15 | } 16 | 17 | .item { 18 | margin: 0 0.5rem; 19 | } 20 | 21 | .error { 22 | color: red; 23 | } 24 | -------------------------------------------------------------------------------- /bin/webpack-dev-server: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | ENV["RAILS_ENV"] ||= ENV["RACK_ENV"] || "development" 4 | ENV["NODE_ENV"] ||= "development" 5 | 6 | require "pathname" 7 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", 8 | Pathname.new(__FILE__).realpath) 9 | 10 | require "rubygems" 11 | require "bundler/setup" 12 | 13 | require "webpacker" 14 | require "webpacker/dev_server_runner" 15 | Webpacker::DevServerRunner.run(ARGV) 16 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "sourceMap": true, 4 | "noImplicitAny": true, 5 | "strictNullChecks": true, 6 | "target": "esnext", 7 | "moduleResolution": "node", 8 | "jsx": "preserve" 9 | }, 10 | "include": [ 11 | "./app/assets/javascripts/**/*", 12 | "./app/assets/packs/**/*" 13 | ], 14 | "awesomeTypescriptLoaderOptions": { 15 | "useBabel": true, 16 | "useCache": true 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /config/initializers/backtrace_silencers.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces. 4 | # Rails.backtrace_cleaner.add_silencer { |line| line =~ /my_noisy_library/ } 5 | 6 | # You can also remove all the silencers if you're trying to debug a problem that might stem from framework code. 7 | # Rails.backtrace_cleaner.remove_silencers! 8 | -------------------------------------------------------------------------------- /app/assets/javascripts/todos/components/App/index.ts: -------------------------------------------------------------------------------- 1 | import { flowRight } from 'lodash' 2 | import { hot } from 'react-hot-loader' 3 | import { connect } from 'react-redux' 4 | import { StoreState, visibleTodos } from '../../reducers' 5 | import App, { Props } from './render' 6 | 7 | export default flowRight([ 8 | hot(module), 9 | connect(({ todos, app }: StoreState) => ({ 10 | todos: visibleTodos(todos, app.sortBy, app.sortOrder, app.doneFilter), 11 | })), 12 | ])(App) 13 | -------------------------------------------------------------------------------- /app/assets/javascripts/todos/types/index.ts: -------------------------------------------------------------------------------- 1 | export interface Todo { 2 | id: number 3 | content: string 4 | done: boolean 5 | dueDate: string 6 | createdAt: string 7 | updatedAt: string 8 | } 9 | 10 | export class IdentifiableError extends Error { 11 | constructor(readonly targetId: number, message?: string) { 12 | super(message) 13 | Object.setPrototypeOf(this, this.constructor.prototype) // restore prototype chain 14 | this.name = 'IdentifiableError' 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /app/assets/javascripts/types/ignore-styles.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | declare module 'ignore-styles' { 4 | type Handler = (m: NodeModule, filename: string) => any 5 | 6 | export const DEFAULT_EXTENSIONS: string[] 7 | 8 | export let oldHandlers: { 9 | [ext: string]: Handler 10 | } 11 | 12 | export function noOp(): void 13 | 14 | export function restore(): void 15 | 16 | export default function register( 17 | extensions?: string[], 18 | handler?: Handler 19 | ): void 20 | } 21 | -------------------------------------------------------------------------------- /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | [ 4 | "env", 5 | { 6 | "modules": false, 7 | "targets": { 8 | "browsers": "> 1%", 9 | "uglify": true 10 | }, 11 | "useBuiltIns": true 12 | } 13 | ], 14 | "react" 15 | ], 16 | "plugins": [ 17 | "syntax-dynamic-import", 18 | ["transform-class-properties", { "spec": true }], 19 | ["transform-object-rest-spread", {"useBuiltIns": true}], 20 | "lodash", 21 | "react-hot-loader/babel" 22 | ] 23 | } 24 | -------------------------------------------------------------------------------- /app/assets/javascripts/todos/components/__stories__/TodoConditions.stories.tsx: -------------------------------------------------------------------------------- 1 | import { action } from '@storybook/addon-actions' 2 | import { storiesOf } from '@storybook/react' 3 | import * as React from 'react' 4 | import TodoConditions from '../TodoConditions/render' 5 | 6 | storiesOf('TodoConditions', module).add('typical', () => ( 7 | 14 | )) 15 | -------------------------------------------------------------------------------- /app/assets/javascripts/todos/components/TodoList/render.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react' 2 | import TodoItem from '../TodoItem' 3 | 4 | export interface Props { 5 | todos: number[] 6 | } 7 | 8 | export default function TodoList({ todos }: Props) { 9 | return ( 10 | 11 | 12 | 13 | 14 | 15 | 17 | 18 | {todos.map(id => )} 19 |
ContentDue date 16 |
20 | ) 21 | } 22 | -------------------------------------------------------------------------------- /config/initializers/wrap_parameters.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # This file contains settings for ActionController::ParamsWrapper which 4 | # is enabled by default. 5 | 6 | # Enable parameter wrapping for JSON. You can disable this by setting :format to an empty array. 7 | ActiveSupport.on_load(:action_controller) do 8 | wrap_parameters format: [:json] 9 | end 10 | 11 | # To enable root element in JSON for ActiveRecord objects. 12 | # ActiveSupport.on_load(:active_record) do 13 | # self.include_root_in_json = true 14 | # end 15 | -------------------------------------------------------------------------------- /bin/spring: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | # This file loads spring without using Bundler, in order to be fast. 4 | # It gets overwritten when you run the `spring binstub` command. 5 | 6 | unless defined?(Spring) 7 | require 'rubygems' 8 | require 'bundler' 9 | 10 | lockfile = Bundler::LockfileParser.new(Bundler.default_lockfile.read) 11 | spring = lockfile.specs.detect { |spec| spec.name == "spring" } 12 | if spring 13 | Gem.use_paths Gem.dir, Bundler.bundle_path.to_s, *Gem.path 14 | gem 'spring', spring.version 15 | require 'spring/binstub' 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /app/assets/images/check-square-o.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "defaultSeverity": "error", 3 | "extends": [ 4 | "tslint:latest", 5 | "tslint-react", 6 | "tslint-eslint-rules", 7 | "tslint-config-prettier" 8 | ], 9 | "rules": { 10 | "quotemark": [true, "single", "jsx-double"], 11 | "semicolon": [true, "never"], 12 | "interface-name": [true, "never-prefix"], 13 | "object-literal-sort-keys": false, 14 | "no-submodule-imports": false, 15 | "member-access": [true, "no-public"], 16 | "jsx-boolean-value": [true, "never"], 17 | "jsx-no-lambda": false, 18 | "no-implicit-dependencies": false 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /app/views/todos/show.html.erb: -------------------------------------------------------------------------------- 1 |

<%= notice %>

2 | 3 |

4 | Content: 5 | <%= @todo.content %> 6 |

7 | 8 |

9 | Due date: 10 | <%= @todo.due_date %> 11 |

12 | 13 |

14 | Done: 15 | <% if @todo.done %> 16 | 17 | <% else %> 18 | 19 | <% end %> 20 |

21 | 22 | <%= link_to 'Edit', edit_todo_path(@todo), class: 'btn btn-secondary' %> | 23 | <%= link_to 'Back', todos_path, class: 'btn btn-secondary' %> 24 | -------------------------------------------------------------------------------- /app/assets/javascripts/lib/case-util.ts: -------------------------------------------------------------------------------- 1 | import * as _ from 'lodash' 2 | 3 | type DictToDict = (obj: _.Dictionary) => _.Dictionary 4 | 5 | export function snakeCaseKeys(obj: object): object { 6 | const tr: DictToDict = o => 7 | _.transform(o, (result, value, key) => { 8 | result[_.snakeCase(key)] = _.isPlainObject(value) ? tr(value) : value 9 | }) 10 | return tr(obj) 11 | } 12 | 13 | export function camelCaseKeys(obj: object): object { 14 | const tr: DictToDict = o => 15 | _.transform(o, (result, value, key) => { 16 | result[_.camelCase(key)] = _.isPlainObject(value) ? tr(value) : value 17 | }) 18 | return tr(obj) 19 | } 20 | -------------------------------------------------------------------------------- /app/assets/javascripts/todos/components/App/render.tsx: -------------------------------------------------------------------------------- 1 | import * as reactIcon from 'images/react.svg' 2 | import * as React from 'react' 3 | import TodoAddForm from '../TodoAddForm' 4 | import TodoConditions from '../TodoConditions' 5 | import TodoList from '../TodoList' 6 | import * as styles from './styles.module.scss' 7 | 8 | export interface Props { 9 | todos: number[] 10 | } 11 | 12 | export default function App({ todos }: Props) { 13 | return ( 14 |
15 | react icon 16 | 17 | 18 | 19 |
20 | ) 21 | } 22 | -------------------------------------------------------------------------------- /config/database.yml: -------------------------------------------------------------------------------- 1 | # SQLite version 3.x 2 | # gem install sqlite3 3 | # 4 | # Ensure the SQLite 3 gem is defined in your Gemfile 5 | # gem 'sqlite3' 6 | # 7 | default: &default 8 | adapter: sqlite3 9 | pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> 10 | timeout: 5000 11 | 12 | development: 13 | <<: *default 14 | database: db/development.sqlite3 15 | 16 | # Warning: The database defined as "test" will be erased and 17 | # re-generated from your development database when you run "rake". 18 | # Do not set this db to the same as development or production. 19 | test: 20 | <<: *default 21 | database: db/test.sqlite3 22 | 23 | production: 24 | <<: *default 25 | database: db/production.sqlite3 26 | -------------------------------------------------------------------------------- /app/assets/javascripts/todos/store/index.ts: -------------------------------------------------------------------------------- 1 | import { applyMiddleware, createStore, Store } from 'redux' 2 | import { composeWithDevTools } from 'redux-devtools-extension/logOnlyInProduction' 3 | import createSagaMiddleware from 'redux-saga' 4 | import reducers, { StoreState } from '../reducers' 5 | import rootSaga from '../sagas' 6 | 7 | export default function createAppStore( 8 | preloadedState: Partial 9 | ): Store { 10 | const sagaMiddleware = createSagaMiddleware() 11 | const enhancer = composeWithDevTools(applyMiddleware(sagaMiddleware)) 12 | 13 | const store = createStore(reducers, preloadedState as StoreState, enhancer) 14 | 15 | sagaMiddleware.run(rootSaga) 16 | 17 | return store 18 | } 19 | -------------------------------------------------------------------------------- /app/assets/javascripts/todos/components/EditButton/render.tsx: -------------------------------------------------------------------------------- 1 | import * as classNames from 'classnames' 2 | import * as React from 'react' 3 | 4 | export interface Props { 5 | className?: string 6 | disabled?: boolean 7 | onClick: (e: React.MouseEvent) => void 8 | } 9 | 10 | export default function EditButton({ 11 | className = '', 12 | disabled = false, 13 | onClick, 14 | }: Props) { 15 | return ( 16 |