Compare commits
460 Commits
Author | SHA1 | Date |
---|---|---|
server | 53bc33fc3e | |
Rick Carlino | 1a7ee04d0b | |
gabrielburnworth | 4a7a683ba7 | |
Rick Carlino | 8700d50c81 | |
gabrielburnworth | 3bab5694b8 | |
Rick Carlino | e205214ba4 | |
gabrielburnworth | 73e9daed05 | |
gabrielburnworth | 426f97ddc2 | |
Rick Carlino | 88e526cce3 | |
Rick Carlino | 9e14c2125d | |
Rick Carlino | 889c78c77a | |
Rick Carlino | 3b1dbe2209 | |
gabrielburnworth | 980d39f70d | |
Rick Carlino | 461f4c2509 | |
gabrielburnworth | d2176fd6ea | |
gabrielburnworth | c9511593a3 | |
Rick Carlino | 66553d143d | |
Rick Carlino | 696350343b | |
Rick Carlino | 1f773c44fc | |
Rick Carlino | 87c22d4a96 | |
Rick Carlino | 9f35dd9992 | |
gabrielburnworth | 14bf5216e0 | |
gabrielburnworth | 1d196d633a | |
Rick Carlino | de607e3e3a | |
gabrielburnworth | d931cd1b84 | |
gabrielburnworth | b3f93dd678 | |
Rick Carlino | 7f9ecd450d | |
gabrielburnworth | 69462e4b60 | |
gabrielburnworth | d3732aed20 | |
Rick Carlino | 6213028f0f | |
gabrielburnworth | 281813369e | |
Rick Carlino | 1014eece5f | |
gabrielburnworth | 6f484ab2e3 | |
Rick Carlino | 0bd6d9a967 | |
gabrielburnworth | 25b2f18c4c | |
Rick Carlino | 1556084dbd | |
Rick Carlino | 0571100229 | |
Rick Carlino | d6909f439c | |
Rick Carlino | 36b5c90b65 | |
Rick Carlino | f3ac957485 | |
Rick Carlino | 6f834517ca | |
Rick Carlino | 44c3f7dc4e | |
Rick Carlino | 5bb77c1c14 | |
Rick Carlino | 3ee1478a58 | |
Rick Carlino | df9e0ef26b | |
Rick Carlino | 0e02ca06ee | |
Rick Carlino | 643bcb1a37 | |
Rick Carlino | 88b20a73ea | |
Rick Carlino | e8a8165635 | |
Rick Carlino | 588d4eb36e | |
Rick Carlino | efea80b593 | |
gabrielburnworth | c75d93f3c4 | |
gabrielburnworth | bee1e0e074 | |
Rick Carlino | 4375a935f0 | |
Rick Carlino | 7d5fe7c9f6 | |
Rick Carlino | e801d53d51 | |
Rick Carlino | bf0a03d11d | |
gabrielburnworth | ec757b1b29 | |
gabrielburnworth | 3c3b120b9b | |
Rick Carlino | 046035ab9e | |
Rick Carlino | 52b481e831 | |
Rick Carlino | 73422eb8ea | |
gabrielburnworth | b087e08f13 | |
Rick Carlino | 1e1b405c32 | |
Rick Carlino | dccea4e474 | |
Rick Carlino | 91d86bad0c | |
Rick Carlino | bfe4df68a8 | |
Rick Carlino | dd6a43d901 | |
Rick Carlino | 726cd6d4e7 | |
Rick Carlino | d730cd9260 | |
Rick Carlino | eb8cfd3c91 | |
Rick Carlino | 8f9bd4a5e7 | |
gabrielburnworth | 3ebf434945 | |
Rick Carlino | 92a7194c6e | |
gabrielburnworth | 24ad841d7f | |
Rick Carlino | b45f806309 | |
Rick Carlino | cf7ec86106 | |
Rick Carlino | 37f7517c51 | |
Rick Carlino | 2a04803dc6 | |
Rick Carlino | 3700406687 | |
Rick Carlino | 1ba0ff7871 | |
Rick Carlino | be23cd44b5 | |
Rick Carlino | 43d1b9da33 | |
Rick Carlino | bda30bae09 | |
Rick Carlino | de21cb16da | |
Rick Carlino | 0a153bc656 | |
Rick Carlino | 149451c270 | |
Gabriel Burnworth | d7de315c20 | |
Rick Carlino | 61c09b69b9 | |
Rick Carlino | 863071824b | |
Rick Carlino | 82f2fbef90 | |
gabrielburnworth | c736348bed | |
gabrielburnworth | 309737dd33 | |
Rick Carlino | 3a9ea9af79 | |
Rick Carlino | bc68f3e79f | |
Rick Carlino | 85be07efe5 | |
gabrielburnworth | fe9ff346a8 | |
gabrielburnworth | ec878e0dae | |
gabrielburnworth | b1c2b36a37 | |
gabrielburnworth | 11f349ac89 | |
Rick Carlino | 67373e4f7e | |
Fabio Dessi | dd46830b9d | |
Fabio Dessi | 63b333746d | |
Rick Carlino | 2c6033f57a | |
gabrielburnworth | 4d2ea00130 | |
gabrielburnworth | c8c57d5340 | |
gabrielburnworth | 4013291787 | |
gabrielburnworth | 25d944e4b7 | |
gabrielburnworth | de6f886586 | |
gabrielburnworth | 800625e8a1 | |
Rick Carlino | bce0700cd9 | |
Rick Carlino | cccecf58f6 | |
MarcRoland | c2308cb987 | |
Rick Carlino | ffbf660143 | |
gabrielburnworth | edb96d3ca8 | |
Rick Carlino | a49e5e67ba | |
gabrielburnworth | 90ddd78bb8 | |
gabrielburnworth | 9bd98aca1e | |
Rick Carlino | 49fdced812 | |
Rick Carlino | 6bc0034d67 | |
Rick Carlino | 8e0cf2603c | |
gabrielburnworth | 4a0035b9eb | |
gabrielburnworth | 19eebde8e2 | |
Rick Carlino | cd52670c0b | |
Rick Carlino | fd62ccd9aa | |
Rick Carlino | 1a4a106179 | |
Rick Carlino | ee8851b0af | |
gabrielburnworth | 40150a307c | |
Rick Carlino | a5b1d5631e | |
Rick Carlino | 26a4f66a75 | |
Rick Carlino | 73222de627 | |
Rick Carlino | ddb480921e | |
Rick Carlino | 5945d2a38d | |
gabrielburnworth | a04ec59ba5 | |
Rick Carlino | 310686508f | |
gabrielburnworth | 66b5e3c962 | |
gabrielburnworth | cf0af59e42 | |
gabrielburnworth | 9dab0c4bc5 | |
Rick Carlino | 94ee85bd83 | |
Rick Carlino | 672aae441b | |
Rick Carlino | 3d0223e56a | |
Rick Carlino | 93d2521511 | |
gabrielburnworth | aafd84fff7 | |
Rick Carlino | 8f8056a3e3 | |
Rick Carlino | c1a9bc63bf | |
Rick Carlino | 2a6fe06ba3 | |
Rick Carlino | 6c3e60999c | |
Rick Carlino | 10a025369d | |
Rick Carlino | e490aa83f6 | |
Rick Carlino | eec9790a0b | |
Rick Carlino | de140d02a5 | |
Rick Carlino | c0fab4a38c | |
Rick Carlino | 313008b21b | |
Fabio Dessi | 2aed62b9f8 | |
Fabio Dessi | 4fe9d89912 | |
Rick Carlino | e989e66d9b | |
gabrielburnworth | 3367bc667b | |
Rick Carlino | 93f5d59bf4 | |
gabrielburnworth | 1af5af0696 | |
gabrielburnworth | e46b4de0bb | |
gabrielburnworth | 464b730cd8 | |
Rick Carlino | 837cbe8a85 | |
Fabio Dessi | 8f3a674f9d | |
Rick Carlino | 3e300defa1 | |
Rick Carlino | cd685d6590 | |
Rick Carlino | 05f6c52f67 | |
Rick Carlino | a565261517 | |
Rick Carlino | e5a154e3a0 | |
Rick Carlino | 286e6b5bbb | |
Pitou | ea031aaf4d | |
Rick Carlino | 4119865370 | |
Rick Carlino | da00ca4d98 | |
Pitou | 9288757f97 | |
Rick Carlino | 66962e1bdb | |
Rick Carlino | 0b4ea1e385 | |
Rick Carlino | 11d08aea99 | |
Rick Carlino | 1934e4ba7c | |
Rick Carlino | 1cfa4f9e9e | |
Rick Carlino | 13b4e159df | |
Rick Carlino | e84e05a45e | |
gabrielburnworth | 313e92b1c3 | |
gabrielburnworth | 9dfd31da10 | |
Rick Carlino | c3029d06ed | |
Rick Carlino | 7e1cad0f9f | |
Rick Carlino | f0eadf2c98 | |
Rick Carlino | 9ccb0fab68 | |
Rick Carlino | e5b20c15c9 | |
Rick Carlino | f11a553231 | |
Rick Carlino | bbd711eb24 | |
gabrielburnworth | 981d005423 | |
gabrielburnworth | 3b2422607f | |
Gabriel Burnworth | e05b4a3d1c | |
Rick Carlino | 39e5418b3e | |
Rick Carlino | fc7f98b79b | |
Rick Carlino | 4451c4decd | |
Rick Carlino | 6fbe9ec1df | |
Rick Carlino | 77ee927ce8 | |
Rick Carlino | d829c4e3dd | |
Rick Carlino | b8eb47b0cc | |
Rick Carlino | ff596c6f1f | |
Rick Carlino | 393f6c3eed | |
Rick Carlino | f6b67052ca | |
Rick Carlino | 9edba110f6 | |
Rick Carlino | 612042efaa | |
Rick Carlino | 3a3e52d46e | |
Rick Carlino | 0fe2329809 | |
gabrielburnworth | ab7c360304 | |
Rick Carlino | 024964d380 | |
Rick Carlino | e19efe31e9 | |
Rick Carlino | 6220a85bd5 | |
Rick Carlino | 1e5ebb9c9b | |
Rick Carlino | 070a882173 | |
Gabriel Burnworth | 6227b17d16 | |
gabrielburnworth | 927ad8c54e | |
gabrielburnworth | 339ec2f3c0 | |
Rick Carlino | a31c21bb4d | |
Pitou | 6f699a72a2 | |
Pitou | 547a73727f | |
Rick Carlino | db040aa301 | |
Rick Carlino | bc08514f7e | |
Rick Carlino | 7f0892d8b2 | |
Rick Carlino | a13272d6be | |
Rick Carlino | d63b9ef39c | |
Rick Carlino | 800fa28f83 | |
Rick Carlino | 37d4d27dce | |
gabrielburnworth | 4549ecf405 | |
gabrielburnworth | e2838539b4 | |
gabrielburnworth | 72dfcb23ee | |
gabrielburnworth | 6f2b74dc52 | |
gabrielburnworth | 8b8b198d93 | |
gabrielburnworth | a10267507b | |
gabrielburnworth | 271884f2d0 | |
gabrielburnworth | 781ac33b10 | |
gabrielburnworth | 9d7833b71c | |
gabrielburnworth | a38e7b6b91 | |
Rick Carlino | a32d9f025b | |
Rick Carlino | 4b06a8ae11 | |
Rick Carlino | 6c6057c97f | |
Rick Carlino | 8b14c32028 | |
Rick Carlino | 69ed6e89b7 | |
Rick Carlino | ab94c0098c | |
Rick Carlino | 1383a5bb1a | |
Rick Carlino | 721fea39b2 | |
Rick Carlino | 2226d3b34b | |
Rick Carlino | d5bbc95b1f | |
Rick Carlino | 44b4604552 | |
Rick Carlino | f51e9ad4c9 | |
Rick Carlino | 3f86376d09 | |
Rick Carlino | 0d9bf3ccc5 | |
Rick Carlino | f9e5559ee0 | |
Rick Carlino | eeabe48cef | |
Rick Carlino | d306b65909 | |
Rick Carlino | 19798b894f | |
Rick Carlino | b7c618aec8 | |
Rick Carlino | 44c1e0b964 | |
Rick Carlino | 47a2e5b1e3 | |
Rick Carlino | 6aff7445f1 | |
Rick Carlino | 51f061a325 | |
Rick Carlino | 1f6a71e6af | |
gabrielburnworth | aed825a7ad | |
gabrielburnworth | afd35f7291 | |
gabrielburnworth | b8707f90cb | |
gabrielburnworth | 31127c4edd | |
gabrielburnworth | 53b09e70a4 | |
Rick Carlino | d854cb9b22 | |
gabrielburnworth | f83a345227 | |
Rick Carlino | f2ca8fc6fa | |
Rick Carlino | 4ea82828d4 | |
Rick Carlino | 3677fb8a37 | |
gabrielburnworth | 1063b38626 | |
gabrielburnworth | ebe8831900 | |
Rick Carlino | c3f5423823 | |
gabrielburnworth | 2ad20ea54d | |
Rick Carlino | 56002e5555 | |
gabrielburnworth | 6bc6e6ffec | |
Rick Carlino | ea8428621a | |
gabrielburnworth | 1455bebba2 | |
gabrielburnworth | 22465a5558 | |
Rick Carlino | 4fa48cb74b | |
gabrielburnworth | c2d80bd55c | |
Rick Carlino | fea40c1d9a | |
Rick Carlino | a810743fa7 | |
Rick Carlino | 79690a90a2 | |
Rick Carlino | 5e52d3c6dd | |
Gabriel Burnworth | 4dd1c04ae8 | |
gabrielburnworth | 071ffe39b5 | |
gabrielburnworth | 9c3340be56 | |
Rick Carlino | cd20fcf943 | |
gabrielburnworth | 8d5218f67c | |
gabrielburnworth | 307105c96e | |
Rick Carlino | f5554a4e00 | |
Rick Carlino | f5be061c4d | |
gabrielburnworth | 6a8bd52902 | |
Rick Carlino | a0abdcb198 | |
Rick Carlino | ac5cc41b95 | |
Rick Carlino | ee20868cb4 | |
Rick Carlino | 545c7ca4c1 | |
Rick Carlino | 9646426964 | |
gabrielburnworth | fa7fc0024e | |
Rick Carlino | 434d6e5d79 | |
Fabio Dessi | 98a0abd7fa | |
Rick Carlino | f803dfd6cf | |
gabrielburnworth | 4b12828262 | |
Rick Carlino | 209b355481 | |
Rick Carlino | 114673d756 | |
Rick Carlino | 4d92f37a98 | |
Rick Carlino | 34b3a69e9e | |
Rick Carlino | 077894bb4d | |
gabrielburnworth | a2ae2ea38e | |
Rick Carlino | df92e1d8db | |
Rick Carlino | 2fa3aa55f4 | |
Rick Carlino | d2549c0208 | |
Rick Carlino | 8e43cb894c | |
Rick Carlino | 2099d7acbb | |
Rick Carlino | f9ac3e659f | |
Rick Carlino | e02673aa79 | |
Rick Carlino | 08e15087cd | |
Rick Carlino | 1607449bb7 | |
Rick Carlino | 1d7534adae | |
Rick Carlino | 205121da43 | |
Rick Carlino | 129309e910 | |
Rick Carlino | 3cd5754b63 | |
Rick Carlino | 2db87096a3 | |
Rick Carlino | 0c9a04c6d8 | |
Rick Carlino | f31c38158f | |
Rick Carlino | 8d91e18650 | |
Rick Carlino | b0718c2e9a | |
Rick Carlino | ed0661917e | |
gabrielburnworth | 74b0373c51 | |
gabrielburnworth | cb3f858fcf | |
Rick Carlino | fc7d0882b2 | |
Rick Carlino | 2a701bdc63 | |
Rick Carlino | 27e7b3f30a | |
Rick Carlino | 0f8f8d63a4 | |
Rick Carlino | 8d6c14cb21 | |
Rick Carlino | a74d389862 | |
Rick Carlino | 3fb1487cdb | |
Rick Carlino | 88b7b1ffae | |
Rick Carlino | 4c7902c0a2 | |
Rick Carlino | 6c6e488295 | |
Rick Carlino | 4490bbc531 | |
Rick Carlino | cad3839e87 | |
Rick Carlino | 566f23b01f | |
gabrielburnworth | 6ba8d6612d | |
Rick Carlino | 15f5b64005 | |
Rick Carlino | e454c7e412 | |
Rick Carlino | 7661f97a98 | |
Rick Carlino | 97889e7021 | |
Rick Carlino | 2ed25887e1 | |
Rick Carlino | f8575fb7eb | |
Rick Carlino | 17c33ba7bc | |
Rick Carlino | 814cb4451e | |
Rick Carlino | 04db845e94 | |
Fabio Dessi | 938789e554 | |
Fabio Dessi | 92374ed20f | |
Fabio Dessi | 8dc809380e | |
Rick Carlino | 88bb6fa2aa | |
Rick Carlino | bbd5f14cfe | |
Rick Carlino | bc847b3611 | |
Rick Carlino | a75a358a96 | |
Rick Carlino | 6092abc03f | |
Rick Carlino | f71ff37caf | |
Rick Carlino | a964b14418 | |
Rick Carlino | 8ae678ce07 | |
Rick Carlino | 70118937fa | |
Rick Carlino | c145fd3de9 | |
Rick Carlino | 0c1fc4d2f3 | |
Rick Carlino | 96b508be1e | |
Rick Carlino | d84b33a203 | |
Rick Carlino | 2a0e390472 | |
Rick Carlino | 3a4fe9cd60 | |
Rick Carlino | 6f5f1f84a7 | |
Rick Carlino | a2bb562c3e | |
Rick Carlino | d129b028f1 | |
Rick Carlino | f1c3fb5baf | |
Rick Carlino | ccc9a98e96 | |
Rick Carlino | 32bbe8ad96 | |
Rick Carlino | eeb199b816 | |
Rick Carlino | 7f6449ece2 | |
Rick Carlino | f4b59ea0d5 | |
Rick Carlino | ea88ad4c26 | |
Rick Carlino | b08826708a | |
Rick Carlino | 4dae2a283f | |
Rick Carlino | bdce179f88 | |
Rick Carlino | 8b15c7fecd | |
Rick Carlino | 2adf28b6dc | |
Rick Carlino | 4037f6bab1 | |
Rick Carlino | 606bc19def | |
Rick Carlino | 7994801daa | |
Rick Carlino | 92869beb32 | |
Rick Carlino | f0dcbcd54f | |
Rick Carlino | c47651282f | |
Rick Carlino | e26d8e870f | |
Rick Carlino | 9a4755c30b | |
Rick Carlino | f54fb07d61 | |
Rick Carlino | 897ed8206a | |
Rick Carlino | fd884ad9fa | |
Rick Carlino | 4e87effeba | |
Rick Carlino | 142611deaa | |
Rick Carlino | 06d0bd1c82 | |
Rick Carlino | d7e4373db7 | |
Rick Carlino | 9541970fb3 | |
Rick Carlino | 4f0373a3a2 | |
Rick Carlino | 2e1ce7d3fa | |
Rick Carlino | 8d50fcdf96 | |
Rick Carlino | 5c6fb08a5d | |
Rick Carlino | 076bdbdb5d | |
Rick Carlino | b0c31b2e61 | |
Rick Carlino | 1fedc1917d | |
Rick Carlino | 435273994a | |
Rick Carlino | b190fe3609 | |
Rick Carlino | d1496ddb1e | |
Rick Carlino | eb231231c7 | |
Rick Carlino | 2782a3e517 | |
Rick Carlino | 0fa65f0eac | |
Rick Carlino | be16f15917 | |
Rick Carlino | 66afa66287 | |
Rick Carlino | c5a6e2052e | |
Rick Carlino | d28c9d67ed | |
Rick Carlino | 2a3a244024 | |
Rick Carlino | 8b6c03216e | |
Rick Carlino | 7813e88a69 | |
Rick Carlino | 976a912c07 | |
Rick Carlino | e2d311e3ea | |
Rick Carlino | 755ce7f178 | |
Rick Carlino | c3bb45e0a2 | |
Rick Carlino | eada674e50 | |
Rick Carlino | 627e46d807 | |
Rick Carlino | fbc63ace3b | |
Rick Carlino | 1f84001e6e | |
Rick Carlino | dc86f82795 | |
Rick Carlino | 3030344426 | |
Rick Carlino | 4f1c767f2c | |
Rick Carlino | 402b9eda3e | |
Rick Carlino | a0e8165361 | |
Rick Carlino | 2073d2022b | |
Rick Carlino | 56b9de1893 | |
Rick Carlino | 62246fbe20 | |
Rick Carlino | 43826465ec | |
Rick Carlino | 1aa316ee62 | |
Rick Carlino | 7f2c174d29 | |
Rick Carlino | 90e97d7bbb | |
Rick Carlino | b8196d5214 | |
Rick Carlino | 187b3bcbab | |
Rick Carlino | 2ee4268048 | |
Rick Carlino | a579ace0e2 | |
Rick Carlino | 531280a927 | |
Rick Carlino | d07dd5eb15 | |
Rick Carlino | 7f5759382a | |
Rick Carlino | 254adfa765 | |
Rick Carlino | 6b70eccf67 | |
Rick Carlino | 906a62596f | |
Rick Carlino | 95e346558c | |
Rick Carlino | a1c2b16d67 | |
Rick Carlino | 6b9209edad | |
Rick Carlino | c88abc010e | |
Rick Carlino | 91c9c6d2f7 | |
Rick Carlino | 32d7b95961 | |
Rick Carlino | 502edf6221 | |
Rick Carlino | 86d0a9238b |
|
@ -1,35 +1,77 @@
|
|||
version: 2
|
||||
jobs:
|
||||
build:
|
||||
version: 2.1
|
||||
|
||||
executors:
|
||||
build-executor:
|
||||
machine: true
|
||||
working_directory: /home/circleci/project
|
||||
|
||||
commands:
|
||||
build-commands:
|
||||
steps:
|
||||
- checkout
|
||||
- restore_cache:
|
||||
keys:
|
||||
- cache-v1-{{ .Revision }}-{{ .Environment.CIRCLE_WORKFLOW_ID }}
|
||||
- run:
|
||||
name: After cache restore
|
||||
command: |
|
||||
git clean -xdn
|
||||
mkdir -p docker_cache
|
||||
ls docker_cache
|
||||
#sudo docker images
|
||||
#if [ -f docker_cache/images.tar.gz ]; then gunzip -c docker_cache/images.tar.gz | sudo docker load; fi
|
||||
- run:
|
||||
name: Build and Install Deps
|
||||
command: |
|
||||
sudo curl -L "https://github.com/docker/compose/releases/download/1.24.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
|
||||
mv .circleci/circle_envs .env
|
||||
echo -e '\ndocker_volumes/db/pg_wal/*' >> .dockerignore
|
||||
sudo docker-compose run web gem install bundler
|
||||
sudo docker-compose run web bundle install
|
||||
sudo docker-compose run web npm install
|
||||
sudo docker-compose run web bundle exec rails db:create
|
||||
sudo docker-compose run web bundle exec rails db:migrate
|
||||
sudo docker-compose run web rake keys:generate
|
||||
- run:
|
||||
name: After cache update
|
||||
command: |
|
||||
git clean -xdn
|
||||
ls docker_cache
|
||||
#sudo docker images
|
||||
#if [ ! -f docker_cache/images.tar.gz ]; then sudo docker save $(sudo docker images ruby -q) | gzip > docker_cache/images.tar.gz; fi
|
||||
- save_cache:
|
||||
key: cache-v1-{{ .Revision }}-{{ .Environment.CIRCLE_WORKFLOW_ID }}
|
||||
paths:
|
||||
- docker_volumes
|
||||
- node_modules
|
||||
- docker_cache
|
||||
rspec-commands:
|
||||
steps:
|
||||
- run:
|
||||
name: Run Ruby Tests
|
||||
command: |
|
||||
sudo docker-compose run web rspec spec
|
||||
sudo docker-compose run web rspec spec --format progress --format RspecJunitFormatter --out test-results/rspec/rspec.xml
|
||||
jest-commands:
|
||||
steps:
|
||||
- run:
|
||||
name: Run JS tests
|
||||
command: |
|
||||
sudo docker-compose run web npm run test-very-slow -- -c .circleci/jest-ci.config.js
|
||||
echo 'export COVERAGE_AVAILABLE=true' >> $BASH_ENV
|
||||
lint-commands:
|
||||
steps:
|
||||
- run:
|
||||
name: Run JS Linters
|
||||
command: |
|
||||
sudo docker-compose run web npm run linters
|
||||
when: always
|
||||
coverage-commands:
|
||||
steps:
|
||||
- run:
|
||||
name: Run JS Tests
|
||||
name: Check coverage status
|
||||
command: |
|
||||
sudo docker-compose run web npm run test-very-slow
|
||||
echo 'export COVERAGE_AVAILABLE=true' >> $BASH_ENV
|
||||
sudo docker-compose run -e CIRCLE_SHA1="$CIRCLE_SHA1" -e CIRCLE_BRANCH="$CIRCLE_BRANCH" -e CIRCLE_PULL_REQUEST="$CIRCLE_PULL_REQUEST" web rake coverage:run
|
||||
no_output_timeout: 15m
|
||||
when: always
|
||||
- run:
|
||||
name: Report coverage to Coveralls
|
||||
command: |
|
||||
|
@ -38,3 +80,60 @@ jobs:
|
|||
sudo docker-compose run -e COVERALLS_REPO_TOKEN=lEX6nkql7y2YFCcIXVq5ORvdvMtYzfZdG web npm run coverage
|
||||
fi
|
||||
when: always # change to `on_success` for a stricter comparison
|
||||
|
||||
|
||||
workflows:
|
||||
version: 2
|
||||
build_and_test:
|
||||
jobs:
|
||||
#- build
|
||||
- all
|
||||
#- test-api:
|
||||
# requires:
|
||||
# - build
|
||||
#- run-linters:
|
||||
# requires:
|
||||
# - build
|
||||
#- test-fe:
|
||||
# requires:
|
||||
# - build
|
||||
|
||||
jobs:
|
||||
build:
|
||||
executor: build-executor
|
||||
steps:
|
||||
- build-commands
|
||||
all:
|
||||
executor: build-executor
|
||||
steps:
|
||||
- build-commands
|
||||
- rspec-commands
|
||||
- lint-commands
|
||||
- jest-commands
|
||||
- store_test_results:
|
||||
path: test-results
|
||||
- coverage-commands
|
||||
test-api:
|
||||
executor: build-executor
|
||||
steps:
|
||||
- build-commands
|
||||
- rspec-commands
|
||||
- store_test_results:
|
||||
path: test-results
|
||||
run-linters:
|
||||
executor: build-executor
|
||||
steps:
|
||||
- build-commands
|
||||
- lint-commands
|
||||
test-fe:
|
||||
executor: build-executor
|
||||
parallelism: 4
|
||||
steps:
|
||||
- build-commands
|
||||
- run:
|
||||
name: Run JS Tests
|
||||
command: |
|
||||
circleci tests glob **/__tests__/**/*.ts* | circleci tests split > /tmp/tests-to-run
|
||||
sudo docker-compose run web npm run test-very-slow -- -c .circleci/jest-ci.config.js $(cat /tmp/tests-to-run)
|
||||
- store_test_results:
|
||||
path: test-results
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
const baseConfig = require("../jest.config");
|
||||
|
||||
baseConfig.rootDir = "..";
|
||||
baseConfig.reporters.push([
|
||||
"jest-junit",
|
||||
{
|
||||
outputDirectory: "test-results/jest"
|
||||
}
|
||||
]);
|
||||
|
||||
module.exports = baseConfig;
|
|
@ -1,6 +1,7 @@
|
|||
.cache
|
||||
.env
|
||||
.vscode
|
||||
.idea
|
||||
*.log
|
||||
*.pem
|
||||
coverage_api
|
||||
|
|
4
Gemfile
4
Gemfile
|
@ -24,6 +24,7 @@ gem "scenic"
|
|||
gem "secure_headers"
|
||||
gem "tzinfo" # For validation of user selected timezone names
|
||||
gem "valid_url"
|
||||
gem "kaminari"
|
||||
|
||||
group :development, :test do
|
||||
gem "climate_control"
|
||||
|
@ -34,8 +35,9 @@ group :development, :test do
|
|||
gem "hashdiff"
|
||||
gem "pry-rails"
|
||||
gem "pry"
|
||||
gem "rspec-rails", "4.0.0.beta3"
|
||||
gem "rspec-rails"
|
||||
gem "rspec"
|
||||
gem 'rspec_junit_formatter'
|
||||
gem "simplecov"
|
||||
gem "smarf_doc", git: "https://github.com/RickCarlino/smarf_doc.git"
|
||||
end
|
||||
|
|
255
Gemfile.lock
255
Gemfile.lock
|
@ -7,38 +7,38 @@ GIT
|
|||
GEM
|
||||
remote: https://rubygems.org/
|
||||
specs:
|
||||
actioncable (6.0.1)
|
||||
actionpack (= 6.0.1)
|
||||
actioncable (6.0.2.2)
|
||||
actionpack (= 6.0.2.2)
|
||||
nio4r (~> 2.0)
|
||||
websocket-driver (>= 0.6.1)
|
||||
actionmailbox (6.0.1)
|
||||
actionpack (= 6.0.1)
|
||||
activejob (= 6.0.1)
|
||||
activerecord (= 6.0.1)
|
||||
activestorage (= 6.0.1)
|
||||
activesupport (= 6.0.1)
|
||||
actionmailbox (6.0.2.2)
|
||||
actionpack (= 6.0.2.2)
|
||||
activejob (= 6.0.2.2)
|
||||
activerecord (= 6.0.2.2)
|
||||
activestorage (= 6.0.2.2)
|
||||
activesupport (= 6.0.2.2)
|
||||
mail (>= 2.7.1)
|
||||
actionmailer (6.0.1)
|
||||
actionpack (= 6.0.1)
|
||||
actionview (= 6.0.1)
|
||||
activejob (= 6.0.1)
|
||||
actionmailer (6.0.2.2)
|
||||
actionpack (= 6.0.2.2)
|
||||
actionview (= 6.0.2.2)
|
||||
activejob (= 6.0.2.2)
|
||||
mail (~> 2.5, >= 2.5.4)
|
||||
rails-dom-testing (~> 2.0)
|
||||
actionpack (6.0.1)
|
||||
actionview (= 6.0.1)
|
||||
activesupport (= 6.0.1)
|
||||
rack (~> 2.0)
|
||||
actionpack (6.0.2.2)
|
||||
actionview (= 6.0.2.2)
|
||||
activesupport (= 6.0.2.2)
|
||||
rack (~> 2.0, >= 2.0.8)
|
||||
rack-test (>= 0.6.3)
|
||||
rails-dom-testing (~> 2.0)
|
||||
rails-html-sanitizer (~> 1.0, >= 1.2.0)
|
||||
actiontext (6.0.1)
|
||||
actionpack (= 6.0.1)
|
||||
activerecord (= 6.0.1)
|
||||
activestorage (= 6.0.1)
|
||||
activesupport (= 6.0.1)
|
||||
actiontext (6.0.2.2)
|
||||
actionpack (= 6.0.2.2)
|
||||
activerecord (= 6.0.2.2)
|
||||
activestorage (= 6.0.2.2)
|
||||
activesupport (= 6.0.2.2)
|
||||
nokogiri (>= 1.8.5)
|
||||
actionview (6.0.1)
|
||||
activesupport (= 6.0.1)
|
||||
actionview (6.0.2.2)
|
||||
activesupport (= 6.0.2.2)
|
||||
builder (~> 3.1)
|
||||
erubi (~> 1.4)
|
||||
rails-dom-testing (~> 2.0)
|
||||
|
@ -48,20 +48,20 @@ GEM
|
|||
activemodel (>= 4.1, < 6.1)
|
||||
case_transform (>= 0.2)
|
||||
jsonapi-renderer (>= 0.1.1.beta1, < 0.3)
|
||||
activejob (6.0.1)
|
||||
activesupport (= 6.0.1)
|
||||
activejob (6.0.2.2)
|
||||
activesupport (= 6.0.2.2)
|
||||
globalid (>= 0.3.6)
|
||||
activemodel (6.0.1)
|
||||
activesupport (= 6.0.1)
|
||||
activerecord (6.0.1)
|
||||
activemodel (= 6.0.1)
|
||||
activesupport (= 6.0.1)
|
||||
activestorage (6.0.1)
|
||||
actionpack (= 6.0.1)
|
||||
activejob (= 6.0.1)
|
||||
activerecord (= 6.0.1)
|
||||
activemodel (6.0.2.2)
|
||||
activesupport (= 6.0.2.2)
|
||||
activerecord (6.0.2.2)
|
||||
activemodel (= 6.0.2.2)
|
||||
activesupport (= 6.0.2.2)
|
||||
activestorage (6.0.2.2)
|
||||
actionpack (= 6.0.2.2)
|
||||
activejob (= 6.0.2.2)
|
||||
activerecord (= 6.0.2.2)
|
||||
marcel (~> 0.3.1)
|
||||
activesupport (6.0.1)
|
||||
activesupport (6.0.2.2)
|
||||
concurrent-ruby (~> 1.0, >= 1.0.2)
|
||||
i18n (>= 0.7, < 2)
|
||||
minitest (~> 5.1)
|
||||
|
@ -69,11 +69,11 @@ GEM
|
|||
zeitwerk (~> 2.2)
|
||||
addressable (2.7.0)
|
||||
public_suffix (>= 2.0.2, < 5.0)
|
||||
amq-protocol (2.3.0)
|
||||
amq-protocol (2.3.1)
|
||||
bcrypt (3.1.13)
|
||||
builder (3.2.3)
|
||||
bunny (2.14.3)
|
||||
amq-protocol (~> 2.3, >= 2.3.0)
|
||||
builder (3.2.4)
|
||||
bunny (2.15.0)
|
||||
amq-protocol (~> 2.3, >= 2.3.1)
|
||||
case_transform (0.2)
|
||||
activesupport
|
||||
climate_control (0.2.0)
|
||||
|
@ -82,9 +82,9 @@ GEM
|
|||
simplecov
|
||||
url
|
||||
coderay (1.1.2)
|
||||
concurrent-ruby (1.1.5)
|
||||
crass (1.0.5)
|
||||
database_cleaner (1.7.0)
|
||||
concurrent-ruby (1.1.6)
|
||||
crass (1.0.6)
|
||||
database_cleaner (1.8.3)
|
||||
declarative (0.0.10)
|
||||
declarative-option (0.1.0)
|
||||
delayed_job (4.1.8)
|
||||
|
@ -99,27 +99,27 @@ GEM
|
|||
responders
|
||||
warden (~> 1.2.3)
|
||||
diff-lcs (1.3)
|
||||
digest-crc (0.4.1)
|
||||
discard (1.1.0)
|
||||
digest-crc (0.5.1)
|
||||
discard (1.2.0)
|
||||
activerecord (>= 4.2, < 7)
|
||||
docile (1.3.2)
|
||||
erubi (1.9.0)
|
||||
factory_bot (5.1.1)
|
||||
factory_bot (5.1.2)
|
||||
activesupport (>= 4.2.0)
|
||||
factory_bot_rails (5.1.1)
|
||||
factory_bot (~> 5.1.0)
|
||||
railties (>= 4.2.0)
|
||||
faker (2.7.0)
|
||||
i18n (>= 1.6, < 1.8)
|
||||
faraday (0.15.4)
|
||||
faker (2.11.0)
|
||||
i18n (>= 1.6, < 2)
|
||||
faraday (0.17.3)
|
||||
multipart-post (>= 1.2, < 3)
|
||||
faraday_middleware (0.13.1)
|
||||
faraday_middleware (0.14.0)
|
||||
faraday (>= 0.7.4, < 1.0)
|
||||
font-awesome-rails (4.7.0.5)
|
||||
railties (>= 3.2, < 6.1)
|
||||
globalid (0.4.2)
|
||||
activesupport (>= 4.2.0)
|
||||
google-api-client (0.34.1)
|
||||
google-api-client (0.37.2)
|
||||
addressable (~> 2.5, >= 2.5.1)
|
||||
googleauth (~> 0.9)
|
||||
httpclient (>= 2.8.1, < 3.0)
|
||||
|
@ -127,90 +127,104 @@ GEM
|
|||
representable (~> 3.0)
|
||||
retriable (>= 2.0, < 4.0)
|
||||
signet (~> 0.12)
|
||||
google-cloud-core (1.4.1)
|
||||
google-cloud-core (1.5.0)
|
||||
google-cloud-env (~> 1.0)
|
||||
google-cloud-env (1.3.0)
|
||||
faraday (~> 0.11)
|
||||
google-cloud-storage (1.24.0)
|
||||
google-cloud-errors (~> 1.0)
|
||||
google-cloud-env (1.3.1)
|
||||
faraday (>= 0.17.3, < 2.0)
|
||||
google-cloud-errors (1.0.0)
|
||||
google-cloud-storage (1.25.1)
|
||||
addressable (~> 2.5)
|
||||
digest-crc (~> 0.4)
|
||||
google-api-client (~> 0.33)
|
||||
google-cloud-core (~> 1.2)
|
||||
googleauth (~> 0.9)
|
||||
mini_mime (~> 1.0)
|
||||
googleauth (0.10.0)
|
||||
faraday (~> 0.12)
|
||||
googleauth (0.11.0)
|
||||
faraday (>= 0.17.3, < 2.0)
|
||||
jwt (>= 1.4, < 3.0)
|
||||
memoist (~> 0.16)
|
||||
multi_json (~> 1.11)
|
||||
os (>= 0.9, < 2.0)
|
||||
signet (~> 0.12)
|
||||
hashdiff (1.0.0)
|
||||
hashdiff (1.0.1)
|
||||
hashie (3.6.0)
|
||||
httpclient (2.8.3)
|
||||
i18n (1.7.0)
|
||||
i18n (1.8.2)
|
||||
concurrent-ruby (~> 1.0)
|
||||
json (2.2.0)
|
||||
json (2.3.0)
|
||||
jsonapi-renderer (0.2.2)
|
||||
jwt (2.2.1)
|
||||
loofah (2.3.1)
|
||||
kaminari (1.2.0)
|
||||
activesupport (>= 4.1.0)
|
||||
kaminari-actionview (= 1.2.0)
|
||||
kaminari-activerecord (= 1.2.0)
|
||||
kaminari-core (= 1.2.0)
|
||||
kaminari-actionview (1.2.0)
|
||||
actionview
|
||||
kaminari-core (= 1.2.0)
|
||||
kaminari-activerecord (1.2.0)
|
||||
activerecord
|
||||
kaminari-core (= 1.2.0)
|
||||
kaminari-core (1.2.0)
|
||||
loofah (2.5.0)
|
||||
crass (~> 1.0.2)
|
||||
nokogiri (>= 1.5.9)
|
||||
mail (2.7.1)
|
||||
mini_mime (>= 0.1.1)
|
||||
marcel (0.3.3)
|
||||
mimemagic (~> 0.3.2)
|
||||
memoist (0.16.1)
|
||||
method_source (0.9.2)
|
||||
mimemagic (0.3.3)
|
||||
memoist (0.16.2)
|
||||
method_source (1.0.0)
|
||||
mimemagic (0.3.4)
|
||||
mini_mime (1.0.2)
|
||||
mini_portile2 (2.4.0)
|
||||
minitest (5.13.0)
|
||||
minitest (5.14.0)
|
||||
multi_json (1.13.1)
|
||||
multipart-post (2.1.1)
|
||||
mutations (0.9.0)
|
||||
mutations (0.9.1)
|
||||
activesupport
|
||||
nio4r (2.5.2)
|
||||
nokogiri (1.10.5)
|
||||
nokogiri (1.10.9)
|
||||
mini_portile2 (~> 2.4.0)
|
||||
orm_adapter (0.5.0)
|
||||
os (1.0.1)
|
||||
passenger (6.0.4)
|
||||
rack
|
||||
rake (>= 0.8.1)
|
||||
pg (1.1.4)
|
||||
pry (0.12.2)
|
||||
coderay (~> 1.1.0)
|
||||
method_source (~> 0.9.0)
|
||||
pg (1.2.3)
|
||||
pry (0.13.1)
|
||||
coderay (~> 1.1)
|
||||
method_source (~> 1.0)
|
||||
pry-rails (0.3.9)
|
||||
pry (>= 0.10.4)
|
||||
public_suffix (4.0.1)
|
||||
rabbitmq_http_api_client (1.12.0)
|
||||
faraday (~> 0.15.4)
|
||||
faraday_middleware (~> 0.13.0)
|
||||
public_suffix (4.0.3)
|
||||
rabbitmq_http_api_client (1.13.0)
|
||||
faraday (>= 0.15, < 1)
|
||||
faraday_middleware (>= 0.13.0, < 1)
|
||||
hashie (~> 3.6)
|
||||
multi_json (~> 1.13.1)
|
||||
rack (2.0.7)
|
||||
rack-attack (6.2.1)
|
||||
rack (2.2.2)
|
||||
rack-attack (6.2.2)
|
||||
rack (>= 1.0, < 3)
|
||||
rack-cors (1.0.6)
|
||||
rack (>= 1.6.0)
|
||||
rack-cors (1.1.1)
|
||||
rack (>= 2.0.0)
|
||||
rack-test (1.1.0)
|
||||
rack (>= 1.0, < 3)
|
||||
rails (6.0.1)
|
||||
actioncable (= 6.0.1)
|
||||
actionmailbox (= 6.0.1)
|
||||
actionmailer (= 6.0.1)
|
||||
actionpack (= 6.0.1)
|
||||
actiontext (= 6.0.1)
|
||||
actionview (= 6.0.1)
|
||||
activejob (= 6.0.1)
|
||||
activemodel (= 6.0.1)
|
||||
activerecord (= 6.0.1)
|
||||
activestorage (= 6.0.1)
|
||||
activesupport (= 6.0.1)
|
||||
rails (6.0.2.2)
|
||||
actioncable (= 6.0.2.2)
|
||||
actionmailbox (= 6.0.2.2)
|
||||
actionmailer (= 6.0.2.2)
|
||||
actionpack (= 6.0.2.2)
|
||||
actiontext (= 6.0.2.2)
|
||||
actionview (= 6.0.2.2)
|
||||
activejob (= 6.0.2.2)
|
||||
activemodel (= 6.0.2.2)
|
||||
activerecord (= 6.0.2.2)
|
||||
activestorage (= 6.0.2.2)
|
||||
activesupport (= 6.0.2.2)
|
||||
bundler (>= 1.3.0)
|
||||
railties (= 6.0.1)
|
||||
railties (= 6.0.2.2)
|
||||
sprockets-rails (>= 2.0.0)
|
||||
rails-dom-testing (2.0.3)
|
||||
activesupport (>= 4.2.0)
|
||||
|
@ -222,9 +236,9 @@ GEM
|
|||
rails_stdout_logging
|
||||
rails_serve_static_assets (0.0.5)
|
||||
rails_stdout_logging (0.0.5)
|
||||
railties (6.0.1)
|
||||
actionpack (= 6.0.1)
|
||||
activesupport (= 6.0.1)
|
||||
railties (6.0.2.2)
|
||||
actionpack (= 6.0.2.2)
|
||||
activesupport (= 6.0.2.2)
|
||||
method_source
|
||||
rake (>= 0.8.7)
|
||||
thor (>= 0.20.3, < 2.0)
|
||||
|
@ -234,48 +248,49 @@ GEM
|
|||
declarative (< 0.1.0)
|
||||
declarative-option (< 0.2.0)
|
||||
uber (< 0.2.0)
|
||||
request_store (1.4.1)
|
||||
request_store (1.5.0)
|
||||
rack (>= 1.4)
|
||||
responders (3.0.0)
|
||||
actionpack (>= 5.0)
|
||||
railties (>= 5.0)
|
||||
retriable (3.1.2)
|
||||
rollbar (2.22.1)
|
||||
rollbar (2.24.0)
|
||||
rspec (3.9.0)
|
||||
rspec-core (~> 3.9.0)
|
||||
rspec-expectations (~> 3.9.0)
|
||||
rspec-mocks (~> 3.9.0)
|
||||
rspec-core (3.9.0)
|
||||
rspec-support (~> 3.9.0)
|
||||
rspec-expectations (3.9.0)
|
||||
rspec-core (3.9.1)
|
||||
rspec-support (~> 3.9.1)
|
||||
rspec-expectations (3.9.1)
|
||||
diff-lcs (>= 1.2.0, < 2.0)
|
||||
rspec-support (~> 3.9.0)
|
||||
rspec-mocks (3.9.0)
|
||||
rspec-mocks (3.9.1)
|
||||
diff-lcs (>= 1.2.0, < 2.0)
|
||||
rspec-support (~> 3.9.0)
|
||||
rspec-rails (4.0.0.beta3)
|
||||
rspec-rails (4.0.0)
|
||||
actionpack (>= 4.2)
|
||||
activesupport (>= 4.2)
|
||||
railties (>= 4.2)
|
||||
rspec-core (~> 3.8)
|
||||
rspec-expectations (~> 3.8)
|
||||
rspec-mocks (~> 3.8)
|
||||
rspec-support (~> 3.8)
|
||||
rspec-support (3.9.0)
|
||||
scenic (1.5.1)
|
||||
rspec-core (~> 3.9)
|
||||
rspec-expectations (~> 3.9)
|
||||
rspec-mocks (~> 3.9)
|
||||
rspec-support (~> 3.9)
|
||||
rspec-support (3.9.2)
|
||||
rspec_junit_formatter (0.4.1)
|
||||
rspec-core (>= 2, < 4, != 2.12.0)
|
||||
scenic (1.5.2)
|
||||
activerecord (>= 4.0.0)
|
||||
railties (>= 4.0.0)
|
||||
secure_headers (6.1.1)
|
||||
signet (0.12.0)
|
||||
secure_headers (6.3.0)
|
||||
signet (0.13.0)
|
||||
addressable (~> 2.3)
|
||||
faraday (~> 0.9)
|
||||
faraday (>= 0.17.3, < 2.0)
|
||||
jwt (>= 1.5, < 3.0)
|
||||
multi_json (~> 1.10)
|
||||
simplecov (0.17.1)
|
||||
simplecov (0.18.5)
|
||||
docile (~> 1.1)
|
||||
json (>= 1.8, < 3)
|
||||
simplecov-html (~> 0.10.0)
|
||||
simplecov-html (0.10.2)
|
||||
simplecov-html (~> 0.11)
|
||||
simplecov-html (0.12.2)
|
||||
sprockets (4.0.0)
|
||||
concurrent-ruby (~> 1.0)
|
||||
rack (> 1, < 3)
|
||||
|
@ -283,9 +298,9 @@ GEM
|
|||
actionpack (>= 4.0)
|
||||
activesupport (>= 4.0)
|
||||
sprockets (>= 3.0.0)
|
||||
thor (0.20.3)
|
||||
thor (1.0.1)
|
||||
thread_safe (0.3.6)
|
||||
tzinfo (1.2.5)
|
||||
tzinfo (1.2.7)
|
||||
thread_safe (~> 0.1)
|
||||
uber (0.1.0)
|
||||
url (0.3.2)
|
||||
|
@ -297,7 +312,7 @@ GEM
|
|||
websocket-driver (0.7.1)
|
||||
websocket-extensions (>= 0.1.0)
|
||||
websocket-extensions (0.1.4)
|
||||
zeitwerk (2.2.1)
|
||||
zeitwerk (2.3.0)
|
||||
|
||||
PLATFORMS
|
||||
ruby
|
||||
|
@ -318,6 +333,7 @@ DEPENDENCIES
|
|||
google-cloud-storage (~> 1.11)
|
||||
hashdiff
|
||||
jwt
|
||||
kaminari
|
||||
mutations
|
||||
passenger
|
||||
pg
|
||||
|
@ -332,7 +348,8 @@ DEPENDENCIES
|
|||
request_store
|
||||
rollbar
|
||||
rspec
|
||||
rspec-rails (= 4.0.0.beta3)
|
||||
rspec-rails
|
||||
rspec_junit_formatter
|
||||
scenic
|
||||
secure_headers
|
||||
simplecov
|
||||
|
@ -344,4 +361,4 @@ RUBY VERSION
|
|||
ruby 2.6.5p114
|
||||
|
||||
BUNDLED WITH
|
||||
1.17.2
|
||||
2.1.4
|
||||
|
|
|
@ -80,6 +80,16 @@ module Api
|
|||
{ root: false, user: current_user }
|
||||
end
|
||||
|
||||
def maybe_paginate(collection)
|
||||
page = params[:page]
|
||||
per = params[:per]
|
||||
|
||||
if page && per
|
||||
render json: collection.page(page).per(per)
|
||||
else
|
||||
render json: collection
|
||||
end
|
||||
end
|
||||
private
|
||||
|
||||
def clean_expired_farm_events
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
module Api
|
||||
class AlertsController < Api::AbstractController
|
||||
def index
|
||||
render json: current_device.alerts
|
||||
maybe_paginate current_device.alerts
|
||||
end
|
||||
|
||||
def destroy
|
||||
|
|
|
@ -1,26 +0,0 @@
|
|||
module Api
|
||||
class DiagnosticDumpsController < Api::AbstractController
|
||||
def index
|
||||
render json: diagnostic_dumps
|
||||
end
|
||||
|
||||
def create
|
||||
mutate DiagnosticDumps::Create.run(raw_json, device: current_device)
|
||||
end
|
||||
|
||||
def destroy
|
||||
diagnostic_dump.destroy!
|
||||
render json: ""
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def diagnostic_dumps
|
||||
current_device.diagnostic_dumps
|
||||
end
|
||||
|
||||
def diagnostic_dump
|
||||
@diagnostic_dump ||= diagnostic_dumps.find(params[:id])
|
||||
end
|
||||
end
|
||||
end
|
|
@ -3,7 +3,7 @@ module Api
|
|||
before_action :clean_expired_farm_events, only: [:index]
|
||||
|
||||
def index
|
||||
render json: current_device.farm_events
|
||||
maybe_paginate current_device.farm_events
|
||||
end
|
||||
|
||||
def show
|
||||
|
|
|
@ -10,7 +10,7 @@ module Api
|
|||
end
|
||||
|
||||
def index
|
||||
render json: farmware_envs
|
||||
maybe_paginate farmware_envs
|
||||
end
|
||||
|
||||
def show
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
module Api
|
||||
class FarmwareInstallationsController < Api::AbstractController
|
||||
def index
|
||||
render json: farmware_installations
|
||||
maybe_paginate farmware_installations
|
||||
end
|
||||
|
||||
def show
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
module Api
|
||||
class FoldersController < Api::AbstractController
|
||||
def create
|
||||
mutate Folders::Create.run(raw_json, device: current_device)
|
||||
end
|
||||
|
||||
def index
|
||||
render json: folders
|
||||
end
|
||||
|
||||
def show
|
||||
render json: folder
|
||||
end
|
||||
|
||||
def update
|
||||
mutate Folders::Update.run(raw_json,
|
||||
folder: folder,
|
||||
device: current_device)
|
||||
end
|
||||
|
||||
def destroy
|
||||
mutate Folders::Destroy.run(folder: folder, device: current_device)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def folder
|
||||
folders.find(params[:id])
|
||||
end
|
||||
|
||||
def folders
|
||||
current_device.folders
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,7 +1,7 @@
|
|||
module Api
|
||||
class PeripheralsController < Api::AbstractController
|
||||
def index
|
||||
render json: current_device.peripherals
|
||||
maybe_paginate current_device.peripherals
|
||||
end
|
||||
|
||||
def show
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
module Api
|
||||
class PinBindingsController < Api::AbstractController
|
||||
def index
|
||||
render json: pin_bindings
|
||||
maybe_paginate pin_bindings
|
||||
end
|
||||
|
||||
def show
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
module Api
|
||||
class PlantTemplatesController < Api::AbstractController
|
||||
def index
|
||||
render json: current_device.plant_templates
|
||||
maybe_paginate current_device.plant_templates
|
||||
end
|
||||
|
||||
def create
|
||||
|
|
|
@ -3,7 +3,7 @@ module Api
|
|||
before_action :clean_expired_farm_events, only: [:destroy]
|
||||
|
||||
def index
|
||||
render json: your_point_groups
|
||||
maybe_paginate your_point_groups
|
||||
end
|
||||
|
||||
def show
|
||||
|
|
|
@ -20,7 +20,7 @@ module Api
|
|||
.where("discarded_at < ?", Time.now - HARD_DELETE_AFTER)
|
||||
.destroy_all
|
||||
|
||||
render json: points(params.fetch(:filter) { "kept" })
|
||||
maybe_paginate points(params.fetch(:filter) { "kept" })
|
||||
end
|
||||
|
||||
def show
|
||||
|
|
|
@ -3,7 +3,7 @@ module Api
|
|||
before_action :clean_expired_farm_events, only: [:destroy]
|
||||
|
||||
def index
|
||||
render json: your_regimens
|
||||
maybe_paginate your_regimens
|
||||
end
|
||||
|
||||
def show
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
module Api
|
||||
class SavedGardensController < Api::AbstractController
|
||||
def index
|
||||
render json: current_device.saved_gardens
|
||||
maybe_paginate current_device.saved_gardens
|
||||
end
|
||||
|
||||
def create
|
||||
|
|
|
@ -1,11 +1,14 @@
|
|||
module Api
|
||||
class SensorReadingsController < Api::AbstractController
|
||||
LIMIT = 5000
|
||||
before_action :clean_old
|
||||
|
||||
def create
|
||||
mutate SensorReadings::Create.run(raw_json, device: current_device)
|
||||
mutate SensorReadings::Create.run(raw_json, device: current_device)
|
||||
end
|
||||
|
||||
def index
|
||||
render json: readings
|
||||
maybe_paginate(readings)
|
||||
end
|
||||
|
||||
def show
|
||||
|
@ -17,10 +20,23 @@ module Api
|
|||
render json: ""
|
||||
end
|
||||
|
||||
private
|
||||
private
|
||||
|
||||
def clean_old
|
||||
if current_device.sensor_readings.count > LIMIT
|
||||
current_device
|
||||
.sensor_readings
|
||||
.where
|
||||
.not(id: readings.pluck(:id))
|
||||
.delete_all
|
||||
end
|
||||
end
|
||||
|
||||
def readings
|
||||
SensorReading.where(device: current_device)
|
||||
@readings ||= SensorReading
|
||||
.where(device: current_device)
|
||||
.order(created_at: :desc)
|
||||
.limit(LIMIT)
|
||||
end
|
||||
|
||||
def reading
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
module Api
|
||||
class SensorsController < Api::AbstractController
|
||||
def index
|
||||
render json: current_device.sensors
|
||||
maybe_paginate current_device.sensors
|
||||
end
|
||||
|
||||
def show
|
||||
|
|
|
@ -2,7 +2,7 @@ module Api
|
|||
class ToolsController < Api::AbstractController
|
||||
|
||||
def index
|
||||
render json: tools
|
||||
maybe_paginate tools
|
||||
end
|
||||
|
||||
def show
|
||||
|
|
|
@ -7,7 +7,7 @@ module Api
|
|||
end
|
||||
|
||||
def index
|
||||
render json: webcams
|
||||
maybe_paginate webcams
|
||||
end
|
||||
|
||||
def show
|
||||
|
|
|
@ -7,6 +7,7 @@ class DashboardController < ApplicationController
|
|||
:main_app,
|
||||
:password_reset,
|
||||
:tos_update,
|
||||
:os_download,
|
||||
:demo]
|
||||
|
||||
OUTPUT_URL = "/" + File.join("assets", "parcel") # <= served from public/ dir
|
||||
|
@ -24,6 +25,7 @@ class DashboardController < ApplicationController
|
|||
password_reset: "/password_reset/index.tsx",
|
||||
tos_update: "/tos_update/index.tsx",
|
||||
demo: "/demo/index.tsx",
|
||||
os_download: "/os_download/index.tsx"
|
||||
}.with_indifferent_access
|
||||
|
||||
# === THESE CONSTANTS ARE NON-CONFIGURABLE. ===
|
||||
|
|
|
@ -26,7 +26,7 @@ module CeleryScript
|
|||
|
||||
def maybe_initialize(parent, leaf_or_node, key = NEVER)
|
||||
if is_node?(leaf_or_node)
|
||||
AstNode.new(parent, leaf_or_node)
|
||||
AstNode.new(parent, **leaf_or_node)
|
||||
else
|
||||
raise TypeCheckError, LEAVES_NEED_KEYS if key == NEVER
|
||||
AstLeaf.new(parent, leaf_or_node, key)
|
||||
|
|
|
@ -26,6 +26,7 @@ module CeleryScript
|
|||
FRIENDLY_ERRORS = {
|
||||
nothing: {
|
||||
write_pin: "You must select a Peripheral in the Control Peripheral step.",
|
||||
toggle_pin: "You must select a Peripheral in the Toggle Peripheral step.",
|
||||
variable_declaration: MISSING_VAR,
|
||||
parameter_declaration: MISSING_PARAM,
|
||||
read_pin: "You must select a Sensor in the Read Sensor step.",
|
||||
|
|
|
@ -90,6 +90,7 @@ module CeleryScript
|
|||
id: sequence.id,
|
||||
created_at: sequence.created_at,
|
||||
updated_at: sequence.updated_at,
|
||||
folder_id: sequence.folder_id,
|
||||
args: Sequence::DEFAULT_ARGS,
|
||||
color: sequence.color,
|
||||
name: sequence.name,
|
||||
|
|
|
@ -5,7 +5,7 @@ class LogService < AbstractServiceRunner
|
|||
THROTTLE_POLICY = ThrottlePolicy.new(name, min: 250, hour: 5_000, day: 25_000)
|
||||
|
||||
LOG_TPL = Rails.env.test? ?
|
||||
"\e[32m.\e[0m" : "FBOS LOG (device_%s): %s\n"
|
||||
"\e[32m.\e[0m" : "FBOS LOG (device_%s) [v%s]: %s\n"
|
||||
ERR_TPL = "MALFORMED LOG CAPTURE: %s"
|
||||
# Clean up excess logs in a non-deterministic manner.
|
||||
# Performs the slow DB query every nth request.
|
||||
|
@ -41,7 +41,9 @@ class LogService < AbstractServiceRunner
|
|||
dev, log = [data.device, data.payload]
|
||||
dev.maybe_unthrottle
|
||||
Log.deliver(Logs::Create.run!(log, device: dev).id)
|
||||
print LOG_TPL % [data.device_id, data.payload["message"] || "??"]
|
||||
print LOG_TPL % [data.device_id,
|
||||
dev.fbos_version || "?",
|
||||
data.payload["message"] || "??"]
|
||||
rescue => x
|
||||
Rollbar.error(x)
|
||||
end
|
||||
|
|
|
@ -46,5 +46,6 @@ module Resources
|
|||
Plant => Points,
|
||||
Point => Points,
|
||||
ToolSlot => Points,
|
||||
Weed => Points,
|
||||
}
|
||||
end # Resources
|
||||
|
|
|
@ -16,9 +16,9 @@ module CeleryScriptSettingsBag
|
|||
end
|
||||
|
||||
PIN_TYPE_MAP = { "Peripheral" => Peripheral,
|
||||
"Sensor" => Sensor,
|
||||
"BoxLed3" => BoxLed,
|
||||
"BoxLed4" => BoxLed }
|
||||
"Sensor" => Sensor,
|
||||
"BoxLed3" => BoxLed,
|
||||
"BoxLed4" => BoxLed }
|
||||
ALLOWED_AXIS = %w(x y z all)
|
||||
ALLOWED_ASSERTION_TYPES = %w(abort recover abort_recover continue)
|
||||
ALLOWED_CHANGES = %w(add remove update)
|
||||
|
@ -30,19 +30,19 @@ module CeleryScriptSettingsBag
|
|||
ALLOWED_PACKAGES = %w(farmbot_os arduino_firmware)
|
||||
ALLOWED_PIN_MODES = [DIGITAL = 0, ANALOG = 1]
|
||||
ALLOWED_PIN_TYPES = PIN_TYPE_MAP.keys
|
||||
ALLOWED_POINTER_TYPE = %w(GenericPointer ToolSlot Plant)
|
||||
ALLOWED_RESOURCE_TYPE = %w(Device Point Plant ToolSlot GenericPointer)
|
||||
ALLOWED_POINTER_TYPE = %w(GenericPointer ToolSlot Plant Weed)
|
||||
ALLOWED_RESOURCE_TYPE = %w(Device Point Plant ToolSlot Weed GenericPointer)
|
||||
ALLOWED_RPC_NODES = %w(assertion calibrate change_ownership
|
||||
check_updates dump_info emergency_lock
|
||||
check_updates emergency_lock
|
||||
emergency_unlock execute execute_script
|
||||
factory_reset find_home flash_firmware home
|
||||
install_farmware install_first_party_farmware _if
|
||||
move_absolute move_relative power_off read_pin
|
||||
read_status reboot remove_farmware resource_update
|
||||
read_status reboot remove_farmware update_resource
|
||||
send_message set_servo_angle set_user_env sync
|
||||
take_photo toggle_pin update_farmware wait
|
||||
write_pin zero)
|
||||
ALLOWED_SPEC_ACTION = %w(dump_info emergency_lock emergency_unlock power_off
|
||||
ALLOWED_SPEC_ACTION = %w(emergency_lock emergency_unlock power_off
|
||||
read_status reboot sync take_photo)
|
||||
ANY_VARIABLE = %i(tool coordinate point identifier)
|
||||
BAD_ALLOWED_PIN_MODES = '"%s" is not a valid pin_mode. Allowed values: %s'
|
||||
|
@ -73,8 +73,7 @@ module CeleryScriptSettingsBag
|
|||
ONLY_ONE_COORD = "Move Absolute does not accept a group of locations " \
|
||||
"as input. Please change your selection to a single" \
|
||||
" location."
|
||||
PLANT_STAGES = %w(planned planted harvested sprouted)
|
||||
RESOURCE_UPDATE_ARGS = [:resource_type, :resource_id, :label, :value]
|
||||
PLANT_STAGES = %w(planned planted harvested sprouted removed)
|
||||
SCOPE_DECLARATIONS = [:variable_declaration, :parameter_declaration]
|
||||
MISC_ENUM_ERR = '"%s" is not valid. Allowed values: %s'
|
||||
MAX_WAIT_MS = 1000 * 60 * 3 # Three Minutes
|
||||
|
@ -82,6 +81,13 @@ module CeleryScriptSettingsBag
|
|||
"A single wait node cannot exceed #{MAX_WAIT_MS / 1000 / 60} minutes. " +
|
||||
"Consider lowering the wait time or using multiple WAIT blocks."
|
||||
Corpus = CeleryScript::Corpus.new
|
||||
THIS_IS_DEPRECATED = {
|
||||
args: [:resource_type, :resource_id, :label, :value],
|
||||
tags: [:function, :api_writer, :network_user],
|
||||
blk: ->(n) do
|
||||
n.invalidate!("Deprecated `mark_as` detected. Delete it and re-add")
|
||||
end,
|
||||
}
|
||||
|
||||
CORPUS_VALUES = {
|
||||
boolean: [TrueClass, FalseClass],
|
||||
|
@ -278,6 +284,9 @@ module CeleryScriptSettingsBag
|
|||
lua: {
|
||||
defn: [v(:string)],
|
||||
},
|
||||
resource: {
|
||||
defn: [n(:identifier), n(:resource)],
|
||||
},
|
||||
}.map do |(name, conf)|
|
||||
blk = conf[:blk]
|
||||
defn = conf.fetch(:defn)
|
||||
|
@ -317,10 +326,6 @@ module CeleryScriptSettingsBag
|
|||
args: [:x, :y, :z],
|
||||
tags: [:data, :location_like],
|
||||
},
|
||||
dump_info: {
|
||||
tags: [:function, :network_user, :disk_user, :api_writer],
|
||||
docs: "Sends an info dump to server administrators for troubleshooting.",
|
||||
},
|
||||
emergency_lock: {
|
||||
tags: [:function, :firmware_user, :control_flow],
|
||||
},
|
||||
|
@ -513,15 +518,22 @@ module CeleryScriptSettingsBag
|
|||
tags: [:function, :firmware_user, :rpi_user],
|
||||
blk: ->(n) { no_rpi_analog(n) },
|
||||
},
|
||||
resource_update: {
|
||||
args: RESOURCE_UPDATE_ARGS,
|
||||
tags: [:function, :api_writer, :network_user],
|
||||
# DEPRECATED- Get rid of this node ASAP -RC 15 APR 2020
|
||||
resource_update: THIS_IS_DEPRECATED,
|
||||
resource: {
|
||||
args: [:resource_type, :resource_id],
|
||||
tags: [:network_user],
|
||||
blk: ->(n) do
|
||||
resource_type = n.args.fetch(:resource_type).value
|
||||
resource_id = n.args.fetch(:resource_id).value
|
||||
check_resource_type(n, resource_type, resource_id, Device.current)
|
||||
end,
|
||||
},
|
||||
update_resource: {
|
||||
args: [:resource],
|
||||
body: [:pair],
|
||||
tags: [:function, :api_writer, :network_user],
|
||||
},
|
||||
point_group: {
|
||||
args: [:point_group_id],
|
||||
tags: [:data, :list_like],
|
||||
|
|
|
@ -16,7 +16,7 @@ class Device < ApplicationRecord
|
|||
images logs peripherals pin_bindings plant_templates
|
||||
points point_groups regimens saved_gardens
|
||||
sensor_readings sensors sequences token_issuances tools
|
||||
webcam_feeds diagnostic_dumps fragments)
|
||||
webcam_feeds fragments)
|
||||
|
||||
PLURAL_RESOURCES.map { |resources| has_many resources, dependent: :destroy }
|
||||
|
||||
|
@ -34,6 +34,7 @@ class Device < ApplicationRecord
|
|||
has_many :in_use_tools
|
||||
has_many :in_use_points
|
||||
has_many :users
|
||||
has_many :folders
|
||||
|
||||
validates_presence_of :name
|
||||
validates :timezone, inclusion: {
|
||||
|
@ -170,9 +171,10 @@ class Device < ApplicationRecord
|
|||
end
|
||||
|
||||
TOO_MANY_CONNECTIONS =
|
||||
"Your device is " +
|
||||
"reconnecting to the server too often. Please " +
|
||||
"see https://developer.farm.bot/docs/connectivity-issues"
|
||||
"Your device is reconnecting to the server too often. " +
|
||||
"This may be a sign of local network issues. " +
|
||||
"Please review the documentation provided at " +
|
||||
"https://software.farm.bot/docs/connecting-farmbot-to-the-internet"
|
||||
def self.connection_warning(username)
|
||||
device_id = username.split("_").last.to_i || 0
|
||||
device = self.find_by(id: device_id)
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
class DiagnosticDump < ApplicationRecord
|
||||
belongs_to :device
|
||||
end
|
|
@ -12,6 +12,7 @@ class FbosConfig < ApplicationRecord
|
|||
ARDUINO = "arduino",
|
||||
FARMDUINO = "farmduino",
|
||||
FARMDUINO_K14 = "farmduino_k14",
|
||||
FARMDUINO_K15 = "farmduino_k15",
|
||||
EXPRESS_K10 = "express_k10",
|
||||
]
|
||||
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
class Folder < ApplicationRecord
|
||||
belongs_to :device
|
||||
|
||||
has_many :sub_folders, class_name: "Folder",
|
||||
foreign_key: "parent_id"
|
||||
|
||||
belongs_to :parent, class_name: "Folder", optional: true
|
||||
end
|
|
@ -78,7 +78,7 @@ class Fragment < ApplicationRecord
|
|||
|
||||
def self.from_celery(device:, kind:, args:, body:, owner:)
|
||||
p = { device: device, kind: kind, args: args, body: body }
|
||||
flat_ast = Fragments::Preprocessor.run!(p)
|
||||
flat_ast = Fragments::Preprocessor.run!(**p)
|
||||
Fragments::Create.run!(device: device,
|
||||
flat_ast: flat_ast,
|
||||
owner: owner)
|
||||
|
|
|
@ -43,7 +43,7 @@ class Image < ApplicationRecord
|
|||
has_one_attached :attachment
|
||||
|
||||
def set_attachment_by_url(url)
|
||||
attachment.attach(io: open(url), filename: "image_#{self.id}")
|
||||
attachment.attach(io: URI.open(url), filename: "image_#{self.id}")
|
||||
self.attachment_processed_at = Time.now
|
||||
self
|
||||
end
|
||||
|
|
|
@ -6,8 +6,9 @@ class InUsePoint < ApplicationRecord
|
|||
DEFAULT_NAME = "point"
|
||||
FANCY_NAMES = {
|
||||
GenericPointer.name => DEFAULT_NAME,
|
||||
ToolSlot.name => "tool slot",
|
||||
ToolSlot.name => "slot",
|
||||
Plant.name => "plant",
|
||||
Weed.name => "weed"
|
||||
}
|
||||
|
||||
def readonly?
|
||||
|
|
|
@ -1,20 +1,18 @@
|
|||
class PinBinding < ApplicationRecord
|
||||
OFF_LIMITS = [
|
||||
2, 3, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 17, 19, 21, 23, 24, 25, 27
|
||||
OFF_LIMITS = [
|
||||
2, 3, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 17, 19, 21, 23, 24, 25, 27,
|
||||
]
|
||||
BAD_PIN_NUM = \
|
||||
"The following pin numbers cannot be used: %s" % OFF_LIMITS.join(", ")
|
||||
BAD_PIN_NUM = "The following pin numbers cannot be used: %s" % OFF_LIMITS.join(", ")
|
||||
|
||||
belongs_to :device
|
||||
belongs_to :sequence
|
||||
enum special_action: { dump_info: "dump_info",
|
||||
emergency_lock: "emergency_lock",
|
||||
enum special_action: { emergency_lock: "emergency_lock",
|
||||
emergency_unlock: "emergency_unlock",
|
||||
power_off: "power_off",
|
||||
read_status: "read_status",
|
||||
reboot: "reboot",
|
||||
sync: "sync",
|
||||
take_photo: "take_photo" }
|
||||
power_off: "power_off",
|
||||
read_status: "read_status",
|
||||
reboot: "reboot",
|
||||
sync: "sync",
|
||||
take_photo: "take_photo" }
|
||||
validates :pin_num, uniqueness: { scope: :device }
|
||||
|
||||
def fancy_name
|
||||
|
|
|
@ -4,7 +4,7 @@ class Point < ApplicationRecord
|
|||
# axis value > 21k right now - RC
|
||||
# Using real constants instead of strings results
|
||||
# in circular dep. errors.
|
||||
POINTER_KINDS = ["GenericPointer", "Plant", "ToolSlot"]
|
||||
POINTER_KINDS = ["GenericPointer", "Plant", "ToolSlot", "Weed"]
|
||||
self.inheritance_column = "pointer_type"
|
||||
|
||||
belongs_to :device
|
||||
|
|
|
@ -3,9 +3,17 @@ class PointGroup < ApplicationRecord
|
|||
%w(xy_ascending xy_descending yx_ascending yx_descending random).sort
|
||||
BAD_SORT = "%{value} is not valid. Valid options are: " +
|
||||
SORT_TYPES.map(&:inspect).join(", ")
|
||||
DEFAULT_CRITERIA = {
|
||||
day: { op: "<", days_ago: 0 },
|
||||
string_eq: {},
|
||||
number_eq: {},
|
||||
number_lt: {},
|
||||
number_gt: {},
|
||||
}
|
||||
|
||||
belongs_to :device
|
||||
has_many :point_group_items, dependent: :destroy
|
||||
validates_inclusion_of :sort_type, in: SORT_TYPES,
|
||||
message: BAD_SORT
|
||||
serialize :criteria
|
||||
end
|
||||
|
|
|
@ -16,6 +16,7 @@ class Sequence < ApplicationRecord
|
|||
include CeleryScriptSettingsBag
|
||||
|
||||
belongs_to :device
|
||||
belongs_to :folder
|
||||
belongs_to :fbos_config, foreign_key: :boot_sequence_id
|
||||
has_one :sequence_usage_report
|
||||
has_many :farm_events, as: :executable
|
||||
|
|
|
@ -11,7 +11,7 @@ class ToolSlot < Point
|
|||
MIN_PULLOUT = PULLOUT_DIRECTIONS.min
|
||||
PULLOUT_ERR = "must be a value between #{MIN_PULLOUT} and #{MAX_PULLOUT}. "\
|
||||
"%{value} is not valid."
|
||||
IN_USE = "already in use by another tool slot. "\
|
||||
IN_USE = "already in use by another slot. "\
|
||||
"Please un-assign the tool from its current slot"\
|
||||
" before reassigning."
|
||||
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
class Weed < Point
|
||||
end
|
|
@ -7,7 +7,9 @@ module Devices
|
|||
"genesis_1.2" => Devices::Seeders::GenesisOneTwo,
|
||||
"genesis_1.3" => Devices::Seeders::GenesisOneThree,
|
||||
"genesis_1.4" => Devices::Seeders::GenesisOneFour,
|
||||
"genesis_1.5" => Devices::Seeders::GenesisOneFive,
|
||||
"genesis_xl_1.4" => Devices::Seeders::GenesisXlOneFour,
|
||||
"genesis_xl_1.5" => Devices::Seeders::GenesisXlOneFive,
|
||||
|
||||
"demo_account" => Devices::Seeders::DemoAccountSeeder,
|
||||
"none" => Devices::Seeders::None,
|
||||
|
|
|
@ -27,7 +27,7 @@ module Devices
|
|||
add_tool_slot(name: ToolNames::SEED_TROUGH_1,
|
||||
x: 0,
|
||||
y: 25,
|
||||
z: -200,
|
||||
z: 0,
|
||||
tool: tools_seed_trough_1,
|
||||
pullout_direction: ToolSlot::NONE,
|
||||
gantry_mounted: true)
|
||||
|
@ -37,25 +37,18 @@ module Devices
|
|||
add_tool_slot(name: ToolNames::SEED_TROUGH_2,
|
||||
x: 0,
|
||||
y: 50,
|
||||
z: -200,
|
||||
z: 0,
|
||||
tool: tools_seed_trough_2,
|
||||
pullout_direction: ToolSlot::NONE,
|
||||
gantry_mounted: true)
|
||||
end
|
||||
|
||||
def tool_slots_slot_3
|
||||
add_tool_slot(name: ToolNames::SEED_TROUGH_3,
|
||||
x: 0,
|
||||
y: 75,
|
||||
z: -200,
|
||||
tool: tools_seed_trough_3,
|
||||
pullout_direction: ToolSlot::NONE,
|
||||
gantry_mounted: true)
|
||||
end
|
||||
|
||||
def tool_slots_slot_3; end
|
||||
def tool_slots_slot_4; end
|
||||
def tool_slots_slot_5; end
|
||||
def tool_slots_slot_6; end
|
||||
def tool_slots_slot_7; end
|
||||
def tool_slots_slot_8; end
|
||||
def tools_seed_bin; end
|
||||
def tools_seed_tray; end
|
||||
|
||||
|
@ -69,11 +62,6 @@ module Devices
|
|||
add_tool(ToolNames::SEED_TROUGH_2)
|
||||
end
|
||||
|
||||
def tools_seed_trough_3
|
||||
@tools_seed_trough_3 ||=
|
||||
add_tool(ToolNames::SEED_TROUGH_3)
|
||||
end
|
||||
|
||||
def tools_seeder; end
|
||||
def tools_soil_sensor; end
|
||||
def tools_watering_nozzle; end
|
||||
|
|
|
@ -75,6 +75,9 @@ module Devices
|
|||
tool: tools_weeder)
|
||||
end
|
||||
|
||||
def tool_slots_slot_7; end
|
||||
def tool_slots_slot_8; end
|
||||
|
||||
def tools_seed_bin
|
||||
@tools_seed_bin ||=
|
||||
add_tool(ToolNames::SEED_BIN)
|
||||
|
@ -87,7 +90,6 @@ module Devices
|
|||
|
||||
def tools_seed_trough_1; end
|
||||
def tools_seed_trough_2; end
|
||||
def tools_seed_trough_3; end
|
||||
|
||||
def tools_seeder
|
||||
@tools_seeder ||=
|
||||
|
|
|
@ -37,7 +37,6 @@ module Devices
|
|||
:tools_seed_tray,
|
||||
:tools_seed_trough_1,
|
||||
:tools_seed_trough_2,
|
||||
:tools_seed_trough_3,
|
||||
:tools_seeder,
|
||||
:tools_soil_sensor,
|
||||
:tools_watering_nozzle,
|
||||
|
@ -50,6 +49,8 @@ module Devices
|
|||
:tool_slots_slot_4,
|
||||
:tool_slots_slot_5,
|
||||
:tool_slots_slot_6,
|
||||
:tool_slots_slot_7,
|
||||
:tool_slots_slot_8,
|
||||
|
||||
# WEBCAM FEEDS ===========================
|
||||
:webcam_feeds,
|
||||
|
@ -152,11 +153,12 @@ module Devices
|
|||
def tool_slots_slot_4; end
|
||||
def tool_slots_slot_5; end
|
||||
def tool_slots_slot_6; end
|
||||
def tool_slots_slot_7; end
|
||||
def tool_slots_slot_8; end
|
||||
def tools_seed_bin; end
|
||||
def tools_seed_tray; end
|
||||
def tools_seed_trough_1; end
|
||||
def tools_seed_trough_2; end
|
||||
def tools_seed_trough_3; end
|
||||
def tools_seeder; end
|
||||
def tools_soil_sensor; end
|
||||
def tools_watering_nozzle; end
|
||||
|
|
|
@ -31,7 +31,6 @@ module Devices
|
|||
LIGHTING = "Lighting"
|
||||
SEED_TROUGH_1 = "Seed Trough 1"
|
||||
SEED_TROUGH_2 = "Seed Trough 2"
|
||||
SEED_TROUGH_3 = "Seed Trough 3"
|
||||
end
|
||||
|
||||
# Stub plants ==============================
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
module Devices
|
||||
module Seeders
|
||||
class GenesisOneFive < AbstractGenesis
|
||||
def settings_firmware
|
||||
device
|
||||
.fbos_config
|
||||
.update!(firmware_hardware: FbosConfig::FARMDUINO_K15)
|
||||
end
|
||||
|
||||
def tool_slots_slot_7
|
||||
add_tool_slot(name: ToolNames::SEED_TROUGH_1,
|
||||
x: 0,
|
||||
y: 25,
|
||||
z: 0,
|
||||
tool: tools_seed_trough_1,
|
||||
pullout_direction: ToolSlot::NONE,
|
||||
gantry_mounted: true)
|
||||
end
|
||||
|
||||
def tool_slots_slot_8
|
||||
add_tool_slot(name: ToolNames::SEED_TROUGH_2,
|
||||
x: 0,
|
||||
y: 50,
|
||||
z: 0,
|
||||
tool: tools_seed_trough_2,
|
||||
pullout_direction: ToolSlot::NONE,
|
||||
gantry_mounted: true)
|
||||
end
|
||||
|
||||
def tools_seed_trough_1
|
||||
@tools_seed_trough_1 ||=
|
||||
add_tool(ToolNames::SEED_TROUGH_1)
|
||||
end
|
||||
|
||||
def tools_seed_trough_2
|
||||
@tools_seed_trough_2 ||=
|
||||
add_tool(ToolNames::SEED_TROUGH_2)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,53 @@
|
|||
module Devices
|
||||
module Seeders
|
||||
class GenesisXlOneFive < AbstractGenesis
|
||||
def settings_firmware
|
||||
device
|
||||
.fbos_config
|
||||
.update!(firmware_hardware: FbosConfig::FARMDUINO_K15)
|
||||
end
|
||||
|
||||
def settings_device_name
|
||||
device.update!(name: "FarmBot Genesis XL")
|
||||
end
|
||||
|
||||
def settings_default_map_size_x
|
||||
device.web_app_config.update!(map_size_x: 5_900)
|
||||
end
|
||||
|
||||
def settings_default_map_size_y
|
||||
device.web_app_config.update!(map_size_y: 2_900)
|
||||
end
|
||||
|
||||
def tool_slots_slot_7
|
||||
add_tool_slot(name: ToolNames::SEED_TROUGH_1,
|
||||
x: 0,
|
||||
y: 25,
|
||||
z: 0,
|
||||
tool: tools_seed_trough_1,
|
||||
pullout_direction: ToolSlot::NONE,
|
||||
gantry_mounted: true)
|
||||
end
|
||||
|
||||
def tool_slots_slot_8
|
||||
add_tool_slot(name: ToolNames::SEED_TROUGH_2,
|
||||
x: 0,
|
||||
y: 50,
|
||||
z: 0,
|
||||
tool: tools_seed_trough_2,
|
||||
pullout_direction: ToolSlot::NONE,
|
||||
gantry_mounted: true)
|
||||
end
|
||||
|
||||
def tools_seed_trough_1
|
||||
@tools_seed_trough_1 ||=
|
||||
add_tool(ToolNames::SEED_TROUGH_1)
|
||||
end
|
||||
|
||||
def tools_seed_trough_2
|
||||
@tools_seed_trough_2 ||=
|
||||
add_tool(ToolNames::SEED_TROUGH_2)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -28,11 +28,12 @@ module Devices
|
|||
def tool_slots_slot_4; end
|
||||
def tool_slots_slot_5; end
|
||||
def tool_slots_slot_6; end
|
||||
def tool_slots_slot_7; end
|
||||
def tool_slots_slot_8; end
|
||||
def tools_seed_bin; end
|
||||
def tools_seed_tray; end
|
||||
def tools_seed_trough_1; end
|
||||
def tools_seed_trough_2; end
|
||||
def tools_seed_trough_3; end
|
||||
def tools_seeder; end
|
||||
def tools_soil_sensor; end
|
||||
def tools_watering_nozzle; end
|
||||
|
|
|
@ -12,6 +12,7 @@ module Devices
|
|||
time :last_saw_mq
|
||||
time :last_ota
|
||||
time :last_ota_checkup
|
||||
boolean :needs_reset
|
||||
integer :mounted_tool_id, nils: true
|
||||
integer :ota_hour, nils: true
|
||||
end
|
||||
|
|
|
@ -1,25 +0,0 @@
|
|||
module DiagnosticDumps
|
||||
class Create < Mutations::Command
|
||||
required do
|
||||
model :device, class: Device
|
||||
string :fbos_version
|
||||
string :fbos_commit
|
||||
string :firmware_commit
|
||||
string :network_interface
|
||||
string :fbos_dmesg_dump
|
||||
string :firmware_state
|
||||
end
|
||||
|
||||
def execute
|
||||
DiagnosticDump
|
||||
.create!(device: device,
|
||||
ticket_identifier: rand(36**5).to_s(36),
|
||||
fbos_version: fbos_version,
|
||||
fbos_commit: fbos_commit,
|
||||
firmware_commit: firmware_commit,
|
||||
network_interface: network_interface,
|
||||
fbos_dmesg_dump: fbos_dmesg_dump,
|
||||
firmware_state: firmware_state,)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,3 +0,0 @@
|
|||
module DiagnosticDumps
|
||||
Destroy = CreateDestroyer.run!(resource: DiagnosticDump)
|
||||
end
|
|
@ -16,7 +16,7 @@ module FarmEvents
|
|||
kind: "internal_#{kind}",
|
||||
args: {},
|
||||
body: body }
|
||||
flat_ast = Fragments::Preprocessor.run!(params)
|
||||
flat_ast = Fragments::Preprocessor.run!(**params)
|
||||
Fragments::Create.run!(device: device,
|
||||
flat_ast: flat_ast,
|
||||
owner: owner)
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
module Folders
|
||||
class Create < Mutations::Command
|
||||
required do
|
||||
model :device
|
||||
string :color
|
||||
string :name
|
||||
end
|
||||
|
||||
optional do
|
||||
integer :parent_id
|
||||
end
|
||||
|
||||
def execute
|
||||
Folder.create!(update_params)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def update_params
|
||||
inputs.except(:parent_id).merge({ parent: parent })
|
||||
end
|
||||
|
||||
def parent
|
||||
@parent ||= device.folders.find_by(id: parent_id)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,44 @@
|
|||
module Folders
|
||||
class Destroy < Mutations::Command
|
||||
IN_USE = "This folder still contains %s %s(s). " \
|
||||
"They must be removed prior to deletion"
|
||||
|
||||
required do
|
||||
model :device
|
||||
model :folder
|
||||
end
|
||||
|
||||
def validate
|
||||
check_subfolders
|
||||
check_sequences
|
||||
end
|
||||
|
||||
def execute
|
||||
folder.destroy! && ""
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def sequences
|
||||
@sequences ||= Sequence.where(folder: folder)
|
||||
end
|
||||
|
||||
def subfolders
|
||||
@subfolders ||= Folder.where(parent: folder)
|
||||
end
|
||||
|
||||
def check_sequences
|
||||
count = sequences.count
|
||||
if count > 0
|
||||
add_error :in_use, :in_use, IN_USE % [count, "sequence"]
|
||||
end
|
||||
end
|
||||
|
||||
def check_subfolders
|
||||
count = subfolders.count
|
||||
if count > 0
|
||||
add_error :in_use, :in_use, IN_USE % [count, "subfolder"]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,28 @@
|
|||
module Folders
|
||||
class Update < Mutations::Command
|
||||
required do
|
||||
model :device
|
||||
model :folder
|
||||
integer :parent_id, nils: true, empty_is_nil: true
|
||||
end
|
||||
|
||||
optional do
|
||||
string :name
|
||||
string :color
|
||||
end
|
||||
|
||||
def execute
|
||||
folder.update!(update_params) && folder
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def update_params
|
||||
inputs.except(:device, :folder).merge({ parent: parent })
|
||||
end
|
||||
|
||||
def parent
|
||||
@parent ||= parent_id && device.folders.find_by(id: parent_id)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -5,7 +5,7 @@ module Fragments
|
|||
def self.run!(kind:, args:, body:, device:)
|
||||
canonical = {kind: kind, args: args, body: body}
|
||||
slicer = CeleryScript::Slicer.new
|
||||
tree = CeleryScript::AstNode.new(canonical.deep_symbolize_keys)
|
||||
tree = CeleryScript::AstNode.new(**canonical.deep_symbolize_keys)
|
||||
checker = CeleryScript::Checker.new(tree, Corpus, device)
|
||||
checker.run!
|
||||
slicer.run!(canonical)
|
||||
|
|
|
@ -8,10 +8,13 @@ module PointGroups
|
|||
array :point_ids, class: Integer
|
||||
end
|
||||
|
||||
criteria
|
||||
|
||||
optional do
|
||||
string :sort_type
|
||||
end
|
||||
|
||||
|
||||
def validate
|
||||
validate_point_ids
|
||||
validate_sort_type
|
||||
|
@ -20,14 +23,21 @@ module PointGroups
|
|||
def execute
|
||||
PointGroup.transaction do
|
||||
PointGroupItem.transaction do
|
||||
pg = PointGroup.new(name: name, device: device)
|
||||
point_ids.uniq.map do |id|
|
||||
pg.point_group_items << PointGroupItem.new(point_id: id)
|
||||
end
|
||||
pg = PointGroup.new(name: name,
|
||||
device: device,
|
||||
criteria: PointGroup::DEFAULT_CRITERIA.merge(criteria || {})
|
||||
)
|
||||
add_point_group_items(pg)
|
||||
pg.save!
|
||||
pg
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def add_point_group_items(pg)
|
||||
point_ids.uniq.map do |id|
|
||||
pg.point_group_items << PointGroupItem.new(point_id: id)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,6 +1,26 @@
|
|||
module PointGroups
|
||||
module ClassLevelHelpers
|
||||
def criteria
|
||||
self.optional do
|
||||
hash :criteria do
|
||||
hash(:day) do
|
||||
string :op, in: [">", "<"]
|
||||
integer :days_ago
|
||||
end
|
||||
hash(:string_eq) { array :*, class: String }
|
||||
hash(:number_eq) { array :*, class: Integer }
|
||||
hash(:number_lt) { integer :* }
|
||||
hash(:number_gt) { integer :* }
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
module Helpers
|
||||
BAD_POINT_IDS = "The group contains invalid points."
|
||||
def self.included(base)
|
||||
base.extend PointGroups::ClassLevelHelpers
|
||||
end
|
||||
|
||||
def points
|
||||
@points ||= Point.where(id: point_ids, device: device)
|
||||
|
|
|
@ -8,6 +8,8 @@ module PointGroups
|
|||
model :point_group, class: PointGroup
|
||||
end
|
||||
|
||||
criteria
|
||||
|
||||
optional do
|
||||
string :name
|
||||
array :point_ids, class: Integer
|
||||
|
@ -34,7 +36,9 @@ module PointGroups
|
|||
private
|
||||
|
||||
def update_attributes
|
||||
@update_attributes ||= inputs.except(*BLACKLISTED_FIELDS)
|
||||
@update_attributes ||= inputs
|
||||
.except(*BLACKLISTED_FIELDS)
|
||||
.merge(criteria: criteria || point_group.criteria)
|
||||
end
|
||||
|
||||
def maybe_reconcile_points
|
||||
|
|
|
@ -27,11 +27,19 @@ module Points
|
|||
end
|
||||
|
||||
def execute
|
||||
Point.transaction { point.update!(inputs.except(:point)) && point }
|
||||
Point.transaction { point.update!(update_params) && point }
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def merged_meta_fields
|
||||
@merged_meta_fields ||= (point.meta || {}).merge(meta || {})
|
||||
end
|
||||
|
||||
def update_params
|
||||
@update_params ||= inputs.except(:point).merge(meta: merged_meta_fields)
|
||||
end
|
||||
|
||||
def new_tool_id?
|
||||
raw_inputs.key?("tool_id")
|
||||
end
|
||||
|
|
|
@ -10,13 +10,14 @@ module SensorReadings
|
|||
end
|
||||
|
||||
optional do
|
||||
time :read_at
|
||||
integer :mode,
|
||||
in: CeleryScriptSettingsBag::ALLOWED_PIN_MODES,
|
||||
default: CeleryScriptSettingsBag::DIGITAL
|
||||
end
|
||||
|
||||
def execute
|
||||
SensorReading.create!(inputs)
|
||||
SensorReading.create!(inputs.merge(read_at: read_at || Time.now))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -12,6 +12,7 @@ module Sequences
|
|||
optional do
|
||||
color
|
||||
args
|
||||
integer :folder_id
|
||||
end
|
||||
|
||||
def validate
|
||||
|
@ -25,6 +26,7 @@ module Sequences
|
|||
p = inputs
|
||||
.merge(migrated_nodes: true)
|
||||
.without(:body, :args, "body", "args")
|
||||
.merge(folder: device.folders.find_by(id: folder_id))
|
||||
seq = Sequence.create!(p)
|
||||
x = CeleryScript::FirstPass.run!(sequence: seq,
|
||||
args: args || {},
|
||||
|
|
|
@ -2,7 +2,12 @@ module Sequences
|
|||
class Update < Mutations::Command
|
||||
include CeleryScriptValidators
|
||||
using CanonicalCeleryHelpers
|
||||
BLACKLIST = [:sequence, :device, :args, :body]
|
||||
BLACKLIST = [:sequence, :device, :args, :body, :folder_id]
|
||||
BASE = "Can't add 'parent' to sequence because "
|
||||
EXPL = {
|
||||
FarmEvent => BASE + "it is in use by FarmEvents on these dates: %{items}",
|
||||
Regimen => BASE + "the following Regimen(s) are using it: %{items}",
|
||||
}
|
||||
|
||||
required do
|
||||
model :device, class: Device
|
||||
|
@ -27,6 +32,7 @@ module Sequences
|
|||
|
||||
optional do
|
||||
color
|
||||
integer :folder_id
|
||||
end
|
||||
|
||||
def validate
|
||||
|
@ -40,7 +46,7 @@ module Sequences
|
|||
Sequence.auto_sync_debounce do
|
||||
ActiveRecord::Base.transaction do
|
||||
sequence.migrated_nodes = true
|
||||
sequence.update!(inputs.except(*BLACKLIST))
|
||||
sequence.update!(inputs.except(*BLACKLIST).merge(folder_stuff))
|
||||
CeleryScript::StoreCelery.run!(sequence: sequence,
|
||||
args: args,
|
||||
body: body)
|
||||
|
@ -49,11 +55,12 @@ module Sequences
|
|||
end
|
||||
CeleryScript::FetchCelery.run!(sequence: sequence, args: args, body: body)
|
||||
end
|
||||
|
||||
BASE = "Can't add 'parent' to sequence because "
|
||||
EXPL = {
|
||||
FarmEvent => BASE + "it is in use by FarmEvents on these dates: %{items}",
|
||||
Regimen => BASE + "the following Regimen(s) are using it: %{items}",
|
||||
}
|
||||
def folder_stuff
|
||||
if folder_id
|
||||
return { folder: device.folders.find_by(id: folder_id) }
|
||||
else
|
||||
return {}
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
module Tools
|
||||
class Destroy < Mutations::Command
|
||||
STILL_IN_USE = "Can't delete tool because the following sequences are "\
|
||||
"still using it: %s"
|
||||
STILL_IN_SLOT = "Can't delete tool because it is still in a tool slot. "\
|
||||
"Please remove it from the tool slot first."
|
||||
STILL_IN_USE = "Can't delete tool or seed container because the " \
|
||||
"following sequences are still using it: %s"
|
||||
STILL_IN_SLOT = "Can't delete tool or seed container because it is " \
|
||||
"still in a slot. Please remove it from the slot first."
|
||||
|
||||
required do
|
||||
model :tool, class: Tool
|
||||
|
@ -15,10 +15,11 @@ module Tools
|
|||
end
|
||||
|
||||
def execute
|
||||
maybe_unmount_tool
|
||||
tool.destroy!
|
||||
end
|
||||
|
||||
private
|
||||
private
|
||||
|
||||
def slot
|
||||
@slot ||= tool.tool_slot
|
||||
|
@ -33,8 +34,14 @@ private
|
|||
end
|
||||
|
||||
def names
|
||||
@names ||= \
|
||||
@names ||=
|
||||
InUseTool.where(tool_id: tool.id).pluck(:sequence_name).join(", ")
|
||||
end
|
||||
|
||||
def maybe_unmount_tool
|
||||
if tool.device.mounted_tool_id == tool.id
|
||||
tool.device.update!(mounted_tool_id: nil)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,6 +1,24 @@
|
|||
class BasePointSerializer < ApplicationSerializer
|
||||
attributes :device_id, :name, :pointer_type, :meta, :x, :y, :z
|
||||
|
||||
# PROBLEM:
|
||||
# * Users need a mutable way to mark a plant's creation time => `planted_at`
|
||||
# * DB Admin needs to know the _real_ created_at time.
|
||||
# * We can't change field names (or destroy data) that is in use by legacy devices
|
||||
#
|
||||
# SOLUTION:
|
||||
# * Don't allow users to modify `created_at`
|
||||
# * Provide `planted_at` if possible.
|
||||
# * Always provide `planted_at` if it is available
|
||||
# * Provide a read-only view of `created_at` if `planted_at` is `nil`
|
||||
def planted_at
|
||||
object.planted_at || object.created_at
|
||||
end
|
||||
|
||||
def created_at
|
||||
planted_at
|
||||
end
|
||||
|
||||
def meta
|
||||
object.meta || {}
|
||||
end
|
||||
|
|
|
@ -6,6 +6,7 @@ class DeviceSerializer < ApplicationSerializer
|
|||
:last_saw_mq,
|
||||
:mounted_tool_id,
|
||||
:name,
|
||||
:needs_reset,
|
||||
:ota_hour,
|
||||
:serial_number,
|
||||
:throttled_at,
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
class DiagnosticDumpSerializer < ApplicationSerializer
|
||||
attributes :device_id, :ticket_identifier, :fbos_commit, :fbos_version,
|
||||
:firmware_commit, :firmware_state, :network_interface,
|
||||
:fbos_dmesg_dump
|
||||
end
|
|
@ -0,0 +1,3 @@
|
|||
class FolderSerializer < ApplicationSerializer
|
||||
attributes :id, :parent_id, :color, :name
|
||||
end
|
|
@ -1,7 +1,11 @@
|
|||
class PointGroupSerializer < ApplicationSerializer
|
||||
attributes :name, :point_ids, :sort_type
|
||||
attributes :name, :point_ids, :sort_type, :criteria
|
||||
|
||||
def point_ids
|
||||
object.point_group_items.pluck(:point_id)
|
||||
end
|
||||
|
||||
def criteria
|
||||
object.criteria || PointGroup::DEFAULT_CRITERIA
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,3 +1,10 @@
|
|||
class SensorReadingSerializer < ApplicationSerializer
|
||||
attributes :mode, :pin, :value, :x, :y, :z
|
||||
attributes :mode, :pin, :value, :x, :y, :z, :read_at
|
||||
# This is for legacy support reasons.
|
||||
# Very old sensor_readings will have a
|
||||
# read_at value of `nil`, so we pre-populate it
|
||||
# to `created_at` for the convinience of API users.
|
||||
def read_at
|
||||
object.read_at || object.created_at
|
||||
end
|
||||
end
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
class WeedSerializer < BasePointSerializer
|
||||
attributes :radius, :discarded_at, :plant_stage
|
||||
end
|
|
@ -0,0 +1 @@
|
|||
<%# Intentionally blank template required by router for content generated by frontend. %>
|
|
@ -8,7 +8,6 @@ FarmBot::Application.routes.draw do
|
|||
# Standard API Resources:
|
||||
{
|
||||
alerts: [:create, :destroy, :index],
|
||||
diagnostic_dumps: [:create, :destroy, :index],
|
||||
farm_events: [:create, :destroy, :index, :show, :update],
|
||||
farmware_envs: [:create, :destroy, :index, :show, :update],
|
||||
first_party_farmwares: [:show, :index],
|
||||
|
@ -25,6 +24,7 @@ FarmBot::Application.routes.draw do
|
|||
sequences: [:create, :destroy, :index, :show, :update],
|
||||
tools: [:create, :destroy, :index, :show, :update],
|
||||
webcam_feeds: [:create, :destroy, :index, :show, :update],
|
||||
folders: [:create, :destroy, :index, :show, :update],
|
||||
}.to_a.map { |(name, only)| resources name, only: only }
|
||||
|
||||
# Singular API Resources:
|
||||
|
@ -114,6 +114,7 @@ FarmBot::Application.routes.draw do
|
|||
match "/app/*path", to: "dashboard#main_app", via: :all, constraints: { format: "html" }
|
||||
|
||||
get "/demo" => "dashboard#demo", as: :demo_main
|
||||
get "/os" => "dashboard#os_download", as: :os_download
|
||||
get "/password_reset/*token" => "dashboard#password_reset", as: :password_reset
|
||||
get "/tos_update" => "dashboard#tos_update", as: :tos_update
|
||||
get "/verify/:token" => "dashboard#confirmation_page", as: :confirmation_page
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
class MakeDefaulDeviceNameFarmbot < ActiveRecord::Migration[5.1]
|
||||
|
||||
def change
|
||||
change_column_default(:devices, :name, "Farmbot")
|
||||
end
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
class AddFolderColumns < ActiveRecord::Migration[6.0]
|
||||
def change
|
||||
create_table :folders do |t|
|
||||
t.references :device, null: false
|
||||
t.timestamps
|
||||
# https://twitter.com/wesbos/status/719678818831757313?lang=en
|
||||
t.string :color, limit: 20, null: false
|
||||
t.string :name, limit: 40, null: false
|
||||
end
|
||||
add_column :folders,
|
||||
:parent_id,
|
||||
:integer,
|
||||
null: true,
|
||||
index: true
|
||||
add_foreign_key :folders,
|
||||
:folders,
|
||||
column: :parent_id
|
||||
|
||||
add_reference :sequences, :folder, index: true
|
||||
end
|
||||
end
|
|
@ -0,0 +1,8 @@
|
|||
class AddNeedsResetToDevices < ActiveRecord::Migration[6.0]
|
||||
def change
|
||||
add_column :devices,
|
||||
:needs_reset,
|
||||
:boolean,
|
||||
default: false
|
||||
end
|
||||
end
|
|
@ -0,0 +1,5 @@
|
|||
class AddReadAtToSensorReadings < ActiveRecord::Migration[6.0]
|
||||
def change
|
||||
add_column :sensor_readings, :read_at, :datetime, default: nil
|
||||
end
|
||||
end
|
|
@ -0,0 +1,5 @@
|
|||
class AddCriteriaToPointGroups < ActiveRecord::Migration[6.0]
|
||||
def change
|
||||
add_column :point_groups, :criteria, :text, limit: 1000
|
||||
end
|
||||
end
|
|
@ -0,0 +1,20 @@
|
|||
class DropDiagnosticDumps < ActiveRecord::Migration[6.0]
|
||||
def change
|
||||
drop_table :diagnostic_dumps do |t|
|
||||
t.references :device, foreign_key: true, null: false
|
||||
t.string :fbos_commit, null: false
|
||||
t.string :fbos_version, null: false
|
||||
t.string :firmware_commit, null: false
|
||||
t.string :firmware_hardware, limit: 12
|
||||
t.string :firmware_state, null: false
|
||||
t.string :firmware_version, limit: 12
|
||||
t.string :network_interface, null: false
|
||||
t.string :soc_temp, limit: 12
|
||||
t.string :sync_status, limit: 12
|
||||
t.string :ticket_identifier, null: false, unique: true
|
||||
t.string :wifi_level, limit: 12
|
||||
t.text :fbos_dmesg_dump, null: false
|
||||
t.timestamps
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,8 @@
|
|||
class AddShowZonesToWebAppConfig < ActiveRecord::Migration[6.0]
|
||||
def change
|
||||
add_column :web_app_configs,
|
||||
:show_zones,
|
||||
:boolean,
|
||||
default: false
|
||||
end
|
||||
end
|
|
@ -0,0 +1,8 @@
|
|||
class AddShowWeedsToWebAppConfig < ActiveRecord::Migration[6.0]
|
||||
def change
|
||||
add_column :web_app_configs,
|
||||
:show_weeds,
|
||||
:boolean,
|
||||
default: false
|
||||
end
|
||||
end
|
|
@ -0,0 +1,5 @@
|
|||
class UpdateMaxImageCount < ActiveRecord::Migration[6.0]
|
||||
def change
|
||||
change_column_default(:devices, :max_images_count, 450)
|
||||
end
|
||||
end
|
176
db/structure.sql
176
db/structure.sql
|
@ -150,8 +150,8 @@ ALTER SEQUENCE public.alerts_id_seq OWNED BY public.alerts.id;
|
|||
CREATE TABLE public.ar_internal_metadata (
|
||||
key character varying NOT NULL,
|
||||
value character varying,
|
||||
created_at timestamp without time zone NOT NULL,
|
||||
updated_at timestamp without time zone NOT NULL
|
||||
created_at timestamp(6) without time zone NOT NULL,
|
||||
updated_at timestamp(6) without time zone NOT NULL
|
||||
);
|
||||
|
||||
|
||||
|
@ -262,7 +262,7 @@ CREATE TABLE public.devices (
|
|||
id integer NOT NULL,
|
||||
name character varying DEFAULT 'FarmBot'::character varying,
|
||||
max_log_count integer DEFAULT 1000,
|
||||
max_images_count integer DEFAULT 100,
|
||||
max_images_count integer DEFAULT 450,
|
||||
timezone character varying(280),
|
||||
last_saw_api timestamp without time zone,
|
||||
last_saw_mq timestamp without time zone,
|
||||
|
@ -276,7 +276,8 @@ CREATE TABLE public.devices (
|
|||
mqtt_rate_limit_email_sent_at timestamp without time zone,
|
||||
last_ota timestamp without time zone,
|
||||
last_ota_checkup timestamp without time zone,
|
||||
ota_hour integer DEFAULT 3
|
||||
ota_hour integer DEFAULT 3,
|
||||
needs_reset boolean DEFAULT false
|
||||
);
|
||||
|
||||
|
||||
|
@ -300,49 +301,6 @@ CREATE SEQUENCE public.devices_id_seq
|
|||
ALTER SEQUENCE public.devices_id_seq OWNED BY public.devices.id;
|
||||
|
||||
|
||||
--
|
||||
-- Name: diagnostic_dumps; Type: TABLE; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE TABLE public.diagnostic_dumps (
|
||||
id bigint NOT NULL,
|
||||
device_id bigint NOT NULL,
|
||||
ticket_identifier character varying NOT NULL,
|
||||
fbos_commit character varying NOT NULL,
|
||||
fbos_version character varying NOT NULL,
|
||||
firmware_commit character varying NOT NULL,
|
||||
firmware_state character varying NOT NULL,
|
||||
network_interface character varying NOT NULL,
|
||||
fbos_dmesg_dump text NOT NULL,
|
||||
created_at timestamp without time zone NOT NULL,
|
||||
updated_at timestamp without time zone NOT NULL,
|
||||
sync_status character varying(12),
|
||||
wifi_level character varying(12),
|
||||
soc_temp character varying(12),
|
||||
firmware_hardware character varying(12),
|
||||
firmware_version character varying(12)
|
||||
);
|
||||
|
||||
|
||||
--
|
||||
-- Name: diagnostic_dumps_id_seq; Type: SEQUENCE; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE SEQUENCE public.diagnostic_dumps_id_seq
|
||||
START WITH 1
|
||||
INCREMENT BY 1
|
||||
NO MINVALUE
|
||||
NO MAXVALUE
|
||||
CACHE 1;
|
||||
|
||||
|
||||
--
|
||||
-- Name: diagnostic_dumps_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER SEQUENCE public.diagnostic_dumps_id_seq OWNED BY public.diagnostic_dumps.id;
|
||||
|
||||
|
||||
--
|
||||
-- Name: edge_nodes; Type: TABLE; Schema: public; Owner: -
|
||||
--
|
||||
|
@ -663,6 +621,40 @@ CREATE SEQUENCE public.firmware_configs_id_seq
|
|||
ALTER SEQUENCE public.firmware_configs_id_seq OWNED BY public.firmware_configs.id;
|
||||
|
||||
|
||||
--
|
||||
-- Name: folders; Type: TABLE; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE TABLE public.folders (
|
||||
id bigint NOT NULL,
|
||||
device_id bigint NOT NULL,
|
||||
created_at timestamp(6) without time zone NOT NULL,
|
||||
updated_at timestamp(6) without time zone NOT NULL,
|
||||
color character varying(20) NOT NULL,
|
||||
name character varying(40) NOT NULL,
|
||||
parent_id integer
|
||||
);
|
||||
|
||||
|
||||
--
|
||||
-- Name: folders_id_seq; Type: SEQUENCE; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE SEQUENCE public.folders_id_seq
|
||||
START WITH 1
|
||||
INCREMENT BY 1
|
||||
NO MINVALUE
|
||||
NO MAXVALUE
|
||||
CACHE 1;
|
||||
|
||||
|
||||
--
|
||||
-- Name: folders_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER SEQUENCE public.folders_id_seq OWNED BY public.folders.id;
|
||||
|
||||
|
||||
--
|
||||
-- Name: fragments; Type: TABLE; Schema: public; Owner: -
|
||||
--
|
||||
|
@ -841,7 +833,8 @@ CREATE TABLE public.sequences (
|
|||
kind character varying(280) DEFAULT 'sequence'::character varying,
|
||||
updated_at timestamp without time zone,
|
||||
created_at timestamp without time zone,
|
||||
migrated_nodes boolean DEFAULT false
|
||||
migrated_nodes boolean DEFAULT false,
|
||||
folder_id bigint
|
||||
);
|
||||
|
||||
|
||||
|
@ -1149,7 +1142,8 @@ CREATE TABLE public.point_groups (
|
|||
device_id bigint NOT NULL,
|
||||
created_at timestamp without time zone NOT NULL,
|
||||
updated_at timestamp without time zone NOT NULL,
|
||||
sort_type character varying(20) DEFAULT 'xy_ascending'::character varying
|
||||
sort_type character varying(20) DEFAULT 'xy_ascending'::character varying,
|
||||
criteria text
|
||||
);
|
||||
|
||||
|
||||
|
@ -1447,7 +1441,8 @@ CREATE TABLE public.sensor_readings (
|
|||
pin integer,
|
||||
created_at timestamp without time zone NOT NULL,
|
||||
updated_at timestamp without time zone NOT NULL,
|
||||
mode integer DEFAULT 0
|
||||
mode integer DEFAULT 0,
|
||||
read_at timestamp without time zone
|
||||
);
|
||||
|
||||
|
||||
|
@ -1733,7 +1728,9 @@ CREATE TABLE public.web_app_configs (
|
|||
confirm_sequence_deletion boolean DEFAULT true,
|
||||
discard_unsaved_sequences boolean DEFAULT false,
|
||||
user_interface_read_only_mode boolean DEFAULT false,
|
||||
assertion_log integer DEFAULT 1
|
||||
assertion_log integer DEFAULT 1,
|
||||
show_zones boolean DEFAULT false,
|
||||
show_weeds boolean DEFAULT false
|
||||
);
|
||||
|
||||
|
||||
|
@ -1838,13 +1835,6 @@ ALTER TABLE ONLY public.delayed_jobs ALTER COLUMN id SET DEFAULT nextval('public
|
|||
ALTER TABLE ONLY public.devices ALTER COLUMN id SET DEFAULT nextval('public.devices_id_seq'::regclass);
|
||||
|
||||
|
||||
--
|
||||
-- Name: diagnostic_dumps id; Type: DEFAULT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY public.diagnostic_dumps ALTER COLUMN id SET DEFAULT nextval('public.diagnostic_dumps_id_seq'::regclass);
|
||||
|
||||
|
||||
--
|
||||
-- Name: edge_nodes id; Type: DEFAULT; Schema: public; Owner: -
|
||||
--
|
||||
|
@ -1887,6 +1877,13 @@ ALTER TABLE ONLY public.fbos_configs ALTER COLUMN id SET DEFAULT nextval('public
|
|||
ALTER TABLE ONLY public.firmware_configs ALTER COLUMN id SET DEFAULT nextval('public.firmware_configs_id_seq'::regclass);
|
||||
|
||||
|
||||
--
|
||||
-- Name: folders id; Type: DEFAULT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY public.folders ALTER COLUMN id SET DEFAULT nextval('public.folders_id_seq'::regclass);
|
||||
|
||||
|
||||
--
|
||||
-- Name: fragments id; Type: DEFAULT; Schema: public; Owner: -
|
||||
--
|
||||
|
@ -2147,14 +2144,6 @@ ALTER TABLE ONLY public.devices
|
|||
ADD CONSTRAINT devices_pkey PRIMARY KEY (id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: diagnostic_dumps diagnostic_dumps_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY public.diagnostic_dumps
|
||||
ADD CONSTRAINT diagnostic_dumps_pkey PRIMARY KEY (id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: edge_nodes edge_nodes_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
|
@ -2203,6 +2192,14 @@ ALTER TABLE ONLY public.firmware_configs
|
|||
ADD CONSTRAINT firmware_configs_pkey PRIMARY KEY (id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: folders folders_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY public.folders
|
||||
ADD CONSTRAINT folders_pkey PRIMARY KEY (id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: fragments fragments_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
|
@ -2498,13 +2495,6 @@ CREATE INDEX index_devices_on_mounted_tool_id ON public.devices USING btree (mou
|
|||
CREATE INDEX index_devices_on_timezone ON public.devices USING btree (timezone);
|
||||
|
||||
|
||||
--
|
||||
-- Name: index_diagnostic_dumps_on_device_id; Type: INDEX; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE INDEX index_diagnostic_dumps_on_device_id ON public.diagnostic_dumps USING btree (device_id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: index_edge_nodes_on_kind_and_value; Type: INDEX; Schema: public; Owner: -
|
||||
--
|
||||
|
@ -2575,6 +2565,13 @@ CREATE INDEX index_fbos_configs_on_device_id ON public.fbos_configs USING btree
|
|||
CREATE INDEX index_firmware_configs_on_device_id ON public.firmware_configs USING btree (device_id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: index_folders_on_device_id; Type: INDEX; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE INDEX index_folders_on_device_id ON public.folders USING btree (device_id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: index_fragments_on_device_id; Type: INDEX; Schema: public; Owner: -
|
||||
--
|
||||
|
@ -2904,6 +2901,13 @@ CREATE INDEX index_sequences_on_created_at ON public.sequences USING btree (crea
|
|||
CREATE INDEX index_sequences_on_device_id ON public.sequences USING btree (device_id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: index_sequences_on_folder_id; Type: INDEX; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE INDEX index_sequences_on_folder_id ON public.sequences USING btree (folder_id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: index_standard_pairs_on_arg_name_id; Type: INDEX; Schema: public; Owner: -
|
||||
--
|
||||
|
@ -3026,6 +3030,14 @@ ALTER TABLE ONLY public.pin_bindings
|
|||
ADD CONSTRAINT fk_rails_1f1c3b6979 FOREIGN KEY (device_id) REFERENCES public.devices(id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: folders fk_rails_58e285f76e; Type: FK CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY public.folders
|
||||
ADD CONSTRAINT fk_rails_58e285f76e FOREIGN KEY (parent_id) REFERENCES public.folders(id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: sensors fk_rails_92e56bf2fb; Type: FK CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
|
@ -3074,14 +3086,6 @@ ALTER TABLE ONLY public.active_storage_attachments
|
|||
ADD CONSTRAINT fk_rails_c3b3935057 FOREIGN KEY (blob_id) REFERENCES public.active_storage_blobs(id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: diagnostic_dumps fk_rails_c5df7fdc83; Type: FK CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY public.diagnostic_dumps
|
||||
ADD CONSTRAINT fk_rails_c5df7fdc83 FOREIGN KEY (device_id) REFERENCES public.devices(id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: farmware_installations fk_rails_c72f38683f; Type: FK CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
|
@ -3368,6 +3372,14 @@ INSERT INTO "schema_migrations" (version) VALUES
|
|||
('20190930202839'),
|
||||
('20191002125625'),
|
||||
('20191107170431'),
|
||||
('20191119204916');
|
||||
('20191119204916'),
|
||||
('20191203163621'),
|
||||
('20191219212755'),
|
||||
('20191220010646'),
|
||||
('20200116140201'),
|
||||
('20200204192005'),
|
||||
('20200204230135'),
|
||||
('20200323235926'),
|
||||
('20200412152208');
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,90 @@
|
|||
# How to install FarmBot Web API on a Debian Buster (10) Machine
|
||||
|
||||
# IMPORTANT NOTE: Resources are limited and Farmbot, inc. cannot provide
|
||||
# longterm support to self-hosted users. If you have never administered a
|
||||
# Ruby on Rails application, we highly advise stopping now. this presents an
|
||||
# extremely high risk of data loss. Free hosting is provided at
|
||||
# https://my.farm.bot and eliminates the risks and troubles of self-hosting.
|
||||
#
|
||||
# You are highly encouraged to use the my.farm.bot servers. Self hosted
|
||||
# documentation is provided with the assumption that you have experience with
|
||||
# Ruby/Javascript development.
|
||||
#
|
||||
# Self-hosting a Farmbot server is not a simple task.
|
||||
|
||||
# Remove old (possibly broke) docker versions
|
||||
sudo apt-get remove docker docker-engine docker.io
|
||||
|
||||
# Install docker
|
||||
sudo apt-get install apt-transport-https ca-certificates curl software-properties-common gnupg2 --yes
|
||||
curl -fsSL https://download.docker.com/linux/debian/gpg | sudo apt-key add -
|
||||
sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/debian buster stable" --yes
|
||||
sudo apt-get update --yes
|
||||
sudo apt-get install docker-ce --yes
|
||||
sudo docker run hello-world # Should run!
|
||||
# Install docker-compose
|
||||
sudo curl -L "https://github.com/docker/compose/releases/download/1.22.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
|
||||
sudo chmod +x /usr/local/bin/docker-compose
|
||||
|
||||
# Install FarmBot Web App
|
||||
# âš SKIP THIS STEP IF UPGRADING!
|
||||
git clone https://github.com/FarmBot/Farmbot-Web-App --depth=5 --branch=master
|
||||
|
||||
cd Farmbot-Web-App
|
||||
|
||||
#snap install micro --classic # Don't like `micro`? vim, nano, etc are fine, too.
|
||||
cp example.env .env # âš SKIP THIS STEP IF UPGRADING!
|
||||
|
||||
# == This is a very important step!!! ==
|
||||
#
|
||||
# Open `.env` in a text editor and change all the values.
|
||||
#
|
||||
# == Nothing will work if you skip this step!!! ==
|
||||
|
||||
vim .env # âš SKIP THIS STEP IF UPGRADING!
|
||||
# ^ This is the most important step
|
||||
# READ NOTE ABOVE. Very important!
|
||||
|
||||
# Install the correct version of bundler for the project
|
||||
sudo docker-compose run web gem install bundler:2.1.4
|
||||
# Install application specific Ruby dependencies
|
||||
sudo docker-compose run web bundle install
|
||||
# Install application specific Javascript deps
|
||||
sudo docker-compose run web npm install
|
||||
# Create a database in PostgreSQL
|
||||
sudo docker-compose run web bundle exec rails db:create db:migrate
|
||||
# Generate a set of *.pem files for data encryption
|
||||
sudo docker-compose run web rake keys:generate # âš SKIP THIS STEP IF UPGRADING!
|
||||
# Build the UI assets via ParcelJS
|
||||
sudo docker-compose run web rake assets:precompile
|
||||
# Run the server! ٩(^‿^)۶
|
||||
# NOTE: DONT TRY TO LOGIN until you see a message similar to this:
|
||||
# "✨ Built in 44.92s"
|
||||
# THIS MAY TAKE A VERY LONG TIME ON SLOW MACHINES (~3 minutes on DigitalOcean)
|
||||
# You will just get an empty screen otherwise.
|
||||
# This only happens during initialization
|
||||
sudo docker-compose up
|
||||
|
||||
# At this point, setup is complete. Content should be visible at ===============
|
||||
# http://YOUR_HOST:3000/.
|
||||
|
||||
# You can optionally verify installation by running unit tests.
|
||||
|
||||
# Create the database for the app to use:
|
||||
sudo docker-compose run -e RAILS_ENV=test web bundle exec rails db:setup
|
||||
# Run the tests in the "test" RAILS_ENV:
|
||||
sudo docker-compose run -e RAILS_ENV=test web rspec spec
|
||||
# Run user-interface unit tests REQUIRES AT LEAST 4 GB OF RAM:
|
||||
sudo docker-compose run web npm run test
|
||||
|
||||
# === BEGIN OPTIONAL UPGRADES
|
||||
# To update to later versions of FarmBot,
|
||||
# shut down the server, create a database backup
|
||||
# and run commands below.
|
||||
git pull https://github.com/FarmBot/Farmbot-Web-App.git master
|
||||
sudo docker-compose build
|
||||
sudo docker-compose run web bundle install # <== âš UPGRADE USERS ONLY
|
||||
sudo docker-compose run web npm install # <== âš UPGRADE USERS ONLY
|
||||
sudo docker-compose run web rails db:migrate # <== âš UPGRADE USERS ONLY
|
||||
# === END OPTIONAL UPGRADES ^
|
||||
|
|
@ -2,7 +2,7 @@ FROM ruby:2.6.5
|
|||
RUN wget -q https://www.postgresql.org/media/keys/ACCC4CF8.asc -O - | apt-key add - && \
|
||||
sh -c 'VERSION_CODENAME=stretch; . /etc/os-release; echo "deb http://apt.postgresql.org/pub/repos/apt/ $VERSION_CODENAME-pgdg main" >> /etc/apt/sources.list.d/pgdg.list' && \
|
||||
apt-get update -qq && apt-get install -y build-essential libpq-dev postgresql postgresql-contrib && \
|
||||
curl -sL https://deb.nodesource.com/setup_8.x | bash - && \
|
||||
curl -sL https://deb.nodesource.com/setup_10.x | bash - && \
|
||||
sh -c 'echo "\nPackage: *\nPin: origin deb.nodesource.com\nPin-Priority: 700\n" >> /etc/apt/preferences' && \
|
||||
apt-get install -y nodejs && \
|
||||
mkdir /farmbot;
|
||||
|
|
|
@ -79,6 +79,10 @@ SMTP_PORT=587
|
|||
# Delete these if you aren't a send grid customer.
|
||||
SENDGRID_PASSWORD=Used by FarmBot, Inc
|
||||
SENDGRID_USERNAME=Used by FarmBot, Inc
|
||||
# If you're using other SMTP server (like Gmail) use this.
|
||||
#SMTP_USERNAME=email@gmail.com
|
||||
#SMTP_PASSWORD=password
|
||||
|
||||
# Used by people who pay for managed database hosting.
|
||||
# Most users should delete this.
|
||||
DATABASE_URL=postgres://user:password@host:5432/db_name
|
||||
|
|
|
@ -1,7 +0,0 @@
|
|||
jest.mock("browser-speech", () => ({
|
||||
talk: jest.fn(),
|
||||
}));
|
||||
|
||||
jest.mock("../open_farm/cached_crop", () => ({
|
||||
cachedCrop: jest.fn(() => Promise.resolve({ svg_icon: "icon" })),
|
||||
}));
|
|
@ -0,0 +1,25 @@
|
|||
import * as React from "react";
|
||||
|
||||
jest.mock("browser-speech", () => ({
|
||||
talk: jest.fn(),
|
||||
}));
|
||||
|
||||
jest.mock("../open_farm/cached_crop", () => ({
|
||||
cachedCrop: jest.fn(() => Promise.resolve({ svg_icon: "icon" })),
|
||||
}));
|
||||
|
||||
const { ancestorOrigins } = window.location;
|
||||
delete window.location;
|
||||
window.location = {
|
||||
assign: jest.fn(),
|
||||
reload: jest.fn(),
|
||||
replace: jest.fn(),
|
||||
ancestorOrigins,
|
||||
pathname: "", href: "", hash: "", search: "",
|
||||
hostname: "", origin: "", port: "", protocol: "", host: "",
|
||||
};
|
||||
|
||||
jest.mock("../error_boundary", () => ({
|
||||
// tslint:disable-next-line:no-any
|
||||
ErrorBoundary: (p: any) => <div>{p.children}</div>,
|
||||
}));
|
|
@ -4,10 +4,15 @@ export const panelState = (): ControlPanelState => {
|
|||
return {
|
||||
homing_and_calibration: false,
|
||||
motors: false,
|
||||
encoders_and_endstops: false,
|
||||
encoders: false,
|
||||
endstops: false,
|
||||
error_handling: false,
|
||||
pin_bindings: false,
|
||||
danger_zone: false,
|
||||
power_and_reset: false,
|
||||
pin_guard: false,
|
||||
diagnostic_dumps: false
|
||||
farm_designer: false,
|
||||
firmware: false,
|
||||
farmbot_os: false,
|
||||
};
|
||||
};
|
||||
|
|
|
@ -1,18 +1,23 @@
|
|||
import { DesignerState } from "../farm_designer/interfaces";
|
||||
|
||||
export const fakeDesignerState = (): DesignerState => ({
|
||||
selectedPlants: undefined,
|
||||
selectedPoints: undefined,
|
||||
selectionPointType: undefined,
|
||||
hoveredPlant: {
|
||||
plantUUID: undefined,
|
||||
icon: ""
|
||||
},
|
||||
hoveredPoint: undefined,
|
||||
hoveredPlantListItem: undefined,
|
||||
hoveredToolSlot: undefined,
|
||||
cropSearchQuery: "",
|
||||
cropSearchResults: [],
|
||||
cropSearchInProgress: false,
|
||||
chosenLocation: { x: undefined, y: undefined, z: undefined },
|
||||
currentPoint: undefined,
|
||||
drawnPoint: undefined,
|
||||
drawnWeed: undefined,
|
||||
openedSavedGarden: undefined,
|
||||
tryGroupSortType: undefined,
|
||||
editGroupAreaInMap: false,
|
||||
settingsSearchTerm: "",
|
||||
});
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
export const mockDispatch = (innerDispatch = jest.fn()) =>
|
||||
jest.fn(x => typeof x === "function" && x(innerDispatch));
|
|
@ -0,0 +1,36 @@
|
|||
import { DeepPartial } from "redux";
|
||||
|
||||
type DomEvent = React.SyntheticEvent<HTMLInputElement>;
|
||||
export const inputEvent = (value: string, name?: string): DomEvent => {
|
||||
const event: DeepPartial<DomEvent> = { currentTarget: { value, name } };
|
||||
return event as DomEvent;
|
||||
};
|
||||
|
||||
type ChangeEvent = React.ChangeEvent<HTMLInputElement>;
|
||||
export const changeEvent = (value: string): ChangeEvent => {
|
||||
const event: DeepPartial<ChangeEvent> = { currentTarget: { value } };
|
||||
return event as ChangeEvent;
|
||||
};
|
||||
|
||||
type IMGEvent = React.SyntheticEvent<HTMLImageElement, Event>;
|
||||
export const imgEvent = (): IMGEvent => {
|
||||
const event: DeepPartial<IMGEvent> = {
|
||||
currentTarget: {
|
||||
getAttribute: jest.fn(),
|
||||
setAttribute: jest.fn(),
|
||||
}
|
||||
};
|
||||
return event as IMGEvent;
|
||||
};
|
||||
|
||||
type FormEvent = React.FormEvent<HTMLFormElement>;
|
||||
export const formEvent = (): FormEvent => {
|
||||
const event: Partial<FormEvent> = { preventDefault: jest.fn() };
|
||||
return event as FormEvent;
|
||||
};
|
||||
|
||||
type DragEvent = React.DragEvent<HTMLElement>;
|
||||
export const dragEvent = (key: string): DragEvent => {
|
||||
const event: DeepPartial<DragEvent> = { dataTransfer: { getData: () => key } };
|
||||
return event as DragEvent;
|
||||
};
|
|
@ -1,7 +0,0 @@
|
|||
import { DeepPartial } from "redux";
|
||||
|
||||
type DomEvent = React.SyntheticEvent<HTMLInputElement>;
|
||||
export const inputEvent = (value: string): DomEvent => {
|
||||
const event: DeepPartial<DomEvent> = { currentTarget: { value } };
|
||||
return event as DomEvent;
|
||||
};
|
|
@ -0,0 +1,17 @@
|
|||
import { HardwareFlags, FarmwareData } from "../sequences/interfaces";
|
||||
|
||||
export const fakeHardwareFlags = (): HardwareFlags => ({
|
||||
findHomeEnabled: { x: false, y: false, z: false },
|
||||
stopAtHome: { x: false, y: false, z: false },
|
||||
stopAtMax: { x: false, y: false, z: false },
|
||||
negativeOnly: { x: false, y: false, z: false },
|
||||
axisLength: { x: 0, y: 0, z: 0 },
|
||||
});
|
||||
|
||||
export const fakeFarmwareData = (): FarmwareData => ({
|
||||
farmwareNames: [],
|
||||
firstPartyFarmwareNames: [],
|
||||
showFirstPartyFarmware: false,
|
||||
farmwareConfigs: {},
|
||||
cameraDisabled: false,
|
||||
});
|
|
@ -1,6 +1,5 @@
|
|||
import { noop } from "lodash";
|
||||
import { Everything } from "../interfaces";
|
||||
import { peripherals as Peripheral } from "./fake_state/peripherals";
|
||||
import { auth } from "./fake_state/token";
|
||||
import { bot } from "./fake_state/bot";
|
||||
import { config } from "./fake_state/config";
|
||||
|
@ -11,7 +10,6 @@ import { resources } from "./fake_state/resources";
|
|||
export function fakeState(_: Function = noop): Everything {
|
||||
return {
|
||||
dispatch: jest.fn(),
|
||||
Peripheral,
|
||||
auth,
|
||||
bot,
|
||||
config,
|
||||
|
|
|
@ -1,17 +1,10 @@
|
|||
import { Everything } from "../../interfaces";
|
||||
import { panelState } from "../control_panel_state";
|
||||
|
||||
export let bot: Everything["bot"] = {
|
||||
export const bot: Everything["bot"] = {
|
||||
"consistent": true,
|
||||
"stepSize": 100,
|
||||
"controlPanelState": {
|
||||
"homing_and_calibration": false,
|
||||
"motors": false,
|
||||
"encoders_and_endstops": false,
|
||||
"danger_zone": false,
|
||||
"power_and_reset": false,
|
||||
"pin_guard": false,
|
||||
"diagnostic_dumps": false
|
||||
},
|
||||
"controlPanelState": panelState(),
|
||||
"hardware": {
|
||||
"gpio_registry": {},
|
||||
"mcu_params": {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { Everything } from "../../interfaces";
|
||||
|
||||
export let config: Everything["config"] = {
|
||||
export const config: Everything["config"] = {
|
||||
"host": "localhost",
|
||||
"port": "3000"
|
||||
};
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue