Merge pull request #403 from RickCarlino/monday
Documentation, FBJS updates, maintenance
This commit is contained in:
commit
89e9200ac2
|
@ -3,7 +3,9 @@
|
|||
If you want to run a server on a LAN for personal use, this is the easiest and cheapest option.
|
||||
|
||||
**Simplicity:** :heart::heart::heart:
|
||||
|
||||
**Reliability:** :broken_heart:
|
||||
|
||||
**Affordability:** :heart::heart::heart:
|
||||
|
||||
1. Follow the [developer setup guide](https://github.com/FarmBot/Farmbot-Web-App#developer-setup).
|
||||
|
@ -13,10 +15,12 @@ If you want to run a server on a LAN for personal use, this is the easiest and c
|
|||
**DEPRECATION NOTICE / PULL REQUESTS WELCOME**: We no longer deploy the server using Dokku. The instructions related to MariaDB are out of date (we use Postgresql now). **If you wish to use Dokku** we would be happy to help you along the way. Please raise an issue if you would like to help with updating the deployment docs.
|
||||
|
||||
**Simplicity:** :broken_heart:
|
||||
|
||||
**Reliability:** :heart::heart:
|
||||
|
||||
**Affordability:** :heart::heart:
|
||||
|
||||
0. Provision a fresh Ubuntu 16 server. We recommend DigitalOcean's "Ubuntu 16 docker" image. Make sure you have at least 1gb of memory. **Don't use the Dokku image that Digital Ocean provides**. It is out of date and will not support this application.
|
||||
0. Provision a fresh Ubuntu 16 server. We recommend DigitalOcean's "Ubuntu 16 Docker" image. Make sure you have at least 1gb of memory. **Don't use the Dokku image that Digital Ocean provides**. It is out of date and will not support this application.
|
||||
1. [Install the latest version of Dokku onto the machine](https://github.com/dokku/dokku#installing)
|
||||
2. Visit the server's URL in a browser. Follow the directions on screen to setup Dokku.
|
||||
3. `git remote add my_server dokku@my_server_name:my_app_name`
|
||||
|
@ -42,7 +46,9 @@ If you want to run a server on a LAN for personal use, this is the easiest and c
|
|||
# Deployment Using Heroku (good)
|
||||
|
||||
**Simplicity:** :heart::heart::heart::heart:
|
||||
|
||||
**Reliability:** :heart::heart::heart::heart:
|
||||
|
||||
**Affordability:** :broken_heart:
|
||||
|
||||
1. Deploy as you would normally [deploy to Heroku](https://devcenter.heroku.com/articles/getting-started-with-rails4#deploy-your-application-to-heroku)
|
||||
|
@ -62,7 +68,7 @@ Wait until you see this message and **DO NOT CONTINUE**:
|
|||
|
||||
```
|
||||
Make sure your web server displays the following content at
|
||||
http://yourdomain.io/.well-known/acme-challenge/SOME-LONG-URL before continuing:
|
||||
http://YOUR_DOMAIN/.well-known/acme-challenge/SOME-LONG-URL before continuing:
|
||||
|
||||
ya6k1edW38z-CopyThisValueNow!!!
|
||||
|
||||
|
@ -77,7 +83,7 @@ You should see this:
|
|||
```
|
||||
IMPORTANT NOTES:
|
||||
- Congratulations! Your certificate and chain have been saved at
|
||||
/etc/letsencrypt/live/yourdomain.io/fullchain.pem
|
||||
/etc/letsencrypt/live/YOUR_DOMAIN/fullchain.pem
|
||||
```
|
||||
|
||||
**Heroku Users**: Run the following snippet to submit the certs to Heroku:
|
||||
|
@ -85,19 +91,16 @@ IMPORTANT NOTES:
|
|||
**First time:**
|
||||
|
||||
```
|
||||
heroku certs:add /etc/letsencrypt/live/yourdomain.io/fullchain.pem /etc/letsencrypt/live/yourdomain.io/privkey.pem
|
||||
heroku certs:add /etc/letsencrypt/live/YOUR_DOMAIN/fullchain.pem /etc/letsencrypt/live/YOUR_DOMAIN/privkey.pem
|
||||
```
|
||||
|
||||
**After that:**
|
||||
|
||||
```
|
||||
sudo heroku certs:update /etc/letsencrypt/live/staging.farmbot.io/fullchain.pem /etc/letsencrypt/live/staging.farmbot.io/privkey.pem --app=farmbot-staging
|
||||
sudo heroku certs:update /etc/letsencrypt/live/YOUR_DOMAIN/fullchain.pem /etc/letsencrypt/live/YOUR_DOMAIN/privkey.pem --app=HEROKU_APP_NAME
|
||||
```
|
||||
Heroku will then give you instructions on which DNS records you must create.
|
||||
|
||||
**Dokku Users**: FarmBot, Inc. no longer uses Dokku. As such, our ability to troubleshoot problems is limited.
|
||||
Please [raise an issue](https://github.com/FarmBot/Farmbot-Web-App/issues/new) to receive community support.
|
||||
|
||||
# Renew SSL Certificates
|
||||
|
||||
1. Run `sudo certbot certonly --manual -d YOUR_DOMAIN_HERE`
|
||||
|
@ -106,7 +109,7 @@ Please [raise an issue](https://github.com/FarmBot/Farmbot-Web-App/issues/new) t
|
|||
```
|
||||
|
||||
Make sure your web server displays the following content at
|
||||
http://staging.farmbot.io/.well-known/acme-challenge/<CODE_HERE> before continuing:
|
||||
http://YOUR_DOMAIN/.well-known/acme-challenge/<CODE_HERE> before continuing:
|
||||
|
||||
3tFAi5c7tJK-YOURS\_WILL\_BE\_DIFFERENT
|
||||
|
||||
|
@ -119,7 +122,7 @@ heroku config:set ACME_SECRET=THAT_BIG_CODE_FROM_PREVIOUS_STEP --app=YOUR_APP_HE
|
|||
|
||||
```
|
||||
- Congratulations! Your certificate and chain have been saved at
|
||||
/etc/letsencrypt/live/staging.farmbot.io/fullchain.pem.
|
||||
/etc/letsencrypt/live/YOUR_DOMAIN/fullchain.pem.
|
||||
```
|
||||
|
||||
4. (Heroku users only) `sudo heroku certs:update /etc/letsencrypt/live/YOUR_DOMAIN_HERE/fullchain.pem /etc/letsencrypt/live/YOUR_DOMAIN_HERE/privkey.pem`
|
||||
|
|
|
@ -14,7 +14,7 @@ If you are a developer interested in contributing or would like to provision you
|
|||
|
||||
# Q: What is the Farmbot Web App?
|
||||
|
||||
This repo contains the web based user interface and RESTful JSON API for Farmbot. This includes things like storage of user data, plant data, authorization tokens and a variety of other resources.
|
||||
This repo contains FarmBot's web based user interface, as well as a RESTful JSON API. The API stores data such as user account information, plant data, authorization tokens and a variety of other resources.
|
||||
|
||||
The key responsibility of the API is *information and permissions management*. This should not be confused with device control, which is done via [MQTT](https://github.com/FarmBot/mqtt-gateway).
|
||||
|
||||
|
@ -40,13 +40,13 @@ You will need the following:
|
|||
0. `cd Farmbot-Web-App`
|
||||
0. `bundle install`
|
||||
0. `yarn install`
|
||||
0. **MOST IMPORTANT STEP**. Copy `config/database.example.yml` to `config/database.yml`. In GNU/Linux or Mac: `mv config/database.example.yml config/database.yml`. **Please read the instructions inside the file. Replace the example values provided with real world values.**
|
||||
0. **MOST IMPORTANT STEP**. Copy `config/database.example.yml` to `config/database.yml` via `mv config/database.example.yml config/database.yml`. **Please read the instructions inside the file. Replace the example values provided with real world values.**
|
||||
0. Give permission to create a database*
|
||||
0. `rake db:create:all db:migrate db:seed`
|
||||
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:3808](http://localhost:3808). The application is now ready for use.
|
||||
0. Open [localhost:3000](http://localhost:3000).
|
||||
0. Although you can now try things out in your browser, you will still need to [provision an MQTT server](https://github.com/FarmBot/mqtt-gateway) before you can control a FarmBot.
|
||||
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:
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
class DashboardController < ApplicationController
|
||||
ACME_SECRET = ENV["ACME_SECRET"]
|
||||
NO_ENV = "NO ACME_SECRET SET"
|
||||
ACME_SECRET = ENV["ACME_SECRET"] || "NO ACME_SECRET SET"
|
||||
LONG_REVISION = ENV["BUILT_AT"] || ENV["HEROKU_SLUG_COMMIT"] || "NONE"
|
||||
$FRONTEND_SHARED_DATA = { NODE_ENV: Rails.env || "development",
|
||||
TOS_URL: ENV.fetch("TOS_URL", ""),
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
# THIS SHOULD NOT EXIST.
|
||||
class ToolBay < ApplicationRecord
|
||||
belongs_to :device
|
||||
has_many :tool_slots
|
||||
end
|
|
@ -3,11 +3,7 @@
|
|||
# etc.
|
||||
class ToolSlot < ApplicationRecord
|
||||
belongs_to :tool
|
||||
belongs_to :tool_bay # <== DELETE THIS ASAP!!!!
|
||||
has_one :point, as: :pointer#, dependent: :destroy
|
||||
# has_many :sequence_dependencies, dependent: :destroy, as: :dependency
|
||||
validates_uniqueness_of :tool,
|
||||
allow_blank: true,
|
||||
allow_nil: true,
|
||||
message: "already in use by another tool slot"
|
||||
has_one :point, as: :pointer
|
||||
IN_USE = "already in use by another tool slot"
|
||||
validates_uniqueness_of :tool, allow_blank: true, allow_nil: true, message: IN_USE
|
||||
end
|
||||
|
|
|
@ -10,6 +10,7 @@ window.globalConfig = <%= raw($FRONTEND_SHARED_DATA) %> // SEE COMMENTS!;
|
|||
<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>
|
||||
<% if Rails.env.development? %>
|
||||
<script async src="http://<%= ENV["API_HOST"] %>:8081/target/target-script-min.js#anonymous">
|
||||
</script>
|
||||
<% end %>
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
FarmBot::Application.routes.draw do
|
||||
|
||||
namespace :api, defaults: {format: :json}, constraints: { format: 'json' } do
|
||||
resources :tool_bays, only: [:index]
|
||||
resources :images, only: [:create, :destroy, :show, :index]
|
||||
resources :regimens, only: [:create, :destroy, :index, :update]
|
||||
resources :peripherals, only: [:create, :destroy, :index, :update]
|
||||
|
@ -40,16 +39,10 @@ FarmBot::Application.routes.draw do
|
|||
# =======================================================================
|
||||
# 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 "/" => '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
|
||||
get "/verify" => 'dashboard#verify', as: :verify
|
||||
end
|
||||
|
|
|
@ -1,115 +0,0 @@
|
|||
class CreateEverything < ActiveRecord::Migration[4.2]
|
||||
def self.up
|
||||
execute """
|
||||
ALTER TABLE schedules
|
||||
ADD CONSTRAINT check_schedules_time_unit_naming
|
||||
CHECK (time_unit IN (minutely hourly daily weekly monthly yearly) )
|
||||
"""
|
||||
|
||||
execute """
|
||||
ALTER TABLE regimens
|
||||
ADD CONSTRAINT check_regimens_color_naming
|
||||
CHECK (color IN (blue green yellow orange purple pink gray red) )
|
||||
"""
|
||||
end
|
||||
|
||||
def self.down
|
||||
execute """
|
||||
ALTER TABLE schedules
|
||||
DROP CONSTRAINT check_schedules_time_unit_naming
|
||||
"""
|
||||
|
||||
execute """
|
||||
ALTER TABLE regimens
|
||||
DROP CONSTRAINT check_regimens_color_naming
|
||||
"""
|
||||
end
|
||||
|
||||
def change
|
||||
create_table :devices do |t|
|
||||
t.integer :planting_area_id
|
||||
t.string :uuid
|
||||
t.string :name
|
||||
end
|
||||
|
||||
create_table :plants do |t|
|
||||
t.integer :device_id
|
||||
t.integer :planting_area_id
|
||||
t.string :name
|
||||
t.string :img_url
|
||||
t.string :icon_url
|
||||
t.string :openfarm_slug
|
||||
t.string :x
|
||||
t.string :y
|
||||
t.string :planted_at
|
||||
end
|
||||
|
||||
create_table :planting_areas do |t|
|
||||
t.integer :width
|
||||
t.integer :length
|
||||
t.integer :device_id
|
||||
end
|
||||
|
||||
create_table :regimens do |t|
|
||||
t.string :color
|
||||
t.string :name
|
||||
t.integer :device_id
|
||||
end
|
||||
|
||||
create_table :regimen_items do |t|
|
||||
t.integer :time_offset
|
||||
t.integer :schedule_id
|
||||
t.integer :regimen_id
|
||||
t.integer :sequence_id
|
||||
end
|
||||
|
||||
create_table :schedules do |t|
|
||||
t.integer :sequence_id
|
||||
t.integer :device_id
|
||||
t.datetime :start_time
|
||||
t.datetime :end_time
|
||||
t.datetime :next_time
|
||||
t.integer :repeat
|
||||
# minutely hourly daily weekly monthly yearly
|
||||
t.string :time_unit
|
||||
end
|
||||
|
||||
create_table :sequences do |t|
|
||||
t.integer :schedule_id
|
||||
t.integer :device_id
|
||||
t.string :regimen
|
||||
t.string :name
|
||||
t.string :color
|
||||
end
|
||||
|
||||
create_table :steps do |t|
|
||||
t.integer :sequence_id
|
||||
t.string :message_type
|
||||
t.integer :position
|
||||
t.text :command
|
||||
end
|
||||
|
||||
### A single system User on the decision support system.
|
||||
create_table :users do |t|
|
||||
|
||||
t.integer :device_id
|
||||
t.string :name
|
||||
|
||||
t.string :email, null: false, default: ""
|
||||
t.string :encrypted_password, null: false, default: ""
|
||||
t.string :reset_password_token
|
||||
t.datetime :reset_password_sent_at
|
||||
t.datetime :remember_created_at
|
||||
t.integer :sign_in_count, default: 0, null: false
|
||||
t.datetime :current_sign_in_at
|
||||
t.datetime :last_sign_in_at
|
||||
t.string :current_sign_in_ip
|
||||
t.string :last_sign_in_ip
|
||||
t.timestamps null: false
|
||||
end
|
||||
add_index :users, :email, unique: true
|
||||
add_index :users, :reset_password_token, unique: true
|
||||
|
||||
end
|
||||
|
||||
end
|
|
@ -1,9 +0,0 @@
|
|||
class ConvertXYToFloatAndRemoveScheduleIdFromRegimenItem < ActiveRecord::Migration[4.2]
|
||||
def change
|
||||
# Make Plant x/y a float
|
||||
[:x,:y].each do |coord|
|
||||
remove_column :plants, coord
|
||||
add_column :plants, coord, :float, default: 0
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,5 +0,0 @@
|
|||
class MakeRegimenItemOffsetBigger < ActiveRecord::Migration[4.2]
|
||||
def change
|
||||
change_column :regimen_items, :time_offset, :integer, limit: 8
|
||||
end
|
||||
end
|
|
@ -1,5 +0,0 @@
|
|||
class AddWebcamUrlToDevices < ActiveRecord::Migration[4.2]
|
||||
def change
|
||||
add_column :devices, :webcam_url, :string
|
||||
end
|
||||
end
|
|
@ -1,7 +0,0 @@
|
|||
class ConvertPlantedAtToDatetime < ActiveRecord::Migration[4.2]
|
||||
def change
|
||||
# Make Plant planted_at a datetime
|
||||
remove_column :plants, :planted_at
|
||||
add_column :plants, :planted_at, :datetime
|
||||
end
|
||||
end
|
|
@ -1,10 +0,0 @@
|
|||
class CreateStepParams < ActiveRecord::Migration[4.2]
|
||||
def change
|
||||
create_table :step_params do |t|
|
||||
t.string :key
|
||||
t.string :value
|
||||
t.belongs_to :step, index: true, foreign_key: true
|
||||
remove_column :steps, :command, :text
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,6 +0,0 @@
|
|||
class RemoveScheduleIdFromSequence < ActiveRecord::Migration[4.2]
|
||||
def change
|
||||
remove_column :sequences, :schedule_id, :integer
|
||||
remove_column :sequences, :regimen, :string
|
||||
end
|
||||
end
|
|
@ -1,6 +0,0 @@
|
|||
class DropStepsAndStepParams < ActiveRecord::Migration[4.2]
|
||||
def change
|
||||
drop_table :step_params
|
||||
drop_table :steps
|
||||
end
|
||||
end
|
|
@ -1,7 +0,0 @@
|
|||
class AddBodyArgsAndKindToSequence < ActiveRecord::Migration[4.2]
|
||||
def change
|
||||
add_column :sequences, :kind, :string, default: "sequence"
|
||||
add_column :sequences, :args, :text
|
||||
add_column :sequences, :body, :text
|
||||
end
|
||||
end
|
|
@ -1,5 +0,0 @@
|
|||
class RemoveScheduleIdFromRegimenItems < ActiveRecord::Migration[4.2]
|
||||
def change
|
||||
remove_column :regimen_items, :schedule_id, :integer
|
||||
end
|
||||
end
|
|
@ -1,5 +0,0 @@
|
|||
class RemoveUuidFromDevice < ActiveRecord::Migration[4.2]
|
||||
def change
|
||||
remove_column :devices, :uuid, :integer
|
||||
end
|
||||
end
|
|
@ -1,12 +0,0 @@
|
|||
class CreateSequenceDependencies < ActiveRecord::Migration[4.2]
|
||||
def change
|
||||
create_table :sequence_dependencies do |t|
|
||||
t.references :dependency, polymorphic: true
|
||||
t.references :sequence
|
||||
end
|
||||
|
||||
add_index :sequence_dependencies, :dependency_id
|
||||
add_index :sequence_dependencies, :dependency_type
|
||||
add_index :sequence_dependencies, :sequence_id
|
||||
end
|
||||
end
|
|
@ -1,12 +0,0 @@
|
|||
class CreatePeripherals < ActiveRecord::Migration[4.2]
|
||||
def change
|
||||
create_table :peripherals do |t|
|
||||
t.references :device, index: true, foreign_key: true
|
||||
t.integer :pin
|
||||
t.integer :mode
|
||||
t.string :label
|
||||
|
||||
t.timestamps null: false
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,22 +0,0 @@
|
|||
class CreateDelayedJobs < ActiveRecord::Migration[4.2]
|
||||
def self.up
|
||||
create_table :delayed_jobs, force: true do |table|
|
||||
table.integer :priority, default: 0, null: false # Allows some jobs to jump to the front of the queue
|
||||
table.integer :attempts, default: 0, null: false # Provides for retries, but still fail eventually.
|
||||
table.text :handler, null: false # YAML-encoded string of the object that will do work
|
||||
table.text :last_error # reason for last failure (See Note below)
|
||||
table.datetime :run_at # When to run. Could be Time.zone.now for immediately, or sometime in the future.
|
||||
table.datetime :locked_at # Set when a client is working on this object
|
||||
table.datetime :failed_at # Set when all retries have failed (actually, by default, the record is deleted instead)
|
||||
table.string :locked_by # Who is working on this object (if locked)
|
||||
table.string :queue # The name of the queue this job is in
|
||||
table.timestamps null: true
|
||||
end
|
||||
|
||||
add_index :delayed_jobs, [:priority, :run_at], name: "delayed_jobs_priority"
|
||||
end
|
||||
|
||||
def self.down
|
||||
drop_table :delayed_jobs
|
||||
end
|
||||
end
|
|
@ -1,24 +0,0 @@
|
|||
class CreateToolStuff < ActiveRecord::Migration[5.0]
|
||||
def change
|
||||
create_table :tool_bays do |t|
|
||||
t.references :device, foreign_key: true
|
||||
t.string :name
|
||||
t.timestamps
|
||||
end
|
||||
|
||||
create_table :tool_slots do |t|
|
||||
t.references :tool_bay, foreign_key: true
|
||||
t.string :name
|
||||
t.integer :x
|
||||
t.integer :y
|
||||
t.integer :z
|
||||
t.timestamps
|
||||
end
|
||||
|
||||
create_table :tools do |t|
|
||||
t.references :tool_slot, foreign_key: true
|
||||
t.string :name
|
||||
t.timestamps
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,11 +0,0 @@
|
|||
class CreateTokenExpirations < ActiveRecord::Migration[5.0]
|
||||
def change
|
||||
create_table :token_expirations do |t|
|
||||
t.string :sub
|
||||
t.integer :exp
|
||||
t.string :jti
|
||||
|
||||
t.timestamps
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,5 +0,0 @@
|
|||
class AddDeviceIdToTools < ActiveRecord::Migration[5.0]
|
||||
def change
|
||||
add_reference :tools, :device, index: true
|
||||
end
|
||||
end
|
|
@ -1,14 +0,0 @@
|
|||
class CreateLogs < ActiveRecord::Migration[5.0]
|
||||
def change
|
||||
create_table :logs do |t|
|
||||
t.text :message
|
||||
t.text :meta
|
||||
t.text :channels
|
||||
t.integer :device_id
|
||||
t.timestamps
|
||||
end
|
||||
|
||||
add_index :logs, :device_id
|
||||
add_column :devices, :max_log_count, :integer, default: 100
|
||||
end
|
||||
end
|
|
@ -1,7 +0,0 @@
|
|||
class FlipFlopToolsRelation < ActiveRecord::Migration[5.0]
|
||||
def change
|
||||
remove_column :tools, :tool_slot_id, :integer
|
||||
add_column :tool_slots, :tool_id, :integer
|
||||
add_index :tool_slots, :tool_id
|
||||
end
|
||||
end
|
|
@ -1,7 +0,0 @@
|
|||
class RemoveLegacyDeviseColumnsFromUserTable < ActiveRecord::Migration[5.0]
|
||||
def change
|
||||
remove_column :users, :reset_password_token, :string
|
||||
remove_column :users, :reset_password_sent_at, :datetime
|
||||
remove_column :users, :remember_created_at, :datetime
|
||||
end
|
||||
end
|
|
@ -1,12 +0,0 @@
|
|||
class AddVerifiedAtToUsersTable < ActiveRecord::Migration[5.0]
|
||||
def up
|
||||
add_column :users, :verified_at, :datetime
|
||||
add_column :users, :verification_token, :string
|
||||
User.update_all(verified_at: Time.now)
|
||||
end
|
||||
|
||||
def down
|
||||
remove_column :users, :verified_at, :datetime
|
||||
remove_column :users, :verification_token, :string
|
||||
end
|
||||
end
|
|
@ -1,13 +0,0 @@
|
|||
class CreateImages < ActiveRecord::Migration[5.0]
|
||||
def change
|
||||
create_table :images do |t|
|
||||
t.integer :device_id
|
||||
t.text :meta
|
||||
t.datetime :attachment_processed_at
|
||||
t.timestamps
|
||||
end
|
||||
|
||||
add_index :images, :device_id
|
||||
add_attachment :images, :attachment
|
||||
end
|
||||
end
|
|
@ -1,15 +0,0 @@
|
|||
class AddMissingDatabaseIndexes < ActiveRecord::Migration[5.0]
|
||||
def change
|
||||
add_index :planting_areas, :device_id
|
||||
add_index :regimen_items, :regimen_id
|
||||
add_index :regimen_items, :sequence_id
|
||||
add_index :schedules, :sequence_id
|
||||
add_index :schedules, :device_id
|
||||
add_index :sequences, :device_id
|
||||
add_index :regimens, :device_id
|
||||
add_index :devices, :planting_area_id
|
||||
add_index :plants, :planting_area_id
|
||||
add_index :plants, :device_id
|
||||
add_index :users, :device_id
|
||||
end
|
||||
end
|
|
@ -1,8 +0,0 @@
|
|||
class AddMaxImageCountToDevices < ActiveRecord::Migration[5.0]
|
||||
def change
|
||||
add_column :devices,
|
||||
:max_images_count,
|
||||
:integer,
|
||||
default: Device::DEFAULT_MAX_IMAGES
|
||||
end
|
||||
end
|
|
@ -1,11 +0,0 @@
|
|||
class ChangeSchedulesIntoFarmEvents < ActiveRecord::Migration[5.0]
|
||||
def change
|
||||
remove_column :schedules, :sequence_id, :integer
|
||||
rename_table :schedules, :farm_events
|
||||
add_column :farm_events, :repeats, :boolean
|
||||
add_reference :farm_events,
|
||||
:executable,
|
||||
polymorphic: true,
|
||||
index: true
|
||||
end
|
||||
end
|
|
@ -1,9 +0,0 @@
|
|||
class AddTimestampsToPlant < ActiveRecord::Migration[5.0]
|
||||
def change
|
||||
add_column :plants, :created_at, :datetime
|
||||
add_index :plants, :created_at
|
||||
remove_column :plants, :planted_at, :integer
|
||||
change_column :plants, :x, :integer
|
||||
change_column :plants, :y, :integer
|
||||
end
|
||||
end
|
|
@ -1,7 +0,0 @@
|
|||
class AddTimestampsToSequence < ActiveRecord::Migration[5.0]
|
||||
def change
|
||||
add_column :sequences, :updated_at, :datetime
|
||||
add_column :sequences, :created_at, :datetime
|
||||
add_index :sequences, :created_at
|
||||
end
|
||||
end
|
|
@ -1,6 +0,0 @@
|
|||
class AddAgreedToTermsToUser < ActiveRecord::Migration[5.0]
|
||||
def change
|
||||
add_column :users, :agreed_to_terms_at, :datetime
|
||||
add_index :users, :agreed_to_terms_at
|
||||
end
|
||||
end
|
|
@ -1,17 +0,0 @@
|
|||
class CreatePoints < ActiveRecord::Migration[5.0]
|
||||
def change
|
||||
enable_extension "hstore"
|
||||
|
||||
create_table :points do |t|
|
||||
t.float :radius
|
||||
t.float :x
|
||||
t.float :y
|
||||
t.float :z
|
||||
t.references :device, foreign_key: true
|
||||
t.hstore :meta
|
||||
|
||||
t.timestamps
|
||||
end
|
||||
add_index :points, :meta, using: :gin
|
||||
end
|
||||
end
|
|
@ -1,6 +0,0 @@
|
|||
class AddRadiusToPlants < ActiveRecord::Migration[5.0]
|
||||
def change
|
||||
add_column :plants, :radius, :float, default: 50
|
||||
remove_column :farm_events, :repeats, :boolean
|
||||
end
|
||||
end
|
|
@ -1,6 +0,0 @@
|
|||
class AddTimezoneToDevices < ActiveRecord::Migration[5.0]
|
||||
def change
|
||||
add_column :devices, :timezone, :string
|
||||
add_index :devices, :timezone
|
||||
end
|
||||
end
|
|
@ -1,7 +0,0 @@
|
|||
class AddMissingForeignKeyConstraints < ActiveRecord::Migration[5.0]
|
||||
def change
|
||||
bad_tools = (ToolSlot.pluck(:tool_id) - Tool.pluck(:id)).compact.uniq.sort
|
||||
ToolSlot.where(tool_id: bad_tools).destroy_all
|
||||
add_foreign_key :tool_slots, :tools
|
||||
end
|
||||
end
|
|
@ -1,10 +0,0 @@
|
|||
class GetOldIconsOutOfTheDb < ActiveRecord::Migration[5.0]
|
||||
def change
|
||||
Plant
|
||||
.where(radius: 50)
|
||||
.update_all(radius: 25)
|
||||
Plant
|
||||
.where(icon_url: "/app-resources/img/icons/Sprout-96.png")
|
||||
.update_all(icon_url: "IRELLEVANT_NOW")
|
||||
end
|
||||
end
|
|
@ -1,11 +0,0 @@
|
|||
class CleanUpOldDatabaseEntries < ActiveRecord::Migration[5.0]
|
||||
def change
|
||||
remove_column :plants, :img_url
|
||||
remove_column :plants, :icon_url
|
||||
remove_column :plants, :planting_area_id
|
||||
remove_column :devices, :planting_area_id
|
||||
remove_column :devices, :timezone
|
||||
remove_column :farm_events, :next_time
|
||||
drop_table :planting_areas
|
||||
end
|
||||
end
|
|
@ -1,59 +0,0 @@
|
|||
class NormalizePoints < ActiveRecord::Migration[5.0]
|
||||
def change
|
||||
# UPDATES TO TABLES ===================================================
|
||||
change_column :points, :x, :float, null: false
|
||||
change_column :points, :y, :float, null: false
|
||||
change_column :points, :z, :float, null: false, default: 0
|
||||
change_column :points, :radius, :float, null: false, default: 50
|
||||
change_column :points, :device_id, :integer,null: false
|
||||
change_column :sequences, :name, :string, null: false
|
||||
change_column_null :sequence_dependencies, :sequence_id, false
|
||||
add_foreign_key :sequence_dependencies,
|
||||
:sequences,
|
||||
column: :sequence_id
|
||||
change_column :plants,
|
||||
:openfarm_slug,
|
||||
:string,
|
||||
null: false,
|
||||
default: 50
|
||||
create_table(:generic_pointers) { |_| /# Empty table..#/ }
|
||||
add_column :points, :name, :string, null: false, default: "untitled"
|
||||
add_reference :points,
|
||||
:pointer,
|
||||
index: true,
|
||||
polymorphic: true
|
||||
# MANUAL MIGRATIONS ===================================================
|
||||
ToolSlot.find_each do |ts|
|
||||
Point.create!(x: ts[:x] || 0,
|
||||
y: ts[:y] || 0,
|
||||
z: ts[:z] || 0,
|
||||
name: ts[:name] || "Untitled Tool Slot" ,
|
||||
device_id: ts.tool_bay[:device_id],
|
||||
pointer: ts,
|
||||
meta: {})
|
||||
end
|
||||
|
||||
Plant.find_each do |pl|
|
||||
Point.create!(x: pl[:x] || 0,
|
||||
y: pl[:y] || 0,
|
||||
z: pl[:z] || 0,
|
||||
name: pl[:openfarm_slug] || "unknown",
|
||||
device_id: pl[:device_id],
|
||||
pointer: pl,
|
||||
meta: {})
|
||||
end
|
||||
|
||||
# DESTRUCTIVE ACTIONS =================================================
|
||||
[:x,:y].each do |coord|
|
||||
remove_column :plants, coord, :float
|
||||
remove_column :tool_slots, coord, :float
|
||||
end
|
||||
remove_column :plants, :device_id, :integer
|
||||
remove_column :plants, :name, :string
|
||||
remove_column :plants, :radius, :float
|
||||
remove_column :tool_slots, :name, :string
|
||||
remove_column :tool_slots, :tool_bay_id, :float
|
||||
remove_column :tool_slots, :z, :float
|
||||
drop_table :tool_bays
|
||||
end
|
||||
end
|
|
@ -1,12 +0,0 @@
|
|||
class EvolveToolSlotDeps < ActiveRecord::Migration[5.0]
|
||||
def change
|
||||
SequenceDependency.transaction do
|
||||
# ToolSlots are merged with points now.
|
||||
SequenceDependency
|
||||
.where(dependency_type: "ToolSlot")
|
||||
.map do |sd|
|
||||
sd.update_attributes!(dependency: sd.dependency.point)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,9 +0,0 @@
|
|||
class AddPolymorphicConstraints < ActiveRecord::Migration[5.1]
|
||||
def change
|
||||
add_polymorphic_constraints :pointer,
|
||||
:points,
|
||||
polymorphic_models: [:plant,
|
||||
:tool_slot,
|
||||
:generic_pointer]
|
||||
end
|
||||
end
|
|
@ -1,13 +0,0 @@
|
|||
class CreateLogDispatches < ActiveRecord::Migration[5.1]
|
||||
def change
|
||||
create_table :log_dispatches do |t|
|
||||
t.references :device, foreign_key: true
|
||||
t.references :log, foreign_key: true
|
||||
t.datetime :sent_at
|
||||
|
||||
t.timestamps
|
||||
end
|
||||
|
||||
add_index :log_dispatches, :sent_at
|
||||
end
|
||||
end
|
|
@ -1,8 +0,0 @@
|
|||
class AddNonNullConstraintToPointsTable < ActiveRecord::Migration[5.1]
|
||||
def change
|
||||
Point.where(pointer_type: nil).destroy_all
|
||||
Point.where(pointer_id: nil).destroy_all
|
||||
change_column :points, :pointer_type, :string, null: false
|
||||
change_column :points, :pointer_id, :integer, null: false
|
||||
end
|
||||
end
|
|
@ -1,6 +0,0 @@
|
|||
class AddTimezoneColumnBack < ActiveRecord::Migration[5.1]
|
||||
def change
|
||||
add_column :devices, :timezone, :string
|
||||
add_index :devices, :timezone
|
||||
end
|
||||
end
|
|
@ -1,5 +0,0 @@
|
|||
class ChangeDefaultRadius < ActiveRecord::Migration[5.1]
|
||||
def change
|
||||
change_column :points, :radius, :float, default: 25
|
||||
end
|
||||
end
|
205
db/migrate/20170629160248_init_schema.rb
Normal file
205
db/migrate/20170629160248_init_schema.rb
Normal file
|
@ -0,0 +1,205 @@
|
|||
class InitSchema < ActiveRecord::Migration[5.1]
|
||||
def up
|
||||
|
||||
# These are extensions that must be enabled in order to support this database
|
||||
enable_extension "plpgsql"
|
||||
enable_extension "hstore"
|
||||
|
||||
create_table "delayed_jobs", id: :serial, force: :cascade do |t|
|
||||
t.integer "priority", default: 0, null: false
|
||||
t.integer "attempts", default: 0, null: false
|
||||
t.text "handler", null: false
|
||||
t.text "last_error"
|
||||
t.datetime "run_at"
|
||||
t.datetime "locked_at"
|
||||
t.datetime "failed_at"
|
||||
t.string "locked_by"
|
||||
t.string "queue"
|
||||
t.datetime "created_at"
|
||||
t.datetime "updated_at"
|
||||
t.index ["priority", "run_at"], name: "delayed_jobs_priority"
|
||||
end
|
||||
|
||||
create_table "devices", id: :serial, force: :cascade do |t|
|
||||
t.string "name"
|
||||
t.string "webcam_url"
|
||||
t.integer "max_log_count", default: 100
|
||||
t.integer "max_images_count", default: 100
|
||||
t.string "timezone"
|
||||
t.index ["timezone"], name: "index_devices_on_timezone"
|
||||
end
|
||||
|
||||
create_table "farm_events", id: :serial, force: :cascade do |t|
|
||||
t.integer "device_id"
|
||||
t.datetime "start_time"
|
||||
t.datetime "end_time"
|
||||
t.integer "repeat"
|
||||
t.string "time_unit"
|
||||
t.string "executable_type"
|
||||
t.integer "executable_id"
|
||||
t.index ["device_id"], name: "index_farm_events_on_device_id"
|
||||
t.index ["executable_type", "executable_id"], name: "index_farm_events_on_executable_type_and_executable_id"
|
||||
end
|
||||
|
||||
create_table "generic_pointers", id: :serial, force: :cascade do |t|
|
||||
end
|
||||
|
||||
create_table "images", id: :serial, force: :cascade do |t|
|
||||
t.integer "device_id"
|
||||
t.text "meta"
|
||||
t.datetime "attachment_processed_at"
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
t.string "attachment_file_name"
|
||||
t.string "attachment_content_type"
|
||||
t.integer "attachment_file_size"
|
||||
t.datetime "attachment_updated_at"
|
||||
t.index ["device_id"], name: "index_images_on_device_id"
|
||||
end
|
||||
|
||||
create_table "log_dispatches", force: :cascade do |t|
|
||||
t.bigint "device_id"
|
||||
t.bigint "log_id"
|
||||
t.datetime "sent_at"
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
t.index ["device_id"], name: "index_log_dispatches_on_device_id"
|
||||
t.index ["log_id"], name: "index_log_dispatches_on_log_id"
|
||||
t.index ["sent_at"], name: "index_log_dispatches_on_sent_at"
|
||||
end
|
||||
|
||||
create_table "logs", id: :serial, force: :cascade do |t|
|
||||
t.text "message"
|
||||
t.text "meta"
|
||||
t.text "channels"
|
||||
t.integer "device_id"
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
t.index ["device_id"], name: "index_logs_on_device_id"
|
||||
end
|
||||
|
||||
create_table "peripherals", id: :serial, force: :cascade do |t|
|
||||
t.integer "device_id"
|
||||
t.integer "pin"
|
||||
t.integer "mode"
|
||||
t.string "label"
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
t.index ["device_id"], name: "index_peripherals_on_device_id"
|
||||
end
|
||||
|
||||
create_table "plants", id: :serial, force: :cascade do |t|
|
||||
t.string "openfarm_slug", default: "50", null: false
|
||||
t.datetime "created_at"
|
||||
t.index ["created_at"], name: "index_plants_on_created_at"
|
||||
end
|
||||
|
||||
create_table "points", id: :serial, force: :cascade do |t|
|
||||
t.float "radius", default: 25.0, null: false
|
||||
t.float "x", null: false
|
||||
t.float "y", null: false
|
||||
t.float "z", default: 0.0, null: false
|
||||
t.integer "device_id", null: false
|
||||
t.hstore "meta"
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
t.string "name", default: "untitled", null: false
|
||||
t.string "pointer_type", null: false
|
||||
t.integer "pointer_id", null: false
|
||||
t.index ["device_id"], name: "index_points_on_device_id"
|
||||
t.index ["meta"], name: "index_points_on_meta", using: :gin
|
||||
t.index ["pointer_type", "pointer_id"], name: "index_points_on_pointer_type_and_pointer_id"
|
||||
end
|
||||
|
||||
create_table "regimen_items", id: :serial, force: :cascade do |t|
|
||||
t.bigint "time_offset"
|
||||
t.integer "regimen_id"
|
||||
t.integer "sequence_id"
|
||||
t.index ["regimen_id"], name: "index_regimen_items_on_regimen_id"
|
||||
t.index ["sequence_id"], name: "index_regimen_items_on_sequence_id"
|
||||
end
|
||||
|
||||
create_table "regimens", id: :serial, force: :cascade do |t|
|
||||
t.string "color"
|
||||
t.string "name"
|
||||
t.integer "device_id"
|
||||
t.index ["device_id"], name: "index_regimens_on_device_id"
|
||||
end
|
||||
|
||||
create_table "sequence_dependencies", id: :serial, force: :cascade do |t|
|
||||
t.string "dependency_type"
|
||||
t.integer "dependency_id"
|
||||
t.integer "sequence_id", null: false
|
||||
t.index ["dependency_id"], name: "index_sequence_dependencies_on_dependency_id"
|
||||
t.index ["dependency_type"], name: "index_sequence_dependencies_on_dependency_type"
|
||||
t.index ["sequence_id"], name: "index_sequence_dependencies_on_sequence_id"
|
||||
end
|
||||
|
||||
create_table "sequences", id: :serial, force: :cascade do |t|
|
||||
t.integer "device_id"
|
||||
t.string "name", null: false
|
||||
t.string "color"
|
||||
t.string "kind", default: "sequence"
|
||||
t.text "args"
|
||||
t.text "body"
|
||||
t.datetime "updated_at"
|
||||
t.datetime "created_at"
|
||||
t.index ["created_at"], name: "index_sequences_on_created_at"
|
||||
t.index ["device_id"], name: "index_sequences_on_device_id"
|
||||
end
|
||||
|
||||
create_table "token_expirations", id: :serial, force: :cascade do |t|
|
||||
t.string "sub"
|
||||
t.integer "exp"
|
||||
t.string "jti"
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
end
|
||||
|
||||
create_table "tool_slots", id: :serial, force: :cascade do |t|
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
t.integer "tool_id"
|
||||
t.index ["tool_id"], name: "index_tool_slots_on_tool_id"
|
||||
end
|
||||
|
||||
create_table "tools", id: :serial, force: :cascade do |t|
|
||||
t.string "name"
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
t.integer "device_id"
|
||||
t.index ["device_id"], name: "index_tools_on_device_id"
|
||||
end
|
||||
|
||||
create_table "users", id: :serial, force: :cascade do |t|
|
||||
t.integer "device_id"
|
||||
t.string "name"
|
||||
t.string "email", default: "", null: false
|
||||
t.string "encrypted_password", default: "", null: false
|
||||
t.integer "sign_in_count", default: 0, null: false
|
||||
t.datetime "current_sign_in_at"
|
||||
t.datetime "last_sign_in_at"
|
||||
t.string "current_sign_in_ip"
|
||||
t.string "last_sign_in_ip"
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
t.datetime "verified_at"
|
||||
t.string "verification_token"
|
||||
t.datetime "agreed_to_terms_at"
|
||||
t.index ["agreed_to_terms_at"], name: "index_users_on_agreed_to_terms_at"
|
||||
t.index ["device_id"], name: "index_users_on_device_id"
|
||||
t.index ["email"], name: "index_users_on_email", unique: true
|
||||
end
|
||||
|
||||
add_foreign_key "log_dispatches", "devices"
|
||||
add_foreign_key "log_dispatches", "logs"
|
||||
add_foreign_key "peripherals", "devices"
|
||||
add_foreign_key "points", "devices"
|
||||
add_foreign_key "sequence_dependencies", "sequences"
|
||||
add_foreign_key "tool_slots", "tools"
|
||||
end
|
||||
|
||||
def down
|
||||
raise ActiveRecord::IrreversibleMigration, "The initial migration is not revertable"
|
||||
end
|
||||
end
|
13
db/migrate/20170814084814_squasher_clean.rb
Normal file
13
db/migrate/20170814084814_squasher_clean.rb
Normal file
|
@ -0,0 +1,13 @@
|
|||
class SquasherClean < ActiveRecord::Migration[5.1]
|
||||
class SchemaMigration < ActiveRecord::Base
|
||||
end
|
||||
|
||||
def up
|
||||
migrations = Dir.glob(File.join(File.dirname(__FILE__), '*.rb'))
|
||||
versions = migrations.map { |file| File.basename(file)[/\A\d+/] }
|
||||
SchemaMigration.where("version NOT IN (?)", versions).delete_all
|
||||
end
|
||||
|
||||
def down
|
||||
end
|
||||
end
|
|
@ -10,7 +10,7 @@
|
|||
#
|
||||
# It's strongly recommended that you check this file into your version control system.
|
||||
|
||||
ActiveRecord::Schema.define(version: 20170807143633) do
|
||||
ActiveRecord::Schema.define(version: 20170814084814) do
|
||||
|
||||
# These are extensions that must be enabled in order to support this database
|
||||
enable_extension "plpgsql"
|
||||
|
@ -107,7 +107,7 @@ ActiveRecord::Schema.define(version: 20170807143633) do
|
|||
end
|
||||
|
||||
create_table "points", id: :serial, force: :cascade do |t|
|
||||
t.float "radius", default: 25.0, null: false
|
||||
t.float "radius", default: 50.0, null: false
|
||||
t.float "x", null: false
|
||||
t.float "y", null: false
|
||||
t.float "z", default: 0.0, null: false
|
||||
|
|
|
@ -53,7 +53,7 @@
|
|||
"deep-freeze": "^0.0.1",
|
||||
"enzyme": "^2.9.1",
|
||||
"extract-text-webpack-plugin": "^2.1.2",
|
||||
"farmbot": "4.3.8",
|
||||
"farmbot": "4.3.9",
|
||||
"farmbot-toastr": "^1.0.3",
|
||||
"fastclick": "^1.0.6",
|
||||
"file-loader": "^0.11.2",
|
||||
|
|
12
spec/controllers/dashboard_spec.rb
Normal file
12
spec/controllers/dashboard_spec.rb
Normal file
|
@ -0,0 +1,12 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe DashboardController do
|
||||
include Devise::Test::ControllerHelpers
|
||||
describe 'ACME endpoint' do
|
||||
|
||||
it 'has a fallback' do
|
||||
process :lets_encrypt, method: :get, params: { id: "FOO" }
|
||||
expect(response.body).to include(DashboardController::NO_ENV)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -11,4 +11,7 @@ describe Sequence do
|
|||
expect { Sequence.create!(optns) }.to raise_error(ActiveRecord::RecordInvalid)
|
||||
end
|
||||
|
||||
it "picks random values" do
|
||||
3.times { expect(Sequence.random).to be_kind_of(Sequence) }
|
||||
end
|
||||
end
|
||||
|
|
|
@ -35,7 +35,10 @@ export let bot: Everything["bot"] = {
|
|||
},
|
||||
"pins": {},
|
||||
"configuration": {},
|
||||
"informational_settings": {},
|
||||
"informational_settings": {
|
||||
busy: false,
|
||||
locked: false
|
||||
},
|
||||
"user_env": {},
|
||||
"process_info": {
|
||||
"farmwares": {}
|
||||
|
|
|
@ -6,13 +6,16 @@ import { mapStateToProps } from "./state_to_props";
|
|||
import { WebcamPanel } from "./webcam_panel";
|
||||
import { Props } from "./interfaces";
|
||||
import { Move } from "./move";
|
||||
import * as _ from "lodash";
|
||||
|
||||
@connect(mapStateToProps)
|
||||
export class Controls extends React.Component<Props, {}> {
|
||||
render() {
|
||||
// TODO: Add this to interface in FBJS - RC 10-aug-17
|
||||
let arduinoBusy = _.get(this.props.bot.hardware.informational_settings, "busy", false);
|
||||
let arduinoBusy = !!this
|
||||
.props
|
||||
.bot
|
||||
.hardware
|
||||
.informational_settings
|
||||
.busy;
|
||||
return (
|
||||
<Page className="controls">
|
||||
<Row>
|
||||
|
|
|
@ -3,7 +3,6 @@ import { t } from "i18next";
|
|||
import { emergencyLock, emergencyUnlock } from "../actions";
|
||||
import { EStopButtonProps } from "../interfaces";
|
||||
import { SyncStatus } from "farmbot/dist";
|
||||
import { get } from "lodash";
|
||||
// Leave this here. Type checker will notify us if we ever need to change
|
||||
// this string.
|
||||
const LOCKED: SyncStatus = "locked";
|
||||
|
@ -12,8 +11,7 @@ export class EStopButton extends React.Component<EStopButtonProps, {}> {
|
|||
render() {
|
||||
let i = this.props.bot.hardware.informational_settings;
|
||||
let { sync_status } = i;
|
||||
// TODO: ADD `.locked` to FBJS interface!
|
||||
let lock1 = get(i, "locked", false);
|
||||
let lock1 = !!i.locked;
|
||||
let lock2 = sync_status === LOCKED;
|
||||
let isLocked = lock1 || lock2;
|
||||
let toggleEmergencyLock = isLocked ? emergencyUnlock : emergencyLock;
|
||||
|
|
|
@ -59,8 +59,6 @@ export let OsUpdateButton = ({ bot }: BotProp) => {
|
|||
<ToggleButton toggleValue={toggleVal}
|
||||
toggleAction={() => {
|
||||
let os_auto_update = !osUpdateBool ? 1 : 0;
|
||||
// TODO: This no longer needs to be a thunk
|
||||
// since it does not change redux state.
|
||||
updateConfig({ os_auto_update })(noop);
|
||||
}} />
|
||||
</Col>
|
||||
|
|
|
@ -61,7 +61,10 @@ export let initialState: BotState = {
|
|||
},
|
||||
pins: {},
|
||||
configuration: {},
|
||||
informational_settings: {},
|
||||
informational_settings: {
|
||||
busy: false,
|
||||
locked: false
|
||||
},
|
||||
user_env: {},
|
||||
process_info: {
|
||||
farmwares: {},
|
||||
|
|
|
@ -12,14 +12,16 @@ import {
|
|||
import { PlantPointer } from "../interfaces";
|
||||
import { SlotWithTool } from "../resources/interfaces";
|
||||
import { BotPosition } from "../devices/interfaces";
|
||||
import { isNumber } from "lodash";
|
||||
|
||||
/** TODO: Use Enums */
|
||||
export type BotOriginQuadrant = 1 | 2 | 3 | 4;
|
||||
export type ZoomLevelPayl = 0.1 | -0.1;
|
||||
|
||||
export function isBotOriginQuadrant(mystery: any):
|
||||
type Mystery = BotOriginQuadrant | number | undefined;
|
||||
export function isBotOriginQuadrant(mystery: Mystery):
|
||||
mystery is BotOriginQuadrant {
|
||||
return [1, 2, 3, 4].includes(mystery);
|
||||
return isNumber(mystery) && [1, 2, 3, 4].includes(mystery);
|
||||
}
|
||||
|
||||
export interface State {
|
||||
|
|
|
@ -19,21 +19,21 @@ export class FarmbotColorPicker extends React.Component<FarmbotPickerProps, {}>
|
|||
}
|
||||
|
||||
hueCSS = (): React.CSSProperties => {
|
||||
// TODO: Investigate if this is a bug with our code or @types/react:
|
||||
// CC @Chris
|
||||
let position: any = "relative";
|
||||
let width = "100%";
|
||||
let paddingBottom = "10%";
|
||||
let overflow: any = "hidden";
|
||||
return { position, width, paddingBottom, overflow };
|
||||
return {
|
||||
position: "relative",
|
||||
width: "100%",
|
||||
paddingBottom: "10%",
|
||||
overflow: "hidden"
|
||||
};
|
||||
}
|
||||
|
||||
saturationCSS = (): React.CSSProperties => {
|
||||
let position: any = "relative";
|
||||
let width = "100%";
|
||||
let paddingBottom = "35%";
|
||||
let overflow: any = "hidden";
|
||||
return { position, width, paddingBottom, overflow };
|
||||
return {
|
||||
position: "relative",
|
||||
width: "100%",
|
||||
paddingBottom: "35%",
|
||||
overflow: "hidden"
|
||||
};
|
||||
}
|
||||
|
||||
hueboxCSS = (): React.CSSProperties => {
|
||||
|
@ -79,7 +79,7 @@ export class FarmbotColorPicker extends React.Component<FarmbotPickerProps, {}>
|
|||
<div style={{ width: "100%", paddingBottom: "15%" }} />
|
||||
<div style={this.hueCSS()}>
|
||||
<Hue
|
||||
{...dontTouchThis as any}
|
||||
{...dontTouchThis}
|
||||
pointer={this.customPointer}
|
||||
onChange={_.noop} />
|
||||
<div style={this.hueboxCSS()} />
|
||||
|
@ -87,7 +87,7 @@ export class FarmbotColorPicker extends React.Component<FarmbotPickerProps, {}>
|
|||
<div style={{ width: "100%", paddingBottom: "2%" }} />
|
||||
<div style={this.saturationCSS()}>
|
||||
<Saturation
|
||||
{...dontTouchThis as any}
|
||||
{...dontTouchThis}
|
||||
pointer={this.customPointer}
|
||||
onChange={_.noop} />
|
||||
<div style={this.saturationboxCSS()} />
|
||||
|
|
|
@ -1958,9 +1958,9 @@ farmbot-toastr@^1.0.0, farmbot-toastr@^1.0.3:
|
|||
farmbot-toastr "^1.0.0"
|
||||
typescript "^2.3.4"
|
||||
|
||||
farmbot@4.3.8:
|
||||
version "4.3.8"
|
||||
resolved "https://registry.yarnpkg.com/farmbot/-/farmbot-4.3.8.tgz#740f4c3c694df738b4ac8acda10eea8f472d23da"
|
||||
farmbot@4.3.9:
|
||||
version "4.3.9"
|
||||
resolved "https://registry.yarnpkg.com/farmbot/-/farmbot-4.3.9.tgz#fdf1ac0f6165a52ab7f6b2d4cd4dfdc21f5b7892"
|
||||
dependencies:
|
||||
mqtt "^1.7.4"
|
||||
typescript "^2.4.2"
|
||||
|
|
Loading…
Reference in a new issue