diff --git a/.browserslistrc b/.browserslistrc new file mode 100644 index 0000000..e94f814 --- /dev/null +++ b/.browserslistrc @@ -0,0 +1 @@ +defaults diff --git a/.env.example b/.env.example index cdff096..183f06f 100644 --- a/.env.example +++ b/.env.example @@ -1,17 +1,15 @@ -# Twilio API credentials -# Found at https://www.twilio.com/console/account/settings -export TWILIO_ACCOUNT_SID=ACXXXXXXXXXXXXXXXXXXXXXX -export TWILIO_AUTH_TOKEN=your-token - -# Twilio phone number -# Purchase one at https://www.twilio.com/console/phone-numbers/incoming -export TWILIO_NUMBER=+15551234567 +# Your Twilio Account SID. Get a free account at twilio.com/try-twilio +TWILIO_ACCOUNT_SID=your_twilio_account_SID +# Your Twilio Auth Token. You can get it at twilio.com/console +TWILIO_AUTH_TOKEN=your_twilio_auth_token +# The Twilio phone number you want to use to send SMS. Get one in the Twilio Console +TWILIO_PHONE_NUMBER=your_twilio_phone_number # Application Configuration -export EVENT_CALLBACK_URL="https://subdomain.ngrok.io/events" -export ASSIGNMENT_CALLBACK_URL="https://subdomain.ngrok.io/assignment" -export WORKFLOW_TIMEOUT=15 -export QUEUE_TIMEOUT=30 -export BOB_NUMBER=+15551234567 -export ALICE_NUMBER=+15551234568 -export MISSED_CALLS_EMAIL_ADDRESS=you@something.com +EVENT_CALLBACK_URL="https://subdomain.ngrok.io/events" +ASSIGNMENT_CALLBACK_URL="https://subdomain.ngrok.io/assignment" +QUEUE_TIMEOUT=30 +WORKFLOW_TIMEOUT=15 +BOB_NUMBER=+15551234567 +ALICE_NUMBER=+15551234568 +MISSED_CALLS_EMAIL_ADDRESS=you@something.com diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..b668c08 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,8 @@ +# See https://git-scm.com/docs/gitattributes for more about git attribute files. + + +# Mark the yarn lockfile as having been generated. +yarn.lock linguist-generated + +# Mark any vendored files as having been vendored. +vendor/* linguist-vendored diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..3cb0750 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,70 @@ +name: build + +on: + push: + branches: [ main ] + pull_request: + branches: [ main ] + +jobs: + build: + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [ubuntu-latest, macos-latest] + + steps: + - name: Checkout code + uses: actions/checkout@v2 + - name: Install SQLite (Ubuntu) + if: runner.os == 'Linux' + run: sudo apt-get update && sudo apt-get install -yqq libsqlite3-dev + - name: Install SQLite (OSX) + if: runner.os == 'macOs' + run: brew install sqlite3 + - name: Install SQLite (Windows) + if: runner.os == 'Windows' + uses: crazy-max/ghaction-chocolatey@v1 + with: + args: install sqlite + - name: Setup Ruby + uses: ruby/setup-ruby@v1 + with: + bundler-cache: false + ruby-version: '3.0' + - name: Install SQLite gem (Windows) + if: runner.os == 'Windows' + run: gem install sqlite3 --platform=ruby -- --with-sqlite3-include=/c:/ProgramData/ProgramData/lib/SQLite/tools + - name: Install gems + run: | + gem install bundler + bundle config path vendor/bundle + bundle install --jobs 4 --retry 3 + - name: Setup Node + uses: actions/setup-node@v1 + with: + node-version: 14.15.4 + - name: Find yarn cache location + id: yarn-cache + run: echo "::set-output name=dir::$(yarn cache dir)" + - name: JS package cache + uses: actions/cache@v1 + with: + path: ${{ steps.yarn-cache.outputs.dir }} + key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }} + restore-keys: | + ${{ runner.os }}-yarn- + - name: Install packages + run: | + yarn install --pure-lockfile + - name: Run tests + run: | + cp .env.example .env + bundle exec rspec + env: + RAILS_ENV: test + TWILIO_ACCOUNT_SID: ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX + TWILIO_AUTH_TOKEN: TWILIOAUTHTOKEN00000 + TWILIO_NUMBER: +12345555555 + BOB_NUMBER: +1234567823 + ALICE_NUMBER: +1234567000 diff --git a/.gitignore b/.gitignore index cad61db..ad3dcb9 100644 --- a/.gitignore +++ b/.gitignore @@ -10,10 +10,33 @@ # Ignore the default SQLite database. /db/*.sqlite3 /db/*.sqlite3-journal +/db/*.sqlite3-* # Ignore all logfiles and tempfiles. /log/* +/tmp/* !/log/.keep -/tmp +!/tmp/.keep +# Ignore uploaded files in development. +/storage/* +!/storage/.keep + +/public/assets +.byebug_history + +# Ignore master key for decrypting credentials and more. +/config/master.key + +/public/packs +/public/packs-test +/node_modules +/yarn-error.log +yarn-debug.log* +.yarn-integrity + +/vendor .env +.env.test + +/.vscode diff --git a/.mergify.yml b/.mergify.yml new file mode 100644 index 0000000..46ab742 --- /dev/null +++ b/.mergify.yml @@ -0,0 +1,8 @@ +pull_request_rules: + - name: automatic merge for Dependabot pull requests + conditions: + - author~=^dependabot(|-preview)\[bot\]$ + - status-success=build + actions: + merge: + method: squash diff --git a/.nvmrc b/.nvmrc new file mode 100644 index 0000000..9a0c3d3 --- /dev/null +++ b/.nvmrc @@ -0,0 +1 @@ +v14.15.4 diff --git a/.rspec b/.rspec index 83e16f8..43ae203 100644 --- a/.rspec +++ b/.rspec @@ -1,2 +1,3 @@ --color --require spec_helper +--format documentation diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 6cff49b..0000000 --- a/.travis.yml +++ /dev/null @@ -1,15 +0,0 @@ -language: ruby -rvm: - - rvm 2.2.1 - - rvm 2.2.2 - -install: - - bundle - -env: - global: - - TWILIO_ACCOUNT_SID=ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX - - TWILIO_AUTH_TOKEN=TWILIOAUTHTOKEN00000 - - TWILIO_NUMBER=+12345555555 - - BOB_NUMBER=+1234567823 - - ALICE_NUMBER=+1234567000 diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..2f0727e --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,73 @@ +# Contributor Covenant Code of Conduct + +## Our Pledge + +In the interest of fostering an open and welcoming environment, we as +contributors and maintainers pledge to making participation in our project and +our community a harassment-free experience for everyone, regardless of age, body +size, disability, ethnicity, sex characteristics, gender identity and expression, +level of experience, education, socio-economic status, nationality, personal +appearance, race, religion, or sexual identity and orientation. + +## Our Standards + +Examples of behavior that contributes to creating a positive environment +include: + +- Using welcoming and inclusive language +- Being respectful of differing viewpoints and experiences +- Gracefully accepting constructive criticism +- Focusing on what is best for the community +- Showing empathy towards other community members + +Examples of unacceptable behavior by participants include: + +- The use of sexualized language or imagery and unwelcome sexual attention or + advances +- Trolling, insulting/derogatory comments, and personal or political attacks +- Public or private harassment +- Publishing others' private information, such as a physical or electronic + address, without explicit permission +- Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Our Responsibilities + +Project maintainers are responsible for clarifying the standards of acceptable +behavior and are expected to take appropriate and fair corrective action in +response to any instances of unacceptable behavior. + +Project maintainers have the right and responsibility to remove, edit, or +reject comments, commits, code, wiki edits, issues, and other contributions +that are not aligned to this Code of Conduct, or to ban temporarily or +permanently any contributor for other behaviors that they deem inappropriate, +threatening, offensive, or harmful. + +## Scope + +This Code of Conduct applies both within project spaces and in public spaces +when an individual is representing the project or its community. Examples of +representing a project or community include using an official project e-mail +address, posting via an official social media account, or acting as an appointed +representative at an online or offline event. Representation of a project may be +further defined and clarified by project maintainers. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported by contacting the project team at open-source@twilio.com. All +complaints will be reviewed and investigated and will result in a response that +is deemed necessary and appropriate to the circumstances. The project team is +obligated to maintain confidentiality with regard to the reporter of an incident. +Further details of specific enforcement policies may be posted separately. + +Project maintainers who do not follow or enforce the Code of Conduct in good +faith may face temporary or permanent repercussions as determined by other +members of the project's leadership. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, +available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html + +[homepage]: https://www.contributor-covenant.org diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..ad3257e --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,3 @@ +# Contributing to Twilio + +All third party contributors acknowledge that any contributions they provide will be made under the same open source license that the open source project is provided under. diff --git a/Gemfile b/Gemfile index 4224132..ee4560f 100644 --- a/Gemfile +++ b/Gemfile @@ -1,20 +1,52 @@ source 'https://rubygems.org' +git_source(:github) { |repo| "https://github.com/#{repo}.git" } -gem 'rails', '4.2.6' -gem 'sqlite3' -gem 'uglifier', '>= 1.3.0' -gem 'jquery-rails' -gem 'turbolinks' -gem 'twilio-ruby', '>= 5.0.0' +ruby '~> 3.0' -group :test do +# Bundle edge Rails instead: gem 'rails', github: 'rails/rails' +gem 'rails', '~> 6.1.1' +# Use sqlite3 as the database for Active Record +gem 'sqlite3', '~> 1.4' +# Use Puma as the app server +gem 'puma', '~> 5.0' +# Transpile app-like JavaScript. Read more: https://github.com/rails/webpacker +gem 'webpacker', '~> 5.0' +# Turbolinks makes navigating your web application faster. Read more: https://github.com/turbolinks/turbolinks +gem 'turbolinks', '~> 5' +# Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder +gem 'jbuilder', '~> 2.7' +# Use Active Model has_secure_password +# gem 'bcrypt', '~> 3.1.7' + +# Reduces boot times through caching; required in config/boot.rb +gem 'bootsnap', '>= 1.4.4', require: false + +group :development, :test do + # Call 'byebug' anywhere in the code to stop execution and get a debugger console + gem 'byebug', platforms: [:mri, :mingw, :x64_mingw] gem 'rspec-rails' - gem 'pry' - gem 'vcr' - gem 'webmock' - gem 'byebug' + gem 'dotenv-rails' end group :development do - gem 'web-console', '~> 2.0' + # Access an interactive console on exception pages or by calling 'console' anywhere in the code. + gem 'web-console', '>= 4.1.0' + # Display performance information such as SQL time and flame graphs for each request in your browser. + # Can be configured to work on production as well see: https://github.com/MiniProfiler/rack-mini-profiler/blob/master/README.md + gem 'rack-mini-profiler', '~> 2.0' + gem 'listen', '~> 3.3' + # Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring + gem 'spring' end + +group :test do + gem 'rails-controller-testing' + gem 'webdrivers' + gem 'webmock' + gem 'vcr' +end + +# Windows does not include zoneinfo files, so bundle the tzinfo-data gem +gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby] +gem "twilio-ruby", "~> 5.46" +gem "bootstrap", "~> 4.5" diff --git a/Gemfile.lock b/Gemfile.lock index 1e6e9cb..2fc665e 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,188 +1,286 @@ GEM remote: https://rubygems.org/ specs: - actionmailer (4.2.6) - actionpack (= 4.2.6) - actionview (= 4.2.6) - activejob (= 4.2.6) + actioncable (6.1.1) + actionpack (= 6.1.1) + activesupport (= 6.1.1) + nio4r (~> 2.0) + websocket-driver (>= 0.6.1) + actionmailbox (6.1.1) + actionpack (= 6.1.1) + activejob (= 6.1.1) + activerecord (= 6.1.1) + activestorage (= 6.1.1) + activesupport (= 6.1.1) + mail (>= 2.7.1) + actionmailer (6.1.1) + actionpack (= 6.1.1) + actionview (= 6.1.1) + activejob (= 6.1.1) + activesupport (= 6.1.1) mail (~> 2.5, >= 2.5.4) - rails-dom-testing (~> 1.0, >= 1.0.5) - actionpack (4.2.6) - actionview (= 4.2.6) - activesupport (= 4.2.6) - rack (~> 1.6) - rack-test (~> 0.6.2) - rails-dom-testing (~> 1.0, >= 1.0.5) - rails-html-sanitizer (~> 1.0, >= 1.0.2) - actionview (4.2.6) - activesupport (= 4.2.6) + rails-dom-testing (~> 2.0) + actionpack (6.1.1) + actionview (= 6.1.1) + activesupport (= 6.1.1) + rack (~> 2.0, >= 2.0.9) + rack-test (>= 0.6.3) + rails-dom-testing (~> 2.0) + rails-html-sanitizer (~> 1.0, >= 1.2.0) + actiontext (6.1.1) + actionpack (= 6.1.1) + activerecord (= 6.1.1) + activestorage (= 6.1.1) + activesupport (= 6.1.1) + nokogiri (>= 1.8.5) + actionview (6.1.1) + activesupport (= 6.1.1) builder (~> 3.1) - erubis (~> 2.7.0) - rails-dom-testing (~> 1.0, >= 1.0.5) - rails-html-sanitizer (~> 1.0, >= 1.0.2) - activejob (4.2.6) - activesupport (= 4.2.6) - globalid (>= 0.3.0) - activemodel (4.2.6) - activesupport (= 4.2.6) - builder (~> 3.1) - activerecord (4.2.6) - activemodel (= 4.2.6) - activesupport (= 4.2.6) - arel (~> 6.0) - activesupport (4.2.6) - i18n (~> 0.7) - json (~> 1.7, >= 1.7.7) - minitest (~> 5.1) - thread_safe (~> 0.3, >= 0.3.4) - tzinfo (~> 1.1) - addressable (2.4.0) - arel (6.0.3) - binding_of_caller (0.7.2) - debug_inspector (>= 0.0.1) - builder (3.2.2) - byebug (9.0.6) - coderay (1.1.1) - coffee-rails (4.1.1) - coffee-script (>= 2.2.0) - railties (>= 4.0.0, < 5.1.x) - coffee-script (2.4.1) - coffee-script-source + erubi (~> 1.4) + rails-dom-testing (~> 2.0) + rails-html-sanitizer (~> 1.1, >= 1.2.0) + activejob (6.1.1) + activesupport (= 6.1.1) + globalid (>= 0.3.6) + activemodel (6.1.1) + activesupport (= 6.1.1) + activerecord (6.1.1) + activemodel (= 6.1.1) + activesupport (= 6.1.1) + activestorage (6.1.1) + actionpack (= 6.1.1) + activejob (= 6.1.1) + activerecord (= 6.1.1) + activesupport (= 6.1.1) + marcel (~> 0.3.1) + mimemagic (~> 0.3.2) + activesupport (6.1.1) + concurrent-ruby (~> 1.0, >= 1.0.2) + i18n (>= 1.6, < 2) + minitest (>= 5.1) + tzinfo (~> 2.0) + zeitwerk (~> 2.3) + addressable (2.7.0) + public_suffix (>= 2.0.2, < 5.0) + autoprefixer-rails (10.2.0.0) execjs - coffee-script-source (1.10.0) - concurrent-ruby (1.0.2) - crack (0.4.2) - safe_yaml (~> 1.0.0) - debug_inspector (0.0.2) - diff-lcs (1.2.5) - erubis (2.7.0) + bindex (0.8.1) + bootsnap (1.5.1) + msgpack (~> 1.0) + bootstrap (4.5.3) + autoprefixer-rails (>= 9.1.0) + popper_js (>= 1.14.3, < 2) + sassc-rails (>= 2.0.0) + builder (3.2.4) + byebug (11.1.3) + childprocess (3.0.0) + concurrent-ruby (1.1.8) + crack (0.4.5) + rexml + crass (1.0.6) + diff-lcs (1.4.4) + dotenv (2.7.6) + dotenv-rails (2.7.6) + dotenv (= 2.7.6) + railties (>= 3.2) + erubi (1.10.0) execjs (2.7.0) - faraday (0.12.1) + faraday (1.3.0) + faraday-net_http (~> 1.0) multipart-post (>= 1.2, < 3) - globalid (0.3.6) - activesupport (>= 4.1.0) - hashdiff (0.2.3) - i18n (0.7.0) - jquery-rails (4.1.1) - rails-dom-testing (>= 1, < 3) - railties (>= 4.2.0) - thor (>= 0.14, < 2.0) - json (1.8.3) - jwt (1.5.6) - libxml-ruby (3.0.0) - loofah (2.0.3) + ruby2_keywords + faraday-net_http (1.0.1) + ffi (1.14.2) + ffi (1.14.2-x64-mingw32) + globalid (0.4.2) + activesupport (>= 4.2.0) + hashdiff (1.0.1) + i18n (1.8.7) + concurrent-ruby (~> 1.0) + jbuilder (2.10.1) + activesupport (>= 5.0.0) + jwt (2.2.2) + listen (3.4.1) + rb-fsevent (~> 0.10, >= 0.10.3) + rb-inotify (~> 0.9, >= 0.9.10) + loofah (2.9.0) + crass (~> 1.0.2) nokogiri (>= 1.5.9) - mail (2.6.4) - mime-types (>= 1.16, < 4) - method_source (0.8.2) - mime-types (3.1) - mime-types-data (~> 3.2015) - mime-types-data (3.2016.0521) - mini_portile2 (2.1.0) - minitest (5.9.0) - multipart-post (2.0.0) - nokogiri (1.6.8) - mini_portile2 (~> 2.1.0) - pkg-config (~> 1.1.7) - pkg-config (1.1.7) - pry (0.10.3) - coderay (~> 1.1.0) - method_source (~> 0.8.1) - slop (~> 3.4) - rack (1.6.4) - rack-test (0.6.3) - rack (>= 1.0) - rails (4.2.6) - actionmailer (= 4.2.6) - actionpack (= 4.2.6) - actionview (= 4.2.6) - activejob (= 4.2.6) - activemodel (= 4.2.6) - activerecord (= 4.2.6) - activesupport (= 4.2.6) - bundler (>= 1.3.0, < 2.0) - railties (= 4.2.6) - sprockets-rails - rails-deprecated_sanitizer (1.0.3) - activesupport (>= 4.2.0.alpha) - rails-dom-testing (1.0.7) - activesupport (>= 4.2.0.beta, < 5.0) - nokogiri (~> 1.6.0) - rails-deprecated_sanitizer (>= 1.0.1) - rails-html-sanitizer (1.0.3) - loofah (~> 2.0) - railties (4.2.6) - actionpack (= 4.2.6) - activesupport (= 4.2.6) + mail (2.7.1) + mini_mime (>= 0.1.1) + marcel (0.3.3) + mimemagic (~> 0.3.2) + method_source (1.0.0) + mimemagic (0.3.5) + mini_mime (1.0.2) + minitest (5.14.3) + msgpack (1.3.3) + multipart-post (2.1.1) + nio4r (2.5.4) + nokogiri (1.11.1-arm64-darwin) + racc (~> 1.4) + nokogiri (1.11.1-x64-mingw32) + racc (~> 1.4) + nokogiri (1.11.1-x86_64-darwin) + racc (~> 1.4) + nokogiri (1.11.1-x86_64-linux) + racc (~> 1.4) + popper_js (1.16.0) + public_suffix (4.0.6) + puma (5.1.1) + nio4r (~> 2.0) + racc (1.5.2) + rack (2.2.3) + rack-mini-profiler (2.3.0) + rack (>= 1.2.0) + rack-proxy (0.6.5) + rack + rack-test (1.1.0) + rack (>= 1.0, < 3) + rails (6.1.1) + actioncable (= 6.1.1) + actionmailbox (= 6.1.1) + actionmailer (= 6.1.1) + actionpack (= 6.1.1) + actiontext (= 6.1.1) + actionview (= 6.1.1) + activejob (= 6.1.1) + activemodel (= 6.1.1) + activerecord (= 6.1.1) + activestorage (= 6.1.1) + activesupport (= 6.1.1) + bundler (>= 1.15.0) + railties (= 6.1.1) + sprockets-rails (>= 2.0.0) + rails-controller-testing (1.0.5) + actionpack (>= 5.0.1.rc1) + actionview (>= 5.0.1.rc1) + activesupport (>= 5.0.1.rc1) + rails-dom-testing (2.0.3) + activesupport (>= 4.2.0) + nokogiri (>= 1.6) + rails-html-sanitizer (1.3.0) + loofah (~> 2.3) + railties (6.1.1) + actionpack (= 6.1.1) + activesupport (= 6.1.1) + method_source rake (>= 0.8.7) - thor (>= 0.18.1, < 2.0) - rake (11.2.2) - rspec-core (3.4.4) - rspec-support (~> 3.4.0) - rspec-expectations (3.4.0) + thor (~> 1.0) + rake (13.0.3) + rb-fsevent (0.10.4) + rb-inotify (0.10.1) + ffi (~> 1.0) + rexml (3.2.4) + rspec-core (3.10.1) + rspec-support (~> 3.10.0) + rspec-expectations (3.10.1) diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.4.0) - rspec-mocks (3.4.1) + rspec-support (~> 3.10.0) + rspec-mocks (3.10.1) diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.4.0) - rspec-rails (3.4.2) - actionpack (>= 3.0, < 4.3) - activesupport (>= 3.0, < 4.3) - railties (>= 3.0, < 4.3) - rspec-core (~> 3.4.0) - rspec-expectations (~> 3.4.0) - rspec-mocks (~> 3.4.0) - rspec-support (~> 3.4.0) - rspec-support (3.4.1) - safe_yaml (1.0.4) - slop (3.6.0) - sprockets (3.6.2) + rspec-support (~> 3.10.0) + rspec-rails (4.0.2) + actionpack (>= 4.2) + activesupport (>= 4.2) + railties (>= 4.2) + rspec-core (~> 3.10) + rspec-expectations (~> 3.10) + rspec-mocks (~> 3.10) + rspec-support (~> 3.10) + rspec-support (3.10.1) + ruby2_keywords (0.0.4) + rubyzip (2.3.0) + sassc (2.4.0) + ffi (~> 1.9) + sassc (2.4.0-x64-mingw32) + ffi (~> 1.9) + sassc-rails (2.1.2) + railties (>= 4.0.0) + sassc (>= 2.0) + sprockets (> 3.0) + sprockets-rails + tilt + selenium-webdriver (3.142.7) + childprocess (>= 0.5, < 4.0) + rubyzip (>= 1.2.2) + semantic_range (2.3.1) + spring (2.1.1) + sprockets (4.0.2) concurrent-ruby (~> 1.0) rack (> 1, < 3) - sprockets-rails (3.0.4) + sprockets-rails (3.2.2) actionpack (>= 4.0) activesupport (>= 4.0) sprockets (>= 3.0.0) - sqlite3 (1.3.11) - thor (0.19.1) - thread_safe (0.3.5) - turbolinks (2.5.3) - coffee-rails - twilio-ruby (5.0.0) - faraday (~> 0.9) - jwt (~> 1.5) - libxml-ruby (= 3.0.0) - tzinfo (1.2.2) - thread_safe (~> 0.1) - uglifier (3.0.0) - execjs (>= 0.3.0, < 3) - vcr (3.0.0) - web-console (2.3.0) - activemodel (>= 4.0) - binding_of_caller (>= 0.7.2) - railties (>= 4.0) - sprockets-rails (>= 2.0, < 4.0) - webmock (1.22.3) + sqlite3 (1.4.2) + thor (1.1.0) + tilt (2.0.10) + turbolinks (5.2.1) + turbolinks-source (~> 5.2) + turbolinks-source (5.2.0) + twilio-ruby (5.46.0) + faraday (>= 0.9, < 2.0) + jwt (>= 1.5, <= 2.5) + nokogiri (>= 1.6, < 2.0) + tzinfo (2.0.4) + concurrent-ruby (~> 1.0) + tzinfo-data (1.2020.6) + tzinfo (>= 1.0.0) + vcr (6.0.0) + web-console (4.1.0) + actionview (>= 6.0.0) + activemodel (>= 6.0.0) + bindex (>= 0.4.0) + railties (>= 6.0.0) + webdrivers (4.5.0) + nokogiri (~> 1.6) + rubyzip (>= 1.3.0) + selenium-webdriver (>= 3.0, < 4.0) + webmock (3.11.1) addressable (>= 2.3.6) crack (>= 0.3.2) - hashdiff + hashdiff (>= 0.4.0, < 2.0.0) + webpacker (5.2.1) + activesupport (>= 5.2) + rack-proxy (>= 0.6.1) + railties (>= 5.2) + semantic_range (>= 2.3.0) + websocket-driver (0.7.3) + websocket-extensions (>= 0.1.0) + websocket-extensions (0.1.5) + zeitwerk (2.4.2) PLATFORMS - ruby + universal-darwin-19 + x64-mingw32 + x86_64-linux DEPENDENCIES + bootsnap (>= 1.4.4) + bootstrap (~> 4.5) byebug - jquery-rails - pry - rails (= 4.2.6) + dotenv-rails + jbuilder (~> 2.7) + listen (~> 3.3) + puma (~> 5.0) + rack-mini-profiler (~> 2.0) + rails (~> 6.1.1) + rails-controller-testing rspec-rails - sqlite3 - turbolinks - twilio-ruby (>= 5.0.0) - uglifier (>= 1.3.0) + spring + sqlite3 (~> 1.4) + turbolinks (~> 5) + twilio-ruby (~> 5.46) + tzinfo-data vcr - web-console (~> 2.0) + web-console (>= 4.1.0) + webdrivers webmock + webpacker (~> 5.0) + +RUBY VERSION + ruby 3.0.0p0 BUNDLED WITH - 1.15.1 + 2.2.6 diff --git a/LICENSE b/LICENSE index a59f2c6..672e28f 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2016 TwilioDevEd +Copyright (c) 2021 Twilio Inc Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index 51e3025..0b63b4e 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,10 @@ - - Twilio + +Twilio - + # Task Router - Rails -[![Build Status](https://travis-ci.org/TwilioDevEd/task-router-rails.svg?branch=master)](https://travis-ci.org/TwilioDevEd/task-router-rails) +![](https://github.com/TwilioDevEd/task-router-rails/actions/workflows/build.yml/badge.svg) Give your customers specialized product support. Learn how to use TaskRouter to create a workflow that will redirect users to an appropriate sales agent, based @@ -12,7 +12,7 @@ on the product they select. ## Local Development -This project is built using [Ruby on Rails](http://rubyonrails.org/) Framework. +This project is built using [Ruby on Rails](http://rubyonrails.org/) Framework for the backend and [NodeJS](https://nodejs.org/en/) to serve the frontend assets. 1. First clone this repository and `cd` into it. @@ -21,12 +21,17 @@ This project is built using [Ruby on Rails](http://rubyonrails.org/) Framework. $ cd task-router-rails ``` -1. Install the dependencies. +1. Install the backend dependencies. Be sure to have [SQLite](https://www.sqlite.org/download.html) installed on your system before running this command. ```bash $ bundle install ``` +1. Install the frontend dependencies. + ```bash + $ npm install + ``` + 1. Expose your application to the wider internet using [ngrok](http://ngrok.com). This step is important because the application won't work as expected if you run it through @@ -63,12 +68,6 @@ This project is built using [Ruby on Rails](http://rubyonrails.org/) Framework. [Twilio Account Settings](https://www.twilio.com/console/account/settings). You will also need a `TWILIO_NUMBER`, which you may find [here](https://www.twilio.com/console/phone-numbers/incoming). - Run: - ```bash - $ source .env - ``` - to export the environment variables. - 1. Create database and run migrations. ```bash @@ -91,36 +90,22 @@ That's it! ## How to Demo -1. First make sure you have exported all the required environment variables from - the `.env.example` file. Bob and Alice's number should be two different numbers - where you can receive calls and SMSs. +1. First make sure you have correctly filled all the required environment variables from the `.env.example` file. Bob and Alice's number should be two different numbers where you can receive calls and SMSs. -1. When you run the app, a new workspace will be configured. Once that is done, - you are ready to call your [Twilio Number](https://www.twilio.com/console/phone-numbers/incoming) - where you'll be asked to select a product using your key pad. +1. When you run the app, a new workspace will be configured. Once that is done, you are ready to call your [Twilio Number](https://www.twilio.com/console/phone-numbers/incoming) where you'll be asked to select a product using your key pad. -1. Select and option and the phone assigned to the product you selected (Bob or Alice's) - will start ringing. You can answer the call and have a conversation. +1. Select and option and the phone assigned to the product you selected (Bob or Alice's) will start ringing. You can answer the call and have a conversation. -1. Alternatively, if you don't answer the call within 15 seconds, the call should be - redirected to the next worker. If the call isn't answered by the second worker, - you should be redirected to voice mail and leave a message. The transcription - of that message should be sent to the email you specified in your environment variables. +1. Alternatively, if you don't answer the call within 15 seconds, the call should be redirected to the next worker. If the call isn't answered by the second worker, you should be redirected to voice mail and leave a message. The transcription of that message should be sent to the email you specified in your environment variables. -1. Each time a worker misses a call, their activity is changed to offline. Right after they - should receive a notification, via SMS, saying that they missed the call. In order to go - back online they can reply with `On`. They can as well reply with `Off` in order - to go back to offline status. +1. Each time a worker misses a call, their activity is changed to offline. Right after they should receive a notification, via SMS, saying that they missed the call. In order to go back online they can reply with `On`. They can as well reply with `Off` in order to go back to offline status. -1. If both workers' activity changes to `Offline` and you call your Twilio Number again, - you should be redirected to voice mail after a few seconds as the workflow timeouts - when there are no available workers. Change your workers status with the `On` - SMS command to be able to receive calls again. +1. If both workers' activity changes to `Offline` and you call your Twilio Number again, you should be redirected to voice mail after a few seconds as the workflow timeouts when there are no available workers. Change your workers status with the `On` SMS command to be able to receive calls again. 1. Navigate to `https://.ngrok.io` to see a list of the missed calls. ## Meta * No warranty expressed or implied. Software is as is. Diggity. -* [MIT License](http://www.opensource.org/licenses/mit-license.html) +* [MIT License](LICENSE) * Lovingly crafted by Twilio Developer Education. diff --git a/Rakefile b/Rakefile index ba6b733..9a5ea73 100644 --- a/Rakefile +++ b/Rakefile @@ -1,6 +1,6 @@ # Add your own tasks in files placed in lib/tasks ending in .rake, # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake. -require File.expand_path('../config/application', __FILE__) +require_relative "config/application" Rails.application.load_tasks diff --git a/app.json b/app.json new file mode 100644 index 0000000..d29428f --- /dev/null +++ b/app.json @@ -0,0 +1,23 @@ +{ + "name": "Appointment Reminders powered by Twilio", + "description": "A template for getting started with Appointment Reminders using Twilio and Ruby on Rails.", + "website": "https://twilio.com", + "logo": "https://www.twilio.com/marketing/bundles/marketing/img/favicons/favicon_114.png", + "success_url": "/", + "addons": [], + "keywords": ["rails", "twilio"], + "env": { + "TWILIO_ACCOUNT_SID": { + "description": "Your Twilio Account SID. Get a free account at twilio.com/try-twilio", + "value": "" + }, + "TWILIO_AUTH_TOKEN": { + "description": "Your Twilio Auth Token. You can get it at twilio.com/console", + "value": "" + }, + "TWILIO_PHONE_NUMBER": { + "description": "The Twilio phone number you want to use to send SMS. Get one in the Twilio Console", + "value": "+12345678910" + } + } +} diff --git a/app/assets/config/manifest.js b/app/assets/config/manifest.js new file mode 100644 index 0000000..5918193 --- /dev/null +++ b/app/assets/config/manifest.js @@ -0,0 +1,2 @@ +//= link_tree ../images +//= link_directory ../stylesheets .css diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js deleted file mode 100644 index e07c5a8..0000000 --- a/app/assets/javascripts/application.js +++ /dev/null @@ -1,16 +0,0 @@ -// This is a manifest file that'll be compiled into application.js, which will include all the files -// listed below. -// -// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts, -// or any plugin's vendor/assets/javascripts directory can be referenced here using a relative path. -// -// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the -// compiled file. -// -// Read Sprockets README (https://github.com/rails/sprockets#sprockets-directives) for details -// about supported directives. -// -//= require jquery -//= require jquery_ujs -//= require turbolinks -//= require_tree . diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css deleted file mode 100644 index f9cd5b3..0000000 --- a/app/assets/stylesheets/application.css +++ /dev/null @@ -1,15 +0,0 @@ -/* - * 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 any plugin's vendor/assets/stylesheets directory 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 - */ diff --git a/app/assets/stylesheets/missed_calls.css b/app/assets/stylesheets/missed_calls.css deleted file mode 100644 index c69f39d..0000000 --- a/app/assets/stylesheets/missed_calls.css +++ /dev/null @@ -1,18 +0,0 @@ -body { - padding-top: 90px; - padding-bottom: 20px; -} - -/* Set padding to keep content from hitting the edges */ -.body-content { - padding-left: 15px; - padding-right: 15px; -} - -.fa.fa-heart{ - color: red; -} - -footer p{ - text-align: center; -} diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index d83690e..09705d1 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -1,5 +1,2 @@ class ApplicationController < ActionController::Base - # Prevent CSRF attacks by raising an exception. - # For APIs, you may want to use :null_session instead. - protect_from_forgery with: :exception end diff --git a/app/controllers/call_controller.rb b/app/controllers/call_controller.rb index 5b025f5..d5f1ea4 100644 --- a/app/controllers/call_controller.rb +++ b/app/controllers/call_controller.rb @@ -1,5 +1,5 @@ class CallController < ApplicationController - skip_before_filter :verify_authenticity_token + skip_before_action :verify_authenticity_token def enqueue digits = params[:Digits] diff --git a/app/controllers/callback_controller.rb b/app/controllers/callback_controller.rb index bbedea1..0c271c7 100644 --- a/app/controllers/callback_controller.rb +++ b/app/controllers/callback_controller.rb @@ -1,5 +1,5 @@ class CallbackController < ApplicationController - skip_before_filter :verify_authenticity_token + skip_before_action :verify_authenticity_token def assignment instruction = { @@ -29,7 +29,7 @@ def events notify_offline_status(worker_attributes['contact_uri']) end - render nothing: true + head :ok end private diff --git a/app/controllers/message_controller.rb b/app/controllers/message_controller.rb index b13ae1e..0ca84b6 100644 --- a/app/controllers/message_controller.rb +++ b/app/controllers/message_controller.rb @@ -1,5 +1,5 @@ class MessageController < ApplicationController - skip_before_filter :verify_authenticity_token + skip_before_action :verify_authenticity_token def incoming command = params['Body'].downcase @@ -9,7 +9,7 @@ def incoming status = 'Offline' activity_sid = WorkspaceInfo.instance.offline_activity_sid else - status = 'Idle' + status = 'Available' activity_sid = WorkspaceInfo.instance.idle_activity_sid end diff --git a/app/jobs/application_job.rb b/app/jobs/application_job.rb new file mode 100644 index 0000000..d394c3d --- /dev/null +++ b/app/jobs/application_job.rb @@ -0,0 +1,7 @@ +class ApplicationJob < ActiveJob::Base + # Automatically retry jobs that encountered a deadlock + # retry_on ActiveRecord::Deadlocked + + # Most jobs are safe to ignore if the underlying records are no longer available + # discard_on ActiveJob::DeserializationError +end diff --git a/app/packs/javascript/application.js b/app/packs/javascript/application.js new file mode 100644 index 0000000..9f0047e --- /dev/null +++ b/app/packs/javascript/application.js @@ -0,0 +1,12 @@ +// This file is automatically compiled by Webpack, along with any other files +// present in this directory. You're encouraged to place your actual application logic in +// a relevant structure within app/javascript and only use these pack files to reference +// that code so it'll be compiled. + +import Rails from "@rails/ujs" +import Turbolinks from "turbolinks" +import "bootstrap" +import "../stylesheets/application" + +Rails.start() +Turbolinks.start() diff --git a/app/packs/stylesheets/application.scss b/app/packs/stylesheets/application.scss new file mode 100644 index 0000000..6b869d8 --- /dev/null +++ b/app/packs/stylesheets/application.scss @@ -0,0 +1,16 @@ +@import "bootstrap"; + +/* Set padding to keep content from hitting the edges */ +.body-content { + padding-left: 15px; + padding-right: 15px; +} + +footer { + bottom: 10px; + text-align: center; + + i { + color:#ff0000; + } +} diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index a2ecc67..7bb5b38 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -1,40 +1,34 @@ - - Warm Transfer - - <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track' => true %> - <%= csrf_meta_tags %> - <%= stylesheet_link_tag "//maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css" %> - <%= stylesheet_link_tag "//maxcdn.bootstrapcdn.com/font-awesome/4.4.0/css/font-awesome.min.css" %> - - -