Merge pull request #395 from RickCarlino/webpack_rails

Fix Caching / iOS refresh issue
This commit is contained in:
Rick Carlino 2017-08-10 15:43:57 -05:00 committed by GitHub
commit 475467420c
498 changed files with 475 additions and 676 deletions

11
.gitignore vendored
View file

@ -21,10 +21,6 @@ _yardoc
/coverage/
/db/*.sqlite3
/log
/public/assets/
/public/build/*
/public/js/*
/public/system
/spec/tmp
/src/config.json
/tmp
@ -50,17 +46,22 @@ node_modules/
npm-debug.log
pickle-email-*.html
pkg
public/*.eot
public/app-index.js
public/app-resources/*.css*
public/app-resources/*.js*
public/app-resources/chunks/*.js*
public/app/*
public/assets/
public/build/*
public/front_page.js
public/index.html
public/password_reset.html
public/tos_update.html
public/verify.html
public/*.eot
public/webpack/*
public/webpack
public/dist
rdoc
rerun.txt
secret.json

View file

@ -19,7 +19,7 @@ script:
- export FW_UPDATE_SERVER=http://example.com
- export DB=postgresql
- export COVERALLS_REPO_TOKEN=lEX6nkql7y2YFCcIXVq5ORvdvMtYzfZdG
- bundle exec rspec
- bundle exec rspec --fail-fast=3
- npm run typecheck
- npm run test
- npm run coverage

View file

@ -26,7 +26,7 @@ gem "pg"
gem "polymorphic_constraints"
gem "tzinfo" # For validation of user selected timezone names
gem "foreman"
gem "webpack-rails"
# Error reporting tools.
# Active on the "official" FarmBot server, set the appropriate ENV
# vars if you wish to use them on your own servers.

View file

@ -267,6 +267,8 @@ GEM
url (0.3.2)
warden (1.2.7)
rack (>= 1.0)
webpack-rails (0.9.10)
railties (>= 3.2.0)
websocket-driver (0.6.5)
websocket-extensions (>= 0.1.0)
websocket-extensions (0.1.2)
@ -306,6 +308,7 @@ DEPENDENCIES
smarf_doc!
thin
tzinfo
webpack-rails
RUBY VERSION
ruby 2.4.1p111

View file

@ -1,3 +1,5 @@
api: rails s -e development -p 3000 -b 0.0.0.0
wrk: rake jobs:work
fe: npm run webpack
# Run Rails & Webpack concurrently
# Example file from webpack-rails gem
rails: rails s -e development -p 3000 -b 0.0.0.0
webpack: ./node_modules/.bin/webpack-dev-server --config config/webpack.config.js
worker: rake jobs:work

View file

@ -46,7 +46,7 @@ You will need the following:
0. (optional) Verify installation with `RAILS_ENV=test rake db:create db:migrate && rspec spec` (API) and `npm run test` (Frontend).
0. Start server with `npm run dev`. Make sure you set an `MQTT_HOST` entry in `application.yml` pointing to the IP address or domain of the (soon-to-be-installed) MQTT server. You will need to set that up next.
0. Now that the API server is running, [provision an MQTT server](https://github.com/FarmBot/mqtt-gateway).
0. Open [localhost:8080](http://localhost:8080). The application is now ready for use.
0. Open [localhost:3808](http://localhost:3808). The application is now ready for use.
0. [Raise an issue](https://github.com/FarmBot/Farmbot-Web-App/issues/new?title=Installation%20Failure) if you hit problems with any of these steps. *We can't fix issues we don't know about.*
\*Give permission to `user` to create database:

View file

@ -1,12 +1,12 @@
class DashboardController < ApplicationController
FE_PATH = "public/app/index.html"
FE_FALLBACK = "app/views/fe_fallback.html"
HAS_FE = File.file? FE_PATH
THE_FRONTEND_APP = File.read(HAS_FE ? FE_PATH : FE_FALLBACK).html_safe
ACME_SECRET = ENV["ACME_SECRET"]
def index
render html: THE_FRONTEND_APP, layout: false
ACME_SECRET = ENV["ACME_SECRET"]
LONG_REVISION = ENV["BUILT_AT"] || ENV["HEROKU_SLUG_COMMIT"] || "NONE"
$FRONTEND_SHARED_DATA = { NODE_ENV: Rails.env || "development",
TOS_URL: ENV.fetch("TOS_URL", ""),
LONG_REVISIONL: LONG_REVISION,
SHORT_REVISION: LONG_REVISION.first(8) }.to_json
[:main_app, :front_page, :tos_update, :verify, :password_reset].map do |actn|
define_method(actn) { render actn, layout: false }
end
# Hit by Certbot / Let's Encrypt when it's time to verify control of domain.

View file

@ -2,10 +2,7 @@ class UserMailer < ApplicationMailer
def welcome_email(user)
@user = user
@user_name = user.name
@the_url = "http:" +
$API_URL +
"/verify.html?token=" +
user.verification_token
@the_url = "http:" + $API_URL + "/verify?token=" + user.verification_token
throw "Bad registration?" unless @the_url.present?
mail(to: @user.email, subject: 'Welcome to The FarmBot Web App!')
end

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,15 @@
<meta charset="UTF-8">
<script>
// IMPORTANT!!!!
// ALWAYS LOAD THIS *FIRST*
window.globalConfig = <%= raw($FRONTEND_SHARED_DATA) %> // SEE COMMENTS!;
// READ COMMENT ABOVE
</script>
<%= render "addons" %>
<meta content="width=device-width, initial-scale=1" name="viewport">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.4.0/css/font-awesome.min.css">
<link href="https://fonts.googleapis.com/css?family=Roboto:300,300i,400,400i,700,700i" rel="stylesheet">
<% if Rails.env.development? && %>
<script src="http://<%= ENV["API_HOST"] %>:8081/target/target-script-min.js#anonymous"></script>
<% end %>

View file

@ -0,0 +1,9 @@
<!DOCTYPE html>
<html>
<head>
<%= render "common_assets" %>
</head>
<body>
<%= javascript_include_tag *webpack_asset_paths("front_page") %>
</body>
</html>

View file

@ -0,0 +1,9 @@
<!DOCTYPE html>
<html>
<head>
<%= render "common_assets" %>
</head>
<body>
<%= javascript_include_tag *webpack_asset_paths("bundle") %>
</body>
</html>

View file

@ -0,0 +1,9 @@
<!DOCTYPE html>
<html>
<head>
<%= render "common_assets" %>
</head>
<body>
<%= javascript_include_tag *webpack_asset_paths("password_reset") %>
</body>
</html>

View file

@ -0,0 +1,9 @@
<!DOCTYPE html>
<html>
<head>
<%= render "common_assets" %>
</head>
<body>
<%= javascript_include_tag *webpack_asset_paths("tos_update") %>
</body>
</html>

View file

@ -0,0 +1,9 @@
<!DOCTYPE html>
<html>
<head>
<%= render "common_assets" %>
</head>
<body>
<%= javascript_include_tag *webpack_asset_paths("verification") %>
</body>
</html>

View file

@ -1,9 +0,0 @@
<html>
<body>
<p>
Farmbot failed to build front end assets during deployment.
</p>
</body>
</html>

View file

@ -4,5 +4,5 @@
</p>
<p>
You can reset your password
<a href='http:<%= @host %>/password_reset#/<%= @token %>'>here</a>.
<a href='http:<%= @host %>/password_reset/<%= @token %>'>here</a>.
</p>

View file

@ -5,4 +5,4 @@ Someone (hopefully you) has requested a password reset for your account.
You can reset your password at the URL below:
http:<%= @host %>/password_reset#/<%= @token %>
http:<%= @host %>/password_reset/<%= @token %>

View file

@ -1,6 +1,5 @@
<h1>Welcome to FarmBot, <%= @user_name %></h1>
<p>
Please verify your email by clicking here
<a href="<%= @the_url %>">here</a>.<br>
Please verify your email by clicking <a href="<%= @the_url %>">here</a>.<br>
</p>
<p>Thanks for joining and have a great day!</p>

View file

@ -1,14 +1,18 @@
FarmBot::Application.configure do
config.action_controller.perform_caching = false
config.action_controller.perform_caching = false
config.action_mailer.default_url_options = {
host: Rails.application.routes.default_url_options[:host],
port: Rails.application.routes.default_url_options[:port]
}
config.active_support.deprecation = :log
config.assets.debug = true
config.cache_classes = false
config.consider_all_requests_local = true
config.eager_load = false
config.action_mailer.delivery_method = :smtp
config.action_mailer.smtp_settings = { :address => "localhost", :port => 1025 }
config.action_mailer.delivery_method = :smtp
config.action_mailer.smtp_settings = { address: "localhost",
port: 1025 }
config.active_support.deprecation = :log
config.assets.debug = true
config.assets.digest = true
config.assets.raise_runtime_errors = true
config.cache_classes = false
config.consider_all_requests_local = true
config.eager_load = false
end

View file

@ -26,4 +26,3 @@ FarmBot::Application.configure do
user_name: uname,
password: pw }
end

View file

@ -36,7 +36,20 @@ FarmBot::Application.routes.draw do
get "/api/storage_auth" => "api/images#storage_auth", as: :storage_auth
# You can set FORCE_SSL when you're done.
get "/.well-known/acme-challenge/:id" => "dashboard#lets_encrypt", as: :lets_encrypt
# Hacks for HTML5 push state routing:
get "/app" => 'dashboard#index', as: :dashboard
match "/app/*path", to: 'dashboard#index', via: :all # Loads /app/index.html
# =======================================================================
# NON-API (USER FACING) URLS:
# =======================================================================
get "/" => 'dashboard#front_page',
as: :front_page
get "/app" => 'dashboard#main_app',
as: :dashboard
match "/app/*path",
to: 'dashboard#main_app',
via: :all
get "/password_reset/*token" => 'dashboard#password_reset',
as: :password_reset
get "/verify" => 'dashboard#verify',
as: :verify
end

5
config/webpack.config.js Normal file
View file

@ -0,0 +1,5 @@
var production = process.env.RAILS_ENV === 'production';
var configFile = production ? "./webpack.prod" : "./webpack.dev";
module.exports = require(configFile);

70
config/webpack.dev.js Normal file
View file

@ -0,0 +1,70 @@
var devServerPort = 3808;
var exec = require("child_process").exec;
var execSync = require("child_process").execSync;
var ExtractTextPlugin = require("extract-text-webpack-plugin");
var fs = require("fs");
var OptimizeCssAssetsPlugin = require("optimize-css-assets-webpack-plugin");
var path = require("path");
var path = require("path");
var production = process.env.RAILS_ENV === 'production';
var StatsPlugin = require('stats-webpack-plugin');
var UglifyJsPlugin = require("webpack-uglify-js-plugin");
var webpack = require("webpack");
console.log("INSIDE DEV MODE WEBPACK CONFIG!");
module.exports = {
entry: {
"bundle": path.resolve(__dirname, "../webpack/entry.tsx"),
"front_page": "./webpack/front_page/index.tsx",
"verification": "./webpack/verification.ts",
"password_reset": "./webpack/password_reset/index.tsx",
"tos_update": "./webpack/tos_update/index.tsx"
},
devtool: "eval",
output: {
// must match config.webpack.output_dir
path: path.join(__dirname, '..', 'public', 'webpack'),
publicPath: '//localhost:' + devServerPort + '/webpack/',
filename: '[name].js'
},
module: {
rules: [
{
test: [/\.scss$/, /\.css$/],
use: ["style-loader", "css-loader", "sass-loader"]
},
{ test: /\.tsx?$/, use: "ts-loader" },
{
test: [/\.woff$/, /\.woff2$/, /\.ttf$/],
use: "url-loader"
},
{
test: [/\.eot$/, /\.svg(\?v=\d+\.\d+\.\d+)?$/],
use: "file-loader"
}
]
},
// Allows imports without file extensions.
resolve: {
extensions: [".js", ".ts", ".tsx", ".css", ".scss", ".json"]
},
devServer: {
port: devServerPort,
headers: { 'Access-Control-Allow-Origin': '*' }
},
plugins: [
// must match config.webpack.manifest_filename
new StatsPlugin('manifest.json', {
// We only need assetsByChunkName
chunkModules: false,
source: false,
chunks: false,
modules: false,
assets: true
}),
new webpack.DefinePlugin({
"process.env.NODE_ENV": JSON.stringify("production")
})
]
}

98
config/webpack.prod.js Normal file
View file

@ -0,0 +1,98 @@
'use strict';
global.WEBPACK_ENV = "production";
var devServerPort = 3808;
var exec = require("child_process").exec;
var execSync = require("child_process").execSync;
var ExtractTextPlugin = require("extract-text-webpack-plugin");
var fs = require("fs");
var OptimizeCssAssetsPlugin = require("optimize-css-assets-webpack-plugin");
var path = require("path");
var path = require("path");
var production = process.env.RAILS_ENV === 'production';
var StatsPlugin = require('stats-webpack-plugin');
var UglifyJsPlugin = require("webpack-uglify-js-plugin");
var webpack = require("webpack");
console.log("INSIDE PRODUCTION WEBPACK CONFIG!");
module.exports = {
entry: {
"bundle": path.resolve(__dirname, "../webpack/entry.tsx"),
"front_page": "./webpack/front_page/index.tsx",
"verification": "./webpack/verification.ts",
"password_reset": "./webpack/password_reset/index.tsx",
"tos_update": "./webpack/tos_update/index.tsx"
},
devtool: "eval",
output: {
// must match config.webpack.output_dir
path: path.join(__dirname, '..', 'public', 'webpack'),
publicPath: '/webpack/',
filename: '[name]-[chunkhash].js'
},
// Shared loaders for prod and dev.
module: {
rules: [
{ test: /\.tsx?$/, use: "ts-loader" },
{
test: [/\.woff$/, /\.woff2$/, /\.ttf$/],
use: "url-loader"
},
{
test: [/\.eot$/, /\.svg(\?v=\d+\.\d+\.\d+)?$/],
use: "file-loader"
},
// CHRIS:
// I had to remove extractTextPlugin temporarily. Let's talk about getting it
// put back in.
// The code below runs DEVELOPMENT MODE in production, which is bad,
// but maybe not as bad as the caching issues.
{
test: [/\.scss$/, /\.css$/],
use: ["style-loader", "css-loader", "sass-loader"]
}
]
},
// Allows imports without file extensions.
resolve: {
extensions: [".js", ".ts", ".tsx", ".css", ".scss", ".json"]
},
plugins: [
// must match config.webpack.manifest_filename
new StatsPlugin('manifest.json', {
// We only need assetsByChunkName
chunkModules: false,
source: false,
chunks: false,
modules: false,
assets: true
}),
new ExtractTextPlugin({
// Temporary hotfix for some issues on staging.
// - RC 12 MAY 17
// filename: "dist/styles.css",
filename: "dist/[name].[chunkhash].css",
disable: false,
allChunks: true
}),
new OptimizeCssAssetsPlugin({
assetNameRegExp: /\.css$/g,
cssProcessor: require("cssnano"),
cssProcessorOptions: { discardComments: { removeAll: true } },
canPrint: true
}),
new UglifyJsPlugin({
cacheFolder: path.resolve(__dirname, "../public/dist/cached_uglify/"),
debug: true,
minimize: true,
sourceMap: true,
screw_ie8: true,
output: { comments: false },
compressor: { warnings: false }
}),
new webpack.DefinePlugin({
"process.env.NODE_ENV": JSON.stringify("production")
})
]
}

View file

@ -1,22 +0,0 @@
#!/bin/bash
echo "========= RUNNING install_frontend.sh"
CURRENT_DIR=$(pwd)
if [ "$NPM_ADDON" ]; then
echo "========= NPM ADD ON DETECTED... INSTALLING"
npm install $NPM_ADDON --save 2>&1
fi
echo "========= Running Yarn"
yarn install 2>&1
# https://github.com/yarnpkg/yarn/issues/1981
npm rebuild node-sass
# Make webpack executable and compile everything.
echo "========= Changing Webpack permissions"
chmod +x node_modules/webpack/bin/webpack.js
echo "========= Running `npm run build`"
npm run build 2>&1
# Move it over to the rails /public directory and install deps
mkdir public/ -p

View file

@ -9,12 +9,12 @@
},
"scripts": {
"coverage": "cat **/*lcov.info | ./node_modules/coveralls/bin/coveralls.js",
"build": "node_modules/webpack/bin/webpack.js --config tools/webpack.config.prd.js --display-error-details",
"build": "TARGET=production bundle exec rake webpack:compile",
"start": "echo '===We use `npm run dev` now.==='",
"heroku-postbuild": "./install_frontend.sh 2>&1",
"heroku-postbuild": "webpack --config=./config/webpack.prod.js",
"dev": "PORT=3000 bundle exec foreman start --procfile=Procfile.dev",
"webpack": "webpack-dev-server --config tools/webpack.config.dev.js --content-base public/ --host 0.0.0.0",
"test": "jest --coverage --no-cache",
"webpack": "./node_modules/.bin/webpack-dev-server --config config/webpack.config.js --host 0.0.0.0",
"test": "jest --coverage --no-cache --bail",
"typecheck": "tsc --noEmit --jsx preserve"
},
"keywords": [
@ -81,6 +81,7 @@
"redux-immutable-state-invariant": "^2.0.0",
"redux-thunk": "^2.0.1",
"sass-loader": "^6.0.6",
"stats-webpack-plugin": "^0.6.1",
"style-loader": "^0.18.2",
"ts-jest": "^20.0.7",
"ts-lint": "^4.5.1",
@ -99,12 +100,20 @@
"webpack-notifier": "^1.5.0"
},
"jest": {
"globals": {
"globalConfig": {
"NODE_ENV": "development",
"TOS_URL": "https://farmbot.io/tos/",
"LONG_REVISION": "------------",
"SHORT_REVISION": "--------"
}
},
"moduleNameMapper": {
"^.*\\.scss$": "<rootDir>/src/__test_support__/stub.ts"
"^.*\\.scss$": "<rootDir>/webpack/__test_support__/stub.ts"
},
"setupFiles": [
"./src/unmock_i18next.ts",
"./src/__test_support__/localstorage.js"
"./webpack/unmock_i18next.ts",
"./webpack/__test_support__/localstorage.js"
],
"transform": {
".(ts|tsx)": "<rootDir>/node_modules/ts-jest/preprocessor.js"
@ -118,7 +127,7 @@
"mapCoverage": true,
"collectCoverage": true,
"collectCoverageFrom": [
"src/**/*.{ts,tsx}"
"webpack/**/*.{ts,tsx}"
],
"coverageReporters": [
"html",

View file

@ -1,89 +1,89 @@
{
"url": "https://api.github.com/repos/FarmBot/farmbot_os/releases/7325676",
"assets_url": "https://api.github.com/repos/FarmBot/farmbot_os/releases/7325676/assets",
"upload_url": "https://uploads.github.com/repos/FarmBot/farmbot_os/releases/7325676/assets{?name,label}",
"html_url": "https://github.com/FarmBot/farmbot_os/releases/tag/5.0.0",
"id": 7325676,
"tag_name": "5.0.0",
"url": "https://api.github.com/repos/FarmBot/farmbot_os/releases/7337459",
"assets_url": "https://api.github.com/repos/FarmBot/farmbot_os/releases/7337459/assets",
"upload_url": "https://uploads.github.com/repos/FarmBot/farmbot_os/releases/7337459/assets{?name,label}",
"html_url": "https://github.com/FarmBot/farmbot_os/releases/tag/v5.0.1",
"id": 7337459,
"tag_name": "v5.0.1",
"target_commitish": "master",
"name": "Version 5.0.0 (Fantastic Fern)",
"name": "Version 5.0.1 (Fantastic Fern)",
"draft": false,
"author": {
"login": "gabrielburnworth",
"id": 12681652,
"avatar_url": "https://avatars2.githubusercontent.com/u/12681652?v=4",
"login": "ConnorRigby",
"id": 21150830,
"avatar_url": "https://avatars3.githubusercontent.com/u/21150830?v=4",
"gravatar_id": "",
"url": "https://api.github.com/users/gabrielburnworth",
"html_url": "https://github.com/gabrielburnworth",
"followers_url": "https://api.github.com/users/gabrielburnworth/followers",
"following_url": "https://api.github.com/users/gabrielburnworth/following{/other_user}",
"gists_url": "https://api.github.com/users/gabrielburnworth/gists{/gist_id}",
"starred_url": "https://api.github.com/users/gabrielburnworth/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/gabrielburnworth/subscriptions",
"organizations_url": "https://api.github.com/users/gabrielburnworth/orgs",
"repos_url": "https://api.github.com/users/gabrielburnworth/repos",
"events_url": "https://api.github.com/users/gabrielburnworth/events{/privacy}",
"received_events_url": "https://api.github.com/users/gabrielburnworth/received_events",
"url": "https://api.github.com/users/ConnorRigby",
"html_url": "https://github.com/ConnorRigby",
"followers_url": "https://api.github.com/users/ConnorRigby/followers",
"following_url": "https://api.github.com/users/ConnorRigby/following{/other_user}",
"gists_url": "https://api.github.com/users/ConnorRigby/gists{/gist_id}",
"starred_url": "https://api.github.com/users/ConnorRigby/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/ConnorRigby/subscriptions",
"organizations_url": "https://api.github.com/users/ConnorRigby/orgs",
"repos_url": "https://api.github.com/users/ConnorRigby/repos",
"events_url": "https://api.github.com/users/ConnorRigby/events{/privacy}",
"received_events_url": "https://api.github.com/users/ConnorRigby/received_events",
"type": "User",
"site_admin": false
},
"prerelease": false,
"created_at": "2017-08-08T22:25:25Z",
"published_at": "2017-08-08T23:15:05Z",
"created_at": "2017-08-09T18:17:00Z",
"published_at": "2017-08-09T18:46:05Z",
"assets": [
{
"url": "https://api.github.com/repos/FarmBot/farmbot_os/releases/assets/4532825",
"id": 4532825,
"name": "farmbot-rpi3-5.0.0.fw",
"url": "https://api.github.com/repos/FarmBot/farmbot_os/releases/assets/4539629",
"id": 4539629,
"name": "farmbot-rpi3-5.0.1.fw",
"label": null,
"uploader": {
"login": "gabrielburnworth",
"id": 12681652,
"avatar_url": "https://avatars2.githubusercontent.com/u/12681652?v=4",
"login": "ConnorRigby",
"id": 21150830,
"avatar_url": "https://avatars3.githubusercontent.com/u/21150830?v=4",
"gravatar_id": "",
"url": "https://api.github.com/users/gabrielburnworth",
"html_url": "https://github.com/gabrielburnworth",
"followers_url": "https://api.github.com/users/gabrielburnworth/followers",
"following_url": "https://api.github.com/users/gabrielburnworth/following{/other_user}",
"gists_url": "https://api.github.com/users/gabrielburnworth/gists{/gist_id}",
"starred_url": "https://api.github.com/users/gabrielburnworth/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/gabrielburnworth/subscriptions",
"organizations_url": "https://api.github.com/users/gabrielburnworth/orgs",
"repos_url": "https://api.github.com/users/gabrielburnworth/repos",
"events_url": "https://api.github.com/users/gabrielburnworth/events{/privacy}",
"received_events_url": "https://api.github.com/users/gabrielburnworth/received_events",
"url": "https://api.github.com/users/ConnorRigby",
"html_url": "https://github.com/ConnorRigby",
"followers_url": "https://api.github.com/users/ConnorRigby/followers",
"following_url": "https://api.github.com/users/ConnorRigby/following{/other_user}",
"gists_url": "https://api.github.com/users/ConnorRigby/gists{/gist_id}",
"starred_url": "https://api.github.com/users/ConnorRigby/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/ConnorRigby/subscriptions",
"organizations_url": "https://api.github.com/users/ConnorRigby/orgs",
"repos_url": "https://api.github.com/users/ConnorRigby/repos",
"events_url": "https://api.github.com/users/ConnorRigby/events{/privacy}",
"received_events_url": "https://api.github.com/users/ConnorRigby/received_events",
"type": "User",
"site_admin": false
},
"content_type": "application/octet-stream",
"state": "uploaded",
"size": 55494480,
"size": 55493131,
"download_count": 0,
"created_at": "2017-08-08T23:08:36Z",
"updated_at": "2017-08-08T23:10:13Z",
"browser_download_url": "https://github.com/FarmBot/farmbot_os/releases/download/5.0.0/farmbot-rpi3-5.0.0.fw"
"created_at": "2017-08-09T18:32:47Z",
"updated_at": "2017-08-09T18:37:42Z",
"browser_download_url": "https://github.com/FarmBot/farmbot_os/releases/download/v5.0.1/farmbot-rpi3-5.0.1.fw"
},
{
"url": "https://api.github.com/repos/FarmBot/farmbot_os/releases/assets/4532823",
"id": 4532823,
"name": "farmbot-rpi3-5.0.0.img",
"url": "https://api.github.com/repos/FarmBot/farmbot_os/releases/assets/4539630",
"id": 4539630,
"name": "farmbot-rpi3-5.0.1.img",
"label": null,
"uploader": {
"login": "gabrielburnworth",
"id": 12681652,
"avatar_url": "https://avatars2.githubusercontent.com/u/12681652?v=4",
"login": "ConnorRigby",
"id": 21150830,
"avatar_url": "https://avatars3.githubusercontent.com/u/21150830?v=4",
"gravatar_id": "",
"url": "https://api.github.com/users/gabrielburnworth",
"html_url": "https://github.com/gabrielburnworth",
"followers_url": "https://api.github.com/users/gabrielburnworth/followers",
"following_url": "https://api.github.com/users/gabrielburnworth/following{/other_user}",
"gists_url": "https://api.github.com/users/gabrielburnworth/gists{/gist_id}",
"starred_url": "https://api.github.com/users/gabrielburnworth/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/gabrielburnworth/subscriptions",
"organizations_url": "https://api.github.com/users/gabrielburnworth/orgs",
"repos_url": "https://api.github.com/users/gabrielburnworth/repos",
"events_url": "https://api.github.com/users/gabrielburnworth/events{/privacy}",
"received_events_url": "https://api.github.com/users/gabrielburnworth/received_events",
"url": "https://api.github.com/users/ConnorRigby",
"html_url": "https://github.com/ConnorRigby",
"followers_url": "https://api.github.com/users/ConnorRigby/followers",
"following_url": "https://api.github.com/users/ConnorRigby/following{/other_user}",
"gists_url": "https://api.github.com/users/ConnorRigby/gists{/gist_id}",
"starred_url": "https://api.github.com/users/ConnorRigby/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/ConnorRigby/subscriptions",
"organizations_url": "https://api.github.com/users/ConnorRigby/orgs",
"repos_url": "https://api.github.com/users/ConnorRigby/repos",
"events_url": "https://api.github.com/users/ConnorRigby/events{/privacy}",
"received_events_url": "https://api.github.com/users/ConnorRigby/received_events",
"type": "User",
"site_admin": false
},
@ -91,44 +91,44 @@
"state": "uploaded",
"size": 343977472,
"download_count": 0,
"created_at": "2017-08-08T23:08:36Z",
"updated_at": "2017-08-08T23:09:55Z",
"browser_download_url": "https://github.com/FarmBot/farmbot_os/releases/download/5.0.0/farmbot-rpi3-5.0.0.img"
"created_at": "2017-08-09T18:32:47Z",
"updated_at": "2017-08-09T18:45:54Z",
"browser_download_url": "https://github.com/FarmBot/farmbot_os/releases/download/v5.0.1/farmbot-rpi3-5.0.1.img"
},
{
"url": "https://api.github.com/repos/FarmBot/farmbot_os/releases/assets/4532824",
"id": 4532824,
"name": "farmbot.rootfs-rpi3-5.0.0.tar.gz",
"url": "https://api.github.com/repos/FarmBot/farmbot_os/releases/assets/4539628",
"id": 4539628,
"name": "farmbot.rootfs-rpi3-5.0.1.tar.gz",
"label": null,
"uploader": {
"login": "gabrielburnworth",
"id": 12681652,
"avatar_url": "https://avatars2.githubusercontent.com/u/12681652?v=4",
"login": "ConnorRigby",
"id": 21150830,
"avatar_url": "https://avatars3.githubusercontent.com/u/21150830?v=4",
"gravatar_id": "",
"url": "https://api.github.com/users/gabrielburnworth",
"html_url": "https://github.com/gabrielburnworth",
"followers_url": "https://api.github.com/users/gabrielburnworth/followers",
"following_url": "https://api.github.com/users/gabrielburnworth/following{/other_user}",
"gists_url": "https://api.github.com/users/gabrielburnworth/gists{/gist_id}",
"starred_url": "https://api.github.com/users/gabrielburnworth/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/gabrielburnworth/subscriptions",
"organizations_url": "https://api.github.com/users/gabrielburnworth/orgs",
"repos_url": "https://api.github.com/users/gabrielburnworth/repos",
"events_url": "https://api.github.com/users/gabrielburnworth/events{/privacy}",
"received_events_url": "https://api.github.com/users/gabrielburnworth/received_events",
"url": "https://api.github.com/users/ConnorRigby",
"html_url": "https://github.com/ConnorRigby",
"followers_url": "https://api.github.com/users/ConnorRigby/followers",
"following_url": "https://api.github.com/users/ConnorRigby/following{/other_user}",
"gists_url": "https://api.github.com/users/ConnorRigby/gists{/gist_id}",
"starred_url": "https://api.github.com/users/ConnorRigby/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/ConnorRigby/subscriptions",
"organizations_url": "https://api.github.com/users/ConnorRigby/orgs",
"repos_url": "https://api.github.com/users/ConnorRigby/repos",
"events_url": "https://api.github.com/users/ConnorRigby/events{/privacy}",
"received_events_url": "https://api.github.com/users/ConnorRigby/received_events",
"type": "User",
"site_admin": false
},
"content_type": "application/gzip",
"state": "uploaded",
"size": 155489434,
"size": 155452506,
"download_count": 0,
"created_at": "2017-08-08T23:08:36Z",
"updated_at": "2017-08-08T23:10:08Z",
"browser_download_url": "https://github.com/FarmBot/farmbot_os/releases/download/5.0.0/farmbot.rootfs-rpi3-5.0.0.tar.gz"
"created_at": "2017-08-09T18:32:46Z",
"updated_at": "2017-08-09T18:36:25Z",
"browser_download_url": "https://github.com/FarmBot/farmbot_os/releases/download/v5.0.1/farmbot.rootfs-rpi3-5.0.1.tar.gz"
}
],
"tarball_url": "https://api.github.com/repos/FarmBot/farmbot_os/tarball/5.0.0",
"zipball_url": "https://api.github.com/repos/FarmBot/farmbot_os/zipball/5.0.0",
"body": ""
"tarball_url": "https://api.github.com/repos/FarmBot/farmbot_os/tarball/v5.0.1",
"zipball_url": "https://api.github.com/repos/FarmBot/farmbot_os/zipball/v5.0.1",
"body": "* Fix not being able to move to a point in some cases.\r\n* Fix a sub sequence never returning. \r\n* add `busy` flag to the bot's state. "
}

Binary file not shown.

Binary file not shown.

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -1,35 +0,0 @@
/// <reference path="../typings/index.d.ts" />
import { RootComponent } from "./routes";
import { store } from "./redux/store";
import { ready } from "./config/actions";
import { detectLanguage } from "./i18n";
import * as i18next from "i18next";
import "./npm_addons";
import { stopIE, attachToRoot, shortRevision, hardRefresh } from "./util";
stopIE();
hardRefresh();
interface DebugStuff {
ip_address: string;
}
let r = shortRevision();
console.log(r);
/** For external device debugging purposes
* See https://github.com/FarmBot/farmbot-web-frontend for details. */
let hmm = process.env.CONFIG as DebugStuff | undefined;
if (hmm
&& hmm.ip_address
&& process.env.NODE_ENV !== "production") {
let ip = hmm.ip_address;
let script = document.createElement("script");
script.src = `http://${ip}:8081/target/target-script-min.js#anonymous`;
document.body.appendChild(script);
}
detectLanguage().then((config) => {
i18next.init(config, (err, t) => {
attachToRoot(RootComponent, { store });
store.dispatch(ready());
});
});

View file

@ -1,10 +0,0 @@
// This module dynamically loads an NPM module of the author's choosing.
// In the case of FarmBot, Inc (the "public servers"), we use this file
// to load non-opensource tools, such as RollBar error reporting.
declare var SHORT_REVISION: string;
// Global variable so that the NPM_ADDON knows the version number of the FE.
SHORT_REVISION = process.env.SHORT_REVISION || "";
if (process.env.NPM_ADDON) {
require(process.env.NPM_ADDON as string);
}

View file

@ -1,18 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta content="width=device-width, initial-scale=1" name="viewport">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.4.0/css/font-awesome.min.css">
<link href="https://fonts.googleapis.com/css?family=Roboto:300,300i,400,400i,700,700i" rel="stylesheet"> {{#if isProd}}
<link rel="stylesheet" href="/dist/styles.css"> {{/if}}
</head>
<body>
{{#each wantedAssets}}
<script type="text/javascript" src="{{name}}"></script>
{{/each}}
</body>
</html>

View file

@ -1,21 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta content="width=device-width, initial-scale=1" name="viewport">
<title>FarmBot</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.4.0/css/font-awesome.min.css">
<link rel="stylesheet" href="/dist/styles.css">
</head>
<body>
{{#each wantedAssets}}
<script type="text/javascript" src="{{name}}"></script>
{{/each}}
</body>
</html>

View file

@ -1,17 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta content="width=device-width, initial-scale=1" name="viewport">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.4.0/css/font-awesome.min.css"> {{#if isProd}}
<link rel="stylesheet" href="/dist/styles.css"> {{/if}}
</head>
<body>
{{#each wantedAssets}}
<script type="text/javascript" src="{{name}}"></script>
{{/each}}
</body>
</html>

View file

@ -1,17 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta content="width=device-width, initial-scale=1" name="viewport">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.4.0/css/font-awesome.min.css"> {{#if isProd}}
<link rel="stylesheet" href="/dist/styles.css"> {{/if}}
</head>
<body>
{{#each wantedAssets}}
<script type="text/javascript" src="{{name}}"></script>
{{/each}}
</body>
</html>

View file

@ -1,15 +0,0 @@
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<p>Verifying email address...</p>
{{#each wantedAssets}}
<script type="text/javascript" src="{{name}}"></script>
{{/each}}
</body>
</html>

View file

@ -1,70 +0,0 @@
var merge = require("lodash").merge;
var hbs = require("handlebars");
var fs = require("fs");
function FarmBotRenderer(options) {
this.options = merge({}, {
path: "/",
filename: "index.html",
outputPath: "/",
isProd: false,
include: "bundle"
}, options);
}
FarmBotRenderer.prototype = {
constructor: FarmBotRenderer,
apply: function (compiler) {
var self = this;
compiler.plugin("after-emit", function (compilation, callback) {
var options = compiler.options;
var stats = compilation.getStats().toJson({
hash: false,
publicPath: true,
assets: true,
chunks: false,
modules: false,
source: false,
errorDetails: false,
timings: false
});
var wantedAssets = [];
stats
.assets
.map(function (asset) {
var name = asset.name;
var isIncluded = asset.name.includes(self.options.include);
var notMapFile = !asset.name.endsWith(".map");
if (isIncluded && notMapFile) {
asset.name = "/" + asset.name.replace("../", ""); // Unacceptable. :(
wantedAssets.push(asset);
}
});
var finalPath = self.options.path;
console.dir(self.options);
fs.readFile(finalPath, "utf-8", function (err, source) {
var data = self.options;
data.wantedAssets = wantedAssets;
var template = hbs.compile(source);
var html = template(data);
var outputDest = self.options.outputPath + "/" + self.options.filename;
fs.writeFile(outputDest, html, function (err, data) {
if (err) { console.error("error in writing file", err); }
});
});
callback();
})
}
}
module.exports = FarmBotRenderer;

View file

@ -1,128 +0,0 @@
var path = require("path");
var webpack = require("webpack");
var exec = require("child_process").exec;
var execSync = require("child_process").execSync;
var webpack = require("webpack");
var fs = require("fs");
var FarmBotRenderer = require("./farmBotRenderer");
var VERSION = JSON.stringify(process.env.BUILT_AT
|| process.env.HEROKU_SLUG_COMMIT
|| "NONE");
// WEBPACK BASE CONFIG
exec("mkdir -p public/app");
exec("echo -n > public/app/index.html");
exec("touch public/app/index.html");
exec("touch public/app/index.html");
exec("rm -rf public/dist");
exec("rm -rf public/*.eot");
var isProd = !!(global.WEBPACK_ENV === "production");
module.exports = function () {
return {
entry: {
"bundle": path.resolve(__dirname, "../src/entry.tsx"),
"front_page": "./src/front_page/index.tsx",
"verification": "./src/verification.ts",
"password_reset": "./src/password_reset/index.tsx",
"tos_update": "./src/tos_update/index.tsx"
},
output: {
path: path.resolve(__dirname, "../public"),
libraryTarget: "umd",
publicPath: "/",
devtoolLineToLine: true
},
devtool: "eval",
// Allows imports without file extensions.
resolve: {
extensions: [".js", ".ts", ".tsx", ".css", ".scss", ".json", ".hbs"]
},
// Shared loaders for prod and dev.
module: {
rules: [
{ test: /\.tsx?$/, use: "ts-loader" },
{
test: [/\.woff$/, /\.woff2$/, /\.ttf$/],
use: "url-loader"
},
{
test: [/\.eot$/, /\.svg(\?v=\d+\.\d+\.\d+)?$/],
use: "file-loader"
}
]
},
// Shared plugins for prod and dev.
plugins: [
new webpack.DefinePlugin({
"process.env.SHORT_REVISION": VERSION
}),
// FarmBot Inc related.
new webpack.DefinePlugin({
"process.env.NPM_ADDON": JSON.stringify(
process.env.NPM_ADDON || false).toString()
}),
// Conditionally add "terms of service"
// Eg: Servers run by FarmBot, Inc.
new webpack.DefinePlugin({
"process.env.TOS_URL": JSON
.stringify(process.env.TOS_URL || false).toString()
}),
// Conditionally add privacy policy.
// Eg: Servers run by FarmBot, Inc.
new webpack.DefinePlugin({
"process.env.PRIV_URL": JSON
.stringify(process.env.PRIV_URL || false).toString()
}),
new FarmBotRenderer({
isProd: isProd,
path: path.resolve(__dirname, "../src/static/app_index.hbs"),
filename: "index.html",
outputPath: path.resolve(__dirname, "../public/app/")
}),
new FarmBotRenderer({
isProd: isProd,
path: path.resolve(__dirname, "../src/static/front_page.hbs"),
filename: "index.html",
outputPath: path.resolve(__dirname, "../public/"),
include: "front_page"
}),
new FarmBotRenderer({
isProd: isProd,
path: path.resolve(__dirname, "../src/static/verification.hbs"),
filename: "verify.html",
outputPath: path.resolve(__dirname, "../public/"),
include: "verification"
}),
new FarmBotRenderer({
isProd: isProd,
path: path.resolve(__dirname, "../src/static/password_reset.hbs"),
filename: "password_reset.html",
outputPath: path.resolve(__dirname, "../public/"),
include: "password_reset"
}),
new FarmBotRenderer({
isProd: isProd,
path: path.resolve(__dirname, "../src/static/tos_update.hbs"),
filename: "tos_update.html",
outputPath: path.resolve(__dirname, "../public/"),
include: "tos_update"
})
],
// Webpack Dev Server.
devServer: {
historyApiFallback: {
rewrites: [
{ from: /\/app\//, to: "/app/index.html" },
{ from: /password_reset/, to: "password_reset.html" },
]
}
}
}
}

View file

@ -1,52 +0,0 @@
var webpack = require("webpack");
var fs = require("fs");
var path = require("path");
var VERSION = JSON.stringify(process.env.BUILT_AT
|| process.env.HEROKU_SLUG_COMMIT
|| "NONE");
var WebpackNotifierPlugin = require("webpack-notifier");
var generateConfig = require("./webpack.config.base");
var exec = require("child_process").execSync;
var configPath = path.resolve(__dirname, "../src/config.json");
var FarmBotRenderer = require("./farmBotRenderer");
global.WEBPACK_ENV = "development";
c = function () {
var conf = generateConfig();
conf.output.filename = "dist/[name].js";
conf
.module
.rules
.push({
test: [/\.scss$/, /\.css$/],
use: ["style-loader", "css-loader", "sass-loader"]
});
conf
.plugins
.push(new webpack.DefinePlugin({
"process.env.NODE_ENV": JSON.stringify("development")
}));
conf
.plugins
.push(new WebpackNotifierPlugin({
title: "Webpack",
excludeWarnings: false
}));
if (fs.existsSync(configPath)) {
var config = require(configPath);
conf.plugins.push(new webpack.DefinePlugin({
"process.env.CONFIG": JSON.stringify(config)
}));
}
return conf;
};
module.exports = c();

View file

@ -1,61 +0,0 @@
global.WEBPACK_ENV = "production";
var VERSION = JSON.stringify(process.env.BUILT_AT
|| process.env.HEROKU_SLUG_COMMIT
|| "NONE");
var webpack = require("webpack");
var exec = require("child_process").execSync;
var path = require("path");
var ExtractTextPlugin = require("extract-text-webpack-plugin");
var OptimizeCssAssetsPlugin = require("optimize-css-assets-webpack-plugin");
var UglifyJsPlugin = require("webpack-uglify-js-plugin");
var generateConfig = require("./webpack.config.base");
var FarmBotRenderer = require("./farmBotRenderer");
c = function () {
var conf = generateConfig();
conf.module.rules.push({
test: [/\.scss$/, /\.css$/],
loader: ExtractTextPlugin.extract("css-loader!sass-loader")
});
conf.output.filename = "dist/[name].[chunkhash].js";
// PLUGINS:
[
new webpack.DefinePlugin({
"process.env.NODE_ENV": JSON.stringify("production")
}),
new ExtractTextPlugin({
// Temporary hotfix for some issues on staging.
// - RC 12 MAY 17
filename: "dist/styles.css",
// filename: "dist/styles.[chunkhash].css",
disable: false,
allChunks: true
}),
new OptimizeCssAssetsPlugin({
assetNameRegExp: /\.css$/g,
cssProcessor: require("cssnano"),
cssProcessorOptions: { discardComments: { removeAll: true } },
canPrint: true
}),
new UglifyJsPlugin({
cacheFolder: path.resolve(__dirname, "../public/dist/cached_uglify/"),
debug: true,
minimize: true,
sourceMap: true,
screw_ie8: true,
output: { comments: false },
compressor: { warnings: false }
})
].forEach(function (x) { conf.plugins.push(x) });
return conf;
}
module.exports = c();

View file

@ -19,7 +19,8 @@
},
"exclude": [
"node_modules",
"typings"
"typings",
"public"
],
"compileOnSave": false,
"buildOnSave": false

3
typings/index.d.ts vendored
View file

@ -1 +1,4 @@
/// <reference path="react-redux.d.ts" />
/** This contains all of the global ENV vars passed from server => client.
* Previously was `process.env.XYZ`. */
declare var globalConfig: { [k: string]: string };

View file

@ -21,7 +21,7 @@ export class API {
// ATTEMPT 1: Most devs running a webpack server on localhost
// run the API on port 3000.
if (location.port === "8080") { return "3000"; }
if (location.port === "3808") { return "3000"; }
// ATTEMPT 2: If they provide an explicit port (as in ://localhost:3000)
// use that port.

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