Compare commits
346 Commits
master
...
thirteen-w
| Author | SHA1 | Date | |
|---|---|---|---|
| 28be8e980e | |||
| 67680ae03d | |||
| ae5b191c9b | |||
| 11d37f4a34 | |||
| a2f153c47d | |||
| fd852b0619 | |||
| b16813fa84 | |||
| f6047bb928 | |||
| 2d4346e213 | |||
| e7c46bd0bd | |||
| 51501e791d | |||
| e960f7edad | |||
| 4313eed64e | |||
| a110452f1f | |||
| d8f2cb487d | |||
| 9bc12e6d4d | |||
| 22049c2fef | |||
| 5be9321cce | |||
| 7da6b9abbe | |||
| 77f13dc109 | |||
| dac62cbe7b | |||
| 7c032fe2d1 | |||
| c855001f99 | |||
| 6ae784daea | |||
| 38fe7ffcd7 | |||
| e1ba77045f | |||
| 0591c25990 | |||
| 4b0c785a67 | |||
| 5f3ed30d21 | |||
| 3f4d2aa44f | |||
| 87a9b8ad33 | |||
| aa4cc4d150 | |||
| ce269f056f | |||
| f8f7414490 | |||
| 64ebd1c509 | |||
| 991de51e49 | |||
| e34ffb0319 | |||
| 9a9eab0d5b | |||
| 11bc9b8f65 | |||
| e726966e84 | |||
| af9b29d085 | |||
| 528f02b3e3 | |||
| f93b6f0791 | |||
| 2d86b6eaa6 | |||
| 43c6d79acc | |||
| f44f70e405 | |||
| b8ce70bcb6 | |||
| 0cb585575d | |||
| 3f076b852c | |||
| 5bfeec5c6a | |||
| 162e2d792c | |||
| 8ce592b605 | |||
| dc99d2711a | |||
| 88452cc245 | |||
| 529e1156ab | |||
| 15f39249ee | |||
| f27e5a0071 | |||
| 834e3da6a3 | |||
| 1090be55be | |||
| ced73753d8 | |||
| 7328ccf331 | |||
| f366db0ee5 | |||
| 6ff340f58b | |||
| 7f584876ce | |||
| 0b72d1e481 | |||
| 4eec2bd563 | |||
| 3f836a5885 | |||
| cb5c043178 | |||
| 52ea5fecef | |||
| d930c01214 | |||
| 75f53fc0d3 | |||
| e4eb30eaae | |||
| 36eed55122 | |||
| 62bb9ab322 | |||
| 5a61da69d0 | |||
| ce60dd2de3 | |||
| a17c52a635 | |||
| 2d2c19800b | |||
| a1d8e6bdcd | |||
| 74ca0a9082 | |||
| 2736c13aac | |||
| 6bd0e4c1de | |||
| b4d0afe90d | |||
| 5882c82f75 | |||
| 062e704798 | |||
| 972efcdf85 | |||
| 5f472c96b8 | |||
| 71a42f109a | |||
| eec022a47b | |||
| 38e983ce08 | |||
| 57498b7a0e | |||
| 09b9d7ff22 | |||
| 3c95bf4859 | |||
| 0f11f515d2 | |||
| a6f084a372 | |||
| ff3de26b48 | |||
| c45487404f | |||
| ffceb89c50 | |||
| e0112f3dc8 | |||
| 3d841dc768 | |||
| 1b49e53c4f | |||
| 8b0809a79f | |||
| e8ad3dff9e | |||
| ce0d3d71fa | |||
| 44894bf4ff | |||
| 1eefcb36f4 | |||
| b696190181 | |||
| a1d01f0016 | |||
| 21727ed359 | |||
| fc516469dc | |||
| 9d9ac53fcd | |||
| 161ef86384 | |||
| 4bf22922ac | |||
| c282a09b17 | |||
| 73ae43632c | |||
| 1285f77154 | |||
| 2afae71d95 | |||
| acd7580e93 | |||
| 60a8a40006 | |||
| 3e35edc379 | |||
| d510e954e0 | |||
| 1856c4d655 | |||
| 0384b434e9 | |||
| 33155b5cb8 | |||
| e53b74e63f | |||
| 440c4352bb | |||
| f99d223992 | |||
| 78a4b725a6 | |||
| 940bcbfb2f | |||
| 18a12afb78 | |||
| ef0c9e69a0 | |||
| 6edf8288fa | |||
| adca780db7 | |||
| 6d8438c675 | |||
| 72255c0765 | |||
| 623d51d388 | |||
| 45bdab0eaf | |||
| a0e7c000fd | |||
| 1c52f306c1 | |||
| 2c5e4171f0 | |||
| 7ef7e30a94 | |||
| db8165f832 | |||
| 42544fdb4e | |||
| 6629b2015a | |||
| 9bbf18219f | |||
| ff5a7c8e89 | |||
| b0e60d5d91 | |||
| c4a4264c8d | |||
| 303e79b9ca | |||
| 8848d793aa | |||
| 0faf426121 | |||
| 9d3f2fe4c7 | |||
| b81969bc90 | |||
| 35d1953318 | |||
| 79c16cc0e1 | |||
| a6f4c2e3b9 | |||
| d809465af1 | |||
| 9db776bfab | |||
| 7839816706 | |||
| dd8286791b | |||
| 7348a5a1bf | |||
| da84fee07a | |||
| 6887ea8bb8 | |||
| 032d2adbd4 | |||
| 470b04df1a | |||
| a63e062d55 | |||
| 292a0db78d | |||
| 870f288936 | |||
| 7571a78afc | |||
| dfb486943a | |||
| d091b43391 | |||
| 081082e0bf | |||
| 92571fc028 | |||
| 143e711fdd | |||
| e64c03fff2 | |||
| 5e6ecdfbb5 | |||
| 1cf9121f0f | |||
| 1242c02779 | |||
| 39e04014bb | |||
| 2d95cc9e3a | |||
| 379aa46300 | |||
| 7c732ef006 | |||
| efdf8376d0 | |||
| 23201ce02c | |||
| 0e373ddbbf | |||
| e1deb80c6a | |||
| 2f4d0eb34f | |||
| a9c7d3fcad | |||
| d20c4fa7b6 | |||
| 8c91245248 | |||
| 56e447879e | |||
| 5a39ad34d0 | |||
| 71593371ab | |||
| 33672a232a | |||
| 37d2d52b8e | |||
| 54b5a12023 | |||
| 8e7d66a283 | |||
| 00a70cef57 | |||
| 607a5b9ffe | |||
| 329b490489 | |||
| c88e7b3f00 | |||
| 29dc6082cf | |||
| a2b8769e33 | |||
| 165d67c994 | |||
| f69ff9d1b0 | |||
| cc0590a316 | |||
| 2c81f123e8 | |||
| 45d90758a6 | |||
| 96219ff1b4 | |||
| 802b692623 | |||
| 1a1e3d1b2f | |||
| 3f954c16f1 | |||
| 40ec18e635 | |||
| 845f515aea | |||
| 275a6290d2 | |||
| 037dca41d5 | |||
| 6b41b5f2d1 | |||
| 03bbc8e21f | |||
| 4602bd18f2 | |||
| 41847395c9 | |||
| 9024e4134d | |||
| fca53d6575 | |||
| d39af457ac | |||
| 3837e6e38a | |||
| df4b77a1c7 | |||
| e9539adaf0 | |||
| 0549e48eef | |||
| 0dd6c9b09f | |||
| d07eca8cd0 | |||
| c85eba4029 | |||
| f499d1fb04 | |||
| 149a915065 | |||
| 44a540cbe8 | |||
| d53ecef3f4 | |||
| 8a3fa049ae | |||
| e747b1cd41 | |||
| ef46165f7a | |||
| fd8ee73fad | |||
| c7e46ac663 | |||
| 5497d0c874 | |||
| a72b8271cb | |||
| 3b7a38d861 | |||
| 34502f4794 | |||
| 38a1e54cca | |||
| c7f91341f8 | |||
| 5bdd7217c7 | |||
| 6a58d32ffd | |||
| abf0bf4b4b | |||
| bef5af7c5a | |||
| 278c3ec0a6 | |||
| a6e897574d | |||
| 9dafd9374a | |||
| 299e46b1a5 | |||
| 2fbe78202a | |||
| 362361dbc1 | |||
| 5d470b225d | |||
| 95794aeaf6 | |||
| c39aeada85 | |||
| 76c6589388 | |||
| 4eb8ee8bbe | |||
| 08bcaf8fba | |||
| 7b5c67e0e4 | |||
| 1aacaddb92 | |||
| 9e7c901551 | |||
| 8b4ac49144 | |||
| ff00434945 | |||
| e3602f367c | |||
| 42c754263b | |||
| 403f60abca | |||
| 6aec34f42e | |||
| b608565ec5 | |||
| 6812938382 | |||
| 3aaed9002f | |||
| af3a248568 | |||
| 5fa3fe4b35 | |||
| e8b9a90dd0 | |||
| 1804618b77 | |||
| f3ff3a9bfe | |||
| 30e66879ba | |||
| 89f5c84d0a | |||
| bd85e3c5c4 | |||
| 37cccaadda | |||
| 1b4a78c3c9 | |||
| 70fb12719a | |||
| 0bdc7f6481 | |||
| d5ef4d6481 | |||
| d163fa2eaa | |||
| 88c6ca6c57 | |||
| 4261347993 | |||
| 6e877c5171 | |||
| 5a7b46edb3 | |||
| a006df6069 | |||
| 8425c7539e | |||
| 14ad73b764 | |||
| b03c6b8392 | |||
| c21c783a59 | |||
| 847515407f | |||
| 9811857f3b | |||
| d9d8de612b | |||
| 937ed38e80 | |||
| 910d36c1ac | |||
| 42bacea451 | |||
| 8b3a3e0dde | |||
| 6298225be5 | |||
| 577b01a1d9 | |||
| 5abbc66446 | |||
| db5efbe670 | |||
| 794f9dc953 | |||
| d671517b47 | |||
| 919e5379f7 | |||
| fad8a9e2c3 | |||
| b665999104 | |||
| 8970379e57 | |||
| 54b65ed212 | |||
| bbfb20a390 | |||
| 00b24af7a2 | |||
| 88da6c0533 | |||
| dfe22f723a | |||
| 758a18df90 | |||
| ca83f75241 | |||
| 1a0a52cfed | |||
| 6f4bc0fcdd | |||
| e6a0214add | |||
| be25ccc8f0 | |||
| 241cc07838 | |||
| 644eeb7ed9 | |||
| 4c9e082122 | |||
| 709415fc8e | |||
| 7a44b21f15 | |||
| d56e663a2c | |||
| 602c3c36f2 | |||
| 6680ae39ed | |||
| b371682c23 | |||
| f8af8ed880 | |||
| 2b81a1f976 | |||
| c2865fb638 | |||
| af24c7f9c9 | |||
| 929185dc2c | |||
| fd5730ceb7 | |||
| fea3e02392 | |||
| 0ae22a7a7f | |||
| dba4e6e871 | |||
| e5145206f8 | |||
| 5987c3caf3 | |||
| a9a9485303 | |||
| 6e39e3031e |
3
.gitignore
vendored
@ -9,6 +9,7 @@
|
|||||||
# Corrections? Improvements? Create a GitHub issue:
|
# Corrections? Improvements? Create a GitHub issue:
|
||||||
# http://github.com/RailsApps/rails-composer/issues
|
# http://github.com/RailsApps/rails-composer/issues
|
||||||
#----------------------------------------------------------------------------
|
#----------------------------------------------------------------------------
|
||||||
|
/spec/reports/
|
||||||
|
|
||||||
# ctags
|
# ctags
|
||||||
tags
|
tags
|
||||||
@ -77,7 +78,9 @@ pickle-email-*.html
|
|||||||
|
|
||||||
# vim artifacts
|
# vim artifacts
|
||||||
**.swp
|
**.swp
|
||||||
|
*.un~
|
||||||
|
|
||||||
# Environment files that may contain sensitive data
|
# Environment files that may contain sensitive data
|
||||||
.env
|
.env
|
||||||
.powenv
|
.powenv
|
||||||
|
node_modules/
|
||||||
|
|||||||
@ -1 +1 @@
|
|||||||
2.6.0
|
3.2.2
|
||||||
|
|||||||
12
Capfile
@ -4,22 +4,26 @@ require 'capistrano/setup'
|
|||||||
# Includes default deployment tasks
|
# Includes default deployment tasks
|
||||||
require 'capistrano/deploy'
|
require 'capistrano/deploy'
|
||||||
|
|
||||||
require 'capistrano/puma'
|
|
||||||
require 'capistrano/puma/workers'
|
|
||||||
require 'capistrano/puma/jungle'
|
|
||||||
require 'capistrano/rbenv'
|
require 'capistrano/rbenv'
|
||||||
|
require 'capistrano/puma'
|
||||||
|
install_plugin Capistrano::Puma # Default puma tasks
|
||||||
|
install_plugin Capistrano::Puma::Systemd
|
||||||
|
# require 'capistrano/puma/workers'
|
||||||
|
# require 'capistrano/puma/jungle'
|
||||||
require 'capistrano/bundler'
|
require 'capistrano/bundler'
|
||||||
require 'capistrano/nginx'
|
require 'capistrano/nginx'
|
||||||
require 'capistrano/rails/assets'
|
require 'capistrano/rails/assets'
|
||||||
require 'capistrano/rails/migrations'
|
require 'capistrano/rails/migrations'
|
||||||
require 'capistrano/postgresql'
|
require 'capistrano/postgresql'
|
||||||
#require 'capistrano/bower'
|
#require 'capistrano/bower'
|
||||||
|
# TODO enable job scheduler require 'capistrano/delayed_job'
|
||||||
|
|
||||||
|
|
||||||
# Includes tasks from other gems included in your Gemfile
|
# Includes tasks from other gems included in your Gemfile
|
||||||
#
|
#
|
||||||
# For documentation on these, see for example:
|
# For documentation on these, see for example:
|
||||||
#
|
require "capistrano/scm/git"
|
||||||
|
install_plugin Capistrano::SCM::Git#
|
||||||
# https://github.com/capistrano/rvm
|
# https://github.com/capistrano/rvm
|
||||||
# https://github.com/capistrano/rbenv
|
# https://github.com/capistrano/rbenv
|
||||||
# https://github.com/capistrano/chruby
|
# https://github.com/capistrano/chruby
|
||||||
|
|||||||
46
Gemfile
@ -1,26 +1,29 @@
|
|||||||
source 'https://rubygems.org'
|
source 'https://rubygems.org'
|
||||||
ruby '2.6.0'
|
ruby '3.2.2'
|
||||||
gem 'rails', '5.2.2'
|
gem 'rails', '~> 7.0'
|
||||||
|
# TODO Upgrade sprockets
|
||||||
|
gem 'redis', '~> 4.0'
|
||||||
|
gem 'sprockets' #, '~> 3.7'
|
||||||
gem 'sass-rails' #, '~> 4.0.3'
|
gem 'sass-rails' #, '~> 4.0.3'
|
||||||
gem 'uglifier' #, '>= 1.3.0'
|
# gem 'uglifier' #, '>= 1.3.0'
|
||||||
gem 'coffee-rails' #, '~> 4.0.0'
|
gem 'coffee-rails' #, '~> 4.0.0'
|
||||||
gem 'jquery-rails'
|
gem 'jquery-rails'
|
||||||
gem 'turbolinks'
|
gem 'jquery-ui-rails'
|
||||||
|
# gem 'turbolinks'
|
||||||
gem 'jbuilder' #, '~> 2.0'
|
gem 'jbuilder' #, '~> 2.0'
|
||||||
gem 'sdoc', group: :doc #, '~> 0.4.0'
|
gem 'sdoc', group: :doc #, '~> 0.4.0'
|
||||||
gem 'spring', group: :development
|
|
||||||
gem 'devise'
|
gem 'devise'
|
||||||
gem 'devise_invitable'
|
gem 'devise_invitable'
|
||||||
gem 'haml-rails'
|
gem 'haml-rails'
|
||||||
gem 'high_voltage'
|
gem 'high_voltage'
|
||||||
gem 'pg'
|
gem 'pg'
|
||||||
gem 'puma'
|
gem 'puma', '6'
|
||||||
gem 'pundit'
|
gem 'pundit'
|
||||||
gem 'simple_form'
|
gem 'simple_form'
|
||||||
gem 'upmin-admin'
|
|
||||||
gem 'dotenv-rails'
|
gem 'dotenv-rails'
|
||||||
gem 'react-rails'
|
gem 'react-rails'
|
||||||
# gem 'react-rails-hot-loader'
|
# gem 'react-rails-hot-loader'
|
||||||
|
gem 'ci_reporter_rspec'
|
||||||
group :development do
|
group :development do
|
||||||
gem 'parallel_tests', group: :development
|
gem 'parallel_tests', group: :development
|
||||||
gem 'better_errors'
|
gem 'better_errors'
|
||||||
@ -30,11 +33,18 @@ group :development do
|
|||||||
gem 'capistrano-bundler'
|
gem 'capistrano-bundler'
|
||||||
gem 'capistrano-rails'
|
gem 'capistrano-rails'
|
||||||
gem 'capistrano-rails-console'
|
gem 'capistrano-rails-console'
|
||||||
gem 'capistrano3-puma'
|
gem 'capistrano3-puma', '~> 6.0.beta'
|
||||||
gem 'capistrano-rbenv'
|
gem 'capistrano-rbenv'
|
||||||
gem 'capistrano-nginx', github: 'koenpunt/capistrano-nginx'
|
gem 'capistrano-nginx', github: 'koenpunt/capistrano-nginx'
|
||||||
gem "capistrano-db-tasks", require: false
|
gem "capistrano-db-tasks", require: false
|
||||||
gem "capistrano-postgresql" #, '~> 4.2.0'
|
gem "capistrano-postgresql" #, '~> 4.2.0'
|
||||||
|
# TODO enable job scheduler gem 'capistrano3-delayed-job', '~> 1.0'
|
||||||
|
# required for ecdsa key
|
||||||
|
gem "bcrypt_pbkdf", require: false
|
||||||
|
gem "net-ssh", ">= 4.0.0", require: false
|
||||||
|
gem "rbnacl", "~> 3.4", require: false
|
||||||
|
gem "rbnacl-libsodium", require: false
|
||||||
|
gem "ed25519", require: false
|
||||||
gem 'guard-bundler'
|
gem 'guard-bundler'
|
||||||
gem 'guard-rails'
|
gem 'guard-rails'
|
||||||
gem 'guard-rspec'
|
gem 'guard-rspec'
|
||||||
@ -47,21 +57,35 @@ group :development do
|
|||||||
gem 'rb-fchange', require: false
|
gem 'rb-fchange', require: false
|
||||||
gem 'rb-fsevent', require: false
|
gem 'rb-fsevent', require: false
|
||||||
gem 'rb-inotify', require: false
|
gem 'rb-inotify', require: false
|
||||||
gem 'spring-commands-rspec'
|
# gem 'spring-commands-rspec'
|
||||||
gem 'guard-ctags-bundler'
|
gem 'guard-ctags-bundler'
|
||||||
end
|
end
|
||||||
group :development, :test, :staging do
|
group :development, :test do
|
||||||
gem 'factory_girl_rails'
|
gem 'factory_girl_rails'
|
||||||
gem 'faker'
|
gem 'faker'
|
||||||
gem 'pry-rails'
|
gem 'pry-rails'
|
||||||
gem 'pry-rescue'
|
gem 'pry-rescue'
|
||||||
gem 'rspec-rails'
|
gem 'rspec-rails'
|
||||||
|
gem 'spring'
|
||||||
|
gem 'spring-commands-rspec'
|
||||||
end
|
end
|
||||||
group :test, :staging do
|
group :test, :staging do
|
||||||
gem 'capybara'
|
gem 'capybara'
|
||||||
gem 'database_cleaner'
|
gem 'database_cleaner'
|
||||||
gem "poltergeist"
|
|
||||||
gem 'launchy'
|
gem 'launchy'
|
||||||
gem 'selenium-webdriver'
|
gem 'selenium-webdriver'
|
||||||
|
gem 'webdrivers'
|
||||||
gem 'simplecov', :require => false
|
gem 'simplecov', :require => false
|
||||||
end
|
end
|
||||||
|
gem 'capybara-screenshot', :group => :test
|
||||||
|
gem 'friendly_id', '~> 5.4.0'
|
||||||
|
gem 'inline_svg'
|
||||||
|
gem 'importmap-rails'
|
||||||
|
gem 'turbo-rails'
|
||||||
|
gem 'stimulus-rails'
|
||||||
|
gem 'will_paginate'
|
||||||
|
# TODO enable telegram bots with job scheduler gem 'telegram-bot-ruby', '~> 1.0'
|
||||||
|
# TODO enable job scheduler gem 'delayed_job_active_record'
|
||||||
|
# TODO enable job scheduler gem 'daemons'
|
||||||
|
|
||||||
|
# TODO enable job scheduler gem "activejob-status", "~> 1.0"
|
||||||
|
|||||||
693
Gemfile.lock
@ -1,5 +1,5 @@
|
|||||||
GIT
|
GIT
|
||||||
remote: git://github.com/koenpunt/capistrano-nginx.git
|
remote: https://github.com/koenpunt/capistrano-nginx.git
|
||||||
revision: 5a91aed41c16fb38b6d9d9462ba1ddfe76dede55
|
revision: 5a91aed41c16fb38b6d9d9462ba1ddfe76dede55
|
||||||
specs:
|
specs:
|
||||||
capistrano-nginx (0.2.1)
|
capistrano-nginx (0.2.1)
|
||||||
@ -8,159 +8,211 @@ GIT
|
|||||||
GEM
|
GEM
|
||||||
remote: https://rubygems.org/
|
remote: https://rubygems.org/
|
||||||
specs:
|
specs:
|
||||||
actioncable (5.2.2)
|
actioncable (7.1.2)
|
||||||
actionpack (= 5.2.2)
|
actionpack (= 7.1.2)
|
||||||
|
activesupport (= 7.1.2)
|
||||||
nio4r (~> 2.0)
|
nio4r (~> 2.0)
|
||||||
websocket-driver (>= 0.6.1)
|
websocket-driver (>= 0.6.1)
|
||||||
actionmailer (5.2.2)
|
zeitwerk (~> 2.6)
|
||||||
actionpack (= 5.2.2)
|
actionmailbox (7.1.2)
|
||||||
actionview (= 5.2.2)
|
actionpack (= 7.1.2)
|
||||||
activejob (= 5.2.2)
|
activejob (= 7.1.2)
|
||||||
|
activerecord (= 7.1.2)
|
||||||
|
activestorage (= 7.1.2)
|
||||||
|
activesupport (= 7.1.2)
|
||||||
|
mail (>= 2.7.1)
|
||||||
|
net-imap
|
||||||
|
net-pop
|
||||||
|
net-smtp
|
||||||
|
actionmailer (7.1.2)
|
||||||
|
actionpack (= 7.1.2)
|
||||||
|
actionview (= 7.1.2)
|
||||||
|
activejob (= 7.1.2)
|
||||||
|
activesupport (= 7.1.2)
|
||||||
mail (~> 2.5, >= 2.5.4)
|
mail (~> 2.5, >= 2.5.4)
|
||||||
rails-dom-testing (~> 2.0)
|
net-imap
|
||||||
actionpack (5.2.2)
|
net-pop
|
||||||
actionview (= 5.2.2)
|
net-smtp
|
||||||
activesupport (= 5.2.2)
|
rails-dom-testing (~> 2.2)
|
||||||
rack (~> 2.0)
|
actionpack (7.1.2)
|
||||||
|
actionview (= 7.1.2)
|
||||||
|
activesupport (= 7.1.2)
|
||||||
|
nokogiri (>= 1.8.5)
|
||||||
|
racc
|
||||||
|
rack (>= 2.2.4)
|
||||||
|
rack-session (>= 1.0.1)
|
||||||
rack-test (>= 0.6.3)
|
rack-test (>= 0.6.3)
|
||||||
rails-dom-testing (~> 2.0)
|
rails-dom-testing (~> 2.2)
|
||||||
rails-html-sanitizer (~> 1.0, >= 1.0.2)
|
rails-html-sanitizer (~> 1.6)
|
||||||
actionview (5.2.2)
|
actiontext (7.1.2)
|
||||||
activesupport (= 5.2.2)
|
actionpack (= 7.1.2)
|
||||||
|
activerecord (= 7.1.2)
|
||||||
|
activestorage (= 7.1.2)
|
||||||
|
activesupport (= 7.1.2)
|
||||||
|
globalid (>= 0.6.0)
|
||||||
|
nokogiri (>= 1.8.5)
|
||||||
|
actionview (7.1.2)
|
||||||
|
activesupport (= 7.1.2)
|
||||||
builder (~> 3.1)
|
builder (~> 3.1)
|
||||||
erubi (~> 1.4)
|
erubi (~> 1.11)
|
||||||
rails-dom-testing (~> 2.0)
|
rails-dom-testing (~> 2.2)
|
||||||
rails-html-sanitizer (~> 1.0, >= 1.0.3)
|
rails-html-sanitizer (~> 1.6)
|
||||||
activejob (5.2.2)
|
activejob (7.1.2)
|
||||||
activesupport (= 5.2.2)
|
activesupport (= 7.1.2)
|
||||||
globalid (>= 0.3.6)
|
globalid (>= 0.3.6)
|
||||||
activemodel (5.2.2)
|
activemodel (7.1.2)
|
||||||
activesupport (= 5.2.2)
|
activesupport (= 7.1.2)
|
||||||
activerecord (5.2.2)
|
activerecord (7.1.2)
|
||||||
activemodel (= 5.2.2)
|
activemodel (= 7.1.2)
|
||||||
activesupport (= 5.2.2)
|
activesupport (= 7.1.2)
|
||||||
arel (>= 9.0)
|
timeout (>= 0.4.0)
|
||||||
activestorage (5.2.2)
|
activestorage (7.1.2)
|
||||||
actionpack (= 5.2.2)
|
actionpack (= 7.1.2)
|
||||||
activerecord (= 5.2.2)
|
activejob (= 7.1.2)
|
||||||
marcel (~> 0.3.1)
|
activerecord (= 7.1.2)
|
||||||
activesupport (5.2.2)
|
activesupport (= 7.1.2)
|
||||||
|
marcel (~> 1.0)
|
||||||
|
activesupport (7.1.2)
|
||||||
|
base64
|
||||||
|
bigdecimal
|
||||||
concurrent-ruby (~> 1.0, >= 1.0.2)
|
concurrent-ruby (~> 1.0, >= 1.0.2)
|
||||||
i18n (>= 0.7, < 2)
|
connection_pool (>= 2.2.5)
|
||||||
minitest (~> 5.1)
|
drb
|
||||||
tzinfo (~> 1.1)
|
i18n (>= 1.6, < 2)
|
||||||
addressable (2.6.0)
|
minitest (>= 5.1)
|
||||||
public_suffix (>= 2.0.2, < 4.0)
|
mutex_m
|
||||||
airbrussh (1.3.1)
|
tzinfo (~> 2.0)
|
||||||
|
addressable (2.8.5)
|
||||||
|
public_suffix (>= 2.0.2, < 6.0)
|
||||||
|
airbrussh (1.5.0)
|
||||||
sshkit (>= 1.6.1, != 1.7.0)
|
sshkit (>= 1.6.1, != 1.7.0)
|
||||||
arel (9.0.0)
|
ast (2.4.2)
|
||||||
ast (2.4.0)
|
|
||||||
babel-source (5.8.35)
|
babel-source (5.8.35)
|
||||||
babel-transpiler (0.7.0)
|
babel-transpiler (0.7.0)
|
||||||
babel-source (>= 4.0, < 6)
|
babel-source (>= 4.0, < 6)
|
||||||
execjs (~> 2.0)
|
execjs (~> 2.0)
|
||||||
bcrypt (3.1.12)
|
base64 (0.2.0)
|
||||||
better_errors (2.5.1)
|
bcrypt (3.1.20)
|
||||||
coderay (>= 1.0.0)
|
bcrypt_pbkdf (1.1.0)
|
||||||
|
better_errors (2.10.1)
|
||||||
erubi (>= 1.0.0)
|
erubi (>= 1.0.0)
|
||||||
rack (>= 0.9.0)
|
rack (>= 0.9.0)
|
||||||
binding_of_caller (0.8.0)
|
rouge (>= 1.0.0)
|
||||||
|
bigdecimal (3.1.4)
|
||||||
|
binding_of_caller (1.0.0)
|
||||||
debug_inspector (>= 0.0.1)
|
debug_inspector (>= 0.0.1)
|
||||||
builder (3.2.3)
|
builder (3.2.4)
|
||||||
capistrano (3.11.0)
|
capistrano (3.18.0)
|
||||||
airbrussh (>= 1.0.0)
|
airbrussh (>= 1.0.0)
|
||||||
i18n
|
i18n
|
||||||
rake (>= 10.0.0)
|
rake (>= 10.0.0)
|
||||||
sshkit (>= 1.9.0)
|
sshkit (>= 1.9.0)
|
||||||
capistrano-bundler (1.5.0)
|
capistrano-bundler (2.1.0)
|
||||||
capistrano (~> 3.1)
|
capistrano (~> 3.1)
|
||||||
capistrano-db-tasks (0.6)
|
capistrano-db-tasks (0.6)
|
||||||
capistrano (>= 3.0.0)
|
capistrano (>= 3.0.0)
|
||||||
capistrano-postgresql (6.2.0)
|
capistrano-postgresql (6.2.0)
|
||||||
capistrano (>= 3.0)
|
capistrano (>= 3.0)
|
||||||
sshkit (>= 1.17.0)
|
sshkit (>= 1.17.0)
|
||||||
capistrano-rails (1.4.0)
|
capistrano-rails (1.6.3)
|
||||||
capistrano (~> 3.1)
|
capistrano (~> 3.1)
|
||||||
capistrano-bundler (~> 1.1)
|
capistrano-bundler (>= 1.1, < 3)
|
||||||
capistrano-rails-console (2.3.0)
|
capistrano-rails-console (2.3.0)
|
||||||
capistrano (>= 3.5.0, < 4.0.0)
|
capistrano (>= 3.5.0, < 4.0.0)
|
||||||
sshkit-interactive (~> 0.3.0)
|
sshkit-interactive (~> 0.3.0)
|
||||||
capistrano-rbenv (2.1.4)
|
capistrano-rbenv (2.2.0)
|
||||||
capistrano (~> 3.1)
|
capistrano (~> 3.1)
|
||||||
sshkit (~> 1.3)
|
sshkit (~> 1.3)
|
||||||
capistrano3-puma (3.1.1)
|
capistrano3-puma (6.0.0.beta.1)
|
||||||
capistrano (~> 3.7)
|
capistrano (~> 3.7)
|
||||||
capistrano-bundler
|
capistrano-bundler
|
||||||
puma (~> 3.4)
|
puma (>= 5.1, < 7.0)
|
||||||
capybara (3.14.0)
|
capybara (3.39.2)
|
||||||
addressable
|
addressable
|
||||||
|
matrix
|
||||||
mini_mime (>= 0.1.3)
|
mini_mime (>= 0.1.3)
|
||||||
nokogiri (~> 1.8)
|
nokogiri (~> 1.8)
|
||||||
rack (>= 1.6.0)
|
rack (>= 1.6.0)
|
||||||
rack-test (>= 0.6.3)
|
rack-test (>= 0.6.3)
|
||||||
regexp_parser (~> 1.2)
|
regexp_parser (>= 1.5, < 3.0)
|
||||||
xpath (~> 3.2)
|
xpath (~> 3.2)
|
||||||
chartkick (3.0.2)
|
capybara-screenshot (1.0.26)
|
||||||
childprocess (0.9.0)
|
capybara (>= 1.0, < 4)
|
||||||
ffi (~> 1.0, >= 1.0.11)
|
launchy
|
||||||
cliver (0.3.2)
|
ci_reporter (2.1.0)
|
||||||
coderay (1.1.2)
|
builder (>= 2.1.2)
|
||||||
coffee-rails (4.2.2)
|
rexml
|
||||||
|
ci_reporter_rspec (1.0.0)
|
||||||
|
ci_reporter (~> 2.0)
|
||||||
|
rspec (>= 2.14, < 4)
|
||||||
|
coderay (1.1.3)
|
||||||
|
coffee-rails (5.0.0)
|
||||||
coffee-script (>= 2.2.0)
|
coffee-script (>= 2.2.0)
|
||||||
railties (>= 4.0.0)
|
railties (>= 5.2.0)
|
||||||
coffee-script (2.4.1)
|
coffee-script (2.4.1)
|
||||||
coffee-script-source
|
coffee-script-source
|
||||||
execjs
|
execjs
|
||||||
coffee-script-source (1.12.2)
|
coffee-script-source (1.12.2)
|
||||||
concurrent-ruby (1.1.4)
|
concurrent-ruby (1.2.2)
|
||||||
connection_pool (2.2.2)
|
connection_pool (2.4.1)
|
||||||
crass (1.0.4)
|
crass (1.0.6)
|
||||||
database_cleaner (1.7.0)
|
database_cleaner (2.0.2)
|
||||||
debug_inspector (0.0.3)
|
database_cleaner-active_record (>= 2, < 3)
|
||||||
devise (4.6.1)
|
database_cleaner-active_record (2.1.0)
|
||||||
|
activerecord (>= 5.a)
|
||||||
|
database_cleaner-core (~> 2.0.0)
|
||||||
|
database_cleaner-core (2.0.1)
|
||||||
|
date (3.3.4)
|
||||||
|
debug_inspector (1.1.0)
|
||||||
|
devise (4.9.3)
|
||||||
bcrypt (~> 3.0)
|
bcrypt (~> 3.0)
|
||||||
orm_adapter (~> 0.1)
|
orm_adapter (~> 0.1)
|
||||||
railties (>= 4.1.0, < 6.0)
|
railties (>= 4.1.0)
|
||||||
responders
|
responders
|
||||||
warden (~> 1.2.3)
|
warden (~> 1.2.3)
|
||||||
devise_invitable (2.0.0)
|
devise_invitable (2.0.9)
|
||||||
actionmailer (>= 5.0)
|
actionmailer (>= 5.0)
|
||||||
devise (>= 4.6)
|
devise (>= 4.6)
|
||||||
diff-lcs (1.3)
|
diff-lcs (1.5.0)
|
||||||
docile (1.3.1)
|
docile (1.4.0)
|
||||||
dotenv (2.7.1)
|
dotenv (2.8.1)
|
||||||
dotenv-rails (2.7.1)
|
dotenv-rails (2.8.1)
|
||||||
dotenv (= 2.7.1)
|
dotenv (= 2.8.1)
|
||||||
railties (>= 3.2, < 6.1)
|
railties (>= 3.2)
|
||||||
em-websocket (0.5.1)
|
drb (2.2.0)
|
||||||
|
ruby2_keywords
|
||||||
|
ed25519 (1.3.0)
|
||||||
|
em-websocket (0.5.3)
|
||||||
eventmachine (>= 0.12.9)
|
eventmachine (>= 0.12.9)
|
||||||
http_parser.rb (~> 0.6.0)
|
http_parser.rb (~> 0)
|
||||||
erubi (1.8.0)
|
erubi (1.12.0)
|
||||||
erubis (2.7.0)
|
erubis (2.7.0)
|
||||||
eventmachine (1.2.7)
|
eventmachine (1.2.7)
|
||||||
execjs (2.7.0)
|
execjs (2.9.1)
|
||||||
factory_girl (4.9.0)
|
factory_girl (4.9.0)
|
||||||
activesupport (>= 3.0.0)
|
activesupport (>= 3.0.0)
|
||||||
factory_girl_rails (4.9.0)
|
factory_girl_rails (4.9.0)
|
||||||
factory_girl (~> 4.9.0)
|
factory_girl (~> 4.9.0)
|
||||||
railties (>= 3.0.0)
|
railties (>= 3.0.0)
|
||||||
faker (1.9.3)
|
faker (3.2.2)
|
||||||
i18n (>= 0.7)
|
i18n (>= 1.8.11, < 2)
|
||||||
ffi (1.10.0)
|
ffi (1.16.3)
|
||||||
formatador (0.2.5)
|
formatador (1.1.0)
|
||||||
globalid (0.4.2)
|
friendly_id (5.4.2)
|
||||||
activesupport (>= 4.2.0)
|
activerecord (>= 4.0.0)
|
||||||
guard (2.15.0)
|
globalid (1.2.1)
|
||||||
|
activesupport (>= 6.1)
|
||||||
|
guard (2.18.1)
|
||||||
formatador (>= 0.2.4)
|
formatador (>= 0.2.4)
|
||||||
listen (>= 2.7, < 4.0)
|
listen (>= 2.7, < 4.0)
|
||||||
lumberjack (>= 1.0.12, < 2.0)
|
lumberjack (>= 1.0.12, < 2.0)
|
||||||
nenv (~> 0.1)
|
nenv (~> 0.1)
|
||||||
notiffany (~> 0.0)
|
notiffany (~> 0.0)
|
||||||
pry (>= 0.9.12)
|
pry (>= 0.13.0)
|
||||||
shellany (~> 0.0)
|
shellany (~> 0.0)
|
||||||
thor (>= 0.18.1)
|
thor (>= 0.18.1)
|
||||||
guard-bundler (2.2.1)
|
guard-bundler (3.0.1)
|
||||||
bundler (>= 1.3.0, < 3)
|
bundler (>= 2.1, < 3)
|
||||||
guard (~> 2.2)
|
guard (~> 2.2)
|
||||||
guard-compat (~> 1.1)
|
guard-compat (~> 1.1)
|
||||||
guard-compat (1.2.1)
|
guard-compat (1.2.1)
|
||||||
@ -179,264 +231,301 @@ GEM
|
|||||||
guard (~> 2.1)
|
guard (~> 2.1)
|
||||||
guard-compat (~> 1.1)
|
guard-compat (~> 1.1)
|
||||||
rspec (>= 2.99.0, < 4.0)
|
rspec (>= 2.99.0, < 4.0)
|
||||||
haml (5.0.4)
|
haml (6.2.3)
|
||||||
temple (>= 0.8.0)
|
temple (>= 0.8.2)
|
||||||
|
thor
|
||||||
tilt
|
tilt
|
||||||
haml-rails (2.0.0)
|
haml-rails (2.1.0)
|
||||||
actionpack (>= 5.1)
|
actionpack (>= 5.1)
|
||||||
activesupport (>= 5.1)
|
activesupport (>= 5.1)
|
||||||
haml (>= 4.0.6, < 6.0)
|
haml (>= 4.0.6)
|
||||||
html2haml (>= 1.0.1)
|
|
||||||
railties (>= 5.1)
|
railties (>= 5.1)
|
||||||
high_voltage (3.1.0)
|
high_voltage (3.1.2)
|
||||||
html2haml (2.2.0)
|
html2haml (2.3.0)
|
||||||
erubis (~> 2.7.0)
|
erubis (~> 2.7.0)
|
||||||
haml (>= 4.0, < 6)
|
haml (>= 4.0)
|
||||||
nokogiri (>= 1.6.0)
|
nokogiri (>= 1.6.0)
|
||||||
ruby_parser (~> 3.5)
|
ruby_parser (~> 3.5)
|
||||||
http_parser.rb (0.6.0)
|
http_parser.rb (0.8.0)
|
||||||
hub (1.12.4)
|
hub (1.12.4)
|
||||||
i18n (1.6.0)
|
i18n (1.14.1)
|
||||||
concurrent-ruby (~> 1.0)
|
concurrent-ruby (~> 1.0)
|
||||||
|
importmap-rails (1.2.3)
|
||||||
|
actionpack (>= 6.0.0)
|
||||||
|
activesupport (>= 6.0.0)
|
||||||
|
railties (>= 6.0.0)
|
||||||
|
inline_svg (1.9.0)
|
||||||
|
activesupport (>= 3.0)
|
||||||
|
nokogiri (>= 1.6)
|
||||||
interception (0.5)
|
interception (0.5)
|
||||||
jaro_winkler (1.5.2)
|
io-console (0.6.0)
|
||||||
jbuilder (2.8.0)
|
irb (1.10.0)
|
||||||
activesupport (>= 4.2.0)
|
rdoc
|
||||||
multi_json (>= 1.2)
|
reline (>= 0.3.8)
|
||||||
jquery-rails (4.3.3)
|
jbuilder (2.11.5)
|
||||||
|
actionview (>= 5.0.0)
|
||||||
|
activesupport (>= 5.0.0)
|
||||||
|
jquery-rails (4.6.0)
|
||||||
rails-dom-testing (>= 1, < 3)
|
rails-dom-testing (>= 1, < 3)
|
||||||
railties (>= 4.2.0)
|
railties (>= 4.2.0)
|
||||||
thor (>= 0.14, < 2.0)
|
thor (>= 0.14, < 2.0)
|
||||||
json (2.2.0)
|
jquery-ui-rails (6.0.1)
|
||||||
kaminari (1.1.1)
|
railties (>= 3.2.16)
|
||||||
activesupport (>= 4.1.0)
|
json (2.7.0)
|
||||||
kaminari-actionview (= 1.1.1)
|
language_server-protocol (3.17.0.3)
|
||||||
kaminari-activerecord (= 1.1.1)
|
launchy (2.5.2)
|
||||||
kaminari-core (= 1.1.1)
|
addressable (~> 2.8)
|
||||||
kaminari-actionview (1.1.1)
|
listen (3.8.0)
|
||||||
actionview
|
rb-fsevent (~> 0.10, >= 0.10.3)
|
||||||
kaminari-core (= 1.1.1)
|
rb-inotify (~> 0.9, >= 0.9.10)
|
||||||
kaminari-activerecord (1.1.1)
|
loofah (2.22.0)
|
||||||
activerecord
|
|
||||||
kaminari-core (= 1.1.1)
|
|
||||||
kaminari-core (1.1.1)
|
|
||||||
launchy (2.4.3)
|
|
||||||
addressable (~> 2.3)
|
|
||||||
listen (3.1.5)
|
|
||||||
rb-fsevent (~> 0.9, >= 0.9.4)
|
|
||||||
rb-inotify (~> 0.9, >= 0.9.7)
|
|
||||||
ruby_dep (~> 1.2)
|
|
||||||
loofah (2.2.3)
|
|
||||||
crass (~> 1.0.2)
|
crass (~> 1.0.2)
|
||||||
nokogiri (>= 1.5.9)
|
nokogiri (>= 1.12.0)
|
||||||
lumberjack (1.0.13)
|
lumberjack (1.2.10)
|
||||||
mail (2.7.1)
|
mail (2.8.1)
|
||||||
mini_mime (>= 0.1.1)
|
mini_mime (>= 0.1.1)
|
||||||
marcel (0.3.3)
|
net-imap
|
||||||
mimemagic (~> 0.3.2)
|
net-pop
|
||||||
method_source (0.9.2)
|
net-smtp
|
||||||
mimemagic (0.3.3)
|
marcel (1.0.2)
|
||||||
mini_mime (1.0.1)
|
matrix (0.4.2)
|
||||||
mini_portile2 (2.4.0)
|
method_source (1.0.0)
|
||||||
minitest (5.11.3)
|
mini_mime (1.1.5)
|
||||||
multi_json (1.13.1)
|
mini_portile2 (2.8.5)
|
||||||
|
minitest (5.20.0)
|
||||||
|
multi_json (1.15.0)
|
||||||
|
mutex_m (0.2.0)
|
||||||
nenv (0.3.0)
|
nenv (0.3.0)
|
||||||
net-scp (1.2.1)
|
net-imap (0.4.7)
|
||||||
net-ssh (>= 2.6.5)
|
date
|
||||||
net-ssh (5.1.0)
|
net-protocol
|
||||||
nio4r (2.3.1)
|
net-pop (0.1.2)
|
||||||
nokogiri (1.10.1)
|
net-protocol
|
||||||
mini_portile2 (~> 2.4.0)
|
net-protocol (0.2.2)
|
||||||
notiffany (0.1.1)
|
timeout
|
||||||
|
net-scp (4.0.0)
|
||||||
|
net-ssh (>= 2.6.5, < 8.0.0)
|
||||||
|
net-smtp (0.4.0)
|
||||||
|
net-protocol
|
||||||
|
net-ssh (7.2.0)
|
||||||
|
nio4r (2.7.0)
|
||||||
|
nokogiri (1.15.5)
|
||||||
|
mini_portile2 (~> 2.8.2)
|
||||||
|
racc (~> 1.4)
|
||||||
|
nokogiri (1.15.5-x86_64-linux)
|
||||||
|
racc (~> 1.4)
|
||||||
|
notiffany (0.1.3)
|
||||||
nenv (~> 0.1)
|
nenv (~> 0.1)
|
||||||
shellany (~> 0.0)
|
shellany (~> 0.0)
|
||||||
orm_adapter (0.5.0)
|
orm_adapter (0.5.0)
|
||||||
parallel (1.14.0)
|
parallel (1.23.0)
|
||||||
parallel_tests (2.28.0)
|
parallel_tests (4.3.0)
|
||||||
parallel
|
parallel
|
||||||
parser (2.6.0.0)
|
parser (3.2.2.4)
|
||||||
ast (~> 2.4.0)
|
ast (~> 2.4.1)
|
||||||
pg (1.1.4)
|
racc
|
||||||
poltergeist (1.18.1)
|
pg (1.5.4)
|
||||||
capybara (>= 2.1, < 4)
|
pry (0.14.2)
|
||||||
cliver (~> 0.3.1)
|
coderay (~> 1.1)
|
||||||
websocket-driver (>= 0.2.0)
|
method_source (~> 1.0)
|
||||||
powerpack (0.1.2)
|
|
||||||
pry (0.12.2)
|
|
||||||
coderay (~> 1.1.0)
|
|
||||||
method_source (~> 0.9.0)
|
|
||||||
pry-rails (0.3.9)
|
pry-rails (0.3.9)
|
||||||
pry (>= 0.10.4)
|
pry (>= 0.10.4)
|
||||||
pry-rescue (1.5.0)
|
pry-rescue (1.5.2)
|
||||||
interception (>= 0.5)
|
interception (>= 0.5)
|
||||||
pry (>= 0.12.0)
|
pry (>= 0.12.0)
|
||||||
psych (3.1.0)
|
psych (5.1.1.1)
|
||||||
public_suffix (3.0.3)
|
stringio
|
||||||
puma (3.12.0)
|
public_suffix (5.0.4)
|
||||||
pundit (2.0.1)
|
puma (6.0.0)
|
||||||
|
nio4r (~> 2.0)
|
||||||
|
pundit (2.3.1)
|
||||||
activesupport (>= 3.0.0)
|
activesupport (>= 3.0.0)
|
||||||
rack (2.0.6)
|
racc (1.7.3)
|
||||||
rack-livereload (0.3.17)
|
rack (3.0.8)
|
||||||
|
rack-livereload (0.5.1)
|
||||||
rack
|
rack
|
||||||
rack-test (1.1.0)
|
rack-session (2.0.0)
|
||||||
rack (>= 1.0, < 3)
|
rack (>= 3.0.0)
|
||||||
rails (5.2.2)
|
rack-test (2.1.0)
|
||||||
actioncable (= 5.2.2)
|
rack (>= 1.3)
|
||||||
actionmailer (= 5.2.2)
|
rackup (2.1.0)
|
||||||
actionpack (= 5.2.2)
|
rack (>= 3)
|
||||||
actionview (= 5.2.2)
|
webrick (~> 1.8)
|
||||||
activejob (= 5.2.2)
|
rails (7.1.2)
|
||||||
activemodel (= 5.2.2)
|
actioncable (= 7.1.2)
|
||||||
activerecord (= 5.2.2)
|
actionmailbox (= 7.1.2)
|
||||||
activestorage (= 5.2.2)
|
actionmailer (= 7.1.2)
|
||||||
activesupport (= 5.2.2)
|
actionpack (= 7.1.2)
|
||||||
bundler (>= 1.3.0)
|
actiontext (= 7.1.2)
|
||||||
railties (= 5.2.2)
|
actionview (= 7.1.2)
|
||||||
sprockets-rails (>= 2.0.0)
|
activejob (= 7.1.2)
|
||||||
rails-dom-testing (2.0.3)
|
activemodel (= 7.1.2)
|
||||||
activesupport (>= 4.2.0)
|
activerecord (= 7.1.2)
|
||||||
|
activestorage (= 7.1.2)
|
||||||
|
activesupport (= 7.1.2)
|
||||||
|
bundler (>= 1.15.0)
|
||||||
|
railties (= 7.1.2)
|
||||||
|
rails-dom-testing (2.2.0)
|
||||||
|
activesupport (>= 5.0.0)
|
||||||
|
minitest
|
||||||
nokogiri (>= 1.6)
|
nokogiri (>= 1.6)
|
||||||
rails-html-sanitizer (1.0.4)
|
rails-html-sanitizer (1.6.0)
|
||||||
loofah (~> 2.2, >= 2.2.2)
|
loofah (~> 2.21)
|
||||||
|
nokogiri (~> 1.14)
|
||||||
rails_layout (1.0.42)
|
rails_layout (1.0.42)
|
||||||
railties (5.2.2)
|
railties (7.1.2)
|
||||||
actionpack (= 5.2.2)
|
actionpack (= 7.1.2)
|
||||||
activesupport (= 5.2.2)
|
activesupport (= 7.1.2)
|
||||||
method_source
|
irb
|
||||||
rake (>= 0.8.7)
|
rackup (>= 1.0.0)
|
||||||
thor (>= 0.19.0, < 2.0)
|
rake (>= 12.2)
|
||||||
rainbow (3.0.0)
|
thor (~> 1.0, >= 1.2.2)
|
||||||
rake (12.3.2)
|
zeitwerk (~> 2.6)
|
||||||
ransack (2.1.1)
|
rainbow (3.1.1)
|
||||||
actionpack (>= 5.0)
|
rake (13.1.0)
|
||||||
activerecord (>= 5.0)
|
|
||||||
activesupport (>= 5.0)
|
|
||||||
i18n
|
|
||||||
rb-fchange (0.0.6)
|
rb-fchange (0.0.6)
|
||||||
ffi
|
ffi
|
||||||
rb-fsevent (0.10.3)
|
rb-fsevent (0.11.2)
|
||||||
rb-inotify (0.10.0)
|
rb-inotify (0.10.1)
|
||||||
ffi (~> 1.0)
|
ffi (~> 1.0)
|
||||||
rdoc (6.1.1)
|
rbnacl (3.4.0)
|
||||||
react-rails (2.4.7)
|
ffi
|
||||||
|
rbnacl-libsodium (1.0.16)
|
||||||
|
rbnacl (>= 3.0.1)
|
||||||
|
rdoc (6.6.0)
|
||||||
|
psych (>= 4.0.0)
|
||||||
|
react-rails (3.1.1)
|
||||||
babel-transpiler (>= 0.7.0)
|
babel-transpiler (>= 0.7.0)
|
||||||
connection_pool
|
connection_pool
|
||||||
execjs
|
execjs
|
||||||
railties (>= 3.2)
|
railties (>= 3.2)
|
||||||
tilt
|
tilt
|
||||||
regexp_parser (1.3.0)
|
redis (4.8.1)
|
||||||
responders (2.4.1)
|
regexp_parser (2.8.3)
|
||||||
actionpack (>= 4.2.0, < 6.0)
|
reline (0.4.1)
|
||||||
railties (>= 4.2.0, < 6.0)
|
io-console (~> 0.5)
|
||||||
rspec (3.8.0)
|
responders (3.1.1)
|
||||||
rspec-core (~> 3.8.0)
|
actionpack (>= 5.2)
|
||||||
rspec-expectations (~> 3.8.0)
|
railties (>= 5.2)
|
||||||
rspec-mocks (~> 3.8.0)
|
rexml (3.2.6)
|
||||||
rspec-core (3.8.0)
|
rouge (4.2.0)
|
||||||
rspec-support (~> 3.8.0)
|
rspec (3.12.0)
|
||||||
rspec-expectations (3.8.2)
|
rspec-core (~> 3.12.0)
|
||||||
|
rspec-expectations (~> 3.12.0)
|
||||||
|
rspec-mocks (~> 3.12.0)
|
||||||
|
rspec-core (3.12.2)
|
||||||
|
rspec-support (~> 3.12.0)
|
||||||
|
rspec-expectations (3.12.3)
|
||||||
diff-lcs (>= 1.2.0, < 2.0)
|
diff-lcs (>= 1.2.0, < 2.0)
|
||||||
rspec-support (~> 3.8.0)
|
rspec-support (~> 3.12.0)
|
||||||
rspec-mocks (3.8.0)
|
rspec-mocks (3.12.6)
|
||||||
diff-lcs (>= 1.2.0, < 2.0)
|
diff-lcs (>= 1.2.0, < 2.0)
|
||||||
rspec-support (~> 3.8.0)
|
rspec-support (~> 3.12.0)
|
||||||
rspec-rails (3.8.2)
|
rspec-rails (6.1.0)
|
||||||
actionpack (>= 3.0)
|
actionpack (>= 6.1)
|
||||||
activesupport (>= 3.0)
|
activesupport (>= 6.1)
|
||||||
railties (>= 3.0)
|
railties (>= 6.1)
|
||||||
rspec-core (~> 3.8.0)
|
rspec-core (~> 3.12)
|
||||||
rspec-expectations (~> 3.8.0)
|
rspec-expectations (~> 3.12)
|
||||||
rspec-mocks (~> 3.8.0)
|
rspec-mocks (~> 3.12)
|
||||||
rspec-support (~> 3.8.0)
|
rspec-support (~> 3.12)
|
||||||
rspec-support (3.8.0)
|
rspec-support (3.12.1)
|
||||||
rubocop (0.65.0)
|
rubocop (1.58.0)
|
||||||
jaro_winkler (~> 1.5.1)
|
json (~> 2.3)
|
||||||
|
language_server-protocol (>= 3.17.0)
|
||||||
parallel (~> 1.10)
|
parallel (~> 1.10)
|
||||||
parser (>= 2.5, != 2.5.1.1)
|
parser (>= 3.2.2.4)
|
||||||
powerpack (~> 0.1)
|
|
||||||
psych (>= 3.1.0)
|
|
||||||
rainbow (>= 2.2.2, < 4.0)
|
rainbow (>= 2.2.2, < 4.0)
|
||||||
|
regexp_parser (>= 1.8, < 3.0)
|
||||||
|
rexml (>= 3.2.5, < 4.0)
|
||||||
|
rubocop-ast (>= 1.30.0, < 2.0)
|
||||||
ruby-progressbar (~> 1.7)
|
ruby-progressbar (~> 1.7)
|
||||||
unicode-display_width (~> 1.4.0)
|
unicode-display_width (>= 2.4.0, < 3.0)
|
||||||
ruby-progressbar (1.10.0)
|
rubocop-ast (1.30.0)
|
||||||
ruby_dep (1.5.0)
|
parser (>= 3.2.1.0)
|
||||||
ruby_parser (3.12.0)
|
ruby-progressbar (1.13.0)
|
||||||
sexp_processor (~> 4.9)
|
ruby2_keywords (0.0.5)
|
||||||
rubyzip (1.2.2)
|
ruby_parser (3.20.3)
|
||||||
sass (3.7.3)
|
sexp_processor (~> 4.16)
|
||||||
sass-listen (~> 4.0.0)
|
rubyzip (2.3.2)
|
||||||
sass-listen (4.0.0)
|
sass-rails (6.0.0)
|
||||||
rb-fsevent (~> 0.9, >= 0.9.4)
|
sassc-rails (~> 2.1, >= 2.1.1)
|
||||||
rb-inotify (~> 0.9, >= 0.9.7)
|
sassc (2.4.0)
|
||||||
sass-rails (5.0.7)
|
ffi (~> 1.9)
|
||||||
railties (>= 4.0.0, < 6)
|
sassc-rails (2.1.2)
|
||||||
sass (~> 3.1)
|
railties (>= 4.0.0)
|
||||||
sprockets (>= 2.8, < 4.0)
|
sassc (>= 2.0)
|
||||||
sprockets-rails (>= 2.0, < 4.0)
|
sprockets (> 3.0)
|
||||||
tilt (>= 1.1, < 3)
|
sprockets-rails
|
||||||
sdoc (1.0.0)
|
tilt
|
||||||
|
sdoc (2.6.1)
|
||||||
rdoc (>= 5.0)
|
rdoc (>= 5.0)
|
||||||
selenium-webdriver (3.141.0)
|
selenium-webdriver (4.10.0)
|
||||||
childprocess (~> 0.5)
|
rexml (~> 3.2, >= 3.2.5)
|
||||||
rubyzip (~> 1.2, >= 1.2.2)
|
rubyzip (>= 1.2.2, < 3.0)
|
||||||
sexp_processor (4.11.0)
|
websocket (~> 1.0)
|
||||||
|
sexp_processor (4.17.0)
|
||||||
shellany (0.0.1)
|
shellany (0.0.1)
|
||||||
simple_form (4.1.0)
|
simple_form (5.3.0)
|
||||||
actionpack (>= 5.0)
|
actionpack (>= 5.2)
|
||||||
activemodel (>= 5.0)
|
activemodel (>= 5.2)
|
||||||
simplecov (0.16.1)
|
simplecov (0.22.0)
|
||||||
docile (~> 1.1)
|
docile (~> 1.1)
|
||||||
json (>= 1.8, < 3)
|
simplecov-html (~> 0.11)
|
||||||
simplecov-html (~> 0.10.0)
|
simplecov_json_formatter (~> 0.1)
|
||||||
simplecov-html (0.10.2)
|
simplecov-html (0.12.3)
|
||||||
spring (2.0.2)
|
simplecov_json_formatter (0.1.4)
|
||||||
activesupport (>= 4.2)
|
spring (4.1.3)
|
||||||
spring-commands-rspec (1.0.4)
|
spring-commands-rspec (1.0.4)
|
||||||
spring (>= 0.9.1)
|
spring (>= 0.9.1)
|
||||||
sprockets (3.7.2)
|
sprockets (4.2.1)
|
||||||
concurrent-ruby (~> 1.0)
|
concurrent-ruby (~> 1.0)
|
||||||
rack (> 1, < 3)
|
rack (>= 2.2.4, < 4)
|
||||||
sprockets-rails (3.2.1)
|
sprockets-rails (3.4.2)
|
||||||
actionpack (>= 4.0)
|
actionpack (>= 5.2)
|
||||||
activesupport (>= 4.0)
|
activesupport (>= 5.2)
|
||||||
sprockets (>= 3.0.0)
|
sprockets (>= 3.0.0)
|
||||||
sshkit (1.18.2)
|
sshkit (1.21.6)
|
||||||
net-scp (>= 1.1.2)
|
net-scp (>= 1.1.2)
|
||||||
net-ssh (>= 2.8.0)
|
net-ssh (>= 2.8.0)
|
||||||
sshkit-interactive (0.3.0)
|
sshkit-interactive (0.3.0)
|
||||||
sshkit (~> 1.12)
|
sshkit (~> 1.12)
|
||||||
temple (0.8.1)
|
stimulus-rails (1.3.0)
|
||||||
thor (0.20.3)
|
railties (>= 6.0.0)
|
||||||
thread_safe (0.3.6)
|
stringio (3.1.0)
|
||||||
tilt (2.0.9)
|
temple (0.10.3)
|
||||||
turbolinks (5.2.0)
|
thor (1.3.0)
|
||||||
turbolinks-source (~> 5.2)
|
tilt (2.3.0)
|
||||||
turbolinks-source (5.2.0)
|
timeout (0.4.1)
|
||||||
tzinfo (1.2.5)
|
turbo-rails (1.5.0)
|
||||||
thread_safe (~> 0.1)
|
actionpack (>= 6.0.0)
|
||||||
uglifier (4.1.20)
|
activejob (>= 6.0.0)
|
||||||
execjs (>= 0.3.0, < 3)
|
railties (>= 6.0.0)
|
||||||
unicode-display_width (1.4.1)
|
tzinfo (2.0.6)
|
||||||
upmin-admin (0.1.3)
|
concurrent-ruby (~> 1.0)
|
||||||
chartkick
|
unicode-display_width (2.5.0)
|
||||||
haml (>= 3.0.0)
|
warden (1.2.9)
|
||||||
jquery-rails
|
rack (>= 2.0.9)
|
||||||
kaminari
|
webdrivers (5.3.1)
|
||||||
rails
|
nokogiri (~> 1.6)
|
||||||
ransack
|
rubyzip (>= 1.3.0)
|
||||||
sass-rails
|
selenium-webdriver (~> 4.0, < 4.11)
|
||||||
warden (1.2.8)
|
webrick (1.8.1)
|
||||||
rack (>= 2.0.6)
|
websocket (1.2.10)
|
||||||
websocket-driver (0.7.0)
|
websocket-driver (0.7.6)
|
||||||
websocket-extensions (>= 0.1.0)
|
websocket-extensions (>= 0.1.0)
|
||||||
websocket-extensions (0.1.3)
|
websocket-extensions (0.1.5)
|
||||||
|
will_paginate (4.0.0)
|
||||||
xpath (3.2.0)
|
xpath (3.2.0)
|
||||||
nokogiri (~> 1.8)
|
nokogiri (~> 1.8)
|
||||||
|
zeitwerk (2.6.12)
|
||||||
|
|
||||||
PLATFORMS
|
PLATFORMS
|
||||||
ruby
|
ruby
|
||||||
|
x86_64-linux
|
||||||
|
|
||||||
DEPENDENCIES
|
DEPENDENCIES
|
||||||
|
bcrypt_pbkdf
|
||||||
better_errors
|
better_errors
|
||||||
binding_of_caller
|
binding_of_caller
|
||||||
capistrano
|
capistrano
|
||||||
@ -447,15 +536,19 @@ DEPENDENCIES
|
|||||||
capistrano-rails
|
capistrano-rails
|
||||||
capistrano-rails-console
|
capistrano-rails-console
|
||||||
capistrano-rbenv
|
capistrano-rbenv
|
||||||
capistrano3-puma
|
capistrano3-puma (~> 6.0.beta)
|
||||||
capybara
|
capybara
|
||||||
|
capybara-screenshot
|
||||||
|
ci_reporter_rspec
|
||||||
coffee-rails
|
coffee-rails
|
||||||
database_cleaner
|
database_cleaner
|
||||||
devise
|
devise
|
||||||
devise_invitable
|
devise_invitable
|
||||||
dotenv-rails
|
dotenv-rails
|
||||||
|
ed25519
|
||||||
factory_girl_rails
|
factory_girl_rails
|
||||||
faker
|
faker
|
||||||
|
friendly_id (~> 5.4.0)
|
||||||
guard-bundler
|
guard-bundler
|
||||||
guard-ctags-bundler
|
guard-ctags-bundler
|
||||||
guard-livereload
|
guard-livereload
|
||||||
@ -465,23 +558,29 @@ DEPENDENCIES
|
|||||||
high_voltage
|
high_voltage
|
||||||
html2haml
|
html2haml
|
||||||
hub
|
hub
|
||||||
|
importmap-rails
|
||||||
|
inline_svg
|
||||||
jbuilder
|
jbuilder
|
||||||
jquery-rails
|
jquery-rails
|
||||||
|
jquery-ui-rails
|
||||||
launchy
|
launchy
|
||||||
|
net-ssh (>= 4.0.0)
|
||||||
parallel_tests
|
parallel_tests
|
||||||
pg
|
pg
|
||||||
poltergeist
|
|
||||||
pry-rails
|
pry-rails
|
||||||
pry-rescue
|
pry-rescue
|
||||||
puma
|
puma (= 6)
|
||||||
pundit
|
pundit
|
||||||
rack-livereload
|
rack-livereload
|
||||||
rails (= 5.2.2)
|
rails (~> 7.0)
|
||||||
rails_layout
|
rails_layout
|
||||||
rb-fchange
|
rb-fchange
|
||||||
rb-fsevent
|
rb-fsevent
|
||||||
rb-inotify
|
rb-inotify
|
||||||
|
rbnacl (~> 3.4)
|
||||||
|
rbnacl-libsodium
|
||||||
react-rails
|
react-rails
|
||||||
|
redis (~> 4.0)
|
||||||
rspec-rails
|
rspec-rails
|
||||||
rubocop
|
rubocop
|
||||||
sass-rails
|
sass-rails
|
||||||
@ -491,12 +590,14 @@ DEPENDENCIES
|
|||||||
simplecov
|
simplecov
|
||||||
spring
|
spring
|
||||||
spring-commands-rspec
|
spring-commands-rspec
|
||||||
turbolinks
|
sprockets
|
||||||
uglifier
|
stimulus-rails
|
||||||
upmin-admin
|
turbo-rails
|
||||||
|
webdrivers
|
||||||
|
will_paginate
|
||||||
|
|
||||||
RUBY VERSION
|
RUBY VERSION
|
||||||
ruby 2.6.0p0
|
ruby 3.2.2p53
|
||||||
|
|
||||||
BUNDLED WITH
|
BUNDLED WITH
|
||||||
1.17.2
|
2.4.22
|
||||||
|
|||||||
149
Guardfile
@ -35,10 +35,10 @@ guard :bundler do
|
|||||||
files.each { |file| watch(helper.real_path(file)) }
|
files.each { |file| watch(helper.real_path(file)) }
|
||||||
end
|
end
|
||||||
|
|
||||||
#guard 'rails', host: '127.0.0.1' do
|
guard 'rails', host: '0.0.0.0', port: 9914 do
|
||||||
# watch('Gemfile.lock')
|
watch('Gemfile.lock')
|
||||||
# watch(%r{^(config|lib)/.*})
|
watch(%r{^(config|lib)/.*})
|
||||||
#end
|
end
|
||||||
|
|
||||||
|
|
||||||
# Note: The cmd option is now required due to the increasing number of ways
|
# Note: The cmd option is now required due to the increasing number of ways
|
||||||
@ -50,61 +50,100 @@ end
|
|||||||
# * zeus: 'zeus rspec' (requires the server to be started separately)
|
# * zeus: 'zeus rspec' (requires the server to be started separately)
|
||||||
# * 'just' rspec: 'rspec'
|
# * 'just' rspec: 'rspec'
|
||||||
|
|
||||||
rspec_options = {
|
#rspec_options = {
|
||||||
cmd: "bundle exec spring rspec",
|
# cmd: "bundle exec rspec",
|
||||||
all_after_pass: false,
|
# all_after_pass: false,
|
||||||
failed_mode: :focus,
|
# failed_mode: :focus,
|
||||||
# run_all: {
|
## run_all: {
|
||||||
# cmd: "bundle exec parallel_rspec -o '",
|
## cmd: "bundle exec parallel_rspec -o '",
|
||||||
# cmd_additional_args: "'"
|
## cmd_additional_args: "'"
|
||||||
# }
|
## }
|
||||||
}
|
#}
|
||||||
guard :rspec, rspec_options do #, failed_mode: :focus
|
#guard :rspec, rspec_options do #, failed_mode: :focus
|
||||||
require "guard/rspec/dsl"
|
# require "guard/rspec/dsl"
|
||||||
dsl = Guard::RSpec::Dsl.new(self)
|
# dsl = Guard::RSpec::Dsl.new(self)
|
||||||
notification :off
|
# notification :off
|
||||||
|
#
|
||||||
|
# # Feel free to open issues for suggestions and improvements
|
||||||
|
#
|
||||||
|
# # RSpec files
|
||||||
|
# rspec = dsl.rspec
|
||||||
|
# watch(rspec.spec_helper) { rspec.spec_dir }
|
||||||
|
# watch(rspec.spec_support) { rspec.spec_dir }
|
||||||
|
# watch(rspec.spec_files)
|
||||||
|
#
|
||||||
|
# # Ruby files
|
||||||
|
# ruby = dsl.ruby
|
||||||
|
# dsl.watch_spec_files_for(ruby.lib_files)
|
||||||
|
#
|
||||||
|
# # Rails files
|
||||||
|
# rails = dsl.rails(view_extensions: %w(erb haml slim))
|
||||||
|
# dsl.watch_spec_files_for(rails.app_files)
|
||||||
|
# dsl.watch_spec_files_for(rails.views)
|
||||||
|
#
|
||||||
|
# watch(rails.controllers) do |m|
|
||||||
|
# [
|
||||||
|
# rspec.spec.("routing/#{m[1]}_routing"),
|
||||||
|
# rspec.spec.("controllers/#{m[1]}_controller"),
|
||||||
|
# rspec.spec.("acceptance/#{m[1]}")
|
||||||
|
# ]
|
||||||
|
# end
|
||||||
|
#
|
||||||
|
# # Rails config changes
|
||||||
|
# watch(rails.spec_helper) { rspec.spec_dir }
|
||||||
|
# watch(rails.routes) { "#{rspec.spec_dir}/routing" }
|
||||||
|
# watch(rails.app_controller) { "#{rspec.spec_dir}/controllers" }
|
||||||
|
#
|
||||||
|
# # Capybara features specs
|
||||||
|
# watch(rails.view_dirs) { |m| rspec.spec.("features/#{m[1]}") }
|
||||||
|
#
|
||||||
|
# # Turnip features and steps
|
||||||
|
# watch(%r{^spec/acceptance/(.+)\.feature$})
|
||||||
|
# watch(%r{^spec/acceptance/steps/(.+)_steps\.rb$}) do |m|
|
||||||
|
# Dir[File.join("**/#{m[1]}.feature")][0] || "spec/acceptance"
|
||||||
|
# end
|
||||||
|
#end
|
||||||
|
#
|
||||||
|
#guard 'ctags-bundler', src_path: ["app", "lib", "spec/support"], project_file: "tags" do
|
||||||
|
# watch(/^(app|lib|spec\/support)\/.*\.rb$/)
|
||||||
|
# watch('Gemfile.lock')
|
||||||
|
#end
|
||||||
|
|
||||||
# Feel free to open issues for suggestions and improvements
|
guard 'livereload' do
|
||||||
|
extensions = {
|
||||||
|
css: :css,
|
||||||
|
scss: :css,
|
||||||
|
sass: :css,
|
||||||
|
js: :js,
|
||||||
|
coffee: :js,
|
||||||
|
html: :html,
|
||||||
|
png: :png,
|
||||||
|
gif: :gif,
|
||||||
|
jpg: :jpg,
|
||||||
|
jpeg: :jpeg,
|
||||||
|
# less: :less, # uncomment if you want LESS stylesheets done in browser
|
||||||
|
}
|
||||||
|
|
||||||
# RSpec files
|
rails_view_exts = %w(erb haml slim)
|
||||||
rspec = dsl.rspec
|
|
||||||
watch(rspec.spec_helper) { rspec.spec_dir }
|
|
||||||
watch(rspec.spec_support) { rspec.spec_dir }
|
|
||||||
watch(rspec.spec_files)
|
|
||||||
|
|
||||||
# Ruby files
|
# file types LiveReload may optimize refresh for
|
||||||
ruby = dsl.ruby
|
compiled_exts = extensions.values.uniq
|
||||||
dsl.watch_spec_files_for(ruby.lib_files)
|
watch(%r{public/.+\.(#{compiled_exts * '|'})})
|
||||||
|
|
||||||
# Rails files
|
extensions.each do |ext, type|
|
||||||
rails = dsl.rails(view_extensions: %w(erb haml slim))
|
watch(%r{
|
||||||
dsl.watch_spec_files_for(rails.app_files)
|
(?:app|vendor)
|
||||||
dsl.watch_spec_files_for(rails.views)
|
(?:/assets/\w+/(?<path>[^.]+) # path+base without extension
|
||||||
|
(?<ext>\.#{ext})) # matching extension (must be first encountered)
|
||||||
watch(rails.controllers) do |m|
|
(?:\.\w+|$) # other extensions
|
||||||
[
|
}x) do |m|
|
||||||
rspec.spec.("routing/#{m[1]}_routing"),
|
path = m[1]
|
||||||
rspec.spec.("controllers/#{m[1]}_controller"),
|
"/assets/#{path}.#{type}"
|
||||||
rspec.spec.("acceptance/#{m[1]}")
|
end
|
||||||
]
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# Rails config changes
|
# file needing a full reload of the page anyway
|
||||||
watch(rails.spec_helper) { rspec.spec_dir }
|
watch(%r{app/views/.+\.(#{rails_view_exts * '|'})$})
|
||||||
watch(rails.routes) { "#{rspec.spec_dir}/routing" }
|
watch(%r{app/helpers/.+\.rb})
|
||||||
watch(rails.app_controller) { "#{rspec.spec_dir}/controllers" }
|
watch(%r{config/locales/.+\.yml})
|
||||||
|
|
||||||
# Capybara features specs
|
|
||||||
watch(rails.view_dirs) { |m| rspec.spec.("features/#{m[1]}") }
|
|
||||||
|
|
||||||
# Turnip features and steps
|
|
||||||
watch(%r{^spec/acceptance/(.+)\.feature$})
|
|
||||||
watch(%r{^spec/acceptance/steps/(.+)_steps\.rb$}) do |m|
|
|
||||||
Dir[File.join("**/#{m[1]}.feature")][0] || "spec/acceptance"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
guard 'ctags-bundler', src_path: ["app", "lib", "spec/support"], project_file: "tags" do
|
|
||||||
watch(/^(app|lib|spec\/support)\/.*\.rb$/)
|
|
||||||
watch('Gemfile.lock')
|
|
||||||
end
|
end
|
||||||
|
|||||||
25
README.md
@ -1,9 +1,32 @@
|
|||||||
Thirteen Tien Len
|
|
||||||
================
|
================
|
||||||
|
|
||||||
|
Development Environment Setup
|
||||||
|
-----------------------------
|
||||||
|
|
||||||
|
bundle install
|
||||||
|
|
||||||
|
cp config/{database.yml.example,database.yml}
|
||||||
|
|
||||||
|
rake db:setup
|
||||||
|
|
||||||
|
guard
|
||||||
|
|
||||||
TODO
|
TODO
|
||||||
----
|
----
|
||||||
|
|
||||||
|
- Add push notifications https://github.com/rpush/rpush#webpush
|
||||||
|
|
||||||
|
- Continue to Private Chat https://www.honeybadger.io/blog/chat-app-rails-actioncable-turbo/
|
||||||
|
|
||||||
|
- Implement video chat https://github.com/domchristie/webrtc-hotwire-rails
|
||||||
|
|
||||||
|
- Abandon previous video chat solution
|
||||||
|
|
||||||
|
- change from google ice server ./frontend/components/video_util.js:6
|
||||||
|
|
||||||
|
- Add video chat https://medium.com/@nicolas.e.schneider/videochat-in-under-30-a-rails-react-tutorial-534930c6cd96
|
||||||
|
|
||||||
- Refactor seat.jsx buttons in to a <form>.
|
- Refactor seat.jsx buttons in to a <form>.
|
||||||
|
|
||||||
- 1st 2nd 3rd place messages. End game message.
|
- 1st 2nd 3rd place messages. End game message.
|
||||||
|
|||||||
9
Rakefile
@ -5,3 +5,12 @@
|
|||||||
require File.expand_path('../config/application', __FILE__)
|
require File.expand_path('../config/application', __FILE__)
|
||||||
|
|
||||||
Rails.application.load_tasks
|
Rails.application.load_tasks
|
||||||
|
|
||||||
|
require 'ci/reporter/rake/rspec'
|
||||||
|
|
||||||
|
# ...
|
||||||
|
# Rake code that creates a task called `:rspec`
|
||||||
|
# ...
|
||||||
|
|
||||||
|
task :rspec => 'ci:setup:rspec'
|
||||||
|
task :spec => 'ci:setup:rspec'
|
||||||
|
|||||||
7
app/assets/config/manifest.js
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
//= link gems.js
|
||||||
|
//= link jquery.js
|
||||||
|
//= link libraries/swiped.min.js
|
||||||
|
//= link_tree ../images
|
||||||
|
//= link_directory ../stylesheets .css
|
||||||
|
//= link_tree ../../javascript .js
|
||||||
|
//= link_tree ../../../vendor/assets/javascripts .js
|
||||||
BIN
app/assets/images/GONGO-coin-white.png
Normal file
|
After Width: | Height: | Size: 89 KiB |
BIN
app/assets/images/GONGO-coin.png
Normal file
|
After Width: | Height: | Size: 38 KiB |
BIN
app/assets/images/ICYPEES-coin.png
Normal file
|
After Width: | Height: | Size: 344 KiB |
BIN
app/assets/images/ICYPEES-glass.png
Normal file
|
After Width: | Height: | Size: 1.6 MiB |
BIN
app/assets/images/chicken-tenders.png
Normal file
|
After Width: | Height: | Size: 244 KiB |
BIN
app/assets/images/gongo-logo.png
Normal file
|
After Width: | Height: | Size: 233 KiB |
10
app/assets/images/icp-coin.svg
Executable file
|
After Width: | Height: | Size: 50 KiB |
BIN
app/assets/images/icy pepe.png
Normal file
|
After Width: | Height: | Size: 89 KiB |
BIN
app/assets/images/telegram-logo.png
Normal file
|
After Width: | Height: | Size: 52 KiB |
BIN
app/assets/images/tendy-logo.jpeg
Normal file
|
After Width: | Height: | Size: 75 KiB |
3
app/assets/javascripts/bots.coffee
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
# Place all the behaviors and hooks related to the matching controller here.
|
||||||
|
# All this logic will automatically be available in application.js.
|
||||||
|
# You can use CoffeeScript in this file: http://coffeescript.org/
|
||||||
13
app/assets/javascripts/cable.js
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
// Action Cable provides the framework to deal with WebSockets in Rails.
|
||||||
|
// You can generate new channels where WebSocket features live using the `rails generate channel` command.
|
||||||
|
//
|
||||||
|
//= require action_cable
|
||||||
|
//= require_self
|
||||||
|
//= require_tree ./channels
|
||||||
|
|
||||||
|
(function() {
|
||||||
|
this.App || (this.App = {});
|
||||||
|
|
||||||
|
App.cable = ActionCable.createConsumer();
|
||||||
|
|
||||||
|
}).call(this);
|
||||||
3
app/assets/javascripts/calls.coffee
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
# Place all the behaviors and hooks related to the matching controller here.
|
||||||
|
# All this logic will automatically be available in application.js.
|
||||||
|
# You can use CoffeeScript in this file: http://coffeescript.org/
|
||||||
9
app/assets/javascripts/channels/call.coffee
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
#App.call = App.cable.subscriptions.create "CallChannel",
|
||||||
|
# connected: ->
|
||||||
|
# # Called when the subscription is ready for use on the server
|
||||||
|
#
|
||||||
|
# disconnected: ->
|
||||||
|
# # Called when the subscription has been terminated by the server
|
||||||
|
#
|
||||||
|
# received: (data) ->
|
||||||
|
# # Called when there's incoming data on the websocket for this channel
|
||||||
3
app/assets/javascripts/commands.coffee
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
# Place all the behaviors and hooks related to the matching controller here.
|
||||||
|
# All this logic will automatically be available in application.js.
|
||||||
|
# You can use CoffeeScript in this file: http://coffeescript.org/
|
||||||
9
app/assets/javascripts/controllers/application.js
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
import { Application } from '@hotwired/stimulus'
|
||||||
|
|
||||||
|
const application = Application.start()
|
||||||
|
|
||||||
|
// Configure Stimulus development experience
|
||||||
|
application.debug = false
|
||||||
|
window.Stimulus = application
|
||||||
|
|
||||||
|
export { application }
|
||||||
5
app/assets/javascripts/controllers/index.js
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
import { application } from 'controllers/application'
|
||||||
|
|
||||||
|
// Eager load all controllers defined in the import map under controllers/**/*_controller
|
||||||
|
import { eagerLoadControllersFrom } from '@hotwired/stimulus-loading'
|
||||||
|
eagerLoadControllersFrom('controllers', application)
|
||||||
17
app/assets/javascripts/controllers/medium_controller.js
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
import { Controller } from '@hotwired/stimulus'
|
||||||
|
|
||||||
|
export default class MediumController extends Controller {
|
||||||
|
connect () {
|
||||||
|
this.reRenderMediaElement()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fix potentially blank videos due to autoplay rules?
|
||||||
|
reRenderMediaElement () {
|
||||||
|
const mediaElement = this.mediaElementTarget
|
||||||
|
const clone = mediaElement.cloneNode(true)
|
||||||
|
mediaElement.parentNode.insertBefore(clone, mediaElement)
|
||||||
|
mediaElement.remove()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MediumController.targets = ['mediaElement']
|
||||||
147
app/assets/javascripts/controllers/video_room_controller.js
Normal file
@ -0,0 +1,147 @@
|
|||||||
|
import { Controller } from '@hotwired/stimulus'
|
||||||
|
import Client from 'models/client'
|
||||||
|
import WebrtcNegotiation from 'models/webrtc_negotiation'
|
||||||
|
import VideoRoomSubscription from 'subscriptions/video_room_subscription'
|
||||||
|
import Signaller from 'subscriptions/signaling_subscription'
|
||||||
|
|
||||||
|
export default class VideoRoomController extends Controller {
|
||||||
|
connect() {
|
||||||
|
this.clients = {}
|
||||||
|
this.client = new Client(this.clientIdValue)
|
||||||
|
|
||||||
|
this.subscription = new VideoRoomSubscription({
|
||||||
|
delegate: this,
|
||||||
|
id: this.idValue,
|
||||||
|
clientId: this.client.id
|
||||||
|
})
|
||||||
|
|
||||||
|
this.signaller = new Signaller({
|
||||||
|
delegate: this,
|
||||||
|
id: this.idValue,
|
||||||
|
clientId: this.client.id
|
||||||
|
})
|
||||||
|
|
||||||
|
this.client.on('iceConnection:checking', ({ detail: { otherClient } }) => {
|
||||||
|
this.startStreamingTo(otherClient)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
async enter () {
|
||||||
|
try {
|
||||||
|
const constraints = { audio: true, video: true }
|
||||||
|
this.client.stream = await navigator.mediaDevices.getUserMedia(constraints)
|
||||||
|
this.localMediumTarget.srcObject = this.client.stream
|
||||||
|
this.localMediumTarget.muted = true // Keep muted on Firefox
|
||||||
|
this.enterTarget.hidden = true
|
||||||
|
|
||||||
|
this.subscription.start()
|
||||||
|
this.signaller.start()
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
greetNewClient ({ from }) {
|
||||||
|
const otherClient = this.findOrCreateClient(from)
|
||||||
|
otherClient.newcomer = true
|
||||||
|
this.subscription.greet({ to: otherClient.id, from: this.client.id })
|
||||||
|
}
|
||||||
|
|
||||||
|
remoteMediumTargetConnected (element) {
|
||||||
|
const clientId = element.id.replace('medium_', '')
|
||||||
|
this.negotiateConnection(clientId)
|
||||||
|
}
|
||||||
|
|
||||||
|
remoteMediumTargetDisconnected (element) {
|
||||||
|
const clientId = element.id.replace('medium_', '')
|
||||||
|
this.teardownClient(clientId)
|
||||||
|
}
|
||||||
|
|
||||||
|
negotiateConnection (clientId) {
|
||||||
|
const otherClient = this.findOrCreateClient(clientId)
|
||||||
|
|
||||||
|
// Be polite to newcomers!
|
||||||
|
const polite = !!otherClient.newcomer
|
||||||
|
|
||||||
|
otherClient.negotiation = this.createNegotiation({ otherClient, polite })
|
||||||
|
|
||||||
|
// The polite client sets up the negotiation last, so we can start streaming
|
||||||
|
// The impolite client signals to the other client that it's ready
|
||||||
|
if (polite) {
|
||||||
|
this.startStreamingTo(otherClient)
|
||||||
|
} else {
|
||||||
|
this.subscription.greet({ to: otherClient.id, from: this.client.id })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
teardownClient (clientId) {
|
||||||
|
this.clients[clientId].stop()
|
||||||
|
delete this.clients[clientId]
|
||||||
|
}
|
||||||
|
|
||||||
|
createNegotiation ({ otherClient, polite }) {
|
||||||
|
const negotiation = new WebrtcNegotiation({
|
||||||
|
signaller: this.signaller,
|
||||||
|
client: this.client,
|
||||||
|
otherClient: otherClient,
|
||||||
|
polite
|
||||||
|
})
|
||||||
|
|
||||||
|
otherClient.on('track', ({ detail }) => {
|
||||||
|
this.startStreamingFrom(otherClient.id, detail)
|
||||||
|
})
|
||||||
|
|
||||||
|
return negotiation
|
||||||
|
}
|
||||||
|
|
||||||
|
startStreamingTo (otherClient) {
|
||||||
|
this.client.streamTo(otherClient)
|
||||||
|
}
|
||||||
|
|
||||||
|
startStreamingFrom (id, { track, streams: [stream] }) {
|
||||||
|
const remoteMediaElement = this.findRemoteMediaElement(id)
|
||||||
|
if (!remoteMediaElement.srcObject) {
|
||||||
|
remoteMediaElement.srcObject = stream
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
findOrCreateClient (id) {
|
||||||
|
return this.clients[id] || (this.clients[id] = new Client(id))
|
||||||
|
}
|
||||||
|
|
||||||
|
findRemoteMediaElement (clientId) {
|
||||||
|
const target = this.remoteMediumTargets.find(
|
||||||
|
target => target.id === `medium_${clientId}`
|
||||||
|
)
|
||||||
|
return target ? target.querySelector('video') : null
|
||||||
|
}
|
||||||
|
|
||||||
|
negotiationFor (id) {
|
||||||
|
return this.clients[id].negotiation
|
||||||
|
}
|
||||||
|
|
||||||
|
// VideoRoomSubscription Delegate
|
||||||
|
|
||||||
|
videoRoomPinged (data) {
|
||||||
|
this.greetNewClient(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Signaler Delegate
|
||||||
|
|
||||||
|
sdpDescriptionReceived ({ from, description }) {
|
||||||
|
this.negotiationFor(from).setDescription(description)
|
||||||
|
}
|
||||||
|
|
||||||
|
iceCandidateReceived ({ from, candidate }) {
|
||||||
|
this.negotiationFor(from).addCandidate(candidate)
|
||||||
|
}
|
||||||
|
|
||||||
|
negotiationRestarted ({ from }) {
|
||||||
|
const negotiation = this.negotiationFor(from)
|
||||||
|
negotiation.restart()
|
||||||
|
negotiation.createOffer()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VideoRoomController.values = { id: String, clientId: String }
|
||||||
|
VideoRoomController.targets = ['localMedium', 'remoteMedium', 'enter']
|
||||||
3
app/assets/javascripts/doodads.coffee
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
# Place all the behaviors and hooks related to the matching controller here.
|
||||||
|
# All this logic will automatically be available in application.js.
|
||||||
|
# You can use CoffeeScript in this file: http://coffeescript.org/
|
||||||
117
app/assets/javascripts/eyecandy.js
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
(function ($, window, undefined) {
|
||||||
|
$.fn.marqueeify = function (options) {
|
||||||
|
var settings = $.extend({
|
||||||
|
horizontal: true,
|
||||||
|
vertical: true,
|
||||||
|
speed: 100, // In pixels per second
|
||||||
|
color: "#00ffff",
|
||||||
|
zindex: 0,
|
||||||
|
container: $(this).parent(),
|
||||||
|
bumpEdge: function () {}
|
||||||
|
}, options);
|
||||||
|
|
||||||
|
return this.each(function () {
|
||||||
|
var containerWidth, containerHeight, elWidth, elHeight, move, getSizes,
|
||||||
|
$el = $(this);
|
||||||
|
|
||||||
|
getSizes = function () {
|
||||||
|
containerWidth = settings.container.outerWidth();
|
||||||
|
containerHeight = settings.container.outerHeight();
|
||||||
|
elWidth = $el.outerWidth();
|
||||||
|
elHeight = $el.outerHeight();
|
||||||
|
};
|
||||||
|
|
||||||
|
move = {
|
||||||
|
right: function () {
|
||||||
|
$el.css("z-index", Math.round(settings.zindex));
|
||||||
|
$el.animate({left: (containerWidth - elWidth)}, {duration: ((containerWidth/settings.speed) * 1000), queue: false, easing: "linear", complete: function () {
|
||||||
|
settings.bumpEdge();
|
||||||
|
move.left();
|
||||||
|
}});
|
||||||
|
},
|
||||||
|
left: function () {
|
||||||
|
$el.css("z-index", Math.round(settings.zindex));
|
||||||
|
$el.animate({left: 0}, {duration: ((containerWidth/settings.speed) * 1000), queue: false, easing: "linear", complete: function () {
|
||||||
|
settings.bumpEdge();
|
||||||
|
move.right();
|
||||||
|
}});
|
||||||
|
},
|
||||||
|
down: function () {
|
||||||
|
$el.css("z-index", Math.round(settings.zindex));
|
||||||
|
$el.animate({top: (containerHeight - elHeight)}, {duration: ((containerHeight/settings.speed) * 1000), queue: false, easing: "linear", complete: function () {
|
||||||
|
settings.bumpEdge();
|
||||||
|
move.up();
|
||||||
|
}});
|
||||||
|
},
|
||||||
|
up: function () {
|
||||||
|
$el.css("z-index", Math.round(settings.zindex));
|
||||||
|
$el.animate({top: 0}, {duration: ((containerHeight/settings.speed) * 1000), queue: false, easing: "linear", complete: function () {
|
||||||
|
settings.bumpEdge();
|
||||||
|
move.down();
|
||||||
|
}});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
getSizes();
|
||||||
|
|
||||||
|
if (settings.horizontal) {
|
||||||
|
move.right();
|
||||||
|
}
|
||||||
|
if (settings.vertical) {
|
||||||
|
move.down();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make that shit responsive!
|
||||||
|
$(window).resize( function() {
|
||||||
|
getSizes();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
})(jQuery, window);
|
||||||
|
|
||||||
|
$(document).ready( function() {
|
||||||
|
|
||||||
|
$(".eyecandy").bind('my-event', function(event) {
|
||||||
|
alert(event);
|
||||||
|
});
|
||||||
|
|
||||||
|
$("#mySecondDiv").trigger('my-event', [1, 2]);
|
||||||
|
|
||||||
|
$('.eyecandy').on( "click", function() {
|
||||||
|
$(this).toggleClass("clicked");
|
||||||
|
// $(this).marqueeify({
|
||||||
|
// speed: Math.random()*420,
|
||||||
|
// bumpEdge: function () {
|
||||||
|
// var newColor = "hsl(" + Math.floor(Math.random()*360) + ", 100%, 50%)";
|
||||||
|
// $('.marquee').css('background', newColor);
|
||||||
|
// $(this)[0].speed = Math.random()*420;
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
} );
|
||||||
|
|
||||||
|
$('.eyecandy').marqueeify({
|
||||||
|
speed: 300,
|
||||||
|
bumpEdge: function () {
|
||||||
|
// svg bgcolor
|
||||||
|
// var newColor = "hsl(" + Math.floor(Math.random()*360) + ", 100%, 50%)";
|
||||||
|
var newColor = Math.floor(Math.random()*16777215).toString(16);
|
||||||
|
// console.log($(this)[0].self);
|
||||||
|
// console.log($(this)[0].color);
|
||||||
|
// console.log($(this)[0].self);
|
||||||
|
// .css("background-color", "#" + newColor);
|
||||||
|
//.css("background-color", "#00ffff");
|
||||||
|
$(this)[0].speed = Math.random()*420;
|
||||||
|
$(this)[0].zindex = Math.random()*20;
|
||||||
|
// .parent.css("display", "none");
|
||||||
|
// console.log(this);
|
||||||
|
// delete this;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// $( ".eyecandy" ).draggable({
|
||||||
|
// addClasses: true
|
||||||
|
// });
|
||||||
|
$(".home-headline,#home-headline").draggable({
|
||||||
|
addClasses: true
|
||||||
|
});
|
||||||
|
});
|
||||||
@ -11,10 +11,28 @@
|
|||||||
// about supported directives.
|
// about supported directives.
|
||||||
//
|
//
|
||||||
//= require jquery
|
//= require jquery
|
||||||
|
//= require jquery-ui
|
||||||
//= require jquery_ujs
|
//= require jquery_ujs
|
||||||
//= require turbolinks
|
// require turbolinks
|
||||||
//= require react
|
// require react
|
||||||
//= require react_ujs
|
// require react_ujs
|
||||||
//= require components
|
// require components
|
||||||
|
// require qrcode.min.js
|
||||||
|
//= require eyecandy
|
||||||
|
// require cable
|
||||||
|
// require_tree ./subscriptions
|
||||||
|
// require_tree ./models
|
||||||
|
// require_tree ./libraries
|
||||||
|
// require_tree ./controllers
|
||||||
// require react-rails-hot-loader
|
// require react-rails-hot-loader
|
||||||
//= require_tree .
|
// require_tree .
|
||||||
|
|
||||||
|
|
||||||
|
$(document).ready(function(){
|
||||||
|
setInterval(function() {
|
||||||
|
// $('#table-component').load("#{request.path} #table-component");
|
||||||
|
$('#play-to-beat').load("#{request.path} #play-to-beat");
|
||||||
|
$('#play-buttons').load("#{request.path} #play-buttons");
|
||||||
|
}, 2000);
|
||||||
|
});
|
||||||
|
|
||||||
0
app/assets/javascripts/libraries/.keep
Normal file
5626
app/assets/javascripts/libraries/adapter.js
Normal file
1
app/assets/javascripts/libraries/swiped.min.js
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
!function(){function t(t,e){document.addEventListener(t,function(t){a._elems.forEach(function(i){for(var n=t.target;n;){if(n===i.elem)return i[e](t),!1;n=n.parentNode}return!1})})}function e(){var t=[].shift.call(arguments),e=arguments[0];for(var i in e)e.hasOwnProperty(i)&&(t[i]=e[i]);return t}var i=window.navigator.msPointerEnabled,n={start:i?"MSPointerDown":"touchstart",move:i?"MSPointerMove":"touchmove",end:i?"MSPointerUp":"touchend"},o=function(){var t=window.getComputedStyle(document.documentElement,""),e=(Array.prototype.slice.call(t).join("").match(/-(moz|webkit|ms)-/)||""===t.OLink&&["","o"])[1];return"-"+e+"-"}(),s=function(){var t,e=document.createElement("fakeelement"),i={transition:"transitionend",OTransition:"oTransitionEnd",MozTransition:"transitionend",WebkitTransition:"webkitTransitionEnd"};for(t in i)if(void 0!==e.style[t])return i[t]}(),r={transition:o+"transition",transform:o+"transform"},h=function(){},a=function(t){var i={duration:200,tolerance:50,time:200,dir:1,right:0,left:0};t=e(i,t||{}),this.duration=t.duration,this.tolerance=t.tolerance,this.time=t.time,this.width=t.left||t.right,this.elem=t.elem,this.list=t.list,this.dir=t.dir,this.group=t.group,this.id=a.elemId++,this.onOpen="function"==typeof t.onOpen?t.onOpen:h,this.onClose="function"==typeof t.onClose?t.onClose:h,this.right=t.right,this.left=t.left,(t.right>0&&t.tolerance>t.right||t.left>0&&t.tolerance>t.left)&&console.warn("tolerance must be less then left and right")};a._elems=[],a.groupCounter=0,a.elemId=0,a.init=function(t){a.groupCounter++;var i=document.querySelectorAll(t.query),n=[];return delete t.query,[].forEach.call(i,function(i){var o=e({elem:i,group:a.groupCounter},t);n.push(new a(o))}),a._bindEvents(),a._elems=a._elems.concat(n),1===n.length?n[0]:n},a._closeAll=function(t){a._elems.forEach(function(e){e.group===t&&e.close(!0)})},a.prototype.transitionEnd=function(t,e){function i(){e.call(n),t.removeEventListener(s,i)}var n=this;t.addEventListener(s,i)},a.prototype.touchStart=function(t){var e=t.changedTouches[0];1===t.touches.length&&(this.touchId=e.identifier,this.x=e.pageX,this.y=e.pageY,this.startTime=new Date,this.resetValue(),this.list?a._closeAll(this.group):this.close(!0))},a.prototype.touchMove=function(t){var e=t.changedTouches[0];this.isValidTouch(t)&&(this.delta=e.pageX-this.x,this.dir=this.delta<0?-1:1,this.width=this.delta<0?this.right:this.left,this.defineUserAction(e),this.startSwipe&&(this.move(),t.preventDefault()))},a.prototype.touchEnd=function(t){this.isValidTouch(t,!0)&&this.startSwipe&&(this.dir*this.delta>this.tolerance||new Date-this.startTime<this.time?this.open():this.close(),t.stopPropagation(),t.preventDefault())},a.prototype.open=function(t){this.animation(this.dir*this.width),this.swiped=!0,t||this.transitionEnd(this.elem,this.onOpen),this.resetValue()},a.prototype.close=function(t){this.animation(0),this.swiped=!1,t||this.transitionEnd(this.elem,this.onClose),this.resetValue()},a.prototype.toggle=function(){this.swiped?this.close():this.open()},a.prototype.resetValue=function(){this.startSwipe=!1,this.startScroll=!1,this.delta=0},a._bindEvents=function(){return a.eventBinded?!1:(t(n.move,"touchMove"),t(n.end,"touchEnd"),t(n.start,"touchStart"),void(a.eventBinded=!0))},a.prototype.defineUserAction=function(t){var e=10,i=10;Math.abs(this.y-t.pageY)>i&&!this.startSwipe?this.startScroll=!0:Math.abs(this.delta)>e&&!this.startScroll&&(this.startSwipe=!0)},a.prototype.isValidTouch=function(t,e){var i=e?"changedTouches":"targetTouches";return t[i][0].identifier===this.touchId},a.prototype.move=function(){if(this.dir>0&&(this.delta<0||0===this.left)||this.dir<0&&(this.delta>0||0===this.right))return!1;var t=Math.abs(this.delta);t>this.width&&(this.delta=this.dir*(this.width+(t-this.width)/8)),this.animation(this.delta,0)},a.prototype.animation=function(t,e){e=void 0===e?this.duration:e,this.elem.style.cssText=r.transition+":"+r.transform+" "+e+"ms; "+r.transform+":translate3d("+t+"px, 0px, 0px)"},a.prototype.destroy=function(t){var e=this.id;a._elems.forEach(function(t,i){t.id===e&&a._elems.splice(i,1)}),t&&this.elem.parentNode.removeChild(this.elem)},window.Swiped=a}();
|
||||||
3
app/assets/javascripts/microposts.coffee
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
# Place all the behaviors and hooks related to the matching controller here.
|
||||||
|
# All this logic will automatically be available in application.js.
|
||||||
|
# You can use CoffeeScript in this file: http://coffeescript.org/
|
||||||
43
app/assets/javascripts/models/client.js
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
export default class Client {
|
||||||
|
constructor (id) {
|
||||||
|
this.callbacks = {}
|
||||||
|
this.id = id
|
||||||
|
}
|
||||||
|
|
||||||
|
get peerConnection () {
|
||||||
|
return this.negotiation && this.negotiation.peerConnection
|
||||||
|
}
|
||||||
|
|
||||||
|
streamTo (otherClient) {
|
||||||
|
if (!otherClient.streaming) {
|
||||||
|
this.stream.getTracks().forEach(track => {
|
||||||
|
otherClient.peerConnection.addTrack(track, this.stream)
|
||||||
|
})
|
||||||
|
otherClient.streaming = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
on (name, callback) {
|
||||||
|
const names = name.split(' ')
|
||||||
|
names.forEach((name) => {
|
||||||
|
this.callbacks[name] = this.callbacks[name] || []
|
||||||
|
this.callbacks[name].push(callback)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
broadcast (name, data) {
|
||||||
|
(this.callbacks[name] || []).forEach(
|
||||||
|
callback => callback.call(null, { type: name, detail: data })
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
off (name) {
|
||||||
|
if (name) return delete this.callbacks[name]
|
||||||
|
else this.callbacks = {}
|
||||||
|
}
|
||||||
|
|
||||||
|
stop () {
|
||||||
|
this.off()
|
||||||
|
this.negotiation.stop()
|
||||||
|
}
|
||||||
|
}
|
||||||
183
app/assets/javascripts/models/webrtc_negotiation.js
Normal file
@ -0,0 +1,183 @@
|
|||||||
|
const RETRY_LIMIT = 10
|
||||||
|
const peerConnectionConfig = {
|
||||||
|
iceServers: [
|
||||||
|
{
|
||||||
|
urls: [
|
||||||
|
'stun:stun.l.google.com:19302',
|
||||||
|
'stun:global.stun.twilio.com:3478'
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
sdpSemantics: 'unified-plan'
|
||||||
|
}
|
||||||
|
|
||||||
|
export default class WebrtcNegotiation {
|
||||||
|
constructor ({ client, otherClient, polite, signaller }) {
|
||||||
|
this.client = client
|
||||||
|
this.otherClient = otherClient
|
||||||
|
this.polite = polite
|
||||||
|
this.signaller = signaller
|
||||||
|
this.makingOffer = false
|
||||||
|
this.isSettingRemoteAnswerPending = false
|
||||||
|
this.candidates = []
|
||||||
|
this.retryCount = 0
|
||||||
|
|
||||||
|
this.start()
|
||||||
|
}
|
||||||
|
|
||||||
|
async createOffer () {
|
||||||
|
if (!this.readyToMakeOffer) return
|
||||||
|
|
||||||
|
try {
|
||||||
|
this.makingOffer = true
|
||||||
|
await this.setLocalDescription(await this.peerConnection.createOffer())
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error)
|
||||||
|
} finally {
|
||||||
|
this.makingOffer = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async setDescription (description) {
|
||||||
|
try {
|
||||||
|
if (this.ignore(description)) return
|
||||||
|
|
||||||
|
await this.setRemoteDescription(description)
|
||||||
|
|
||||||
|
if (description.type === 'offer') {
|
||||||
|
await this.setLocalDescription(await this.peerConnection.createAnswer())
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
if (this.retryCount < RETRY_LIMIT) {
|
||||||
|
this.initiateManualRollback()
|
||||||
|
this.retryCount++
|
||||||
|
} else {
|
||||||
|
this.stop()
|
||||||
|
console.error(`Negotiation failed after ${this.retryCount} retries`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async setLocalDescription (description) {
|
||||||
|
await this.peerConnection.setLocalDescription(description)
|
||||||
|
|
||||||
|
this.signaller.signal({
|
||||||
|
type: this.peerConnection.localDescription ? 'description' : undefined,
|
||||||
|
to: this.otherClient.id,
|
||||||
|
from: this.client.id,
|
||||||
|
description: this.peerConnection.localDescription
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
async setRemoteDescription (description) {
|
||||||
|
this.isSettingRemoteAnswerPending = description.type === 'answer'
|
||||||
|
await this.peerConnection.setRemoteDescription(description) // SRD rolls back as needed
|
||||||
|
this.addCandidates()
|
||||||
|
this.isSettingRemoteAnswerPending = false
|
||||||
|
}
|
||||||
|
|
||||||
|
addCandidate (candidate) {
|
||||||
|
this.candidates.push(candidate)
|
||||||
|
this.addCandidates()
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO try/catch and ignore failures if necessary?
|
||||||
|
addCandidates () {
|
||||||
|
if (this.peerConnection.remoteDescription) {
|
||||||
|
while (this.candidates.length) {
|
||||||
|
this.peerConnection.addIceCandidate(this.candidates.shift())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
get readyToMakeOffer () {
|
||||||
|
return !this.makingOffer && this.peerConnection.signalingState === 'stable'
|
||||||
|
}
|
||||||
|
|
||||||
|
get readyToReceiveOffer () {
|
||||||
|
return !this.makingOffer && (
|
||||||
|
this.peerConnection.signalingState === 'stable' ||
|
||||||
|
this.isSettingRemoteAnswerPending
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
collides (description) {
|
||||||
|
return description.type === 'offer' && !this.readyToReceiveOffer
|
||||||
|
}
|
||||||
|
|
||||||
|
ignore (description) {
|
||||||
|
return !this.polite && this.collides(description)
|
||||||
|
}
|
||||||
|
|
||||||
|
initiateManualRollback() {
|
||||||
|
this.restart()
|
||||||
|
this.signaller.signal({
|
||||||
|
type: 'restart',
|
||||||
|
to: this.otherClient.id,
|
||||||
|
from: this.client.id
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
restart() {
|
||||||
|
this.stop()
|
||||||
|
this.start()
|
||||||
|
}
|
||||||
|
|
||||||
|
start () {
|
||||||
|
this.setupPeerConnection()
|
||||||
|
}
|
||||||
|
|
||||||
|
stop () {
|
||||||
|
this.makingOffer = false
|
||||||
|
this.isSettingRemoteAnswerPending = false
|
||||||
|
this.candidates = []
|
||||||
|
this.teardownPeerConnection()
|
||||||
|
this.otherClient.streaming = false
|
||||||
|
}
|
||||||
|
|
||||||
|
setupPeerConnection () {
|
||||||
|
this.peerConnection = new RTCPeerConnection(peerConnectionConfig)
|
||||||
|
|
||||||
|
this._onnegotiationneeded = () => this.createOffer()
|
||||||
|
|
||||||
|
this._onicecandidate = ({ candidate }) => {
|
||||||
|
this.signaller.signal({
|
||||||
|
type: candidate ? 'candidate' : undefined,
|
||||||
|
to: this.otherClient.id,
|
||||||
|
from: this.client.id,
|
||||||
|
candidate
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
this._oniceconnectionstatechange = (event) => {
|
||||||
|
this.client.broadcast(`iceConnection:${this.peerConnection.iceConnectionState}`, { otherClient: this.otherClient })
|
||||||
|
|
||||||
|
switch (this.peerConnection.iceConnectionState) {
|
||||||
|
case 'completed':
|
||||||
|
this.retryCount = 0
|
||||||
|
break;
|
||||||
|
case 'failed':
|
||||||
|
if ('restartIce' in this.peerConnection) this.peerConnection.restartIce()
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this._ontrack = (event) => this.otherClient.broadcast('track', event)
|
||||||
|
|
||||||
|
this.peerConnection.addEventListener('negotiationneeded', this._onnegotiationneeded)
|
||||||
|
this.peerConnection.addEventListener('icecandidate', this._onicecandidate)
|
||||||
|
this.peerConnection.addEventListener('iceconnectionstatechange', this._oniceconnectionstatechange)
|
||||||
|
this.peerConnection.addEventListener('track', this._ontrack)
|
||||||
|
}
|
||||||
|
|
||||||
|
teardownPeerConnection () {
|
||||||
|
this.peerConnection.close()
|
||||||
|
this.peerConnection.removeEventListener('negotiationneeded', this._onnegotiationneeded)
|
||||||
|
this.peerConnection.removeEventListener('icecandidate', this._onicecandidate)
|
||||||
|
this.peerConnection.removeEventListener('iceconnectionstatechange', this._oniceconnectionstatechange)
|
||||||
|
this.peerConnection.removeEventListener('track', this._ontrack)
|
||||||
|
this.peerConnection = null
|
||||||
|
}
|
||||||
|
}
|
||||||
3
app/assets/javascripts/profiles.coffee
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
# Place all the behaviors and hooks related to the matching controller here.
|
||||||
|
# All this logic will automatically be available in application.js.
|
||||||
|
# You can use CoffeeScript in this file: http://coffeescript.org/
|
||||||
3
app/assets/javascripts/projects.coffee
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
# Place all the behaviors and hooks related to the matching controller here.
|
||||||
|
# All this logic will automatically be available in application.js.
|
||||||
|
# You can use CoffeeScript in this file: http://coffeescript.org/
|
||||||
3
app/assets/javascripts/relationships.coffee
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
# Place all the behaviors and hooks related to the matching controller here.
|
||||||
|
# All this logic will automatically be available in application.js.
|
||||||
|
# You can use CoffeeScript in this file: http://coffeescript.org/
|
||||||
3
app/assets/javascripts/rooms.coffee
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
# Place all the behaviors and hooks related to the matching controller here.
|
||||||
|
# All this logic will automatically be available in application.js.
|
||||||
|
# You can use CoffeeScript in this file: http://coffeescript.org/
|
||||||
3
app/assets/javascripts/social_links.coffee
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
# Place all the behaviors and hooks related to the matching controller here.
|
||||||
|
# All this logic will automatically be available in application.js.
|
||||||
|
# You can use CoffeeScript in this file: http://coffeescript.org/
|
||||||
@ -0,0 +1,35 @@
|
|||||||
|
import { cable } from '@hotwired/turbo-rails'
|
||||||
|
|
||||||
|
export default class SignalingSubscription {
|
||||||
|
constructor({ delegate, id, clientId }) {
|
||||||
|
this.callbacks = {}
|
||||||
|
this.delegate = delegate
|
||||||
|
this.id = id
|
||||||
|
this.clientId = clientId
|
||||||
|
}
|
||||||
|
|
||||||
|
async start () {
|
||||||
|
const self = this
|
||||||
|
|
||||||
|
this.subscription = await cable.subscribeTo({
|
||||||
|
channel: 'SignalingChannel',
|
||||||
|
id: this.id
|
||||||
|
}, {
|
||||||
|
received (data) {
|
||||||
|
const { to, from, type, description, candidate } = data
|
||||||
|
if (to != self.clientId) return
|
||||||
|
|
||||||
|
if (description) return self.delegate.sdpDescriptionReceived({ from, description })
|
||||||
|
if (candidate) return self.delegate.iceCandidateReceived({ from, candidate })
|
||||||
|
if (type === 'restart') return self.delegate.negotiationRestarted({ from })
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
this.started = true
|
||||||
|
}
|
||||||
|
|
||||||
|
signal (data) {
|
||||||
|
if (!this.started) return
|
||||||
|
this.subscription.perform('signal', data)
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,36 @@
|
|||||||
|
import { cable } from '@hotwired/turbo-rails'
|
||||||
|
|
||||||
|
export default class VideoRoomSubscription {
|
||||||
|
constructor ({ delegate, id, clientId }) {
|
||||||
|
this.delegate = delegate
|
||||||
|
this.id = id
|
||||||
|
this.clientId = clientId
|
||||||
|
}
|
||||||
|
|
||||||
|
async start () {
|
||||||
|
const self = this
|
||||||
|
|
||||||
|
this.subscription = await cable.subscribeTo({
|
||||||
|
channel: 'VideoRoomChannel',
|
||||||
|
id: this.id,
|
||||||
|
client_id: this.clientId
|
||||||
|
}, {
|
||||||
|
greet (data) {
|
||||||
|
this.perform('greet', data)
|
||||||
|
},
|
||||||
|
|
||||||
|
received (data) {
|
||||||
|
// Ignore self-sent data
|
||||||
|
if (data.from === self.clientId) return
|
||||||
|
|
||||||
|
if (data.type === 'ping') self.delegate.videoRoomPinged(data) }
|
||||||
|
})
|
||||||
|
|
||||||
|
this.started = true
|
||||||
|
}
|
||||||
|
|
||||||
|
greet (data) {
|
||||||
|
if (!this.started) return
|
||||||
|
this.subscription.greet(data)
|
||||||
|
}
|
||||||
|
}
|
||||||
7
app/assets/javascripts/table-loader.js
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
$(document).ready(function(){
|
||||||
|
setInterval(function() {
|
||||||
|
if ( $('.taking-turn.player[data-soft-token=' + soft_token + ']').length < 1 ) {
|
||||||
|
$('#table-component').load(window.location.pathname +" #table-component");
|
||||||
|
}
|
||||||
|
}, 5000);
|
||||||
|
});
|
||||||
3
app/assets/javascripts/tokens.coffee
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
# Place all the behaviors and hooks related to the matching controller here.
|
||||||
|
# All this logic will automatically be available in application.js.
|
||||||
|
# You can use CoffeeScript in this file: http://coffeescript.org/
|
||||||
@ -1,18 +1,3 @@
|
|||||||
/*
|
|
||||||
* This is a manifest file that'll be compiled into application.css, which will include all the files
|
|
||||||
* listed below.
|
|
||||||
*
|
|
||||||
* Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
|
|
||||||
* or vendor/assets/stylesheets of plugins, if any, can be referenced here using a relative path.
|
|
||||||
*
|
|
||||||
* You're free to add application-wide styles to this file and they'll appear at the bottom of the
|
|
||||||
* compiled file so the styles you add here take precedence over styles defined in any styles
|
|
||||||
* defined in the other CSS/SCSS files in this directory. It is generally better to create a new
|
|
||||||
* file per style scope.
|
|
||||||
*
|
|
||||||
*= require_tree .
|
|
||||||
*= require_self
|
|
||||||
*/
|
|
||||||
|
|
||||||
html
|
html
|
||||||
box-sizing: border-box
|
box-sizing: border-box
|
||||||
@ -28,19 +13,44 @@ body
|
|||||||
margin: 0
|
margin: 0
|
||||||
background: image-url('backgrounds/felt-green.png')
|
background: image-url('backgrounds/felt-green.png')
|
||||||
font-size: 2vmin
|
font-size: 2vmin
|
||||||
|
// overflow: hidden
|
||||||
|
|
||||||
|
body, .social-links, .social-link a
|
||||||
|
text-shadow: -1px 1px #e1b027, 1px -1px #00ddff
|
||||||
|
|
||||||
a
|
a
|
||||||
text-decoration: none
|
text-decoration: none
|
||||||
color: white
|
color: #e7dede
|
||||||
outline: none
|
outline: none
|
||||||
|
&:hover
|
||||||
|
color: gold
|
||||||
|
|
||||||
|
p
|
||||||
|
font-family: sans
|
||||||
|
text-shadow: none
|
||||||
|
b
|
||||||
|
font-family: "Anton", Impact, fantasy, sans-serif
|
||||||
|
text-shadow: -1px 1px #e1b027, 1px -1px #00ddff
|
||||||
|
|
||||||
h1
|
h1
|
||||||
font-size: 7vmin
|
font-size: 7vmin
|
||||||
margin: 0 0 5vmin 0
|
margin-bottom: 0
|
||||||
|
font-family: "Press Start 2P", "Anton", Impact, fantasy, sans-serif
|
||||||
|
|
||||||
|
// h2
|
||||||
|
margin-bottom: 0
|
||||||
|
|
||||||
|
a
|
||||||
|
text-shadow: none
|
||||||
|
|
||||||
header
|
header
|
||||||
|
.home-link
|
||||||
|
font-family: "Press Start 2P", "Anton", Impact, fantasy, sans-serif
|
||||||
|
margin-left: 0
|
||||||
|
padding-left: 0
|
||||||
|
align-self: start
|
||||||
font-size: 3vmin
|
font-size: 3vmin
|
||||||
margin-bottom: 10vmin
|
// margin-bottom: 10vmin
|
||||||
nav
|
nav
|
||||||
padding: 1vmin
|
padding: 1vmin
|
||||||
background: #222
|
background: #222
|
||||||
@ -53,9 +63,12 @@ header
|
|||||||
ul
|
ul
|
||||||
margin: 0
|
margin: 0
|
||||||
display: flex
|
display: flex
|
||||||
|
padding-left: 1em
|
||||||
li
|
li
|
||||||
flex: 1 1 auto
|
flex: 1 1 auto
|
||||||
text-align: center
|
text-align: center
|
||||||
|
&:nth-child(even)
|
||||||
|
align-self: end
|
||||||
|
|
||||||
#content
|
#content
|
||||||
flex: 3 1 auto
|
flex: 3 1 auto
|
||||||
@ -64,11 +77,21 @@ header
|
|||||||
flex-direction: column
|
flex-direction: column
|
||||||
flex-wrap: wrap
|
flex-wrap: wrap
|
||||||
align-items: center
|
align-items: center
|
||||||
|
background: #00ff0060
|
||||||
|
border-radius: 0 13em 0 0
|
||||||
|
font-size: 2em
|
||||||
|
> h1
|
||||||
|
align-self: start
|
||||||
|
// padding-top: .6em
|
||||||
|
// text-indent: .4em
|
||||||
|
|
||||||
|
|
||||||
#home-headline
|
#home-headline, .home-headline
|
||||||
|
margin-top: 6em
|
||||||
flex: 1 1 auto
|
flex: 1 1 auto
|
||||||
text-align: center
|
text-align: center
|
||||||
|
z-index: 10
|
||||||
|
cursor: pointer
|
||||||
h1
|
h1
|
||||||
font-size: 10vmin
|
font-size: 10vmin
|
||||||
color: #111
|
color: #111
|
||||||
@ -76,26 +99,172 @@ header
|
|||||||
padding: 5vmin
|
padding: 5vmin
|
||||||
margin: 0
|
margin: 0
|
||||||
border: 3px solid black
|
border: 3px solid black
|
||||||
|
background-color: #33cc3399
|
||||||
|
text-shadow: -3px 3px #e1b027, 3px -3px #00ddff
|
||||||
|
line-height: 1.3em
|
||||||
|
|
||||||
#main-menu
|
#main-menu
|
||||||
flex: 1 1 auto
|
flex: 1 1 auto
|
||||||
font-size: 5vmin
|
font-size: 5vmin
|
||||||
display: flex
|
display: flex
|
||||||
flex-direction: column
|
flex-direction: column
|
||||||
|
z-index: 10
|
||||||
|
background: #00ff33
|
||||||
|
background: #00000066
|
||||||
|
border-radius: 100px 100px 0 0
|
||||||
|
padding: 2em
|
||||||
a
|
a
|
||||||
|
display:inline
|
||||||
background: green
|
background: green
|
||||||
margin: 4px 0 4px
|
margin: 4px 0 4px
|
||||||
padding: 8px
|
padding: 8px
|
||||||
border: 2px solid black
|
border: 2px solid black
|
||||||
text-align: center
|
text-align: center
|
||||||
&:hover
|
&:hover
|
||||||
background: #bada55
|
background: #ffffff44
|
||||||
color: black
|
color: yellow
|
||||||
&:active
|
&:active
|
||||||
background: (#bada55 + 100)
|
background: (#bada55 + 100)
|
||||||
|
|
||||||
*, *:before, *:after
|
*, *:before, *:after
|
||||||
box-sizing: inherit
|
box-sizing: inherit
|
||||||
|
font-weight: lighter
|
||||||
|
body
|
||||||
|
font-family: "Anton", Impact, fantasy, sans-serif
|
||||||
|
.eyecandy
|
||||||
|
display: block
|
||||||
|
left: 0
|
||||||
|
position: absolute
|
||||||
|
top: 0
|
||||||
|
// background-color: hotpink
|
||||||
|
border-radius: 10em
|
||||||
|
overflow: hidden
|
||||||
|
&.icypepe
|
||||||
|
// zoom: 70%
|
||||||
|
border-radius: 600em
|
||||||
|
padding: 1em 5em 1em 2em
|
||||||
|
cursor: pointer
|
||||||
|
transition: background-color 0.2s, box-shadow 0.2s
|
||||||
|
svg
|
||||||
|
// zoom: 80%
|
||||||
|
&:hover
|
||||||
|
background-color: gold
|
||||||
|
box-shadow: 1px 1px 8px 4px gold
|
||||||
|
img
|
||||||
|
cursor: pointer
|
||||||
|
transition: background-color 0.2s, box-shadow 0.2s
|
||||||
|
&:hover
|
||||||
|
background-color: gold
|
||||||
|
box-shadow: 1px 1px 8px 4px gold
|
||||||
|
img
|
||||||
|
width: 4rem
|
||||||
|
padding: 0.2em
|
||||||
|
&.clicked
|
||||||
|
img, &.icypepe
|
||||||
|
background-color: #00ffff
|
||||||
|
box-shadow: 0px 0px 8px 4px #00ffff
|
||||||
|
|
||||||
li
|
li
|
||||||
list-style: none
|
list-style: none
|
||||||
|
|
||||||
|
.alert
|
||||||
|
padding: 1em
|
||||||
|
background: #ffffff77
|
||||||
|
font-size: 1.2rem
|
||||||
|
color: #ffffff
|
||||||
|
text-shadow: 0 0 3px black
|
||||||
|
letter-spacing: 0.3
|
||||||
|
|
||||||
|
footer
|
||||||
|
padding: 2em 3em
|
||||||
|
text-align: right
|
||||||
|
background: #00000066
|
||||||
|
a
|
||||||
|
img
|
||||||
|
width: 4em
|
||||||
|
height: 4em
|
||||||
|
.footer-tokens
|
||||||
|
text-align: left
|
||||||
|
a
|
||||||
|
padding: 2em
|
||||||
|
background: #e1b02733
|
||||||
|
box-shadow: 0px 0px 8px #00000042
|
||||||
|
border-radius: 12em
|
||||||
|
display: inline-block
|
||||||
|
|
||||||
|
#skyspaces
|
||||||
|
width: 100%
|
||||||
|
height: 100%
|
||||||
|
|
||||||
|
.hide
|
||||||
|
display: none
|
||||||
|
|
||||||
|
.video-cover
|
||||||
|
position: absolute
|
||||||
|
z-index: 2
|
||||||
|
top: 0
|
||||||
|
left: 0
|
||||||
|
width: 100%
|
||||||
|
height: 100%
|
||||||
|
#videoplayer
|
||||||
|
position: absolute
|
||||||
|
z-index: 1
|
||||||
|
top: 0
|
||||||
|
left: 0
|
||||||
|
width: 100%
|
||||||
|
height: 100%
|
||||||
|
object-fit: fill
|
||||||
|
|
||||||
|
// form
|
||||||
|
width: 100%
|
||||||
|
padding: 1em
|
||||||
|
|
||||||
|
textarea
|
||||||
|
width: 100%
|
||||||
|
min-height: 8em
|
||||||
|
padding: 5em
|
||||||
|
overflow: hidden
|
||||||
|
border-radius: 0 8em 0 8em
|
||||||
|
|
||||||
|
.navigation-wallet
|
||||||
|
// font-family: "Press Start 2P", "Anton", Impact, fantasy, sans-serif
|
||||||
|
h1
|
||||||
|
font-size: 1em
|
||||||
|
margin-top: 0
|
||||||
|
line-height: 2em
|
||||||
|
font-size: 0.7em
|
||||||
|
text-align: right
|
||||||
|
padding: 0.5em
|
||||||
|
background: #00ff0060
|
||||||
|
border-radius: 0 0 0 79em
|
||||||
|
word-wrap: break-word
|
||||||
|
h2
|
||||||
|
font-size: 1em
|
||||||
|
margin: 0
|
||||||
|
padding: 0
|
||||||
|
span
|
||||||
|
font-family: monospace, monospace
|
||||||
|
text-shadow: none
|
||||||
|
color: #111
|
||||||
|
// font-family: "Press Start 2P", "Anton", Impact, fantasy, sans-serif
|
||||||
|
|
||||||
|
|
||||||
|
.contain
|
||||||
|
width: 100%
|
||||||
|
max-width: 1200px
|
||||||
|
margin: 0 auto
|
||||||
|
padding-left: .33em
|
||||||
|
|
||||||
|
.table-container
|
||||||
|
max-width: 100%
|
||||||
|
overflow-x: auto
|
||||||
|
align-self: start
|
||||||
|
|
||||||
|
@import doodads
|
||||||
|
@import profiles
|
||||||
|
@import tokens
|
||||||
|
@import microposts
|
||||||
|
@import projects
|
||||||
|
@import rooms
|
||||||
|
@import tables
|
||||||
|
@import game
|
||||||
|
|||||||
3
app/assets/stylesheets/bots.scss
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
// Place all the styles related to the Bots controller here.
|
||||||
|
// They will automatically be included in application.css.
|
||||||
|
// You can use Sass (SCSS) here: https://sass-lang.com/
|
||||||
3
app/assets/stylesheets/calls.scss
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
// Place all the styles related to the Calls controller here.
|
||||||
|
// They will automatically be included in application.css.
|
||||||
|
// You can use Sass (SCSS) here: https://sass-lang.com/
|
||||||
3
app/assets/stylesheets/commands.scss
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
// Place all the styles related to the Commands controller here.
|
||||||
|
// They will automatically be included in application.css.
|
||||||
|
// You can use Sass (SCSS) here: https://sass-lang.com/
|
||||||
12
app/assets/stylesheets/doodads.sass
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
.doodad
|
||||||
|
word-wrap: break-word
|
||||||
|
padding: 1em
|
||||||
|
background: darkgoldenrod
|
||||||
|
box-shadow: 0px -2px 8px black
|
||||||
|
|
||||||
|
.doodads-view
|
||||||
|
form
|
||||||
|
width: 100%
|
||||||
|
padding: 1em
|
||||||
|
|
||||||
|
|
||||||
@ -27,9 +27,13 @@
|
|||||||
|
|
||||||
//// Show Game#show
|
//// Show Game#show
|
||||||
|
|
||||||
button
|
button,
|
||||||
|
input[type=submit]
|
||||||
font-size: 4vmin
|
font-size: 4vmin
|
||||||
|
&.smallbtn
|
||||||
|
font-size: 2vmin
|
||||||
|
|
||||||
|
#table-component,
|
||||||
#game-component-container-container
|
#game-component-container-container
|
||||||
display: flex
|
display: flex
|
||||||
flex-direction: column
|
flex-direction: column
|
||||||
@ -110,35 +114,73 @@ ol#cards-to-beat
|
|||||||
flex-wrap: wrap
|
flex-wrap: wrap
|
||||||
text-align: center
|
text-align: center
|
||||||
li
|
li
|
||||||
|
position: relative
|
||||||
|
margin-left: -21vmin
|
||||||
|
// Don't offset first card
|
||||||
|
&:first-of-type
|
||||||
|
margin-left: -4vmin
|
||||||
|
flex: 1 1 auto
|
||||||
//flex: 1 1 auto
|
//flex: 1 1 auto
|
||||||
text-align: center
|
text-align: center
|
||||||
display: inline-block
|
display: inline-block
|
||||||
img
|
img
|
||||||
width: 6vmin
|
width: 16vmin
|
||||||
border: 1px solid black
|
border: 1px solid black
|
||||||
border-radius: .3vmin
|
border-radius: .3vmin
|
||||||
|
|
||||||
|
|
||||||
////// Inventory
|
////// Inventory
|
||||||
|
|
||||||
.player form
|
.player
|
||||||
|
&.taking-turn
|
||||||
|
font-weight: bold
|
||||||
|
box-shadow: 0px 0px .5vmin 1vmin inset rgba(white,0.2)
|
||||||
ul#inventory
|
ul#inventory
|
||||||
display: flex
|
display: flex
|
||||||
flex-wrap: wrap
|
flex-wrap: wrap
|
||||||
text-align: left
|
text-align: left
|
||||||
li
|
li
|
||||||
|
margin-left: -21vmin
|
||||||
|
// Don't offset first card
|
||||||
|
&:first-of-type
|
||||||
|
// margin-left: 0
|
||||||
|
margin-left: -4vmin
|
||||||
flex: 1 1 auto
|
flex: 1 1 auto
|
||||||
input[type="checkbox"]
|
input[type="checkbox"]
|
||||||
visibility: hidden
|
// Capybara test requires visible checkbox
|
||||||
|
// visibility: hidden
|
||||||
|
opacity: .000001
|
||||||
position: absolute
|
position: absolute
|
||||||
&:checked ~ img
|
&:checked ~ img
|
||||||
box-shadow: 0px 0px 2px 6px cadetblue
|
box-shadow: 0px 0px 2px 5px #05adff, inset 0 0 2px 3px #056dff
|
||||||
|
margin-top: -2vmin
|
||||||
img
|
img
|
||||||
width: 6vmin
|
width: 26vmin
|
||||||
border: 1px solid black
|
border: 1px solid black
|
||||||
border-radius: .3vmin
|
border-radius: 1.2vmin
|
||||||
|
transition: margin-top ease-out .10s
|
||||||
|
|
||||||
|
#mid
|
||||||
|
ul#inventory
|
||||||
|
margin-left: 8vmin
|
||||||
|
li
|
||||||
|
margin-left: -8vmin
|
||||||
|
// Don't offset first card
|
||||||
|
&:first-of-type
|
||||||
|
// margin-left: -0vmin
|
||||||
|
img
|
||||||
|
width: 16vmin
|
||||||
|
|
||||||
|
.inventory
|
||||||
|
text-align: left
|
||||||
|
|
||||||
.inventory
|
.inventory
|
||||||
|
text-align: center
|
||||||
img
|
img
|
||||||
width: 6vmin
|
width: 6vmin
|
||||||
border: 1px solid black
|
border: 2px solid black
|
||||||
border-radius: .3vmin
|
border-radius: .3vmin
|
||||||
|
margin-left: -2vmin
|
||||||
|
// Don't offset first card
|
||||||
|
&:first-of-type
|
||||||
|
// margin-left: 0vmin
|
||||||
|
|||||||
30
app/assets/stylesheets/microposts.sass
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
// .micropost_form
|
||||||
|
textarea
|
||||||
|
transition: 1s all
|
||||||
|
&:focus
|
||||||
|
color: #ddd
|
||||||
|
box-shadow: 0px 0px 0px 10px black inset, 0px 0px 0px 43px white inset, 0px 0px 116px 62px black inset
|
||||||
|
rotate: -36deg
|
||||||
|
ol.microposts
|
||||||
|
padding: 0
|
||||||
|
.micropost
|
||||||
|
.display-name, .timestamp, .delete
|
||||||
|
font-family: "Press Start 2P", "Anton", Impact, fantasy, sans-serif
|
||||||
|
font-size: .4em
|
||||||
|
margin: 1em
|
||||||
|
padding: 1em
|
||||||
|
background: #ffffff33
|
||||||
|
.content
|
||||||
|
font-family: sans
|
||||||
|
font-size: .8em
|
||||||
|
text-shadow: none
|
||||||
|
.delete
|
||||||
|
&.emoji
|
||||||
|
font-size: .6em
|
||||||
|
a
|
||||||
|
text-shadow: -1px 1px #e1b027, 1px -1px #00ddff
|
||||||
|
&.text a
|
||||||
|
color: #cc0000
|
||||||
|
text-shadow: -1px 1px #e1b027, 1px -1px #00ddff
|
||||||
|
// a
|
||||||
|
color: #111111
|
||||||
56
app/assets/stylesheets/profiles.sass
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
.profile
|
||||||
|
text-align: center
|
||||||
|
background: #ffffff33
|
||||||
|
border-radius: 1rem
|
||||||
|
padding: .8em 1em .6em 1em
|
||||||
|
margin: 1em
|
||||||
|
border: .1rem solid #333333
|
||||||
|
transition: background-color .2s, border-color .2s, box-shadow .2s, color .2s
|
||||||
|
h1
|
||||||
|
line-height: 1
|
||||||
|
p
|
||||||
|
line-height: 1.2
|
||||||
|
h1, p, span
|
||||||
|
margin: 0
|
||||||
|
|
||||||
|
a.profile
|
||||||
|
display: block
|
||||||
|
&:hover
|
||||||
|
background: #ffffff55
|
||||||
|
span, p, .social-links
|
||||||
|
color: black
|
||||||
|
|
||||||
|
.social-links
|
||||||
|
width: 100%
|
||||||
|
text-align: center
|
||||||
|
position: relative
|
||||||
|
background: #40a10b
|
||||||
|
background: linear-gradient(90deg, rgba(0,0,0,0) 0%, #e1b02777 47%, rgba(0, 0, 0, 0) 95%)
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-evenly;
|
||||||
|
// padding-bottom: .3em
|
||||||
|
> a
|
||||||
|
padding: 0 1em
|
||||||
|
.dscvr-logo, .x-logo
|
||||||
|
width: 1em
|
||||||
|
vertical-align: middle
|
||||||
|
.controls
|
||||||
|
a
|
||||||
|
font-size: 0.6em
|
||||||
|
|
||||||
|
.about
|
||||||
|
background: #34b134
|
||||||
|
background: image-url('backgrounds/felt-green.png')
|
||||||
|
width: 100%
|
||||||
|
color: #019d01
|
||||||
|
background: #031804
|
||||||
|
text-shadow: none
|
||||||
|
h2
|
||||||
|
text-align: center
|
||||||
|
color: #000
|
||||||
|
text-shadow: -1px 1px #e1b027, 1px -1px #00ddff
|
||||||
|
p
|
||||||
|
text-shadow: 0px 0px 2px #34b134
|
||||||
|
font-family: "sans"
|
||||||
10
app/assets/stylesheets/projects.sass
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
.projects-index
|
||||||
|
.project
|
||||||
|
text-align: center
|
||||||
|
&:hover h1
|
||||||
|
text-shadow: 0px 0px 9px #e1b027
|
||||||
|
h1
|
||||||
|
text-shadow: -1px 1px #e1b027, 1px -1px #00ddff
|
||||||
|
transition: .15s text-shadow
|
||||||
|
p
|
||||||
|
margin-top: 0
|
||||||
3
app/assets/stylesheets/relationships.sass
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
// Place all the styles related to the Relationships controller here.
|
||||||
|
// They will automatically be included in application.css.
|
||||||
|
// You can use Sass (SCSS) here: https://sass-lang.com/
|
||||||
14
app/assets/stylesheets/rooms.sass
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
#messages
|
||||||
|
font-family: sans-serif
|
||||||
|
width: 100%
|
||||||
|
|
||||||
|
.message
|
||||||
|
background: #ffffff44
|
||||||
|
padding: 0.2em
|
||||||
|
margin: 0.2em 0
|
||||||
|
h6
|
||||||
|
margin: 0
|
||||||
|
.from_name
|
||||||
|
padding: 0.15em
|
||||||
|
color: #aaa
|
||||||
|
text-shadow: none
|
||||||
0
app/assets/stylesheets/social_links.sass
Normal file
29
app/assets/stylesheets/tables.css.sass
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
#table-component, #table-component-container, .table
|
||||||
|
width: 100%
|
||||||
|
height: 100%
|
||||||
|
|
||||||
|
.owner-controls
|
||||||
|
form
|
||||||
|
display: inline-block
|
||||||
|
|
||||||
|
#table-controls
|
||||||
|
text-align: right
|
||||||
|
padding: 0 1em
|
||||||
|
#newgame
|
||||||
|
float: left
|
||||||
|
|
||||||
|
#qrcode
|
||||||
|
float: right
|
||||||
|
margin-top: -7em
|
||||||
|
margin-right: 1.25em
|
||||||
|
transform: scale(10%)
|
||||||
|
transition: all 0.25s ease-out
|
||||||
|
width: 38px
|
||||||
|
height: 38px
|
||||||
|
&.full
|
||||||
|
margin-top: -6em
|
||||||
|
margin-right: 0
|
||||||
|
margin-bottom: 1em
|
||||||
|
transform: scale(100%)
|
||||||
|
width: 384px
|
||||||
|
height: 384px
|
||||||
@ -1,10 +0,0 @@
|
|||||||
// Place all the styles related to the Tables controller here.
|
|
||||||
// They will automatically be included in application.css.
|
|
||||||
// You can use Sass (SCSS) here: http://sass-lang.com/
|
|
||||||
|
|
||||||
#table-component-container-container,
|
|
||||||
#table-component-container,
|
|
||||||
.table {
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
18
app/assets/stylesheets/tokens.sass
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
.token-logo
|
||||||
|
max-width: 100%
|
||||||
|
width: 4.20rem
|
||||||
|
|
||||||
|
.table-container
|
||||||
|
background: #39272799
|
||||||
|
width: 100%
|
||||||
|
table.token-index
|
||||||
|
font-family: "monospace"
|
||||||
|
font-size: 1.2rem
|
||||||
|
text-shadow: none
|
||||||
|
color: #aaaaaa
|
||||||
|
.token-logo
|
||||||
|
max-width: 4rem
|
||||||
|
vertical-align: middle
|
||||||
|
|
||||||
|
.token-show
|
||||||
|
font-size: 1rem
|
||||||
BIN
app/assets/videos/video.mp4
Normal file
4
app/channels/application_cable/channel.rb
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
module ApplicationCable
|
||||||
|
class Channel < ActionCable::Channel::Base
|
||||||
|
end
|
||||||
|
end
|
||||||
15
app/channels/application_cable/connection.rb
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
module ApplicationCable
|
||||||
|
class Connection < ActionCable::Connection::Base
|
||||||
|
identified_by :current_client
|
||||||
|
|
||||||
|
def connect
|
||||||
|
self.current_client = find_client
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def find_client
|
||||||
|
Client.new(id: cookies.encrypted[:client_id])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
9
app/channels/call_channel.rb
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
class CallChannel < ApplicationCable::Channel
|
||||||
|
def subscribed
|
||||||
|
stream_from "call_channel"
|
||||||
|
end
|
||||||
|
|
||||||
|
def unsubscribed
|
||||||
|
# Any cleanup needed when channel is unsubscribed
|
||||||
|
end
|
||||||
|
end
|
||||||
9
app/channels/signaling_channel.rb
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
class SignalingChannel < ApplicationCable::Channel
|
||||||
|
def subscribed
|
||||||
|
stream_for VideoRoom.new(id: params[:id])
|
||||||
|
end
|
||||||
|
|
||||||
|
def signal(data)
|
||||||
|
broadcast_to(VideoRoom.new(id: params[:id]), data)
|
||||||
|
end
|
||||||
|
end
|
||||||
29
app/channels/video_room_channel.rb
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
class VideoRoomChannel < ApplicationCable::Channel
|
||||||
|
def subscribed
|
||||||
|
@video_room = find_video_room
|
||||||
|
stream_for @video_room
|
||||||
|
broadcast_to @video_room, { type: 'ping', from: params[:client_id] }
|
||||||
|
end
|
||||||
|
|
||||||
|
def unsubscribed
|
||||||
|
Turbo::StreamsChannel.broadcast_remove_to(
|
||||||
|
find_video_room,
|
||||||
|
target: "medium_#{current_client.id}"
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
def greet(data)
|
||||||
|
Turbo::StreamsChannel.broadcast_append_to(
|
||||||
|
data['to'],
|
||||||
|
target: 'media',
|
||||||
|
partial: 'media/medium',
|
||||||
|
locals: { client_id: data['from'] }
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def find_video_room
|
||||||
|
VideoRoom.new(id: params[:id])
|
||||||
|
end
|
||||||
|
end
|
||||||
@ -1,25 +1,31 @@
|
|||||||
class ApplicationController < ActionController::Base
|
class ApplicationController < ActionController::Base
|
||||||
|
include Pundit::Authorization
|
||||||
# Prevent CSRF attacks by raising an exception.
|
# Prevent CSRF attacks by raising an exception.
|
||||||
# For APIs, you may want to use :null_session instead.
|
# For APIs, you may want to use :null_session instead.
|
||||||
protect_from_forgery with: :exception
|
# protect_from_forgery with: :exception
|
||||||
|
protect_from_forgery unless: -> { request.format.json? }
|
||||||
|
# skip_before_action :verify_authenticity_token
|
||||||
after_action :flash_to_http_header
|
after_action :flash_to_http_header
|
||||||
|
before_action :get_footer_tokens
|
||||||
|
before_action :get_global_doodads
|
||||||
|
|
||||||
if (Rails.env.development? || Rails.env.test?)
|
# if (Rails.env.development? || Rails.env.test?)
|
||||||
# https://github.com/RailsApps/rails-devise-pundit/issues/10
|
after_action :verify_authorized, unless: -> { devise_controller? }
|
||||||
include Pundit
|
# after_action :verify_policy_scoped, only: :index
|
||||||
# https://github.com/elabs/pundit#ensuring-policies-are-used
|
|
||||||
#after_action :verify_authorized, except: :index
|
|
||||||
#after_action :verify_policy_scoped, only: :index
|
|
||||||
|
|
||||||
rescue_from Pundit::NotAuthorizedError, with: :user_not_authorized
|
rescue_from Pundit::NotAuthorizedError, with: :user_not_authorized
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def user_not_authorized
|
def user_not_authorized(exception)
|
||||||
flash[:alert] = 'Access denied.'
|
policy_name = exception.policy.class.to_s.underscore
|
||||||
|
# flash[:alert] = "#{policy_name}.#{exception.query}"
|
||||||
|
flash[:error] = t "#{policy_name}.#{exception.query}", scope: "pundit", default: :default
|
||||||
|
if flash[:error] == "You cannot perform this action."
|
||||||
|
flash[:error] = "Unable to #{exception.query[0..-2]} #{policy_name.split("_")[0].capitalize}"
|
||||||
|
end
|
||||||
redirect_to (request.referrer || root_path)
|
redirect_to (request.referrer || root_path)
|
||||||
end
|
end
|
||||||
end
|
# end
|
||||||
|
|
||||||
def authenticate_user!(args = nil)
|
def authenticate_user!(args = nil)
|
||||||
current_user.present?
|
current_user.present?
|
||||||
@ -31,6 +37,19 @@ class ApplicationController < ActionController::Base
|
|||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
|
def add_body_css_class(css_class)
|
||||||
|
@body_css_classes ||= []
|
||||||
|
@body_css_classes << css_class
|
||||||
|
end
|
||||||
|
|
||||||
|
def get_footer_tokens
|
||||||
|
@footer_tokens = policy_scope(Token)
|
||||||
|
end
|
||||||
|
|
||||||
|
def get_global_doodads
|
||||||
|
@global_doodads = policy_scope(Doodad).where(is_global: true)
|
||||||
|
end
|
||||||
|
|
||||||
def flash_to_http_header
|
def flash_to_http_header
|
||||||
return unless request.xhr?
|
return unless request.xhr?
|
||||||
return if flash.empty?
|
return if flash.empty?
|
||||||
|
|||||||
80
app/controllers/bots_controller.rb
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
class BotsController < ApplicationController
|
||||||
|
before_action :set_bot, only: %i[ show edit update destroy telegram_listen ]
|
||||||
|
|
||||||
|
# GET /bots or /bots.json
|
||||||
|
def index
|
||||||
|
authorize @bots = policy_scope(Bot)
|
||||||
|
end
|
||||||
|
|
||||||
|
# GET /bots/1 or /bots/1.json
|
||||||
|
def show
|
||||||
|
authorize @bot
|
||||||
|
end
|
||||||
|
|
||||||
|
# GET /bots/new
|
||||||
|
def new
|
||||||
|
authorize @bot = current_user.bots.new
|
||||||
|
end
|
||||||
|
|
||||||
|
# GET /bots/1/edit
|
||||||
|
def edit
|
||||||
|
authorize @bot
|
||||||
|
end
|
||||||
|
|
||||||
|
def telegram_listen
|
||||||
|
authorize @bot
|
||||||
|
# TODO enable bots with job scheduler
|
||||||
|
# @bot.delay.telegram_listen
|
||||||
|
redirect_to request.referrer
|
||||||
|
end
|
||||||
|
|
||||||
|
# POST /bots or /bots.json
|
||||||
|
def create
|
||||||
|
authorize @bot = Bot.new(bot_params)
|
||||||
|
|
||||||
|
respond_to do |format|
|
||||||
|
if @bot.save
|
||||||
|
format.html { redirect_to bot_url(@bot), notice: "Bot was successfully created." }
|
||||||
|
format.json { render :show, status: :created, location: @bot }
|
||||||
|
else
|
||||||
|
format.html { render :new, status: :unprocessable_entity }
|
||||||
|
format.json { render json: @bot.errors, status: :unprocessable_entity }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# PATCH/PUT /bots/1 or /bots/1.json
|
||||||
|
def update
|
||||||
|
authorize @bot
|
||||||
|
respond_to do |format|
|
||||||
|
if @bot.update(bot_params)
|
||||||
|
format.html { redirect_to bot_url(@bot), notice: "Bot was successfully updated." }
|
||||||
|
format.json { render :show, status: :ok, location: @bot }
|
||||||
|
else
|
||||||
|
format.html { render :edit, status: :unprocessable_entity }
|
||||||
|
format.json { render json: @bot.errors, status: :unprocessable_entity }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# DELETE /bots/1 or /bots/1.json
|
||||||
|
def destroy
|
||||||
|
@bot.destroy
|
||||||
|
|
||||||
|
respond_to do |format|
|
||||||
|
format.html { redirect_to bots_url, notice: "Bot was successfully destroyed." }
|
||||||
|
format.json { head :no_content }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
# Use callbacks to share common setup or constraints between actions.
|
||||||
|
def set_bot
|
||||||
|
@bot = Bot.find(params[:id])
|
||||||
|
end
|
||||||
|
|
||||||
|
# Only allow a list of trusted parameters through.
|
||||||
|
def bot_params
|
||||||
|
params.require(:bot).permit(:name, :telegram_api_token, :discord_api_token, :user_id, :profile_id)
|
||||||
|
end
|
||||||
|
end
|
||||||
12
app/controllers/calls_controller.rb
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
class CallsController < ApplicationController
|
||||||
|
before_action :skip_authorization
|
||||||
|
def create
|
||||||
|
head :no_content
|
||||||
|
ActionCable.server.broadcast("call_channel", call_params)
|
||||||
|
end
|
||||||
|
private
|
||||||
|
|
||||||
|
def call_params
|
||||||
|
params.permit(:call, :type, :from, :to, :sdp, :candida)
|
||||||
|
end
|
||||||
|
end
|
||||||
73
app/controllers/canisters_controller.rb
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
class CanistersController < ApplicationController
|
||||||
|
before_action :set_canister, only: %i[ show edit update destroy ]
|
||||||
|
|
||||||
|
# GET /canisters or /canisters.json
|
||||||
|
def index
|
||||||
|
authorize @canisters = policy_scope(Canister)
|
||||||
|
end
|
||||||
|
|
||||||
|
# GET /canisters/1 or /canisters/1.json
|
||||||
|
def show
|
||||||
|
authorize @canister
|
||||||
|
end
|
||||||
|
|
||||||
|
# GET /canisters/new
|
||||||
|
def new
|
||||||
|
authorize @canister = current_user.canisters.new
|
||||||
|
end
|
||||||
|
|
||||||
|
# GET /canisters/1/edit
|
||||||
|
def edit
|
||||||
|
authorize @canister
|
||||||
|
end
|
||||||
|
|
||||||
|
# POST /canisters or /canisters.json
|
||||||
|
def create
|
||||||
|
authorize @canister = Canister.new(canister_params)
|
||||||
|
|
||||||
|
respond_to do |format|
|
||||||
|
if @canister.save
|
||||||
|
format.html { redirect_to @canister, notice: "Canister was successfully created." }
|
||||||
|
format.json { render :show, status: :created, location: @canister }
|
||||||
|
else
|
||||||
|
format.html { render :new, status: :unprocessable_entity }
|
||||||
|
format.json { render json: @canister.errors, status: :unprocessable_entity }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# PATCH/PUT /canisters/1 or /canisters/1.json
|
||||||
|
def update
|
||||||
|
authorize @canister
|
||||||
|
respond_to do |format|
|
||||||
|
if @canister.update(canister_params)
|
||||||
|
format.html { redirect_to @canister, notice: "Canister was successfully updated." }
|
||||||
|
format.json { render :show, status: :ok, location: @canister }
|
||||||
|
else
|
||||||
|
format.html { render :edit, status: :unprocessable_entity }
|
||||||
|
format.json { render json: @canister.errors, status: :unprocessable_entity }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# DELETE /canisters/1 or /canisters/1.json
|
||||||
|
def destroy
|
||||||
|
authorize @canister
|
||||||
|
@canister.destroy
|
||||||
|
respond_to do |format|
|
||||||
|
format.html { redirect_to canisters_url, notice: "Canister was successfully destroyed." }
|
||||||
|
format.json { head :no_content }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
# Use callbacks to share common setup or constraints between actions.
|
||||||
|
def set_canister
|
||||||
|
@canister = Canister.find(params[:id])
|
||||||
|
end
|
||||||
|
|
||||||
|
# Only allow a list of trusted parameters through.
|
||||||
|
def canister_params
|
||||||
|
params.require(:canister).permit(:icid, :name, :user_id)
|
||||||
|
end
|
||||||
|
end
|
||||||
81
app/controllers/commands_controller.rb
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
class CommandsController < ApplicationController
|
||||||
|
before_action :set_command, only: %i[ show edit update destroy run ]
|
||||||
|
|
||||||
|
# GET /commands or /commands.json
|
||||||
|
def index
|
||||||
|
authorize @commands = Command.all
|
||||||
|
end
|
||||||
|
|
||||||
|
# GET /commands/1 or /commands/1.json
|
||||||
|
def show
|
||||||
|
authorize @command
|
||||||
|
end
|
||||||
|
|
||||||
|
# RUN /commands/1/run
|
||||||
|
def run
|
||||||
|
authorize @command
|
||||||
|
response_text = eval(@command.body)
|
||||||
|
redirect_to (request.referrer || @command), notice: response_text
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
# GET /commands/new
|
||||||
|
def new
|
||||||
|
@command = Command.new
|
||||||
|
end
|
||||||
|
|
||||||
|
# GET /commands/1/edit
|
||||||
|
def edit
|
||||||
|
authorize @command
|
||||||
|
end
|
||||||
|
|
||||||
|
# POST /commands or /commands.json
|
||||||
|
def create
|
||||||
|
@command = Command.new(command_params)
|
||||||
|
|
||||||
|
respond_to do |format|
|
||||||
|
if @command.save
|
||||||
|
format.html { redirect_to command_url(@command), notice: "Command was successfully created." }
|
||||||
|
format.json { render :show, status: :created, location: @command }
|
||||||
|
else
|
||||||
|
format.html { render :new, status: :unprocessable_entity }
|
||||||
|
format.json { render json: @command.errors, status: :unprocessable_entity }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# PATCH/PUT /commands/1 or /commands/1.json
|
||||||
|
def update
|
||||||
|
authorize @command
|
||||||
|
respond_to do |format|
|
||||||
|
if @command.update(command_params)
|
||||||
|
format.html { redirect_to command_url(@command), notice: "Command was successfully updated." }
|
||||||
|
format.json { render :show, status: :ok, location: @command }
|
||||||
|
else
|
||||||
|
format.html { render :edit, status: :unprocessable_entity }
|
||||||
|
format.json { render json: @command.errors, status: :unprocessable_entity }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# DELETE /commands/1 or /commands/1.json
|
||||||
|
def destroy
|
||||||
|
@command.destroy
|
||||||
|
|
||||||
|
respond_to do |format|
|
||||||
|
format.html { redirect_to commands_url, notice: "Command was successfully destroyed." }
|
||||||
|
format.json { head :no_content }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
# Use callbacks to share common setup or constraints between actions.
|
||||||
|
def set_command
|
||||||
|
@command = Command.find(params[:id])
|
||||||
|
end
|
||||||
|
|
||||||
|
# Only allow a list of trusted parameters through.
|
||||||
|
def command_params
|
||||||
|
params.require(:command).permit(:name, :trigger, :body)
|
||||||
|
end
|
||||||
|
end
|
||||||
73
app/controllers/doodads_controller.rb
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
class DoodadsController < ApplicationController
|
||||||
|
before_action :set_doodad, only: %i[ show edit update destroy ]
|
||||||
|
|
||||||
|
# GET /doodads or /doodads.json
|
||||||
|
def index
|
||||||
|
authorize @doodads = policy_scope(Doodad)
|
||||||
|
end
|
||||||
|
|
||||||
|
# GET /doodads/1 or /doodads/1.json
|
||||||
|
def show
|
||||||
|
authorize @doodad
|
||||||
|
end
|
||||||
|
|
||||||
|
# GET /doodads/new
|
||||||
|
def new
|
||||||
|
authorize @doodad = current_user.doodads.new
|
||||||
|
end
|
||||||
|
|
||||||
|
# GET /doodads/1/edit
|
||||||
|
def edit
|
||||||
|
authorize @doodad
|
||||||
|
end
|
||||||
|
|
||||||
|
# POST /doodads or /doodads.json
|
||||||
|
def create
|
||||||
|
authorize @doodad = Doodad.new(doodad_params)
|
||||||
|
|
||||||
|
respond_to do |format|
|
||||||
|
if @doodad.save
|
||||||
|
format.html { redirect_to @doodad, notice: "Doodad was successfully created." }
|
||||||
|
format.json { render :show, status: :created, location: @doodad }
|
||||||
|
else
|
||||||
|
format.html { render :new, status: :unprocessable_entity }
|
||||||
|
format.json { render json: @doodad.errors, status: :unprocessable_entity }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# PATCH/PUT /doodads/1 or /doodads/1.json
|
||||||
|
def update
|
||||||
|
authorize @doodad
|
||||||
|
respond_to do |format|
|
||||||
|
if @doodad.update(doodad_params)
|
||||||
|
format.html { redirect_to @doodad, notice: "Doodad was successfully updated." }
|
||||||
|
format.json { render :show, status: :ok, location: @doodad }
|
||||||
|
else
|
||||||
|
format.html { render :edit, status: :unprocessable_entity }
|
||||||
|
format.json { render json: @doodad.errors, status: :unprocessable_entity }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# DELETE /doodads/1 or /doodads/1.json
|
||||||
|
def destroy
|
||||||
|
authorize @doodad
|
||||||
|
@doodad.destroy
|
||||||
|
respond_to do |format|
|
||||||
|
format.html { redirect_to doodads_url, notice: "Doodad was successfully destroyed." }
|
||||||
|
format.json { head :no_content }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
# Use callbacks to share common setup or constraints between actions.
|
||||||
|
def set_doodad
|
||||||
|
@doodad = Doodad.find(params[:id])
|
||||||
|
end
|
||||||
|
|
||||||
|
# Only allow a list of trusted parameters through.
|
||||||
|
def doodad_params
|
||||||
|
params.require(:doodad).permit(:body, :user_id, :is_public, :is_global)
|
||||||
|
end
|
||||||
|
end
|
||||||
@ -28,6 +28,7 @@ class GamesController < ApplicationController
|
|||||||
end
|
end
|
||||||
|
|
||||||
def play_hand
|
def play_hand
|
||||||
|
authorize @game
|
||||||
# TODO: move this logic out of controller maybe to model(s) ?
|
# TODO: move this logic out of controller maybe to model(s) ?
|
||||||
|
|
||||||
# validate player's turn
|
# validate player's turn
|
||||||
@ -35,23 +36,27 @@ class GamesController < ApplicationController
|
|||||||
|
|
||||||
# Player action: pass
|
# Player action: pass
|
||||||
# TODO: wtf do we need game params for? And why nest hand_type in it?
|
# TODO: wtf do we need game params for? And why nest hand_type in it?
|
||||||
if params[:game]
|
# if params[:game]
|
||||||
if params[:game][:hand_type] == 'pass'
|
if params[:hand_type] == 'Pass'
|
||||||
@game.set_controlling_player 'next'
|
@game.set_controlling_player 'next'
|
||||||
flash[:notice] = 'Successfully passed.'
|
flash[:notice] = 'Successfully passed.'
|
||||||
@game.save
|
# Clear play to beat if play returns to owner
|
||||||
|
if @game.play_to_beat.try(:player).try(:id) == @game.controlling_player_id
|
||||||
|
@game.play_to_beat_id = nil
|
||||||
end
|
end
|
||||||
end
|
@game.save
|
||||||
|
|
||||||
# Player action: play_hand
|
# Player action: play_hand
|
||||||
if params[:player_card_ids]
|
elsif params[:player_card_ids]
|
||||||
@cards_to_play = @game.controlling_player.try(:player_cards).order(:value).find(params[:player_card_ids])
|
@cards_to_play = @game.controlling_player.try(:player_cards).order(:value).find(params[:player_card_ids])
|
||||||
# Instantiate the play
|
# Instantiate the play
|
||||||
@play = @game.controlling_player.plays.new
|
@play = @game.controlling_player.plays.new
|
||||||
@play.game_id = @game.id
|
@play.game_id = @game.id
|
||||||
|
|
||||||
|
# TODO Bug next player fails if inventory is empty
|
||||||
|
@next_player_id = @game.next_player_id
|
||||||
@play.player_cards << @cards_to_play
|
@play.player_cards << @cards_to_play
|
||||||
if @play.save
|
if @play.save
|
||||||
@game.set_controlling_player 'next'
|
@game.controlling_player_id = @next_player_id
|
||||||
@game.save
|
@game.save
|
||||||
else
|
else
|
||||||
# TODO: Does anything need to happen here?
|
# TODO: Does anything need to happen here?
|
||||||
@ -74,8 +79,9 @@ class GamesController < ApplicationController
|
|||||||
end
|
end
|
||||||
|
|
||||||
respond_to do |format|
|
respond_to do |format|
|
||||||
format.html { redirect_to(@game) }
|
|
||||||
## TODO: Return status message of attempt to play_hand
|
## TODO: Return status message of attempt to play_hand
|
||||||
|
# flash[:notice] = 'I hi'
|
||||||
|
format.html { redirect_to(@game.table) }
|
||||||
format.json { render json: @game }
|
format.json { render json: @game }
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -104,10 +110,12 @@ class GamesController < ApplicationController
|
|||||||
|
|
||||||
def play_now
|
def play_now
|
||||||
# First joinable game or create new game
|
# First joinable game or create new game
|
||||||
@game = Game.play_now(current_user)
|
@game = Game.play_now
|
||||||
@seats = @game.seats.order(:position).map {|s| s.occupied? ? nil : s}
|
@seats = @game.table.seats.order(:position).map {|s| s.occupied? ? nil : s}
|
||||||
@seats.compact.last.sit(current_user)
|
# @seats = @game.table.seats
|
||||||
redirect_to @game
|
@seat = @seats.compact.last.sit(current_user)
|
||||||
|
@seat.save
|
||||||
|
redirect_to @game.table
|
||||||
end
|
end
|
||||||
|
|
||||||
def join
|
def join
|
||||||
@ -117,18 +125,19 @@ class GamesController < ApplicationController
|
|||||||
end
|
end
|
||||||
|
|
||||||
def start
|
def start
|
||||||
|
authorize @game
|
||||||
begin
|
begin
|
||||||
@game.start
|
@game.start
|
||||||
rescue StandardError => e
|
rescue StandardError => e
|
||||||
@game.errors.messages.each do |key, msg|
|
@game.errors.messages.each do |key, msg|
|
||||||
flash[key] = msg.join
|
flash[key] = msg.join
|
||||||
end
|
end
|
||||||
redirect_to(@game)
|
redirect_to(@game.table)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
flash[:notice] = 'Game started.'
|
flash[:notice] = 'Game started.'
|
||||||
|
|
||||||
redirect_to(@game)
|
redirect_to(@game.table)
|
||||||
end
|
end
|
||||||
|
|
||||||
def my_inventory
|
def my_inventory
|
||||||
|
|||||||
13
app/controllers/messages_controller.rb
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
class MessagesController < ApplicationController
|
||||||
|
def create
|
||||||
|
@message = current_user.messages.build(content: msg_params[:content], room_id: params[:room_id])
|
||||||
|
authorize @message
|
||||||
|
@message.save
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def msg_params
|
||||||
|
params.require(:message).permit(:content)
|
||||||
|
end
|
||||||
|
end
|
||||||
90
app/controllers/metapurses_controller.rb
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
class MetapursesController < ApplicationController
|
||||||
|
before_action :set_metapurse, only: %i[ show edit update destroy data ]
|
||||||
|
|
||||||
|
# GET /metapurses or /metapurses.json
|
||||||
|
def index
|
||||||
|
authorize @metapurses = policy_scope(Metapurse)
|
||||||
|
end
|
||||||
|
|
||||||
|
# GET /metapurses/1 or /metapurses/1.json
|
||||||
|
def show
|
||||||
|
authorize @metapurse
|
||||||
|
end
|
||||||
|
|
||||||
|
def data
|
||||||
|
authorize @metapurse
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
# GET /metapurses/new
|
||||||
|
def new
|
||||||
|
authorize @metapurse = current_user.metapurses.new
|
||||||
|
@metapurse.data = "ryjl3-tyaaa-aaaaa-aaaba-cai 100 ICP
|
||||||
|
iozql-7iaaa-aaaah-advvq-cai 880 TENDIES
|
||||||
|
whdfs-saaaa-aaaao-awh4a-cai 240 NEED
|
||||||
|
ss2fx-dyaaa-aaaar-qacoq-cai 0.1 ckETH
|
||||||
|
nwd3n-qaaaa-aaaak-afmda-cai 192.92 INSANE
|
||||||
|
eayyd-iiaaa-aaaah-adtea-cai 5678.1234 iDoge
|
||||||
|
rh2pm-ryaaa-aaaan-qeniq-cai 69420.98 Windoge98 EXE
|
||||||
|
7tx3o-zyaaa-aaaak-aes6q-cai 1337456899999 DOGMI
|
||||||
|
wnnwu-4iaaa-aaaar-qacxq-cai 420690000 SKIBIDI
|
||||||
|
67mu5-maaaa-aaaar-qadca-cai 360 MCS
|
||||||
|
kz5t3-pyaaa-aaaap-ab2qq-cai 5000000 iVishnu"
|
||||||
|
end
|
||||||
|
|
||||||
|
# GET /metapurses/1/edit
|
||||||
|
def edit
|
||||||
|
authorize @metapurse
|
||||||
|
end
|
||||||
|
|
||||||
|
# POST /metapurses or /metapurses.json
|
||||||
|
def create
|
||||||
|
authorize @metapurse = Metapurse.new(metapurse_params)
|
||||||
|
|
||||||
|
respond_to do |format|
|
||||||
|
if @metapurse.save
|
||||||
|
format.html { redirect_to metapurse_url(@metapurse), notice: "Metapurse was successfully created." }
|
||||||
|
format.json { render :show, status: :created, location: @metapurse }
|
||||||
|
else
|
||||||
|
format.html { render :new, status: :unprocessable_entity }
|
||||||
|
format.json { render json: @metapurse.errors, status: :unprocessable_entity }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# PATCH/PUT /metapurses/1 or /metapurses/1.json
|
||||||
|
def update
|
||||||
|
authorize @metapurse
|
||||||
|
respond_to do |format|
|
||||||
|
if @metapurse.update(metapurse_params)
|
||||||
|
format.html { redirect_to metapurse_url(@metapurse), notice: "Metapurse was successfully updated." }
|
||||||
|
format.json { render :show, status: :ok, location: @metapurse }
|
||||||
|
else
|
||||||
|
format.html { render :edit, status: :unprocessable_entity }
|
||||||
|
format.json { render json: @metapurse.errors, status: :unprocessable_entity }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# DELETE /metapurses/1 or /metapurses/1.json
|
||||||
|
def destroy
|
||||||
|
authorize @metapurse
|
||||||
|
@metapurse.destroy!
|
||||||
|
|
||||||
|
respond_to do |format|
|
||||||
|
format.html { redirect_to metapurses_url, notice: "Metapurse was successfully destroyed." }
|
||||||
|
format.json { head :no_content }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
# Use callbacks to share common setup or constraints between actions.
|
||||||
|
def set_metapurse
|
||||||
|
@metapurse = Metapurse.find(params[:id])
|
||||||
|
end
|
||||||
|
|
||||||
|
# Only allow a list of trusted parameters through.
|
||||||
|
def metapurse_params
|
||||||
|
params.require(:metapurse).permit(:name, :data, :user_id, :is_private)
|
||||||
|
end
|
||||||
|
end
|
||||||
33
app/controllers/microposts_controller.rb
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
class MicropostsController < ApplicationController
|
||||||
|
before_action :set_micropost, only: %i[ show edit update destroy ]
|
||||||
|
def create
|
||||||
|
@micropost = Micropost.new(micropost_params)
|
||||||
|
authorize @micropost
|
||||||
|
if @micropost.save
|
||||||
|
flash[:success] = "Post created!"
|
||||||
|
redirect_to request.referrer || root_url
|
||||||
|
else
|
||||||
|
flash[:error] = "Post failed!"
|
||||||
|
redirect_to request.referrer || root_url
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def destroy
|
||||||
|
authorize @micropost
|
||||||
|
@micropost.destroy
|
||||||
|
respond_to do |format|
|
||||||
|
format.html { redirect_to request.referrer || root_url, notice: "Post was deleted." }
|
||||||
|
format.json { head :no_content }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
# Use callbacks to share common setup or constraints between actions.
|
||||||
|
def set_micropost
|
||||||
|
@micropost = Micropost.find(params[:id])
|
||||||
|
end
|
||||||
|
|
||||||
|
def micropost_params
|
||||||
|
params.require(:micropost).permit(:content, :micropostable_type, :micropostable_id)
|
||||||
|
end
|
||||||
|
end
|
||||||
5
app/controllers/pages_controller.rb
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
class PagesController < ApplicationController
|
||||||
|
before_action :skip_authorization
|
||||||
|
def czechers
|
||||||
|
end
|
||||||
|
end
|
||||||
81
app/controllers/profiles_controller.rb
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
class ProfilesController < ApplicationController
|
||||||
|
before_action :set_profile, only: %i[ show edit update destroy ]
|
||||||
|
|
||||||
|
# GET /profiles or /profiles.json
|
||||||
|
def index
|
||||||
|
@profiles = policy_scope Profile.all
|
||||||
|
authorize @profiles
|
||||||
|
end
|
||||||
|
|
||||||
|
# GET /profiles/1 or /profiles/1.json
|
||||||
|
def show
|
||||||
|
authorize @profile
|
||||||
|
@followable = @profile
|
||||||
|
if @profile.user == current_user
|
||||||
|
@micropost = @profile.microposts.build
|
||||||
|
else
|
||||||
|
@micropost = current_user.microposts.build if current_user.signed_in?
|
||||||
|
end
|
||||||
|
@microposts = @profile.microposts.paginate(page: params[:page])
|
||||||
|
end
|
||||||
|
|
||||||
|
# GET /profiles/new
|
||||||
|
def new
|
||||||
|
authorize @profile = current_user.profiles.new
|
||||||
|
end
|
||||||
|
|
||||||
|
# GET /profiles/1/edit
|
||||||
|
def edit
|
||||||
|
authorize @profile
|
||||||
|
end
|
||||||
|
|
||||||
|
# POST /profiles or /profiles.json
|
||||||
|
def create
|
||||||
|
authorize @profile = Profile.new(profile_params)
|
||||||
|
|
||||||
|
respond_to do |format|
|
||||||
|
if @profile.save
|
||||||
|
format.html { redirect_to profile_url(@profile), notice: "Profile was successfully created." }
|
||||||
|
format.json { render :show, status: :created, location: @profile }
|
||||||
|
else
|
||||||
|
format.html { render :new, status: :unprocessable_entity }
|
||||||
|
format.json { render json: @profile.errors, status: :unprocessable_entity }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# PATCH/PUT /profiles/1 or /profiles/1.json
|
||||||
|
def update
|
||||||
|
authorize @profile
|
||||||
|
respond_to do |format|
|
||||||
|
if @profile.update(profile_params)
|
||||||
|
format.html { redirect_to profile_url(@profile), notice: "Profile was successfully updated." }
|
||||||
|
format.json { render :show, status: :ok, location: @profile }
|
||||||
|
else
|
||||||
|
format.html { render :edit, status: :unprocessable_entity }
|
||||||
|
format.json { render json: @profile.errors, status: :unprocessable_entity }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# DELETE /profiles/1 or /profiles/1.json
|
||||||
|
def destroy
|
||||||
|
@profile.destroy
|
||||||
|
|
||||||
|
respond_to do |format|
|
||||||
|
format.html { redirect_to profiles_url, notice: "Profile was successfully destroyed." }
|
||||||
|
format.json { head :no_content }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
# Use callbacks to share common setup or constraints between actions.
|
||||||
|
def set_profile
|
||||||
|
@profile = Profile.find(params[:id])
|
||||||
|
end
|
||||||
|
|
||||||
|
# Only allow a list of trusted parameters through.
|
||||||
|
def profile_params
|
||||||
|
params.require(:profile).permit(:user_id, :name, :summary, :about)
|
||||||
|
end
|
||||||
|
end
|
||||||
76
app/controllers/projects_controller.rb
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
class ProjectsController < ApplicationController
|
||||||
|
before_action :set_project, only: %i[ show edit update destroy ]
|
||||||
|
|
||||||
|
# GET /projects or /projects.json
|
||||||
|
def index
|
||||||
|
@projects = authorize Project.all
|
||||||
|
end
|
||||||
|
|
||||||
|
# GET /projects/1 or /projects/1.json
|
||||||
|
def show
|
||||||
|
authorize @project
|
||||||
|
@followable = @project
|
||||||
|
if @project.user == current_user
|
||||||
|
@micropost = @project.microposts.build
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# GET /projects/new
|
||||||
|
def new
|
||||||
|
authorize @project = current_user.projects.new
|
||||||
|
end
|
||||||
|
|
||||||
|
# GET /projects/1/edit
|
||||||
|
def edit
|
||||||
|
authorize @project
|
||||||
|
end
|
||||||
|
|
||||||
|
# POST /projects or /projects.json
|
||||||
|
def create
|
||||||
|
authorize @project = Project.new(project_params)
|
||||||
|
|
||||||
|
respond_to do |format|
|
||||||
|
if @project.save
|
||||||
|
format.html { redirect_to project_url(@project), notice: "Project was successfully created." }
|
||||||
|
format.json { render :show, status: :created, location: @project }
|
||||||
|
else
|
||||||
|
format.html { render :new, status: :unprocessable_entity }
|
||||||
|
format.json { render json: @project.errors, status: :unprocessable_entity }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# PATCH/PUT /projects/1 or /projects/1.json
|
||||||
|
def update
|
||||||
|
respond_to do |format|
|
||||||
|
if @project.update(project_params)
|
||||||
|
format.html { redirect_to project_url(@project), notice: "Project was successfully updated." }
|
||||||
|
format.json { render :show, status: :ok, location: @project }
|
||||||
|
else
|
||||||
|
format.html { render :edit, status: :unprocessable_entity }
|
||||||
|
format.json { render json: @project.errors, status: :unprocessable_entity }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# DELETE /projects/1 or /projects/1.json
|
||||||
|
def destroy
|
||||||
|
@project.destroy
|
||||||
|
|
||||||
|
respond_to do |format|
|
||||||
|
format.html { redirect_to projects_url, notice: "Project was successfully destroyed." }
|
||||||
|
format.json { head :no_content }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
# Use callbacks to share common setup or constraints between actions.
|
||||||
|
def set_project
|
||||||
|
@project = Project.find(params[:id])
|
||||||
|
end
|
||||||
|
|
||||||
|
# Only allow a list of trusted parameters through.
|
||||||
|
def project_params
|
||||||
|
params.require(:project).permit(:title, :description, :user_id)
|
||||||
|
end
|
||||||
|
end
|
||||||
16
app/controllers/relationships_controller.rb
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
class RelationshipsController < ApplicationController
|
||||||
|
def create
|
||||||
|
authorize Relationship
|
||||||
|
leader = params[:followable_type].constantize.find(params[:followable_id])
|
||||||
|
current_user.follow(leader)
|
||||||
|
redirect_to leader
|
||||||
|
end
|
||||||
|
|
||||||
|
def destroy
|
||||||
|
relationship = Relationship.find(params[:id])
|
||||||
|
authorize relationship
|
||||||
|
leader = relationship.followable
|
||||||
|
current_user.unfollow(leader)
|
||||||
|
redirect_to leader
|
||||||
|
end
|
||||||
|
end
|
||||||
31
app/controllers/rooms_controller.rb
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
class RoomsController < ApplicationController
|
||||||
|
before_action :set_room, only: %i[ show edit update destroy ]
|
||||||
|
def index
|
||||||
|
@rooms = policy_scope Room.all
|
||||||
|
authorize @rooms
|
||||||
|
authorize @new_room = Room.new
|
||||||
|
end
|
||||||
|
|
||||||
|
def create
|
||||||
|
authorize @room = Room.build(name: params["room"]["name"])
|
||||||
|
@room.save
|
||||||
|
end
|
||||||
|
|
||||||
|
def show
|
||||||
|
authorize @room
|
||||||
|
@rooms = Room.public_rooms
|
||||||
|
@message = Message.new
|
||||||
|
@messages = @room.messages
|
||||||
|
@new_room = Room.new
|
||||||
|
|
||||||
|
render "index"
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
# Use callbacks to share common setup or constraints between actions.
|
||||||
|
def set_room
|
||||||
|
@room = Room.find(params[:id])
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
@ -1,5 +1,7 @@
|
|||||||
class SeatsController < ApplicationController
|
class SeatsController < ApplicationController
|
||||||
before_action :set_seat, only: [:show, :edit, :update, :destroy, :sit, :stand]
|
before_action :set_seat, only: [:show, :edit, :update, :destroy,
|
||||||
|
:sit, :stand, :add_bot, :remove_bot, :empty,
|
||||||
|
:remove_player]
|
||||||
|
|
||||||
respond_to :html, :json
|
respond_to :html, :json
|
||||||
|
|
||||||
@ -42,6 +44,7 @@ class SeatsController < ApplicationController
|
|||||||
# PATCH/PUT /seats/1
|
# PATCH/PUT /seats/1
|
||||||
# PATCH/PUT /seats/1.json
|
# PATCH/PUT /seats/1.json
|
||||||
def update
|
def update
|
||||||
|
authorize @seat
|
||||||
respond_to do |format|
|
respond_to do |format|
|
||||||
if @seat.update(seat_params)
|
if @seat.update(seat_params)
|
||||||
format.html { redirect_to @seat, notice: 'Seat was successfully updated.' }
|
format.html { redirect_to @seat, notice: 'Seat was successfully updated.' }
|
||||||
@ -56,6 +59,7 @@ class SeatsController < ApplicationController
|
|||||||
# DELETE /seats/1
|
# DELETE /seats/1
|
||||||
# DELETE /seats/1.json
|
# DELETE /seats/1.json
|
||||||
def destroy
|
def destroy
|
||||||
|
authorize @seat
|
||||||
@seat.destroy
|
@seat.destroy
|
||||||
respond_to do |format|
|
respond_to do |format|
|
||||||
format.html { redirect_to seats_url, notice: 'Seat was successfully destroyed.' }
|
format.html { redirect_to seats_url, notice: 'Seat was successfully destroyed.' }
|
||||||
@ -65,11 +69,44 @@ class SeatsController < ApplicationController
|
|||||||
|
|
||||||
# POST /seats/1
|
# POST /seats/1
|
||||||
def sit
|
def sit
|
||||||
|
authorize @seat
|
||||||
@message = @seat.sit current_user
|
@message = @seat.sit current_user
|
||||||
|
respond_to do |format|
|
||||||
|
if @seat.save
|
||||||
|
format.html { redirect_to @seat.table, notice: 'Seat was successfully sat in.' }
|
||||||
|
else
|
||||||
|
format.html { redirect_to @seat.table, notice: 'Failed to sit.' }
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def stand
|
def stand
|
||||||
|
authorize @seat
|
||||||
@message = @seat.stand current_user
|
@message = @seat.stand current_user
|
||||||
|
redirect_to @seat.table, notice: @message
|
||||||
|
end
|
||||||
|
|
||||||
|
def add_bot
|
||||||
|
authorize @seat
|
||||||
|
@message = @seat.add_bot
|
||||||
|
redirect_to @seat.table, notice: @message
|
||||||
|
end
|
||||||
|
|
||||||
|
def remove_bot
|
||||||
|
@message = @seat.remove_bot
|
||||||
|
redirect_to @seat.table, notice: @message
|
||||||
|
end
|
||||||
|
|
||||||
|
def empty
|
||||||
|
authorize @seat
|
||||||
|
@message = @seat.empty
|
||||||
|
redirect_to @seat.table, notice: @message
|
||||||
|
end
|
||||||
|
|
||||||
|
def remove_player
|
||||||
|
authorize @seat
|
||||||
|
@message = @seat.remove_player
|
||||||
|
redirect_to @seat.table, notice: @message
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|||||||
77
app/controllers/social_links_controller.rb
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
class SocialLinksController < ApplicationController
|
||||||
|
before_action :set_social_link, only: %i[ show edit update destroy ]
|
||||||
|
|
||||||
|
# GET /social_links or /social_links.json
|
||||||
|
def index
|
||||||
|
@social_links = policy_scope SocialLink.all
|
||||||
|
authorize @social_links
|
||||||
|
end
|
||||||
|
|
||||||
|
# GET /social_links/1 or /social_links/1.json
|
||||||
|
def show
|
||||||
|
authorize @social_link
|
||||||
|
end
|
||||||
|
|
||||||
|
# GET /social_links/new
|
||||||
|
def new
|
||||||
|
@social_link = SocialLink.new
|
||||||
|
@social_link.profile_id = params[:profile_id] if params[:profile_id]
|
||||||
|
authorize @social_link
|
||||||
|
end
|
||||||
|
|
||||||
|
# GET /social_links/1/edit
|
||||||
|
def edit
|
||||||
|
authorize @social_link
|
||||||
|
end
|
||||||
|
|
||||||
|
# POST /social_links or /social_links.json
|
||||||
|
def create
|
||||||
|
authorize @social_link = SocialLink.new(social_link_params)
|
||||||
|
|
||||||
|
respond_to do |format|
|
||||||
|
if @social_link.save
|
||||||
|
format.html { redirect_to @social_link.profile, notice: "Social link was successfully created." }
|
||||||
|
format.json { render :show, status: :created, location: @social_link }
|
||||||
|
else
|
||||||
|
format.html { render :new, status: :unprocessable_entity }
|
||||||
|
format.json { render json: @social_link.errors, status: :unprocessable_entity }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# PATCH/PUT /social_links/1 or /social_links/1.json
|
||||||
|
def update
|
||||||
|
authorize @social_link
|
||||||
|
respond_to do |format|
|
||||||
|
if @social_link.update(social_link_params)
|
||||||
|
format.html { redirect_to @social_link.profile, notice: "Social link was successfully updated." }
|
||||||
|
format.json { render :show, status: :ok, location: @social_link }
|
||||||
|
else
|
||||||
|
format.html { render :edit, status: :unprocessable_entity }
|
||||||
|
format.json { render json: @social_link.errors, status: :unprocessable_entity }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# DELETE /social_links/1 or /social_links/1.json
|
||||||
|
def destroy
|
||||||
|
authorize @social_link
|
||||||
|
@social_link.destroy
|
||||||
|
|
||||||
|
respond_to do |format|
|
||||||
|
format.html { redirect_to social_links_url, notice: "Social link was successfully destroyed." }
|
||||||
|
format.json { head :no_content }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
# Use callbacks to share common setup or constraints between actions.
|
||||||
|
def set_social_link
|
||||||
|
@social_link = SocialLink.find(params[:id])
|
||||||
|
end
|
||||||
|
|
||||||
|
# Only allow a list of trusted parameters through.
|
||||||
|
def social_link_params
|
||||||
|
params.require(:social_link).permit(:profile_id, :url)
|
||||||
|
end
|
||||||
|
end
|
||||||
@ -1,32 +1,79 @@
|
|||||||
class TablesController < ApplicationController
|
class TablesController < ApplicationController
|
||||||
before_action :set_table, only: [:show, :edit, :update, :destroy]
|
before_action :set_table, only: [:show, :edit, :update, :destroy, :new_game]
|
||||||
|
|
||||||
respond_to :html, :json
|
respond_to :html, :json
|
||||||
|
|
||||||
|
def play_now
|
||||||
|
# First empty seat
|
||||||
|
@seat = Seat.where(user_soft_token: nil).select{|s| !s.player.try("is_bot?")}.first
|
||||||
|
if @seat
|
||||||
|
authorize @seat
|
||||||
|
@seat.sit current_user
|
||||||
|
else
|
||||||
|
authorize @table = Table.create(title: "Table " + current_user.soft_token[0..4])
|
||||||
|
@seat = @table.seats.first
|
||||||
|
@seat.sit current_user
|
||||||
|
end
|
||||||
|
redirect_to @seat.table
|
||||||
|
# @game = Game.play_now(current_user)
|
||||||
|
# @table = @game.table
|
||||||
|
# @seats = @table.seats.order(:position).map {|s| s.occupied? ? nil : s}
|
||||||
|
# @seat = @seats.compact.last.sit(current_user)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
# GET /tables
|
# GET /tables
|
||||||
# GET /tables.json
|
# GET /tables.json
|
||||||
def index
|
def index
|
||||||
@tables = Table.all
|
@tables = authorize Table.all
|
||||||
end
|
end
|
||||||
|
|
||||||
# GET /tables/1
|
# GET /tables/1
|
||||||
# GET /tables/1.json
|
# GET /tables/1.json
|
||||||
def show
|
def show
|
||||||
|
authorize @table
|
||||||
|
if @game
|
||||||
|
authorize @game
|
||||||
|
# TODO refactor to ensure play for 2nd and 3rd place
|
||||||
|
|
||||||
|
if @game.controlling_player.try("is_bot?")
|
||||||
|
@game.controlling_player.auto_play
|
||||||
|
@game.save
|
||||||
|
@game.reload
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def new_game
|
||||||
|
authorize @table
|
||||||
|
@game = @table.add_game
|
||||||
|
begin
|
||||||
|
@game.start
|
||||||
|
rescue
|
||||||
|
flash[:errors] = @game.errors
|
||||||
|
end
|
||||||
|
redirect_to @table
|
||||||
|
end
|
||||||
|
|
||||||
|
def tutorial
|
||||||
|
flash[:notice] = "Tutorial coming soon!"
|
||||||
|
redirect_to root_path
|
||||||
end
|
end
|
||||||
|
|
||||||
# GET /tables/new
|
# GET /tables/new
|
||||||
def new
|
def new
|
||||||
@table = Table.new
|
authorize @table = Table.new
|
||||||
end
|
end
|
||||||
|
|
||||||
# GET /tables/1/edit
|
# GET /tables/1/edit
|
||||||
def edit
|
def edit
|
||||||
|
authorize @table
|
||||||
end
|
end
|
||||||
|
|
||||||
# POST /tables
|
# POST /tables
|
||||||
# POST /tables.json
|
# POST /tables.json
|
||||||
def create
|
def create
|
||||||
@table = Table.new(table_params)
|
authorize @table = Table.new(table_params)
|
||||||
|
|
||||||
respond_to do |format|
|
respond_to do |format|
|
||||||
if @table.save
|
if @table.save
|
||||||
@ -42,6 +89,7 @@ class TablesController < ApplicationController
|
|||||||
# PATCH/PUT /tables/1
|
# PATCH/PUT /tables/1
|
||||||
# PATCH/PUT /tables/1.json
|
# PATCH/PUT /tables/1.json
|
||||||
def update
|
def update
|
||||||
|
authorize @table
|
||||||
respond_to do |format|
|
respond_to do |format|
|
||||||
if @table.update(table_params)
|
if @table.update(table_params)
|
||||||
format.html { redirect_to @table, notice: 'Table was successfully updated.' }
|
format.html { redirect_to @table, notice: 'Table was successfully updated.' }
|
||||||
@ -56,6 +104,7 @@ class TablesController < ApplicationController
|
|||||||
# DELETE /tables/1
|
# DELETE /tables/1
|
||||||
# DELETE /tables/1.json
|
# DELETE /tables/1.json
|
||||||
def destroy
|
def destroy
|
||||||
|
authorize @table
|
||||||
@table.destroy
|
@table.destroy
|
||||||
respond_to do |format|
|
respond_to do |format|
|
||||||
format.html { redirect_to tables_url, notice: 'Table was successfully destroyed.' }
|
format.html { redirect_to tables_url, notice: 'Table was successfully destroyed.' }
|
||||||
@ -66,11 +115,14 @@ class TablesController < ApplicationController
|
|||||||
private
|
private
|
||||||
# Use callbacks to share common setup or constraints between actions.
|
# Use callbacks to share common setup or constraints between actions.
|
||||||
def set_table
|
def set_table
|
||||||
@table = Table.find(params[:id])
|
# @table = Table.find(params[:id])
|
||||||
|
@table = Table.friendly.find(params[:id])
|
||||||
|
@game = @table.current_game
|
||||||
|
@seats = @table.seats.order(:id)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Never trust parameters from the scary internet, only allow the white list through.
|
# Never trust parameters from the scary internet, only allow the white list through.
|
||||||
def table_params
|
def table_params
|
||||||
params.require(:table).permit(:title)
|
params.require(:table).permit(:title, :token_id)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
135
app/controllers/tokens_controller.rb
Normal file
@ -0,0 +1,135 @@
|
|||||||
|
class TokensController < ApplicationController
|
||||||
|
before_action :set_token, only: %i[ show edit update destroy refresh launch]
|
||||||
|
|
||||||
|
# GET /tokens or /tokens.json
|
||||||
|
def index
|
||||||
|
authorize @tokens = Token.all
|
||||||
|
@mytokens = Token.where(ownable_id: current_user.soft_token)
|
||||||
|
end
|
||||||
|
|
||||||
|
# GET /tokens/1 or /tokens/1.json
|
||||||
|
def show
|
||||||
|
authorize @token
|
||||||
|
end
|
||||||
|
|
||||||
|
# GET /tokens/new
|
||||||
|
def new
|
||||||
|
authorize @token = Token.new(ownable_id: current_user.soft_token)
|
||||||
|
end
|
||||||
|
|
||||||
|
def add_existing
|
||||||
|
authorize @token = Token.new
|
||||||
|
end
|
||||||
|
|
||||||
|
# GET /tokens/1/edit
|
||||||
|
def edit
|
||||||
|
authorize @token
|
||||||
|
end
|
||||||
|
|
||||||
|
def launch
|
||||||
|
authorize @token
|
||||||
|
redirect_to @token, notice: "Launch function coming soon!"
|
||||||
|
end
|
||||||
|
|
||||||
|
def refresh
|
||||||
|
authorize @token
|
||||||
|
# if call icrc1_metadata #icrc1
|
||||||
|
metadata = `dfx canister --network ic call #{@token.canister_id} icrc1_metadata 2>&1`
|
||||||
|
if metadata.scan(/no update method/).present?
|
||||||
|
# TODO: Use getTokenInfo instead of getMetadata
|
||||||
|
metadata = `dfx canister --network ic call #{@token.canister_id} getMetadata 2>&1`
|
||||||
|
if metadata.scan(/no update method/).present?
|
||||||
|
@token.standard = :unknown
|
||||||
|
else
|
||||||
|
@token.standard = :dip20
|
||||||
|
|
||||||
|
# TODO: Use getTokenInfo instead of getMetadata
|
||||||
|
tokenInfo = `dfx canister --network ic call #{@token.canister_id} getTokenInfo 2>&1`
|
||||||
|
@token.holder_number = tokenInfo.lines[2].split[2]
|
||||||
|
|
||||||
|
@token.transfer_fee = metadata.lines[2].split[2].to_i
|
||||||
|
@token.decimals = metadata.lines[3].split[2]
|
||||||
|
# @token.owner = metadata.lines[4].split[3]
|
||||||
|
# @token.logo_url = metadata.lines[5].split("\"")[1]
|
||||||
|
@token.logo_url = tokenInfo.lines[8].split[2].split('"')[1]
|
||||||
|
@token.name = metadata.lines[6].split("\"")[1]
|
||||||
|
@token.total_supply = metadata.lines[7].split[2].to_i/(10.0**@token.decimals)
|
||||||
|
@token.symbol = metadata.lines[8].split("\"")[1]
|
||||||
|
end
|
||||||
|
else
|
||||||
|
@token.standard = :icrc1
|
||||||
|
@token.transfer_fee = metadata.lines[2].split[7].to_i
|
||||||
|
@token.decimals = metadata.lines[5].split[7].to_i
|
||||||
|
begin
|
||||||
|
@token.logo_url = metadata.lines[9].split("\"")[1]
|
||||||
|
rescue
|
||||||
|
end
|
||||||
|
@token.name = metadata.lines[3].split("\"")[3]
|
||||||
|
total_supply = `dfx canister --network ic call #{@token.canister_id} icrc1_total_supply 2>&1`
|
||||||
|
@token.total_supply = total_supply.split[0][1..-1].to_i/(10.0**@token.decimals)
|
||||||
|
@token.symbol = metadata.lines[4].split("\"")[3]
|
||||||
|
end
|
||||||
|
# elsif call getMetadata #dip20
|
||||||
|
respond_to do |format|
|
||||||
|
if @token.save
|
||||||
|
format.html { redirect_to token_url(@token), notice: "Token was successfully refreshed." }
|
||||||
|
format.json { render :show, status: :created, location: @token }
|
||||||
|
else
|
||||||
|
format.html { render :new, status: :unprocessable_entity }
|
||||||
|
format.json { render json: @token.errors, status: :unprocessable_entity }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# POST /tokens or /tokens.json
|
||||||
|
def create
|
||||||
|
authorize @token = Token.new(token_params)
|
||||||
|
@token.canister_id = nil if @token.canister_id.blank?
|
||||||
|
respond_to do |format|
|
||||||
|
if @token.save
|
||||||
|
format.html { redirect_to (request.referrer.split("/")[-1].match("add_existing") ? refresh_token_url(@token) : @token), notice: "Token was successfully created." }
|
||||||
|
format.json { render :show, status: :created, location: @token }
|
||||||
|
else
|
||||||
|
format.html { render (request.referrer.split("/")[-1].match("add_existing") ? :add_existing : :new), status: :unprocessable_entity }
|
||||||
|
format.json { render json: @token.errors, status: :unprocessable_entity }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# PATCH/PUT /tokens/1 or /tokens/1.json
|
||||||
|
def update
|
||||||
|
authorize @token
|
||||||
|
@token.canister_id = nil if @token.canister_id.blank?
|
||||||
|
respond_to do |format|
|
||||||
|
if @token.update(token_params)
|
||||||
|
format.html { redirect_to token_url(@token), notice: "Token was successfully updated." }
|
||||||
|
format.json { render :show, status: :ok, location: @token }
|
||||||
|
else
|
||||||
|
format.html { render :edit, status: :unprocessable_entity }
|
||||||
|
format.json { render json: @token.errors, status: :unprocessable_entity }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# DELETE /tokens/1 or /tokens/1.json
|
||||||
|
def destroy
|
||||||
|
authorize @token
|
||||||
|
@token.destroy
|
||||||
|
|
||||||
|
respond_to do |format|
|
||||||
|
format.html { redirect_to tokens_url, notice: "Token was successfully destroyed." }
|
||||||
|
format.json { head :no_content }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
# Use callbacks to share common setup or constraints between actions.
|
||||||
|
def set_token
|
||||||
|
@token = Token.find(params[:id])
|
||||||
|
end
|
||||||
|
|
||||||
|
# Only allow a list of trusted parameters through.
|
||||||
|
def token_params
|
||||||
|
params.require(:token).permit(:canister_id, :standard, :symbol, :name, :total_supply, :decimals, :transfer_fee, :logo_url, :ownable_id)
|
||||||
|
end
|
||||||
|
end
|
||||||
@ -40,7 +40,7 @@ class Users::RegistrationsController < Devise::RegistrationsController
|
|||||||
|
|
||||||
# If you have extra params to permit, append them to the sanitizer.
|
# If you have extra params to permit, append them to the sanitizer.
|
||||||
def configure_sign_up_params
|
def configure_sign_up_params
|
||||||
devise_parameter_sanitizer.for(:sign_up) << :soft_token
|
devise_parameter_sanitizer.permit(:sign_up, keys: [:soft_token])
|
||||||
end
|
end
|
||||||
|
|
||||||
# If you have extra params to permit, append them to the sanitizer.
|
# If you have extra params to permit, append them to the sanitizer.
|
||||||
|
|||||||
@ -3,15 +3,28 @@ class UsersController < ApplicationController
|
|||||||
after_action :verify_authorized
|
after_action :verify_authorized
|
||||||
|
|
||||||
def index
|
def index
|
||||||
@users = User.all
|
@users = policy_scope User.all
|
||||||
authorize User
|
authorize @users
|
||||||
end
|
end
|
||||||
|
|
||||||
def show
|
def show
|
||||||
@user = User.find(params[:id])
|
@user ||= User.find(params[:id])
|
||||||
|
@micropost = current_user.microposts.build if current_user.signed_in?
|
||||||
|
@microposts = @user.microposts.paginate(page: params[:page])
|
||||||
authorize @user
|
authorize @user
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def home
|
||||||
|
authorize current_user
|
||||||
|
@user = current_user
|
||||||
|
@micropost = current_user.microposts.build if current_user.signed_in?
|
||||||
|
@microposts = @user.microposts.paginate(page: params[:page])
|
||||||
|
@feed_items = current_user.feed.paginate(page: params[:page], per_page: 10)
|
||||||
|
# authorize @user
|
||||||
|
# redirect_to current_user
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
def update
|
def update
|
||||||
@user = User.find(params[:id])
|
@user = User.find(params[:id])
|
||||||
authorize @user
|
authorize @user
|
||||||
|
|||||||
16
app/controllers/video_rooms_controller.rb
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
class VideoRoomsController < ApplicationController
|
||||||
|
before_action :skip_authorization
|
||||||
|
|
||||||
|
def new
|
||||||
|
end
|
||||||
|
|
||||||
|
def create
|
||||||
|
redirect_to room_path(SecureRandom.uuid)
|
||||||
|
end
|
||||||
|
|
||||||
|
def show
|
||||||
|
@client = Client.new(id: SecureRandom.uuid)
|
||||||
|
cookies.encrypted[:client_id] = @client.id
|
||||||
|
@video_room = VideoRoom.new(id: params[:id])
|
||||||
|
end
|
||||||
|
end
|
||||||
@ -1,2 +1,14 @@
|
|||||||
class VisitorsController < ApplicationController
|
class VisitorsController < ApplicationController
|
||||||
|
before_action :skip_authorization
|
||||||
|
|
||||||
|
def index
|
||||||
|
@doodads = authorize policy_scope(Doodad)
|
||||||
|
# todo Canister feature
|
||||||
|
# @canisters = authorize Canister.all
|
||||||
|
@feed_items = current_user.feed.paginate(page: params[:page])
|
||||||
|
end
|
||||||
|
|
||||||
|
def games_index
|
||||||
|
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@ -1,2 +1,106 @@
|
|||||||
module ApplicationHelper
|
module ApplicationHelper
|
||||||
|
def body_css_class
|
||||||
|
@body_css_classes ||= []
|
||||||
|
# view_css_class = [controller_path.split('/'), action_name, 'view'].flatten.join('-')
|
||||||
|
view_css_class = [controller_path.split('/'), action_name, 'view'].flatten[0] + "-view"
|
||||||
|
@body_css_classes.unshift(view_css_class).join(' ')
|
||||||
|
end
|
||||||
|
|
||||||
|
def currency_balance(principal, currency_symbol, dfx_id = nil)
|
||||||
|
canisters = {
|
||||||
|
ICYPEES: "es3he-kyaaa-aaaah-abzna-cai",
|
||||||
|
EVL: "7wqow-haaaa-aaaao-ahbpq-cai",
|
||||||
|
"SNS-1": "zfcdd-tqaaa-aaaaq-aaaga-cai",
|
||||||
|
TENDY: "72uqs-pqaaa-aaaak-aes7a-cai",
|
||||||
|
YC: "5gxp5-jyaaa-aaaag-qarma-cai",
|
||||||
|
CZECH: "fkhzl-saaaa-aaaan-qd26a-cai",
|
||||||
|
ICL: "5573k-xaaaa-aaaak-aacnq-cai",
|
||||||
|
OT: "imeri-bqaaa-aaaai-qnpla-cai",
|
||||||
|
"01": "6ohjj-4qaaa-aaaai-aapua-cai",
|
||||||
|
BABYAROFdip20: "iy6hh-xaaaa-aaaan-qauza-cai"}
|
||||||
|
multipliers = {
|
||||||
|
TENDY: 100000000,
|
||||||
|
ICYPEES: 100000000,
|
||||||
|
CZECH: 100000000,
|
||||||
|
OT: 100000000,
|
||||||
|
EVL: 100000000,
|
||||||
|
"SNS-1": 100000000,
|
||||||
|
ICL: 100000000,
|
||||||
|
"01": 100000,
|
||||||
|
BABYAROFDIP20: 100000000
|
||||||
|
}
|
||||||
|
begin
|
||||||
|
# if currency_symbol == "ICL"
|
||||||
|
# binding.pry
|
||||||
|
# end
|
||||||
|
if ["SNS-1"].any?{ |s| s.casecmp(currency_symbol)==0 }
|
||||||
|
wallet_currency_balance = `dfx canister --network ic call #{canisters[:"#{currency_symbol}"]} #{currency_symbol == "SNS-1" ? "icrc1_balance_of" : "balanceOf"} '(record { owner = principal "#{principal}"})'`.gsub("_","").match(/\d+/)[0].to_f/(multipliers[:"#{currency_symbol}"])
|
||||||
|
elsif ["BTC"].any?{ |s| s.casecmp(currency_symbol)==0 }
|
||||||
|
puts "BTC"
|
||||||
|
`bitcoin-core.cli loadwallet #{dfx_id}`
|
||||||
|
wallet_currency_balance = `bitcoin-core.cli getbalance`.strip
|
||||||
|
if wallet_currency_balance.to_s.empty?
|
||||||
|
`bitcoin-core.cli createwallet "#{dfx_id}"`
|
||||||
|
`bitcoin-core.cli loadwallet #{dfx_id}`
|
||||||
|
end
|
||||||
|
wallet_currency_balance = `bitcoin-core.cli getbalance`.strip
|
||||||
|
`bitcoin-core.cli unloadwallet #{dfx_id}`
|
||||||
|
elsif ["testBTC"].any?{ |s| s.casecmp(currency_symbol)==0 }
|
||||||
|
puts "testBTC"
|
||||||
|
`bitcoin-core.cli loadwallet #{dfx_id}`
|
||||||
|
wallet_currency_balance = `bitcoin-core.cli -testnet getbalance`.strip
|
||||||
|
if wallet_currency_balance.to_s.empty?
|
||||||
|
`bitcoin-core.cli -testnet createwallet "#{dfx_id}"`
|
||||||
|
end
|
||||||
|
`bitcoin-core.cli -testnet loadwallet #{dfx_id}`
|
||||||
|
wallet_currency_balance = `bitcoin-core.cli -testnet getbalance`.strip
|
||||||
|
`bitcoin-core.cli -testnet unloadwallet #{dfx_id}`
|
||||||
|
elsif ["ICP"].any?{ |s| s.casecmp(currency_symbol)==0 }
|
||||||
|
wallet_currency_balance = icp_balance(dfx_id)
|
||||||
|
elsif ["ETH"].any?{ |s| s.casecmp(currency_symbol)==0 }
|
||||||
|
wallet_currency_balance = `eth address:balance -n mainnet #{dfx_id}`.strip
|
||||||
|
if wallet_currency_balance.empty?
|
||||||
|
new_address = JSON.parse `eth address:random`
|
||||||
|
`eth address:add #{dfx_id} #{new_address["privateKey"]}`
|
||||||
|
wallet_currency_balance = `eth address:balance -n mainnet #{dfx_id}`.strip
|
||||||
|
end
|
||||||
|
elsif ["goerliBaseETH"].any?{ |s| s.casecmp(currency_symbol)==0 }
|
||||||
|
wallet_currency_balance = `eth address:balance -n goerliBase #{dfx_id}`.strip
|
||||||
|
if wallet_currency_balance.empty?
|
||||||
|
new_address = JSON.parse `eth address:random`
|
||||||
|
`eth address:add #{dfx_id} #{new_address["privateKey"]}`
|
||||||
|
wallet_currency_balance = `eth address:balance -n goerliBase #{dfx_id}`.strip
|
||||||
|
end
|
||||||
|
elsif ["goerliETH"].any?{ |s| s.casecmp(currency_symbol)==0 }
|
||||||
|
wallet_currency_balance = `eth address:balance -n goerli #{dfx_id}`.strip
|
||||||
|
if wallet_currency_balance.empty?
|
||||||
|
new_address = JSON.parse `eth address:random`
|
||||||
|
`eth address:add #{dfx_id} #{new_address["privateKey"]}`
|
||||||
|
wallet_currency_balance = `eth address:balance -n goerli #{dfx_id}`.strip
|
||||||
|
end
|
||||||
|
elsif ["sepETH"].any?{ |s| s.casecmp(currency_symbol)==0 }
|
||||||
|
wallet_currency_balance = `eth address:balance -n sep #{dfx_id}`.strip
|
||||||
|
if wallet_currency_balance.empty?
|
||||||
|
new_address = JSON.parse `eth address:random`
|
||||||
|
`eth address:add #{dfx_id} #{new_address["privateKey"]}`
|
||||||
|
wallet_currency_balance = `eth address:balance -n sep #{dfx_id}`.strip
|
||||||
|
end
|
||||||
|
elsif canisters.keys.map{|k| k.to_s}.any?{ |s| s.casecmp(currency_symbol)==0 }
|
||||||
|
# binding.pry
|
||||||
|
wallet_currency_balance = `dfx canister --network ic call #{canisters[:"#{currency_symbol.upcase}"]} balanceOf '(principal "#{principal}")'`.gsub("_","").match(/\d+/)[0].to_f/(multipliers[:"#{currency_symbol.upcase}"])
|
||||||
|
else
|
||||||
|
return "Currency not found"
|
||||||
|
end
|
||||||
|
rescue
|
||||||
|
return "Error fetching balance"
|
||||||
|
end
|
||||||
|
if wallet_currency_balance.to_s.empty?
|
||||||
|
return "Error fetching "
|
||||||
|
else
|
||||||
|
return wallet_currency_balance
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|||||||
2
app/helpers/bots_helper.rb
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
module BotsHelper
|
||||||
|
end
|
||||||
2
app/helpers/calls_helper.rb
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
module CallsHelper
|
||||||
|
end
|
||||||
2
app/helpers/canisters_helper.rb
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
module CanistersHelper
|
||||||
|
end
|
||||||
2
app/helpers/commands_helper.rb
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
module CommandsHelper
|
||||||
|
end
|
||||||
2
app/helpers/doodads_helper.rb
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
module DoodadsHelper
|
||||||
|
end
|
||||||
2
app/helpers/metapurses_helper.rb
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
module MetapursesHelper
|
||||||
|
end
|
||||||
2
app/helpers/microposts_helper.rb
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
module MicropostsHelper
|
||||||
|
end
|
||||||
2
app/helpers/pages_helper.rb
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
module PagesHelper
|
||||||
|
end
|
||||||
2
app/helpers/profiles_helper.rb
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
module ProfilesHelper
|
||||||
|
end
|
||||||