├── .devcontainer ├── Dockerfile ├── compose.yaml └── devcontainer.json ├── .dockerignore ├── .env.development ├── .env.test ├── .gitattributes ├── .github └── workflows │ └── ci.yml ├── .gitignore ├── .node-version ├── .rubocop.yml ├── .ruby-version ├── .tool-versions ├── .yarn └── releases │ └── yarn-1.22.19.cjs ├── .yarnrc ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── Capfile ├── Dockerfile ├── Gemfile ├── Gemfile.lock ├── OLDREADME.md ├── Procfile.dev ├── ProdDockerfile ├── README.md ├── Rakefile ├── app ├── assets │ ├── builds │ │ └── .keep │ ├── config │ │ └── manifest.js │ ├── images │ │ ├── .keep │ │ ├── activities_local_conferences.png │ │ ├── activities_local_hackathons.png │ │ ├── activities_local_meetups.png │ │ ├── activities_local_programming.png │ │ ├── activities_local_workshops.png │ │ ├── add.png │ │ ├── arc_dark_gray_logo.png │ │ ├── arc_logo_coloured.png │ │ ├── brands_facebook.png │ │ ├── brands_github.png │ │ ├── brands_instagram.png │ │ ├── brands_linkedin.png │ │ ├── brands_telegram.png │ │ ├── brands_twitter.png │ │ ├── chapter.jpg │ │ ├── conference.jpg │ │ ├── countries.png │ │ ├── country_kenya.png │ │ ├── country_rwanda.png │ │ ├── country_tanzania.png │ │ ├── country_uganda.png │ │ ├── developers.jpg │ │ ├── email_arc_logo.png │ │ ├── favicon.ico │ │ ├── intro-landing.jpg │ │ ├── sign_up_karate.png │ │ ├── sponsors │ │ │ ├── current │ │ │ │ ├── app_signal.png │ │ │ │ ├── finplus.png │ │ │ │ ├── friendly_rb.jpg │ │ │ │ ├── kca.png │ │ │ │ ├── kopo_kopo.png │ │ │ │ ├── microverse.png │ │ │ │ ├── nairobits.png │ │ │ │ ├── planet_argon.png │ │ │ │ ├── ruby_central.png │ │ │ │ └── solutech_official.svg │ │ │ └── previous │ │ │ │ ├── andela.png │ │ │ │ ├── ihub.png │ │ │ │ ├── kopokopo.png │ │ │ │ ├── kwara.png │ │ │ │ ├── shopify.webp │ │ │ │ └── turing.png │ │ └── workshop.jpg │ └── stylesheets │ │ ├── application.tailwind.css │ │ └── mailgun_mails.css ├── channels │ └── application_cable │ │ ├── channel.rb │ │ └── connection.rb ├── controllers │ ├── application_controller.rb │ ├── chapters_controller.rb │ ├── concerns │ │ └── .keep │ ├── countries_controller.rb │ ├── landing_controller.rb │ ├── projects_controller.rb │ ├── turbo_devise_controller.rb │ └── users │ │ └── registrations_controller.rb ├── helpers │ ├── application_helper.rb │ ├── chapters_helper.rb │ ├── countries_helper.rb │ └── projects_helper.rb ├── javascript │ ├── application.js │ └── controllers │ │ ├── application.js │ │ ├── hello_controller.js │ │ ├── index.js │ │ ├── removals_controller.js │ │ └── turbo_frames_controller.js ├── jobs │ └── application_job.rb ├── mailers │ ├── application_mailer.rb │ └── devise_mailer.rb ├── models │ ├── ability.rb │ ├── application_record.rb │ ├── chapter.rb │ ├── concerns │ │ └── .keep │ ├── country.rb │ ├── feature_flag.rb │ ├── motor │ │ └── ability.rb │ ├── project.rb │ ├── user.rb │ └── users_chapter.rb └── views │ ├── chapters │ ├── _chapter.html.erb │ ├── index.html.erb │ └── show.html.erb │ ├── countries │ ├── _country.html.erb │ ├── _created_country.html.erb │ ├── index.html.erb │ └── show.html.erb │ ├── devise │ ├── confirmations │ │ └── new.html.erb │ ├── mailer │ │ ├── confirmation_instructions.html.erb │ │ ├── email_changed.html.erb │ │ ├── password_change.html.erb │ │ ├── reset_password_instructions.html.erb │ │ └── unlock_instructions.html.erb │ ├── passwords │ │ ├── edit.html.erb │ │ └── new.html.erb │ ├── registrations │ │ ├── edit.html.erb │ │ └── new.html.erb │ ├── sessions │ │ └── new.html.erb │ ├── shared │ │ ├── _error_messages.html.erb │ │ └── _links.html.erb │ └── unlocks │ │ └── new.html.erb │ ├── landing │ ├── about.html.erb │ ├── home │ │ ├── _activities.html.erb │ │ ├── _chapters.html.erb │ │ ├── _coming_up_events.html.erb │ │ ├── _featured_sponsors.html.erb │ │ ├── _intro.html.erb │ │ ├── _previous_sponsors.html.erb │ │ ├── _projects.html.erb │ │ └── _who_we_are.html.erb │ ├── index.html.erb │ └── learn.html.erb │ ├── layouts │ ├── _flash_messages.html.erb │ ├── _footer.html.erb │ ├── _navbar.html.erb │ ├── application.html.erb │ ├── mailer.html.erb │ └── mailer.text.erb │ └── projects │ ├── _project.html.erb │ ├── index.html.erb │ └── show.html.erb ├── bin ├── bundle ├── dev ├── docker-entrypoint ├── rails ├── rake └── setup ├── config.ru ├── config ├── application.rb ├── boot.rb ├── cable.yml ├── credentials.yml.enc ├── credentials │ └── production.yml.enc ├── database.yml ├── deploy.rb ├── deploy │ └── production.rb ├── dockerfile.yml ├── environment.rb ├── environments │ ├── development.rb │ ├── production.rb │ └── test.rb ├── initializers │ ├── assets.rb │ ├── content_security_policy.rb │ ├── devise.rb │ ├── filter_parameter_logging.rb │ ├── inflections.rb │ ├── permissions_policy.rb │ ├── simple_form.rb │ └── simple_form_daisy.rb ├── locales │ ├── devise.en.yml │ ├── en.yml │ └── simple_form.en.yml ├── motor.yml ├── puma.rb ├── routes.rb ├── sitemap.rb └── storage.yml ├── db ├── migrate │ ├── 20221118122721_devise_create_users.rb │ ├── 20221227125811_create_countries.rb │ ├── 20230117033124_create_chapters.rb │ ├── 20230212202017_create_projects.rb │ ├── 20230225213826_add_role_to_users.rb │ ├── 20230225222048_create_users_chapters.rb │ ├── 20230226063248_add_extra_fields_to_users.rb │ ├── 20230305084113_install_motor_admin.rb │ ├── 20230305235848_create_active_storage_tables.active_storage.rb │ ├── 20230309154521_create_feature_flags.rb │ ├── 20230313002939_rename_feature_to_name_for_feature_flags.rb │ └── 20230531154135_add_index_to_columns.rb ├── schema.rb └── seeds.rb ├── dev-docker-entrypoint.sh ├── docker-compose.yml ├── fly.toml ├── lib ├── assets │ └── .keep ├── tasks │ ├── .keep │ └── auto_annotate_models.rake └── templates │ └── erb │ └── scaffold │ └── _form.html.erb ├── log └── .keep ├── package.json ├── public ├── 404.html ├── 422.html ├── 500.html ├── apple-touch-icon-precomposed.png ├── apple-touch-icon.png ├── favicon.ico ├── robots.txt └── sitemap.xml ├── storage └── .keep ├── tailwind.config.js ├── test-docker-entrypoint.sh ├── test ├── application_system_test_case.rb ├── channels │ └── application_cable │ │ └── connection_test.rb ├── controllers │ ├── .keep │ ├── chapters_controller_test.rb │ ├── countries_controller_test.rb │ └── projects_controller_test.rb ├── fixtures │ ├── chapters.yml │ ├── countries.yml │ ├── feature_flags.yml │ ├── files │ │ └── .keep │ ├── projects.yml │ ├── users.yml │ └── users_chapters.yml ├── helpers │ └── .keep ├── integration │ └── .keep ├── mailers │ └── .keep ├── models │ ├── .keep │ ├── chapter_test.rb │ ├── country_test.rb │ ├── feature_flag_test.rb │ ├── project_test.rb │ ├── user_test.rb │ └── users_chapter_test.rb ├── system │ ├── .keep │ ├── chapters_test.rb │ ├── countries_test.rb │ └── projects_test.rb └── test_helper.rb ├── tmp ├── .keep ├── pids │ └── .keep └── storage │ └── .keep ├── vendor └── .keep └── yarn.lock /.devcontainer/Dockerfile: -------------------------------------------------------------------------------- 1 | # Make sure RUBY_VERSION matches the Ruby version in .ruby-version 2 | ARG RUBY_VERSION=3.4.1 3 | FROM ghcr.io/rails/devcontainer/images/ruby:$RUBY_VERSION 4 | -------------------------------------------------------------------------------- /.devcontainer/compose.yaml: -------------------------------------------------------------------------------- 1 | name: "arc_platform" 2 | 3 | services: 4 | rails-app: 5 | build: 6 | context: .. 7 | dockerfile: .devcontainer/Dockerfile 8 | 9 | volumes: 10 | - ../..:/workspaces:cached 11 | 12 | # Overrides default command so things don't shut down after the process ends. 13 | command: sleep infinity 14 | 15 | # Uncomment the next line to use a non-root user for all processes. 16 | # user: vscode 17 | 18 | # Use "forwardPorts" in **devcontainer.json** to forward an app port locally. 19 | # (Adding the "ports" property to this file will not forward from a Codespace.) 20 | depends_on: 21 | - selenium 22 | - redis 23 | - postgres 24 | 25 | selenium: 26 | image: selenium/standalone-chromium 27 | restart: unless-stopped 28 | 29 | redis: 30 | image: redis:7.2 31 | restart: unless-stopped 32 | volumes: 33 | - redis-data:/data 34 | 35 | postgres: 36 | image: postgres:16.1 37 | restart: unless-stopped 38 | networks: 39 | - default 40 | volumes: 41 | - postgres-data:/var/lib/postgresql/data 42 | environment: 43 | POSTGRES_USER: postgres 44 | POSTGRES_PASSWORD: postgres 45 | 46 | volumes: 47 | redis-data: 48 | postgres-data: 49 | -------------------------------------------------------------------------------- /.devcontainer/devcontainer.json: -------------------------------------------------------------------------------- 1 | // For format details, see https://aka.ms/devcontainer.json. For config options, see the 2 | // README at: https://github.com/devcontainers/templates/tree/main/src/ruby 3 | { 4 | "name": "arc_platform", 5 | "dockerComposeFile": "compose.yaml", 6 | "service": "rails-app", 7 | "workspaceFolder": "/workspaces/${localWorkspaceFolderBasename}", 8 | 9 | // Features to add to the dev container. More info: https://containers.dev/features. 10 | "features": { 11 | "ghcr.io/devcontainers/features/github-cli:1": {}, 12 | "ghcr.io/rails/devcontainer/features/activestorage": {}, 13 | "ghcr.io/devcontainers/features/node:1": {}, 14 | "ghcr.io/rails/devcontainer/features/postgres-client": {} 15 | }, 16 | 17 | "containerEnv": { 18 | "CAPYBARA_SERVER_PORT": "45678", 19 | "SELENIUM_HOST": "selenium", 20 | "REDIS_URL": "redis://redis:6379/1", 21 | "DB_HOST": "postgres" 22 | }, 23 | 24 | // Use 'forwardPorts' to make a list of ports inside the container available locally. 25 | "forwardPorts": [3000, 5432, 6379], 26 | 27 | // Configure tool-specific properties. 28 | // "customizations": {}, 29 | 30 | // Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root. 31 | // "remoteUser": "root", 32 | 33 | 34 | // Use 'postCreateCommand' to run commands after the container is created. 35 | "postCreateCommand": "bin/setup" 36 | } 37 | -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | # See https://docs.docker.com/engine/reference/builder/#dockerignore-file for more about ignoring files. 2 | 3 | # Ignore git directory. 4 | /.git/ 5 | 6 | # Ignore bundler config. 7 | /.bundle 8 | 9 | # Ignore all default key files. 10 | /config/master.key 11 | /config/credentials/*.key 12 | 13 | # Ignore all environment files. 14 | /.env* 15 | !/.env.example 16 | 17 | # Ignore all logfiles and tempfiles. 18 | /log/* 19 | /tmp/* 20 | !/log/.keep 21 | !/tmp/.keep 22 | 23 | # Ignore pidfiles, but keep the directory. 24 | /tmp/pids/* 25 | !/tmp/pids/ 26 | !/tmp/pids/.keep 27 | 28 | # Ignore storage (uploaded files in development and any SQLite databases). 29 | /storage/* 30 | !/storage/.keep 31 | /tmp/storage/* 32 | !/tmp/storage/ 33 | !/tmp/storage/.keep 34 | 35 | # Ignore assets. 36 | /node_modules/ 37 | /app/assets/builds/* 38 | !/app/assets/builds/.keep 39 | /public/assets 40 | -------------------------------------------------------------------------------- /.env.development: -------------------------------------------------------------------------------- 1 | DATABASE_HOST=arc_db 2 | DATABASE_USERNAME=postgres 3 | DATABASE_PASSWORD=password 4 | DATABASE_NAME=arc_development 5 | DATABASE_PORT=5432 -------------------------------------------------------------------------------- /.env.test: -------------------------------------------------------------------------------- 1 | DATABASE_HOST=arc_db 2 | DATABASE_USERNAME=postgres 3 | DATABASE_PASSWORD=password 4 | DATABASE_NAME=arc_development 5 | DATABASE_PORT=5432 -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # See https://git-scm.com/docs/gitattributes for more about git attribute files. 2 | 3 | # Mark the database schema as having been generated. 4 | db/schema.rb linguist-generated 5 | 6 | # Mark any vendored files as having been vendored. 7 | vendor/* linguist-vendored 8 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: Arc Platform CI Workflow 2 | on: [push, pull_request] 3 | jobs: 4 | linters: 5 | name: RuboCop Linter 6 | runs-on: ubuntu-latest 7 | steps: 8 | - uses: actions/checkout@v4 9 | - name: Setup Ruby 3.4.1 10 | uses: ruby/setup-ruby@v1 11 | with: 12 | ruby-version: '3.4.1' # Not needed with a .ruby-version file 13 | bundler-cache: true 14 | 15 | - run: bundle exec rubocop 16 | 17 | test: 18 | name: Rails Test 19 | runs-on: ubuntu-latest 20 | services: 21 | db: 22 | image: postgres:11@sha256:85d79cba2d4942dad7c99f84ec389a5b9cc84fb07a3dcd3aff0fb06948cdc03b 23 | ports: ['5432:5432'] 24 | options: >- 25 | --health-cmd pg_isready 26 | --health-interval 10s 27 | --health-timeout 5s 28 | --health-retries 5 29 | 30 | steps: 31 | - uses: actions/checkout@v4 32 | - name: Setup Ruby 3.4.1 33 | uses: ruby/setup-ruby@v1 34 | with: 35 | ruby-version: '3.4.1' # Not needed with a .ruby-version file 36 | bundler-cache: true 37 | 38 | - name: Setup Node 39 | uses: actions/setup-node@v4 40 | with: 41 | node-version: '18' 42 | 43 | - name: Find yarn cache location 44 | id: yarn-cache 45 | run: echo "::set-output name=dir::$(yarn cache dir)" 46 | 47 | - name: JS package cache 48 | uses: actions/cache@v4 49 | with: 50 | path: ${{ steps.yarn-cache.outputs.dir }} 51 | key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }} 52 | restore-keys: | 53 | ${{ runner.os }}-yarn- 54 | - name: Install packages 55 | run: | 56 | yarn install --pure-lockfile 57 | 58 | - name: Build and run tests 59 | env: 60 | DATABASE_URL: postgres://postgres:@localhost:5432/test 61 | #POSTGRES_PASSWORD: postgres 62 | RAILS_ENV: test 63 | #RAILS_MASTER_KEY: ${{ secrets.RAILS_MASTER_KEY }} 64 | run: | 65 | sudo apt-get -yqq install libpq-dev 66 | gem install bundler 67 | bundle install --jobs 4 --retry 3 68 | bin/rails javascript:build 69 | bin/rails css:build 70 | bundle exec rails db:prepare 71 | bundle exec rails test 72 | 73 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files for more about ignoring files. 2 | # 3 | # If you find yourself ignoring temporary files generated by your text editor 4 | # or operating system, you probably want to add a global ignore instead: 5 | # git config --global core.excludesfile '~/.gitignore_global' 6 | 7 | # Ignore bundler config. 8 | /.bundle 9 | 10 | # Ignore all logfiles and tempfiles. 11 | /log/* 12 | /tmp/* 13 | !/log/.keep 14 | !/tmp/.keep 15 | 16 | # Ignore pidfiles, but keep the directory. 17 | /tmp/pids/* 18 | !/tmp/pids/ 19 | !/tmp/pids/.keep 20 | 21 | # Ignore uploaded files in development. 22 | /storage/* 23 | !/storage/.keep 24 | /tmp/storage/* 25 | !/tmp/storage/ 26 | !/tmp/storage/.keep 27 | 28 | /public/assets 29 | 30 | # Ignore master key for decrypting credentials and more. 31 | /config/master.key 32 | 33 | /app/assets/builds/* 34 | !/app/assets/builds/.keep 35 | 36 | /node_modules 37 | 38 | /config/credentials/production.key 39 | 40 | coverage/ 41 | 42 | # Ignore JetBrains IDE .idea directory 43 | .idea/ 44 | -------------------------------------------------------------------------------- /.node-version: -------------------------------------------------------------------------------- 1 | 18.14.0 -------------------------------------------------------------------------------- /.rubocop.yml: -------------------------------------------------------------------------------- 1 | require: 2 | - rubocop-performance 3 | - rubocop-rails 4 | 5 | AllCops: 6 | NewCops: enable 7 | SuggestExtensions: 8 | rubocop-rake: false 9 | TargetRubyVersion: 3.0.2 10 | Exclude: 11 | - bin/**/* 12 | - config/**/* 13 | - db/migrate/* 14 | - db/schema.rb 15 | - node_modules/**/* 16 | - public/**/* 17 | - tmp/**/* 18 | - vendor/**/* 19 | 20 | Style/Documentation: 21 | Enabled: false 22 | -------------------------------------------------------------------------------- /.ruby-version: -------------------------------------------------------------------------------- 1 | 3.4.1 2 | -------------------------------------------------------------------------------- /.tool-versions: -------------------------------------------------------------------------------- 1 | nodejs 20.9.0 2 | ruby 3.4.1 -------------------------------------------------------------------------------- /.yarnrc: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | yarn-path ".yarn/releases/yarn-1.22.19.cjs" 6 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | ## Code of Conduct 2 | 3 | Everyone interacting in the ARC project's codebases, issue trackers, chat rooms, and mailing lists is expected to follow the following code of conduct: 4 | 5 | * Be respectful of others. 6 | * Avoid name-calling, personal attacks, and other forms of harassment. 7 | * Be inclusive and welcoming to everyone, regardless of their background or experience. 8 | * Resolve conflict constructively. 9 | * Use clear and concise language. 10 | * Stay on topic. 11 | 12 | 13 | ### Enforcement 14 | 15 | Enforcement of this code of conduct is at the discretion of the maintainers. If a maintainer determines that someone has violated the code of conduct, they may take any action they deem appropriate, including issuing warnings, temporary bans, or permanent bans. 16 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | ## Contributing 2 | 3 | Thank you for your interest in contributing to the ARC project! We welcome code and non-code contributions from new and seasoned developers at any career stage, and any sector. 4 |
5 | [Hactoberfest participation guide](https://hacktoberfest.com/participation/#contributors) 6 | 7 | 8 | ### Finding Issues to Work On 9 | 10 | We label our issues to help contributors find ones that match their skills and experience level. Here are some labels you might find helpful: 11 | 12 | 13 | | Difficulty Level | Description | Label | 14 | |------------------|------------------------------------------|----------| 15 | | Easy/ Beginner/ Novice | Issues that are ideal for first-time contributors | ![DifficultyLevelEasy](https://img.shields.io/badge/DifficultyLevelEasy-green.svg?style=for-the-badge)| 16 | | Very Easy | Simple issues that can be fixed quickly | ![DifficultyLevelVeryEasy](https://img.shields.io/badge/DifficultyLevelVeryEasy-619B16?style=for-the-badge)| 17 | | Average/ Normal/ Medium/ Standard/ Intermediate | Issues that require some understanding of the codebase | ![DifficultyLevelAverage](https://img.shields.io/badge/DifficultyLevelAverage-DAD22C?style=for-the-badge&color=fbca04) | 18 | | Hard/ Expert/ Difficult | Issues that require a significant amount of time and effort | ![DifficultyLevelHard](https://img.shields.io/badge/DifficultyLevelHard-E1803C?style=for-the-badge&color=d93f0b) | 19 | | Harder | Very challenging issues that require advanced knowledge | ![DifficultyLevelHarder](https://img.shields.io/badge/DifficultyLevelHarder-C70039?style=for-the-badge)| 20 | 21 | 22 | 23 | ### Making Changes 24 | 25 | Once you have found an issue you want to work on, follow these steps to make changes: 26 | 27 | 1. Fork the repository. 28 | 2. Create a new branch for your changes. 29 | 3. Make your changes to the codebase. 30 | 4. Add unit tests for your changes. 31 | 5. Commit your changes and push them to your fork. 32 | 6. Create a pull request against the upstream repository. 33 | 34 | 35 | Once you have created a pull request, a maintainer will review your changes. If your changes are approved, they will be merged into the upstream repository. 36 | 37 | ## Hactoberfest technical contributions 38 | 39 | 40 | ## Non-code and Low-code Contribution 41 | 42 | [Low-code and non-code contributions](https://www.youtube.com/watch?v=Z7ppp_DrxyM) are an excellent way to get involved in supporting the ARC project. Here are some examples of ways you can contribute: 43 | 44 | LOW-CODE 45 | 46 | - Technical documentation 47 | - User experience testing 48 | - Technical blog post or tutorial 49 | - Case studies 50 | 51 | NON-CODE CONTRIBUTIONS: 52 | 53 | - Writing 54 | - Translating 55 | - Talks or presentations 56 | - Social media 57 | - Blog posts 58 | 59 | 60 | ### Thank You! 61 | 62 | Thank you for taking the time to contribute to the ARC platform project! Your contributions help to make the project better for everyone. 63 | -------------------------------------------------------------------------------- /Capfile: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Load DSL and set up stages 4 | require 'capistrano/setup' 5 | 6 | # Include default deployment tasks 7 | require 'capistrano/deploy' 8 | 9 | # Load the SCM plugin appropriate to your project: 10 | # 11 | # require "capistrano/scm/hg" 12 | # install_plugin Capistrano::SCM::Hg 13 | # or 14 | # require "capistrano/scm/svn" 15 | # install_plugin Capistrano::SCM::Svn 16 | # or 17 | require 'capistrano/scm/git' 18 | install_plugin Capistrano::SCM::Git 19 | 20 | # Include tasks from other gems included in your Gemfile 21 | # 22 | # For documentation on these, see for example: 23 | # 24 | # https://github.com/capistrano/rvm 25 | # https://github.com/capistrano/rbenv 26 | # https://github.com/capistrano/chruby 27 | # https://github.com/capistrano/bundler 28 | # https://github.com/capistrano/rails 29 | # https://github.com/capistrano/passenger 30 | # 31 | # require "capistrano/rvm" 32 | # require "capistrano/rbenv" 33 | # require "capistrano/chruby" 34 | # require "capistrano/bundler" 35 | # require "capistrano/rails/assets" 36 | # require "capistrano/rails/migrations" 37 | require 'capistrano/passenger' 38 | require 'capistrano/rails' 39 | require 'capistrano/sidekiq' 40 | require 'capistrano/asdf' 41 | 42 | # Load custom tasks from `lib/capistrano/tasks` if you have any defined 43 | Dir.glob('lib/capistrano/tasks/*.rake').each { |r| import r } 44 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ruby:3.4.1-alpine 2 | 3 | ENV APP_PATH /var/app 4 | ENV BUNDLE_VERSION 2.3.1 5 | ENV BUNDLE_PATH /usr/local/bundle/gems 6 | ENV TMP_PATH /tmp/ 7 | ENV RAILS_LOG_TO_STDOUT true 8 | ENV RAILS_PORT 3000 9 | 10 | # Install system dependencies 11 | RUN apt-get update && apt-get install -y \ 12 | build-essential \ 13 | git \ 14 | postgresql-client \ 15 | libxml2-dev \ 16 | libxslt-dev \ 17 | nodejs \ 18 | npm \ 19 | imagemagick \ 20 | tzdata \ 21 | less \ 22 | && rm -rf /var/lib/apt/lists/* \ 23 | && mkdir -p $APP_PATH 24 | 25 | RUN gem install bundler --version "$BUNDLE_VERSION" \ 26 | && rm -rf $GEM_HOME/cache/* 27 | 28 | # navigate to app directory 29 | WORKDIR $APP_PATH 30 | 31 | EXPOSE $RAILS_PORT 32 | 33 | ENTRYPOINT [ "bundle", "exec" ] -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | source 'https://rubygems.org' 4 | git_source(:github) { |repo| "https://github.com/#{repo}.git" } 5 | 6 | ruby '3.4.1' 7 | 8 | gem 'active_storage_validations', '~> 1.0' # Active Storage gems for validating attachments https://github.com/igorkasyanchuk/active_storage_validations 9 | gem 'aws-sdk-s3', '~> 1.119', require: false # Official AWS Ruby gem for Amazon S3 10 | gem 'bootsnap', require: false # Reduces boot times through caching; required in config/boot.rb 11 | gem 'cancancan', '~> 3.4' # Authorization library which restricts what resources a given user is allowed to access 12 | gem 'cssbundling-rails' # Bundle and process CSS [https://github.com/rails/cssbundling-rails] 13 | gem 'devise' # Devise 4.0 works with Rails 4.1 onwards. 14 | # Use Active Storage variants [https://guides.rubyonrails.org/active_storage_overview.html#transforming-images] 15 | gem 'image_processing', '~> 1.2' 16 | gem 'jbuilder' # Build JSON APIs with ease [https://github.com/rails/jbuilder] 17 | gem 'jsbundling-rails' # Bundle and transpile JavaScript [https://github.com/rails/jsbundling-rails] 18 | gem 'mini_magick', '~> 4.12' 19 | # Motor Admin allows you to deploy a no-code admin panel for your application in less than a minute 20 | gem 'motor-admin', '~> 0.4.7' 21 | gem 'pg', '~> 1.1' # Use postgresql as the database for Active Record 22 | gem 'premailer-rails', '~> 1.12' # This gem is a drop in solution for styling HTML emails with CSS 23 | gem 'puma', '~> 5.0' # Use the Puma web server [https://github.com/puma/puma] 24 | gem 'rails', '~> 7.2.2.1' # Bundle edge Rails instead: gem "rails", github: "rails/rails", branch: "main" 25 | gem 'redis', '~> 4.0' # Use Redis adapter to run Action Cable in production 26 | # An ActionMailer adapter to send email using SendGrid's HTTPS Web API (instead of SMTP). 27 | gem 'sendgrid-actionmailer', '~> 3.2' 28 | gem 'simple_form', '~> 5.1' # Gem to pimp up forms 29 | gem 'sitemap_generator' # A dynamic sitemap generator gem for the Ruby on Rails framework 30 | gem 'sprockets-rails' # The original asset pipeline for Rails [https://github.com/rails/sprockets-rails] 31 | gem 'stimulus-rails' # Hotwire's modest JavaScript framework [https://stimulus.hotwired.dev] 32 | gem 'turbo-rails' # Hotwire's SPA-like page accelerator [https://turbo.hotwired.dev] 33 | # Windows does not include zoneinfo files, so bundle the tzinfo-data gem 34 | gem 'tzinfo-data', platforms: %i[mingw mswin x64_mingw jruby] 35 | 36 | # gem "kredis" # Use Kredis to get higher-level data types in Redis [https://github.com/rails/kredis] 37 | # Use Active Model has_secure_password [https://guides.rubyonrails.org/active_model_basics.html#securepassword] 38 | # gem "bcrypt", "~> 3.1.7" 39 | # gem "sassc-rails" # Use Sass to process CSS 40 | 41 | group :development, :test do 42 | # See https://guides.rubyonrails.org/debugging_rails_applications.html#debugging-with-the-debug-gem 43 | gem 'debug', platforms: %i[mri mingw x64_mingw] 44 | gem 'rubocop', '~> 1.51.0', require: false 45 | gem 'rubocop-performance', '~> 1.18', require: false 46 | gem 'rubocop-rails', '~> 2.19.1', require: false 47 | end 48 | 49 | group :development do 50 | # Use console on exceptions pages [https://github.com/rails/web-console] 51 | 52 | # Add speed badges [https://github.com/MiniProfiler/rack-mini-profiler] 53 | # gem "rack-mini-profiler" 54 | 55 | # Speed up commands on slow machines / big apps [https://github.com/rails/spring] 56 | # gem "spring" 57 | 58 | gem 'annotate', '~> 3.2', '>= 3.2.0' 59 | 60 | # Capistrano - deployment gems 61 | gem 'capistrano', '~> 3.11' 62 | gem 'capistrano-asdf' 63 | gem 'capistrano-passenger', '~> 0.2.0' 64 | gem 'capistrano-rails', '~> 1.4' 65 | gem 'capistrano-sidekiq' 66 | gem 'capistrano-webpacker-precompile', require: false 67 | gem 'dockerfile-rails', '>= 1.2' 68 | gem 'letter_opener' 69 | end 70 | 71 | group :test do 72 | # Use system testing [https://guides.rubyonrails.org/testing.html#system-testing] 73 | gem 'capybara' 74 | gem 'faker', '~> 3.1' 75 | gem 'selenium-webdriver' 76 | gem 'simplecov', require: false # Code coverage analysis tool for ruby 77 | gem 'webdrivers' 78 | end 79 | -------------------------------------------------------------------------------- /Procfile.dev: -------------------------------------------------------------------------------- 1 | web: bin/rails server -p 3000 2 | js: yarn build --watch 3 | css: yarn build:css --watch 4 | -------------------------------------------------------------------------------- /ProdDockerfile: -------------------------------------------------------------------------------- 1 | # syntax = docker/dockerfile:1 2 | 3 | # Make sure RUBY_VERSION matches the Ruby version in .ruby-version and Gemfile 4 | ARG RUBY_VERSION=3.0.2 5 | FROM ruby:$RUBY_VERSION-slim as base 6 | 7 | LABEL fly_launch_runtime="rails" 8 | 9 | # Rails app lives here 10 | WORKDIR /rails 11 | 12 | # Set production environment 13 | ENV RAILS_ENV="production" \ 14 | BUNDLE_WITHOUT="development:test" \ 15 | BUNDLE_DEPLOYMENT="1" 16 | 17 | # Update gems and bundler 18 | RUN gem update --system --no-document && \ 19 | gem install -N bundler 20 | 21 | 22 | # Throw-away build stage to reduce size of final image 23 | FROM base as build 24 | 25 | # Install packages needed to build gems and node modules 26 | RUN apt-get update -qq && \ 27 | apt-get install --no-install-recommends -y build-essential curl libpq-dev libvips node-gyp pkg-config python-is-python3 28 | 29 | # Install JavaScript dependencies 30 | ARG NODE_VERSION=18.14.0 31 | ARG YARN_VERSION=1.22.19 32 | ENV PATH=/usr/local/node/bin:$PATH 33 | RUN curl -sL https://github.com/nodenv/node-build/archive/master.tar.gz | tar xz -C /tmp/ && \ 34 | /tmp/node-build-master/bin/node-build "${NODE_VERSION}" /usr/local/node && \ 35 | npm install -g yarn@$YARN_VERSION && \ 36 | rm -rf /tmp/node-build-master 37 | 38 | # Install application gems 39 | COPY --link Gemfile Gemfile.lock ./ 40 | RUN bundle install && \ 41 | bundle exec bootsnap precompile --gemfile && \ 42 | rm -rf ~/.bundle/ $BUNDLE_PATH/ruby/*/cache $BUNDLE_PATH/ruby/*/bundler/gems/*/.git 43 | 44 | # Install node modules 45 | COPY --link package.json yarn.lock ./ 46 | RUN yarn install --frozen-lockfile 47 | 48 | # Copy application code 49 | COPY --link . . 50 | 51 | # Precompile bootsnap code for faster boot times 52 | RUN bundle exec bootsnap precompile app/ lib/ 53 | 54 | # Precompiling assets for production without requiring secret RAILS_MASTER_KEY 55 | RUN ./bin/rails assets:precompile 56 | 57 | 58 | # Final stage for app image 59 | FROM base 60 | 61 | # Install packages needed for deployment 62 | RUN apt-get update -qq && \ 63 | apt-get install --no-install-recommends -y imagemagick libvips postgresql-client && \ 64 | rm -rf /var/lib/apt/lists /var/cache/apt/archives 65 | 66 | # Run and own the application files as a non-root user for security 67 | RUN useradd rails --home /rails --shell /bin/bash 68 | USER rails:rails 69 | 70 | # Copy built artifacts: gems, application 71 | COPY --from=build /usr/local/bundle /usr/local/bundle 72 | COPY --from=build --chown=rails:rails /rails /rails 73 | 74 | # Deployment options 75 | ENV RAILS_LOG_TO_STDOUT="1" \ 76 | RAILS_SERVE_STATIC_FILES="true" 77 | 78 | # Entrypoint prepares the database. 79 | ENTRYPOINT ["/rails/bin/docker-entrypoint"] 80 | 81 | # Start the server by default, this can be overwritten at runtime 82 | EXPOSE 3000 83 | CMD ["./bin/rails", "server"] 84 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Add your own tasks in files placed in lib/tasks ending in .rake, 4 | # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake. 5 | 6 | require_relative 'config/application' 7 | 8 | Rails.application.load_tasks 9 | -------------------------------------------------------------------------------- /app/assets/builds/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/African-Ruby-Community/arc_platform/c77a4f421418b59f00b462a04269f720dc73f1dd/app/assets/builds/.keep -------------------------------------------------------------------------------- /app/assets/config/manifest.js: -------------------------------------------------------------------------------- 1 | //= link_tree ../images 2 | //= link_tree ../builds 3 | //= link mailgun_mails.css 4 | //= link application.tailwind.css 5 | //= link_tree ../../javascript .js 6 | -------------------------------------------------------------------------------- /app/assets/images/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/African-Ruby-Community/arc_platform/c77a4f421418b59f00b462a04269f720dc73f1dd/app/assets/images/.keep -------------------------------------------------------------------------------- /app/assets/images/activities_local_conferences.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/African-Ruby-Community/arc_platform/c77a4f421418b59f00b462a04269f720dc73f1dd/app/assets/images/activities_local_conferences.png -------------------------------------------------------------------------------- /app/assets/images/activities_local_hackathons.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/African-Ruby-Community/arc_platform/c77a4f421418b59f00b462a04269f720dc73f1dd/app/assets/images/activities_local_hackathons.png -------------------------------------------------------------------------------- /app/assets/images/activities_local_meetups.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/African-Ruby-Community/arc_platform/c77a4f421418b59f00b462a04269f720dc73f1dd/app/assets/images/activities_local_meetups.png -------------------------------------------------------------------------------- /app/assets/images/activities_local_programming.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/African-Ruby-Community/arc_platform/c77a4f421418b59f00b462a04269f720dc73f1dd/app/assets/images/activities_local_programming.png -------------------------------------------------------------------------------- /app/assets/images/activities_local_workshops.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/African-Ruby-Community/arc_platform/c77a4f421418b59f00b462a04269f720dc73f1dd/app/assets/images/activities_local_workshops.png -------------------------------------------------------------------------------- /app/assets/images/add.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/African-Ruby-Community/arc_platform/c77a4f421418b59f00b462a04269f720dc73f1dd/app/assets/images/add.png -------------------------------------------------------------------------------- /app/assets/images/arc_dark_gray_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/African-Ruby-Community/arc_platform/c77a4f421418b59f00b462a04269f720dc73f1dd/app/assets/images/arc_dark_gray_logo.png -------------------------------------------------------------------------------- /app/assets/images/arc_logo_coloured.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/African-Ruby-Community/arc_platform/c77a4f421418b59f00b462a04269f720dc73f1dd/app/assets/images/arc_logo_coloured.png -------------------------------------------------------------------------------- /app/assets/images/brands_facebook.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/African-Ruby-Community/arc_platform/c77a4f421418b59f00b462a04269f720dc73f1dd/app/assets/images/brands_facebook.png -------------------------------------------------------------------------------- /app/assets/images/brands_github.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/African-Ruby-Community/arc_platform/c77a4f421418b59f00b462a04269f720dc73f1dd/app/assets/images/brands_github.png -------------------------------------------------------------------------------- /app/assets/images/brands_instagram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/African-Ruby-Community/arc_platform/c77a4f421418b59f00b462a04269f720dc73f1dd/app/assets/images/brands_instagram.png -------------------------------------------------------------------------------- /app/assets/images/brands_linkedin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/African-Ruby-Community/arc_platform/c77a4f421418b59f00b462a04269f720dc73f1dd/app/assets/images/brands_linkedin.png -------------------------------------------------------------------------------- /app/assets/images/brands_telegram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/African-Ruby-Community/arc_platform/c77a4f421418b59f00b462a04269f720dc73f1dd/app/assets/images/brands_telegram.png -------------------------------------------------------------------------------- /app/assets/images/brands_twitter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/African-Ruby-Community/arc_platform/c77a4f421418b59f00b462a04269f720dc73f1dd/app/assets/images/brands_twitter.png -------------------------------------------------------------------------------- /app/assets/images/chapter.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/African-Ruby-Community/arc_platform/c77a4f421418b59f00b462a04269f720dc73f1dd/app/assets/images/chapter.jpg -------------------------------------------------------------------------------- /app/assets/images/conference.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/African-Ruby-Community/arc_platform/c77a4f421418b59f00b462a04269f720dc73f1dd/app/assets/images/conference.jpg -------------------------------------------------------------------------------- /app/assets/images/countries.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/African-Ruby-Community/arc_platform/c77a4f421418b59f00b462a04269f720dc73f1dd/app/assets/images/countries.png -------------------------------------------------------------------------------- /app/assets/images/country_kenya.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/African-Ruby-Community/arc_platform/c77a4f421418b59f00b462a04269f720dc73f1dd/app/assets/images/country_kenya.png -------------------------------------------------------------------------------- /app/assets/images/country_rwanda.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/African-Ruby-Community/arc_platform/c77a4f421418b59f00b462a04269f720dc73f1dd/app/assets/images/country_rwanda.png -------------------------------------------------------------------------------- /app/assets/images/country_tanzania.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/African-Ruby-Community/arc_platform/c77a4f421418b59f00b462a04269f720dc73f1dd/app/assets/images/country_tanzania.png -------------------------------------------------------------------------------- /app/assets/images/country_uganda.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/African-Ruby-Community/arc_platform/c77a4f421418b59f00b462a04269f720dc73f1dd/app/assets/images/country_uganda.png -------------------------------------------------------------------------------- /app/assets/images/developers.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/African-Ruby-Community/arc_platform/c77a4f421418b59f00b462a04269f720dc73f1dd/app/assets/images/developers.jpg -------------------------------------------------------------------------------- /app/assets/images/email_arc_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/African-Ruby-Community/arc_platform/c77a4f421418b59f00b462a04269f720dc73f1dd/app/assets/images/email_arc_logo.png -------------------------------------------------------------------------------- /app/assets/images/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/African-Ruby-Community/arc_platform/c77a4f421418b59f00b462a04269f720dc73f1dd/app/assets/images/favicon.ico -------------------------------------------------------------------------------- /app/assets/images/intro-landing.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/African-Ruby-Community/arc_platform/c77a4f421418b59f00b462a04269f720dc73f1dd/app/assets/images/intro-landing.jpg -------------------------------------------------------------------------------- /app/assets/images/sign_up_karate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/African-Ruby-Community/arc_platform/c77a4f421418b59f00b462a04269f720dc73f1dd/app/assets/images/sign_up_karate.png -------------------------------------------------------------------------------- /app/assets/images/sponsors/current/app_signal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/African-Ruby-Community/arc_platform/c77a4f421418b59f00b462a04269f720dc73f1dd/app/assets/images/sponsors/current/app_signal.png -------------------------------------------------------------------------------- /app/assets/images/sponsors/current/finplus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/African-Ruby-Community/arc_platform/c77a4f421418b59f00b462a04269f720dc73f1dd/app/assets/images/sponsors/current/finplus.png -------------------------------------------------------------------------------- /app/assets/images/sponsors/current/friendly_rb.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/African-Ruby-Community/arc_platform/c77a4f421418b59f00b462a04269f720dc73f1dd/app/assets/images/sponsors/current/friendly_rb.jpg -------------------------------------------------------------------------------- /app/assets/images/sponsors/current/kca.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/African-Ruby-Community/arc_platform/c77a4f421418b59f00b462a04269f720dc73f1dd/app/assets/images/sponsors/current/kca.png -------------------------------------------------------------------------------- /app/assets/images/sponsors/current/kopo_kopo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/African-Ruby-Community/arc_platform/c77a4f421418b59f00b462a04269f720dc73f1dd/app/assets/images/sponsors/current/kopo_kopo.png -------------------------------------------------------------------------------- /app/assets/images/sponsors/current/microverse.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/African-Ruby-Community/arc_platform/c77a4f421418b59f00b462a04269f720dc73f1dd/app/assets/images/sponsors/current/microverse.png -------------------------------------------------------------------------------- /app/assets/images/sponsors/current/nairobits.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/African-Ruby-Community/arc_platform/c77a4f421418b59f00b462a04269f720dc73f1dd/app/assets/images/sponsors/current/nairobits.png -------------------------------------------------------------------------------- /app/assets/images/sponsors/current/planet_argon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/African-Ruby-Community/arc_platform/c77a4f421418b59f00b462a04269f720dc73f1dd/app/assets/images/sponsors/current/planet_argon.png -------------------------------------------------------------------------------- /app/assets/images/sponsors/current/ruby_central.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/African-Ruby-Community/arc_platform/c77a4f421418b59f00b462a04269f720dc73f1dd/app/assets/images/sponsors/current/ruby_central.png -------------------------------------------------------------------------------- /app/assets/images/sponsors/previous/andela.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/African-Ruby-Community/arc_platform/c77a4f421418b59f00b462a04269f720dc73f1dd/app/assets/images/sponsors/previous/andela.png -------------------------------------------------------------------------------- /app/assets/images/sponsors/previous/ihub.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/African-Ruby-Community/arc_platform/c77a4f421418b59f00b462a04269f720dc73f1dd/app/assets/images/sponsors/previous/ihub.png -------------------------------------------------------------------------------- /app/assets/images/sponsors/previous/kopokopo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/African-Ruby-Community/arc_platform/c77a4f421418b59f00b462a04269f720dc73f1dd/app/assets/images/sponsors/previous/kopokopo.png -------------------------------------------------------------------------------- /app/assets/images/sponsors/previous/kwara.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/African-Ruby-Community/arc_platform/c77a4f421418b59f00b462a04269f720dc73f1dd/app/assets/images/sponsors/previous/kwara.png -------------------------------------------------------------------------------- /app/assets/images/sponsors/previous/shopify.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/African-Ruby-Community/arc_platform/c77a4f421418b59f00b462a04269f720dc73f1dd/app/assets/images/sponsors/previous/shopify.webp -------------------------------------------------------------------------------- /app/assets/images/sponsors/previous/turing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/African-Ruby-Community/arc_platform/c77a4f421418b59f00b462a04269f720dc73f1dd/app/assets/images/sponsors/previous/turing.png -------------------------------------------------------------------------------- /app/assets/images/workshop.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/African-Ruby-Community/arc_platform/c77a4f421418b59f00b462a04269f720dc73f1dd/app/assets/images/workshop.jpg -------------------------------------------------------------------------------- /app/assets/stylesheets/application.tailwind.css: -------------------------------------------------------------------------------- 1 | @import url('https://fonts.googleapis.com/css2?family=Inter:wght@100..900&display=swap'); 2 | 3 | @tailwind base; 4 | @tailwind components; 5 | @tailwind utilities; 6 | 7 | 8 | @layer base { 9 | :root { 10 | /* Override colors and other variables */ 11 | } 12 | } 13 | 14 | @layer components { 15 | 16 | .turbo-progress-bar { 17 | background: linear-gradient(to right, hsl(var(--p)), hsl(var(--b1))); 18 | } 19 | 20 | @keyframes appear-then-fade { 21 | 0%, 100% { 22 | opacity: 0 23 | } 24 | 5%, 60% { 25 | opacity: 1 26 | } 27 | } 28 | 29 | .alert_custom_class { 30 | animation: appear-then-fade 6s both; 31 | margin-top: 50px; 32 | } 33 | 34 | .text-error { 35 | font-size: .875rem; 36 | color: hsl(var(--er)/var(--tw-border-opacity)); 37 | } 38 | 39 | .resp-table { 40 | width: 100%; 41 | display: table; 42 | } 43 | .resp-table-body{ 44 | display: table-row-group; 45 | } 46 | .resp-table-row{ 47 | display: table-row; 48 | } 49 | .table-body-cell{ 50 | display: table-cell; 51 | border: 1px solid #dddddd; 52 | padding: 8px; 53 | line-height: 1.42857143; 54 | vertical-align: top; 55 | } 56 | 57 | .chapter-grid { 58 | img { 59 | width: 330px; 60 | height: 167px; 61 | } 62 | } 63 | 64 | .rounded-box { 65 | position: relative; 66 | overflow: hidden; 67 | } 68 | 69 | .rounded-box .absolute { 70 | position: absolute; 71 | top: 0; 72 | left: 0; 73 | right: 0; 74 | bottom: 0; 75 | display: flex; 76 | align-items: center; 77 | justify-content: center; 78 | z-index: 10; 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /app/channels/application_cable/channel.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module ApplicationCable 4 | class Channel < ActionCable::Channel::Base 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /app/channels/application_cable/connection.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module ApplicationCable 4 | class Connection < ActionCable::Connection::Base 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /app/controllers/application_controller.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class ApplicationController < ActionController::Base 4 | before_action :authenticate_user! # All users should be authenticated in all controllers by default 5 | before_action :configure_permitted_parameters, if: :devise_controller? 6 | 7 | ## 8 | # CanCanCan permission exception capture 9 | rescue_from CanCan::AccessDenied do |exception| 10 | respond_to do |format| 11 | if user_signed_in? 12 | format.html { redirect_to root_path, alert: exception.message } 13 | else 14 | format.html { redirect_to root_path, alert: t('unauthorized.sign_in') } 15 | end 16 | end 17 | end 18 | 19 | protected 20 | 21 | ## 22 | # Add extra permitted parameters to User's model when devise controller is used 23 | def configure_permitted_parameters 24 | keys = %i[name phone_number github_username] 25 | devise_parameter_sanitizer.permit(:sign_up, keys: keys) 26 | devise_parameter_sanitizer.permit(:account_update, keys: keys) 27 | end 28 | end 29 | -------------------------------------------------------------------------------- /app/controllers/chapters_controller.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class ChaptersController < ApplicationController 4 | include ActiveStorage::SetCurrent 5 | 6 | before_action :set_chapter, only: %i[show] 7 | skip_before_action :authenticate_user!, only: %i[index show] 8 | 9 | # GET /chapters or /chapters.json 10 | def index 11 | @chapters = Chapter.all 12 | end 13 | 14 | # GET /chapters/1 or /chapters/1.json 15 | def show; end 16 | 17 | private 18 | 19 | # Use callbacks to share common setup or constraints between actions. 20 | def set_chapter 21 | @chapter = Chapter.find(params[:id]) 22 | end 23 | end 24 | -------------------------------------------------------------------------------- /app/controllers/concerns/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/African-Ruby-Community/arc_platform/c77a4f421418b59f00b462a04269f720dc73f1dd/app/controllers/concerns/.keep -------------------------------------------------------------------------------- /app/controllers/countries_controller.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class CountriesController < ApplicationController 4 | before_action :set_country, only: %i[show] 5 | 6 | # GET /countries or /countries.json 7 | def index 8 | @countries = Country.all 9 | end 10 | 11 | # GET /countries/1 or /countries/1.json 12 | def show; end 13 | 14 | private 15 | 16 | # Use callbacks to share common setup or constraints between actions. 17 | def set_country 18 | @country = Country.find(params[:id]) 19 | end 20 | end 21 | -------------------------------------------------------------------------------- /app/controllers/landing_controller.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class LandingController < ApplicationController 4 | # People should not require authentication for following actions 5 | skip_before_action :authenticate_user!, only: %i[index about learn] 6 | def index; end 7 | 8 | ## 9 | # About us page 10 | def about; end 11 | 12 | ## 13 | # Featured learning materials 14 | def learn; end 15 | end 16 | -------------------------------------------------------------------------------- /app/controllers/projects_controller.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class ProjectsController < ApplicationController 4 | before_action :set_project, only: %i[show] 5 | 6 | # GET /projects or /projects.json 7 | def index 8 | @projects = Project.all 9 | end 10 | 11 | # GET /projects/1 or /projects/1.json 12 | def show; end 13 | 14 | private 15 | 16 | # Use callbacks to share common setup or constraints between actions. 17 | def set_project 18 | @project = Project.find(params[:id]) 19 | end 20 | end 21 | -------------------------------------------------------------------------------- /app/controllers/turbo_devise_controller.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class TurboDeviseController < ApplicationController 4 | class Responder < ActionController::Responder 5 | def to_turbo_stream 6 | controller.render(options.merge(formats: :html)) 7 | rescue ActionView::MissingTemplate => e 8 | if get? 9 | raise e 10 | elsif has_errors? && default_action 11 | render rendering_options.merge(formats: :html, status: :unprocessable_entity) 12 | else 13 | redirect_to navigation_location 14 | end 15 | end 16 | end 17 | 18 | self.responder = Responder 19 | respond_to :html, :turbo_stream 20 | end 21 | -------------------------------------------------------------------------------- /app/controllers/users/registrations_controller.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | ## 4 | # Devise override Registration controller 5 | module Users 6 | class RegistrationsController < Devise::RegistrationsController 7 | ## 8 | # Devise override Registration create action 9 | def create 10 | super do 11 | resource.users_chapters.create(chapter_id: params[:chapter_id], main_chapter: true) if resource.persisted? 12 | end 13 | end 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /app/helpers/application_helper.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module ApplicationHelper 4 | end 5 | -------------------------------------------------------------------------------- /app/helpers/chapters_helper.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module ChaptersHelper 4 | ACTIVITIES = [ 5 | { image: 'activities_local_meetups.png', title: 'Local meetups' }, 6 | { image: 'activities_local_conferences.png', title: 'conferences' }, 7 | { image: 'activities_local_programming.png', title: 'programming' }, 8 | { image: 'activities_local_workshops.png', title: 'workshops' }, 9 | { image: 'activities_local_hackathons.png', title: 'hackathons' } 10 | ].freeze 11 | 12 | CHAPTERS = [ 13 | { country: 'Kenya', image: 'country_kenya.png', alt: 'Nairuby' }, 14 | { country: 'Rwanda', image: 'country_rwanda.png', alt: 'ARC_Rwanda' }, 15 | { country: 'Tanzania', image: 'country_tanzania.png', alt: 'ARC_Tanzania' }, 16 | { country: 'Uganda', image: 'country_uganda.png', alt: 'ARC_Uganda' } 17 | ].freeze 18 | 19 | FEATURED_SPONSORS = [ 20 | { image: 'sponsors/current/solutech_official.svg', link: 'https://solutech.co.ke', alt: 'Solutech' }, 21 | { image: 'sponsors/current/microverse.png', link: 'https://www.microverse.org/', alt: 'Microverse' }, 22 | { image: 'sponsors/current/app_signal.png', link: 'https://www.appsignal.com', alt: 'App Signal' }, 23 | { image: 'sponsors/current/ruby_central.png', link: 'https://rubycentral.org/', alt: 'Ruby Central' }, 24 | 25 | { image: 'sponsors/current/kopo_kopo.png', link: 'https://kopokopo.co.ke', alt: 'Kopo Kopo' }, 26 | { image: 'sponsors/current/finplus.png', link: 'https://finplusgroup.com', alt: 'Finplus Group' }, 27 | { image: 'sponsors/current/planet_argon.png', link: 'https://www.planetargon.com', alt: 'Planet Argon' }, 28 | { image: 'sponsors/current/friendly_rb.jpg', link: 'https://friendlyrb.com/', alt: 'FriendlyRB' }, 29 | { image: 'sponsors/current/kca.png', link: 'https://www.kcau.ac.ke', alt: 'KCA University' }, 30 | { image: 'sponsors/current/nairobits.png', link: 'https://www.nairobits.com/', alt: 'Nairobits' } 31 | ].freeze 32 | 33 | PREVIOUS_SPONSORS = [ 34 | { image: 'sponsors/previous/shopify.webp', link: 'https://www.shopify.com/', alt: 'Shopify' }, 35 | { image: 'sponsors/previous/turing.png', link: 'https://www.turing.com/', alt: 'Turing' }, 36 | { image: 'sponsors/previous/kopokopo.png', link: 'https://kopokopo.co.ke', alt: 'Kopokopo' }, 37 | { image: 'sponsors/previous/kwara.png', link: 'https://kwara.com/', alt: 'Kwara' }, 38 | { image: 'sponsors/previous/ihub.png', link: 'https://ihub.co.ke/', alt: 'iHub, Nairobi' }, 39 | { image: 'sponsors/previous/andela.png', link: 'https://andela.com/', alt: 'Andela' } 40 | ].freeze 41 | 42 | SOCIALS = [ 43 | { alt: 'ARC Twitter', link: 'https://twitter.com/ruby_african', image: 'brands_twitter.png', show: true }, 44 | { alt: 'ARC telegram', link: '#', image: 'brands_telegram.png', 45 | show: FeatureFlag.find_by(name: 'telegram')&.enabled }, 46 | { alt: 'ARC facebook', link: 'https://www.facebook.com/rubycommunity.africa', image: 'brands_facebook.png', 47 | show: true }, 48 | { alt: 'ARC Instagram', link: '#', image: 'brands_instagram.png', show: true }, 49 | { alt: 'ARC LinkedIn', link: 'https://www.linkedin.com/company/african-ruby-community/', 50 | image: 'brands_linkedin.png', show: true }, 51 | { alt: 'ARC Github', link: 'https://github.com/nairuby', image: 'brands_github.png', show: true } 52 | ].freeze 53 | 54 | def activities 55 | ACTIVITIES 56 | end 57 | 58 | def chapters 59 | CHAPTERS 60 | end 61 | 62 | def featured_sponsors 63 | FEATURED_SPONSORS 64 | end 65 | 66 | def previous_sponsors 67 | PREVIOUS_SPONSORS 68 | end 69 | 70 | def socials 71 | SOCIALS 72 | end 73 | end 74 | -------------------------------------------------------------------------------- /app/helpers/countries_helper.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module CountriesHelper 4 | end 5 | -------------------------------------------------------------------------------- /app/helpers/projects_helper.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module ProjectsHelper 4 | end 5 | -------------------------------------------------------------------------------- /app/javascript/application.js: -------------------------------------------------------------------------------- 1 | // Entry point for the build script in your package.json 2 | import "@hotwired/turbo-rails" 3 | import "./controllers" 4 | -------------------------------------------------------------------------------- /app/javascript/controllers/application.js: -------------------------------------------------------------------------------- 1 | import { Application } from "@hotwired/stimulus" 2 | 3 | const application = Application.start() 4 | 5 | // Configure Stimulus development experience 6 | application.debug = false 7 | window.Stimulus = application 8 | 9 | export { application } 10 | -------------------------------------------------------------------------------- /app/javascript/controllers/hello_controller.js: -------------------------------------------------------------------------------- 1 | import { Controller } from "@hotwired/stimulus" 2 | 3 | export default class extends Controller { 4 | connect() { 5 | this.element.textContent = "Hello World!" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /app/javascript/controllers/index.js: -------------------------------------------------------------------------------- 1 | // This file is auto-generated by ./bin/rails stimulus:manifest:update 2 | // Run that command whenever you add a new controller or create them with 3 | // ./bin/rails generate stimulus controllerName 4 | 5 | import { application } from "./application" 6 | 7 | import HelloController from "./hello_controller.js" 8 | application.register("hello", HelloController) 9 | 10 | import RemovalsController from "./removals_controller.js" 11 | application.register("removals", RemovalsController) 12 | 13 | import TurboFramesController from "./turbo_frames_controller.js" 14 | application.register("turbo_frames", TurboFramesController) 15 | -------------------------------------------------------------------------------- /app/javascript/controllers/removals_controller.js: -------------------------------------------------------------------------------- 1 | import { Controller } from "@hotwired/stimulus" 2 | 3 | // Connects to data-controller="removals" 4 | export default class extends Controller { 5 | remove() { 6 | this.element.remove() 7 | } 8 | 9 | remove_on_click() { 10 | // TODO: add animation to slowly remove element. 11 | this.element.remove() 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /app/javascript/controllers/turbo_frames_controller.js: -------------------------------------------------------------------------------- 1 | import {Controller} from "@hotwired/stimulus" 2 | 3 | export default class extends Controller { 4 | connect() { 5 | if (this.element.id.includes("chapter-modal")) { 6 | window.location.href = "#" + this.element.id 7 | } 8 | } 9 | 10 | disconnect() { 11 | if (this.element.id.includes("chapter-modal")) { 12 | window.location.href = "#" 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /app/jobs/application_job.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class ApplicationJob < ActiveJob::Base 4 | # Automatically retry jobs that encountered a deadlock 5 | # retry_on ActiveRecord::Deadlocked 6 | 7 | # Most jobs are safe to ignore if the underlying records are no longer available 8 | # discard_on ActiveJob::DeserializationError 9 | end 10 | -------------------------------------------------------------------------------- /app/mailers/application_mailer.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class ApplicationMailer < ActionMailer::Base 4 | default from: 'no-reply@rubycommunity.africa' 5 | layout 'mailer' 6 | end 7 | -------------------------------------------------------------------------------- /app/mailers/devise_mailer.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class DeviseMailer < Devise::Mailer 4 | default from: 'no-reply@rubycommunity.africa' 5 | layout 'mailer' 6 | end 7 | -------------------------------------------------------------------------------- /app/models/ability.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class Ability 4 | include CanCan::Ability 5 | 6 | def initialize(user) 7 | # Define abilities for the user here. For example: 8 | # 9 | # return unless user.present? 10 | # can :read, :all 11 | # return unless user.admin? 12 | # can :manage, :all 13 | # 14 | # The first argument to `can` is the action you are giving the user 15 | # permission to do. 16 | # If you pass :manage it will apply to every action. Other common actions 17 | # here are :read, :create, :update and :destroy. 18 | # 19 | # The second argument is the resource the user can perform the action on. 20 | # If you pass :all it will apply to every resource. Otherwise pass a Ruby 21 | # class of the resource. 22 | # 23 | # The third argument is an optional hash of conditions to further filter the 24 | # objects. 25 | # For example, here the user can only update published articles. 26 | # 27 | # can :update, Article, published: true 28 | # 29 | # See the wiki for details: 30 | # https://github.com/CanCanCommunity/cancancan/blob/develop/docs/define_check_abilities.md 31 | 32 | user ||= User.new # guest user (not logged in) 33 | 34 | return unless user.organization_admin? 35 | 36 | can :manage, :all # Organization admin can manage everything 37 | end 38 | end 39 | -------------------------------------------------------------------------------- /app/models/application_record.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class ApplicationRecord < ActiveRecord::Base 4 | primary_abstract_class 5 | end 6 | -------------------------------------------------------------------------------- /app/models/chapter.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # == Schema Information 4 | # 5 | # Table name: chapters 6 | # 7 | # id :bigint not null, primary key 8 | # description :text 9 | # location :string 10 | # name :string 11 | # created_at :datetime not null 12 | # updated_at :datetime not null 13 | # country_id :bigint 14 | # 15 | # Indexes 16 | # 17 | # index_chapters_on_country_id (country_id) 18 | # index_chapters_on_name (name) UNIQUE 19 | # 20 | class Chapter < ApplicationRecord 21 | # Attachments 22 | has_one_attached :image 23 | 24 | # Associations 25 | belongs_to :country 26 | has_many :projects, dependent: :nullify 27 | has_many :users_chapters, dependent: :destroy 28 | has_many :users, through: :users_chapters 29 | 30 | # Validations 31 | validates :name, :location, :description, presence: true 32 | validates :name, uniqueness: true 33 | 34 | ## 35 | # Image validation not working because of 'no implicit conversion of StringIO into String' error 36 | # validates :image, attached: true, content_type: %i[jpg png jpeg], 37 | # dimension: { 38 | # width: 400, height: 225, 39 | # message: 'is not given between dimension. It should be 400x225', 40 | # } 41 | end 42 | -------------------------------------------------------------------------------- /app/models/concerns/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/African-Ruby-Community/arc_platform/c77a4f421418b59f00b462a04269f720dc73f1dd/app/models/concerns/.keep -------------------------------------------------------------------------------- /app/models/country.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # == Schema Information 4 | # 5 | # Table name: countries 6 | # 7 | # id :bigint not null, primary key 8 | # name :string 9 | # created_at :datetime not null 10 | # updated_at :datetime not null 11 | # 12 | class Country < ApplicationRecord 13 | # Associations 14 | has_many :chapters, dependent: :nullify 15 | 16 | # Callbacks 17 | after_create_commit lambda { 18 | broadcast_prepend_to 'countries', partial: 'countries/created_country', 19 | locals: { country: self }, target: 'countries' 20 | } 21 | 22 | after_update_commit lambda { 23 | broadcast_update_to 'countries', partial: 'countries/updated_country', 24 | locals: { country: self }, target: self 25 | } 26 | 27 | after_destroy_commit -> { broadcast_remove_to 'countries', target: self } 28 | 29 | # Validations 30 | validates :name, presence: true 31 | end 32 | -------------------------------------------------------------------------------- /app/models/feature_flag.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # == Schema Information 4 | # 5 | # Table name: feature_flags 6 | # 7 | # id :bigint not null, primary key 8 | # description :text 9 | # enabled :boolean 10 | # name :string 11 | # created_at :datetime not null 12 | # updated_at :datetime not null 13 | # 14 | class FeatureFlag < ApplicationRecord 15 | end 16 | -------------------------------------------------------------------------------- /app/models/motor/ability.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | ## 4 | # CanCan permissions for motor_admin 5 | module Motor 6 | class Ability 7 | include CanCan::Ability 8 | 9 | def initialize(user, _request) 10 | case user.role 11 | when 'organization_admin' 12 | can :manage, :all 13 | end 14 | end 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /app/models/project.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # == Schema Information 4 | # 5 | # Table name: projects 6 | # 7 | # id :bigint not null, primary key 8 | # description :text 9 | # end_date :datetime 10 | # name :string 11 | # start_date :datetime 12 | # created_at :datetime not null 13 | # updated_at :datetime not null 14 | # chapter_id :bigint not null 15 | # 16 | # Indexes 17 | # 18 | # index_projects_on_chapter_id (chapter_id) 19 | # 20 | # Foreign Keys 21 | # 22 | # fk_rails_... (chapter_id => chapters.id) 23 | # 24 | class Project < ApplicationRecord 25 | belongs_to :chapter 26 | end 27 | -------------------------------------------------------------------------------- /app/models/user.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # == Schema Information 4 | # 5 | # Table name: users 6 | # 7 | # id :bigint not null, primary key 8 | # confirmation_sent_at :datetime 9 | # confirmation_token :string 10 | # confirmed_at :datetime 11 | # current_sign_in_at :datetime 12 | # current_sign_in_ip :string 13 | # email :string default(""), not null 14 | # encrypted_password :string default(""), not null 15 | # failed_attempts :integer default(0), not null 16 | # github_username :string 17 | # last_sign_in_at :datetime 18 | # last_sign_in_ip :string 19 | # locked_at :datetime 20 | # name :string 21 | # phone_number :string 22 | # remember_created_at :datetime 23 | # reset_password_sent_at :datetime 24 | # reset_password_token :string 25 | # role :integer 26 | # sign_in_count :integer default(0), not null 27 | # unconfirmed_email :string 28 | # unlock_token :string 29 | # created_at :datetime not null 30 | # updated_at :datetime not null 31 | # 32 | # Indexes 33 | # 34 | # index_users_on_confirmation_token (confirmation_token) UNIQUE 35 | # index_users_on_email (email) UNIQUE 36 | # index_users_on_github_username (github_username) UNIQUE 37 | # index_users_on_reset_password_token (reset_password_token) UNIQUE 38 | # index_users_on_unlock_token (unlock_token) UNIQUE 39 | # 40 | class User < ApplicationRecord 41 | # Include default devise modules. Others available are: 42 | # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable 43 | devise :database_authenticatable, :registerable, 44 | :recoverable, :rememberable, :validatable, 45 | :confirmable, :lockable, :timeoutable 46 | 47 | # Associations 48 | has_many :users_chapters, dependent: :nullify 49 | has_many :chapters, through: :users_chapters 50 | 51 | # Callbacks 52 | before_create :set_defaults # Set model defaults before create 53 | 54 | # Enums 55 | enum role: { member: 0, chapter_admin: 1, organization_admin: 2 } 56 | 57 | # Validations 58 | validates :email, :name, :phone_number, :github_username, presence: true 59 | validates :github_username, :phone_number, uniqueness: true 60 | 61 | # Validate the format the Github username when it's present 62 | validates :github_username, format: 63 | { with: /\A(?!.*--|.*-$|.*_)[a-zA-Z0-9][\w-]+[a-zA-Z0-9]{0,39}\z/ }, 64 | unless: -> { github_username.blank? } 65 | 66 | private 67 | 68 | ## 69 | # A method to set model defaults if they are not set. e.g. if role is not set the default will be 70 | # :member. 71 | def set_defaults 72 | self.role ||= :member 73 | end 74 | end 75 | -------------------------------------------------------------------------------- /app/models/users_chapter.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # == Schema Information 4 | # 5 | # Table name: users_chapters 6 | # 7 | # id :bigint not null, primary key 8 | # main_chapter :boolean default(FALSE) 9 | # created_at :datetime not null 10 | # updated_at :datetime not null 11 | # chapter_id :bigint not null 12 | # user_id :bigint not null 13 | # 14 | # Indexes 15 | # 16 | # index_users_chapters_on_chapter_id (chapter_id) 17 | # index_users_chapters_on_user_id (user_id) 18 | # 19 | # Foreign Keys 20 | # 21 | # fk_rails_... (chapter_id => chapters.id) 22 | # fk_rails_... (user_id => users.id) 23 | # 24 | class UsersChapter < ApplicationRecord 25 | # Associations 26 | belongs_to :chapter 27 | belongs_to :user 28 | end 29 | -------------------------------------------------------------------------------- /app/views/chapters/_chapter.html.erb: -------------------------------------------------------------------------------- 1 |
2 | <%= chapter.name %> 3 |
4 |
5 | <%= chapter.country.try(:name) %> 6 |
7 |
8 | <%= chapter.location %> 9 |
10 | -------------------------------------------------------------------------------- /app/views/chapters/index.html.erb: -------------------------------------------------------------------------------- 1 | <% content_for(:title,"Chapters") %> 2 | <% content_for(:description," A showcase of the different ruby communities spread across the East African region.") %> 3 |
4 |

5 | Chapters 6 |

7 | 8 |
10 | <% @chapters.each do |chapter| %> 11 |
13 | <%= image_tag chapter.image.attached? ? chapter.image.url : image_path('chapter.jpg'), 14 | alt: chapter.name, 15 | class: "rounded-lg rounded-tl-2xl" 16 | %> 17 | 18 |
19 | <%= chapter.name %> 20 |
21 |
22 | <% end %> 23 |
24 |
25 | -------------------------------------------------------------------------------- /app/views/chapters/show.html.erb: -------------------------------------------------------------------------------- 1 |

<%= notice %>

2 | 3 | <%= render @chapter %> 4 | 5 |
6 | <%= link_to "Back to chapters", chapters_path %> 7 |
8 | -------------------------------------------------------------------------------- /app/views/countries/_country.html.erb: -------------------------------------------------------------------------------- 1 |
2 |

3 | Name: 4 | <%= country.name %> 5 |

6 |
7 | -------------------------------------------------------------------------------- /app/views/countries/_created_country.html.erb: -------------------------------------------------------------------------------- 1 |
2 |

3 | Name: 4 | <%= country.name %> 5 |

6 |
-------------------------------------------------------------------------------- /app/views/countries/index.html.erb: -------------------------------------------------------------------------------- 1 | <%= turbo_stream_from "countries" %> 2 | 3 |
4 |

5 | Countries 6 |

7 | 8 |
9 | <%= turbo_frame_tag Country.new %> 10 |
11 |
12 |
13 |
14 |
15 | Name 16 |
17 |
18 | Actions 19 |
20 |
21 |
22 | 23 | <%= turbo_frame_tag :countries, class: "resp-table-body" do %> 24 | <% @countries.each do |country| %> 25 | <%= turbo_frame_tag country, class: "resp-table-row" do %> 26 |
27 | <%= country.name %> 28 |
29 | <% end %> 30 | <% end %> 31 | <% end %> 32 |
33 |
34 |
35 |
36 | 37 | -------------------------------------------------------------------------------- /app/views/countries/show.html.erb: -------------------------------------------------------------------------------- 1 |

<%= notice %>

2 | 3 | <%= render @country %> 4 | 5 |
6 | <%= link_to "Back to countries", countries_path %> 7 |
8 | -------------------------------------------------------------------------------- /app/views/devise/confirmations/new.html.erb: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 | <%= image_tag 'sign_up_karate.png' %> 5 |
6 |
7 |

Resend confirmation instructions

8 | 9 | <%= simple_form_for(resource, as: resource_name, 10 | url: confirmation_path(resource_name)) do |f| %> 11 | <%= f.input :email, placeholder: 'Enter email address', label: 'Email', 12 | input_html: { class: 'input-bordered w-full', autocomplete: 'email', 13 | autofocus: true, 14 | value: (resource.pending_reconfirmation? ? resource.unconfirmed_email : resource.email) } %> 15 | 16 |
17 | <%= f.button :button, 'Resend instructions', class: 'btn btn-primary' %> 18 |
19 | <% end %> 20 | 21 |
22 | <%= render "devise/shared/links" %> 23 |
24 |
25 |
26 | -------------------------------------------------------------------------------- /app/views/devise/mailer/confirmation_instructions.html.erb: -------------------------------------------------------------------------------- 1 | 2 | 3 | Confirm your email 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 18 | 19 |
12 |

Welcome <%= @email %>!

13 | 14 |

You can confirm your account email through the link below:

15 | 16 |

<%= link_to 'Confirm my account', confirmation_url(@resource, confirmation_token: @token) %>

17 |
20 | 21 | 22 | -------------------------------------------------------------------------------- /app/views/devise/mailer/email_changed.html.erb: -------------------------------------------------------------------------------- 1 | 2 | 3 | Your email has changed 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 20 | 21 |
12 |

Hello <%= @email %>!

13 | 14 | <% if @resource.try(:unconfirmed_email?) %> 15 |

We're contacting you to notify you that your email is being changed to <%= @resource.unconfirmed_email %>.

16 | <% else %> 17 |

We're contacting you to notify you that your email has been changed to <%= @resource.email %>.

18 | <% end %> 19 |
22 | 23 | 24 | -------------------------------------------------------------------------------- /app/views/devise/mailer/password_change.html.erb: -------------------------------------------------------------------------------- 1 | 2 | 3 | Your password has changed 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 16 | 17 |
12 |

Hello <%= @resource.email %>!

13 | 14 |

We're contacting you to notify you that your password has been changed.

15 |
18 | 19 | 20 | -------------------------------------------------------------------------------- /app/views/devise/mailer/reset_password_instructions.html.erb: -------------------------------------------------------------------------------- 1 | 2 | 3 | Reset password instructions 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 22 | 23 |
12 |

Hello <%= @resource.email %>!

13 | 14 |

Someone has requested a link to change your password. You can do this through the link 15 | below.

16 | 17 |

<%= link_to 'Change my password', edit_password_url(@resource, reset_password_token: @token) %>

18 | 19 |

If you didn't request this, please ignore this email.

20 |

Your password won't change until you access the link above and create a new one.

21 |
24 | 25 | 26 | -------------------------------------------------------------------------------- /app/views/devise/mailer/unlock_instructions.html.erb: -------------------------------------------------------------------------------- 1 | 2 | 3 | Unlock account instructions 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 20 | 21 |
12 |

Hello <%= @resource.email %>!

13 | 14 |

Your account has been locked due to an excessive number of unsuccessful sign in attempts.

15 | 16 |

Click the link below to unlock your account:

17 | 18 |

<%= link_to 'Unlock my account', unlock_url(@resource, unlock_token: @token) %>

19 |
22 | 23 | 24 | -------------------------------------------------------------------------------- /app/views/devise/passwords/edit.html.erb: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 | <%= image_tag 'sign_up_karate.png' %> 5 |
6 |
7 |

Change your password

8 | 9 | <%= simple_form_for(resource, as: resource_name, 10 | url: password_path(resource_name), html: { method: :put }) do |f| %> 11 | <%= f.hidden_field :reset_password_token %> 12 | 13 | <%= f.input :password, placeholder: 'Enter new password', label: 'Password', 14 | input_html: { class: 'input-bordered w-full', autofocus: true, 15 | autocomplete: "new-password" } %> 16 | 17 | <%= f.input :password_confirmation, placeholder: 'Confirm new password', 18 | label: 'Confirm password', input_html: { class: 'input-bordered w-full', 19 | autocomplete: "new-password" } %> 20 | 21 |
22 | <%= f.button :button, 'Change my password', class: 'btn btn-primary' %> 23 |
24 | <% end %> 25 | 26 |
27 | <%= render "devise/shared/links" %> 28 |
29 |
30 |
31 | 32 | -------------------------------------------------------------------------------- /app/views/devise/passwords/new.html.erb: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 | <%= image_tag 'sign_up_karate.png' %> 5 |
6 |
7 |

Forgot your password?

8 | 9 | <%= simple_form_for(resource, as: resource_name, 10 | url: password_path(resource_name)) do |f| %> 11 | <%= f.input :email, placeholder: 'Enter email address', label: 'Email', 12 | input_html: { class: 'input-bordered w-full', autocomplete: 'email', 13 | autofocus: true } %> 14 | 15 |
16 | <%= f.button :button, 'Send me instructions', class: 'btn btn-primary' %> 17 |
18 | <% end %> 19 | 20 |
21 | <%= render "devise/shared/links" %> 22 |
23 |
24 |
25 | -------------------------------------------------------------------------------- /app/views/devise/registrations/edit.html.erb: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 |

Edit account

5 | 6 | <%= simple_form_for(resource, as: resource_name, 7 | url: registration_path(resource_name), html_input: { method: :put }) do |f| %> 8 | <%= f.input :email, placeholder: 'Enter email address', label: 'Email', 9 | input_html: { class: 'input-bordered w-full', autocomplete: 'email' } %> 10 | 11 | <%= f.input :name, placeholder: 'Enter full name', label: 'Full name', 12 | input_html: { class: 'input-bordered w-full', autocomplete: 'name' } %> 13 | 14 | <%= f.input :phone_number, placeholder: 'Enter phone number', label: 'Phone number', 15 | hint: 'Start with a country e.g 254xxxxxxxxx. Use a WhatsApp number if possible', 16 | input_html: { class: 'input-bordered w-full', autocomplete: 'phone_number' } %> 17 | 18 | 24 | 25 | <%= f.input :github_username, placeholder: 'Enter Github username', label: 'Github username', 26 | input_html: { class: 'input-bordered w-full', autocomplete: 'github_username' } %> 27 | 28 | <%= f.input :password, placeholder: 'Enter password', label: 'Password', 29 | hint: "Leave blank if you don't want to change it", 30 | input_html: { class: 'input-bordered w-full' } %> 31 | 32 | <%= f.input :password_confirmation, placeholder: 'Confirm Password', 33 | label: 'Confirm Password', input_html: { class: 'input-bordered w-full' } %> 34 | 35 | <%= f.input :current_password, placeholder: 'Current Password', 36 | hint: 'We need your current password to confirm your changes', 37 | label: 'Current Password', input_html: { class: 'input-bordered w-full' } %> 38 | 39 |
40 | <%= f.button :button, 'Update Account', class: 'btn btn-primary' %> 41 |
42 | <% end %> 43 | 44 |
45 | 46 |
47 | 48 | <%= button_to "Unhappy? Cancel my account", registration_path(resource_name), 49 | data: { confirm: "Are you sure?" }, method: :delete %> 50 | 51 |
52 |
53 |
54 |
55 | -------------------------------------------------------------------------------- /app/views/devise/registrations/new.html.erb: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 | <%= image_tag 'sign_up_karate.png' %> 5 |
6 |
7 |

Create an account

8 | 9 | <%= simple_form_for(resource, as: resource_name, 10 | url: registration_path(resource_name)) do |f| %> 11 | <%= f.input :email, placeholder: 'Enter email address', label: 'Email', 12 | input_html: { class: 'input-bordered w-full', autocomplete: 'email' } %> 13 | 14 | <%= f.input :name, placeholder: 'Enter full name', label: 'Full name', 15 | input_html: { class: 'input-bordered w-full', autocomplete: 'name' } %> 16 | 17 | <%= f.input :phone_number, placeholder: 'Enter phone number', label: 'Phone number', 18 | hint: 'Start with a country e.g 254xxxxxxxxx. Use a WhatsApp number if possible', 19 | input_html: { class: 'input-bordered w-full', autocomplete: 'phone_number' } %> 20 | 21 | 27 | 28 | <%= f.input :github_username, placeholder: 'Enter Github username', label: 'Github username', 29 | input_html: { class: 'input-bordered w-full', autocomplete: 'github_username' } %> 30 | 31 | <%= f.input :password, placeholder: 'Enter password', label: 'Password', 32 | input_html: { class: 'input-bordered w-full' } %> 33 | 34 | <%= f.input :password_confirmation, placeholder: 'Confirm Password', 35 | label: 'Confirm Password', input_html: { class: 'input-bordered w-full' } %> 36 | 37 |
38 | <%= f.button :button, 'Create Account', class: 'btn btn-primary' %> 39 |
40 | <% end %> 41 | 42 |
43 | <%= render "devise/shared/links" %> 44 |
45 |
46 |
47 | -------------------------------------------------------------------------------- /app/views/devise/sessions/new.html.erb: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 | <%= image_tag 'sign_up_karate.png' %> 5 |
6 |
7 |

Sign In

8 | <%= simple_form_for(resource, as: resource_name, 9 | url: session_path(resource_name)) do |f| %> 10 | <%= f.input :email, placeholder: 'Enter email address', label: 'Email', 11 | input_html: { class: 'input-bordered w-full', autofocus: true, autocomplete: 'email' } %> 12 | 13 | <%= f.input :password, placeholder: 'Enter password', label: 'Password', 14 | input_html: { class: 'input-bordered w-full' } %> 15 | 16 |
17 | <%= f.button :button, 'Sign In', class: 'btn btn-primary' %> 18 |
19 | <% end %> 20 | 21 |
22 | <%= render "devise/shared/links" %> 23 |
24 |
25 |
26 | -------------------------------------------------------------------------------- /app/views/devise/shared/_error_messages.html.erb: -------------------------------------------------------------------------------- 1 | <% if resource.errors.any? %> 2 |
3 |

4 | <%= I18n.t("errors.messages.not_saved", 5 | count: resource.errors.count, 6 | resource: resource.class.model_name.human.downcase) 7 | %> 8 |

9 | 14 |
15 | <% end %> 16 | -------------------------------------------------------------------------------- /app/views/devise/shared/_links.html.erb: -------------------------------------------------------------------------------- 1 | <%- if controller_name != 'sessions' %> 2 |
3 | 4 | <%= link_to "Have an account? Go to login", new_session_path(resource_name) %> 5 | 6 |
7 | <% end %> 8 | 9 | <%- if devise_mapping.registerable? && controller_name != 'registrations' %> 10 |
11 | 12 | <%= link_to "Need an account? Sign up!", new_registration_path(resource_name) %> 13 | 14 |
15 | <% end %> 16 | 17 | <%- if devise_mapping.recoverable? && controller_name != 'passwords' && controller_name != 'registrations' %> 18 |
19 | 20 | <%= link_to "Forgot your password?", new_password_path(resource_name) %> 21 | 22 |
23 | <% end %> 24 | 25 | <%- if devise_mapping.confirmable? && controller_name != 'confirmations' %> 26 |
27 | 28 | <%= link_to "Didn't receive confirmation instructions?", new_confirmation_path(resource_name) %> 29 | 30 |
31 | <% end %> 32 | 33 | <%- if devise_mapping.lockable? && resource_class.unlock_strategy_enabled?(:email) && controller_name != 'unlocks' %> 34 |
35 | 36 | <%= link_to "Didn't receive unlock instructions?", new_unlock_path(resource_name) %> 37 | 38 |
39 | <% end %> 40 | 41 | <%- if devise_mapping.omniauthable? %> 42 | <%- resource_class.omniauth_providers.each do |provider| %> 43 |
44 | 45 | <%= link_to "Sign in with #{OmniAuth::Utils.camelize(provider)}", omniauth_authorize_path(resource_name, provider), method: :post %> 46 | 47 |
48 | <% end %> 49 | <% end %> 50 | -------------------------------------------------------------------------------- /app/views/devise/unlocks/new.html.erb: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 | <%= image_tag 'sign_up_karate.png' %> 5 |
6 |
7 |

Resend unlock instructions

8 | 9 | <%= simple_form_for(resource, as: resource_name, 10 | url: unlock_path(resource_name)) do |f| %> 11 | <%= f.input :email, placeholder: 'Enter email address', label: 'Email', 12 | input_html: { class: 'input-bordered w-full', autocomplete: 'email', 13 | autofocus: true } %> 14 | 15 |
16 | <%= f.button :button, 'Resend instructions', class: 'btn btn-primary' %> 17 |
18 | <% end %> 19 | 20 |
21 | <%= render "devise/shared/links" %> 22 |
23 |
24 |
25 | -------------------------------------------------------------------------------- /app/views/landing/about.html.erb: -------------------------------------------------------------------------------- 1 | <% content_for(:title,"About us") %> 2 | <% content_for(:description,"ARC brings entrepreneurs, developers, Designers, open source contributors together") %> 3 |
4 | <%= image_tag('workshop.jpg', alt:"ARC Workshop", class: "pt-20 w-fit h-fit", style: "filter: brightness(40%);") %> 5 |
6 | 7 |
8 |

9 | About ARC - African Ruby Community 10 |

11 | 12 |

13 | African Ruby Community, ARC, is an organization that was started in 2010. 14 | The community currently has a reach of over 5,000 members spread across East Africa, 15 | made up of developers (engineers), entrepreneurs, designers, and freelancers. 16 | In terms of development and demonstrations, the community focuses on Ruby technologies and frameworks, 17 | which are all open source and widely used by startups to prototype and carry out proof of concept with a go-to-market strategy. 18 |

19 | 20 |

21 | The community hosts weekly and monthly meetups in different cities in East Africa. 22 | The community brings you Ruby Conference every year with different themes to fill the gap 23 | that exists between school and industry and in return helps spur innovation and growth in 24 | contribution to the global economy. 25 |

26 | 27 |

28 | ARC brings entrepreneurs, developers, designers, and open source contributors. 29 | Why? We believe in a holistic approach; through entrepreneurship, a “solution approach,” 30 | and open source, we can solve so many problems. This in return empowers everyone who 31 | attends with technology “tools” and entrepreneurship “methodology” to reach their fullest 32 | potential and inspire the rest of the world and their communities. 33 |

34 |
35 | -------------------------------------------------------------------------------- /app/views/landing/home/_activities.html.erb: -------------------------------------------------------------------------------- 1 |

2 | Activities 3 |

4 | 5 |
6 | <% activities.each do |activity| %> 7 |
8 | <%= image_tag activity[:image], alt: activity[:title], class: 'hover:scale-105' %> 9 |

<%= activity[:title] %>

10 |
11 | <% end %> 12 |
13 | -------------------------------------------------------------------------------- /app/views/landing/home/_chapters.html.erb: -------------------------------------------------------------------------------- 1 |
2 |

3 | Chapters 4 |

5 | 6 |
7 | <% chapters. each do |chapter| %> 8 | <%= link_to new_user_registration_path, class: 'place-self-center w-72 md:w-48 card border border-red-600 rounded flex flex-col gap-4 hover:scale-95 p-3' do %> 9 | <%= image_tag chapter[:image], alt: chapter[:alt], class: 'pt-2 place-self-center h-16 md:36' %> 10 |

<%= chapter[:country] %>

11 |

Join community

12 | <% end %> 13 | <% end %> 14 | 15 | 16 | <%= image_tag('add.png',alt:" Add Chapter",class: 'pt-2 place-self-center h-16 md:36') %> 17 |

Request new chapter

18 |

19 |
20 |
21 |
22 | -------------------------------------------------------------------------------- /app/views/landing/home/_coming_up_events.html.erb: -------------------------------------------------------------------------------- 1 |
2 |
3 |

Events Coming Up

4 |
5 | 6 |
7 | 45 |
46 | 47 |
48 | 49 |
50 |

51 | View more events 52 |

53 | 54 |
55 | 57 | 60 | 61 |
62 |
63 |
64 |
65 |
66 | -------------------------------------------------------------------------------- /app/views/landing/home/_featured_sponsors.html.erb: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | <%# featured_sponsors.each do |sponsor| %> 8 | <%#= link_to sponsor[:link], target: '_blank' do %> 9 | 10 | <%#= image_tag sponsor[:image], alt: sponsor[:alt] %> 11 | 12 | <%# end %> 13 | <%# end %> 14 | 15 | 16 | 17 |
18 |

19 | Featured Sponsors 20 |

21 | 22 |
23 | <% featured_sponsors.each do |sponsor| %> 24 | <%= link_to sponsor[:link], target: '_blank' do %> 25 |
26 |
27 | <%= image_tag sponsor[:image], alt: sponsor[:alt], class: 'w-full h-full object-contain' %> 28 |
29 |
30 | <% end %> 31 | <% end %> 32 |
33 | 34 |
-------------------------------------------------------------------------------- /app/views/landing/home/_intro.html.erb: -------------------------------------------------------------------------------- 1 |
2 |
3 | <%= image_tag 'intro-landing.jpg', alt: "Ruby Conf Africa 2025", class: "w-full object-cover rounded-lg" %> 4 |
5 |
6 | <%= link_to "https://rubyconf.africa", title: "Click to visit Ruby Conf Africa 2025", class: "block relative z-10" do %> 7 |
8 | 9 | Ruby Conf Africa 2025 🔗 10 | 11 | 12 | <% end %> 13 |
14 |
15 |
16 | 17 |
18 |
19 |

20 | African Ruby Community 21 |

22 | 23 |

24 | A community organization that seeks to promote computer software programming skills with 25 | the Ruby programming language. 26 |

27 | 28 |
29 | <%= link_to new_user_registration_path do %> 30 | 38 | <% end %> 39 |
40 |
41 | 42 |
43 |
44 |

5000 +

45 |

Members across East Africa

46 |
47 |
48 | <%= image_tag 'developers.jpg', class: 'w-full lg:h-[110%] object-cover rounded-lg lg:rounded-tr-full' %> 49 |
50 |
51 | <%= image_tag 'conference.jpg', class: 'w-full h-full object-cover rounded-lg lg:rounded-bl-full' %> 52 |
53 |
54 |

55 | <%= Time.now.year - 2010 %> + 56 |

57 |

58 | Years of Ruby community 59 |

60 |
61 |
62 |
63 | -------------------------------------------------------------------------------- /app/views/landing/home/_previous_sponsors.html.erb: -------------------------------------------------------------------------------- 1 |
2 |

3 | Previous Sponsors 4 |

5 | 6 |
7 | 8 | <% previous_sponsors.each do |sponsor| %> 9 | <%= link_to sponsor[:link], target: '_blank' do %> 10 |
11 |
12 | <%= image_tag sponsor[:image], alt: sponsor[:alt] %> 13 |
14 |
15 | <% end %> 16 | <% end %> 17 |
18 | 19 | 31 |
32 | 33 | -------------------------------------------------------------------------------- /app/views/landing/home/_projects.html.erb: -------------------------------------------------------------------------------- 1 |
2 |
3 |

Projects

4 |

ARC members also create open source applications that are of use to the 5 | wider Ruby 6 | community and showcase software development skills available.

7 |
8 |
9 |
10 | 48 |
49 | 50 | 68 |
69 |
70 | -------------------------------------------------------------------------------- /app/views/landing/home/_who_we_are.html.erb: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 |
5 |
6 |

7 | African Ruby Community 8 |

9 |

10 | Who are We? 11 |

12 |
13 |
14 |
15 |
16 |

17 | African Ruby Community, ARC is an organization that was started in 2010. The community currently has over reach of over 5,000 members spread across East Africa, made of developers (Engineers), entrepreneurs, designers and freelancers. In terms of development and demonstrations the community focuses on ruby technologies and frameworks, which are all open source and widely used by startups to prototype and carry out proof of concept with a go to market strategy. 18 |

19 |

20 | The community hosts weekly and monthly meetups in different cities in East Africa. The community brings you Ruby Conference every year with different themes to fill the gap that exist between school and industry and in return helps spur innovation and growth in contribution to global economy. 21 |

22 |
23 | 24 |
25 | <%= link_to landing_about_path do %> 26 | 34 | <% end %> 35 |
36 |
37 |
38 |
39 |
40 | -------------------------------------------------------------------------------- /app/views/landing/index.html.erb: -------------------------------------------------------------------------------- 1 | <%= render 'landing/home/intro' %> 2 | 3 | <% if FeatureFlag.find_by(name: 'events').try(:enabled) %> 4 | <%= render 'landing/home/coming_up_events' %> 5 | <% end %> 6 | 7 | <%= render 'landing/home/who_we_are' %> 8 | 9 | <%= render 'landing/home/activities' %> 10 | 11 | <% if FeatureFlag.find_by(name: 'projects').try(:enabled) %> 12 | <%= render 'landing/home/projects' %> 13 | <% end %> 14 | 15 | <%= render 'landing/home/chapters' %> 16 | 17 | <%= render 'landing/home/featured_sponsors' %> 18 | 19 | <%= render 'landing/home/previous_sponsors' %> 20 | -------------------------------------------------------------------------------- /app/views/landing/learn.html.erb: -------------------------------------------------------------------------------- 1 | <% content_for(:title,"Learning Materials") %> 2 | <% content_for(:description,"A list of ruby and ruby on rails learning resources compiled by the ARC community") %> 3 |
4 |

5 | Featured learning materials 6 |

7 | 8 |

9 | Take a look at our list of resources that can help you get up to speed with the Ruby programming 10 | language from the basic building blocks upto to the various frameworks and tools in the Ruby 11 | ecosystem. If you want to add your own resources, fork this repo and send in a pull request. 12 |

13 | 14 |

15 | Ruby 16 |

17 | 18 | 74 | 75 |

76 | Ruby Tools 77 |

78 | 79 | 85 | 86 |

87 | Frameworks 88 |

89 | 90 | 158 |
159 | -------------------------------------------------------------------------------- /app/views/layouts/_flash_messages.html.erb: -------------------------------------------------------------------------------- 1 |
2 | <% if notice || alert %> 3 | <%= content_tag :div, 4 | class: "alert #{ alert ? 'alert-error' : 'alert-success'} alert_custom_class", 5 | data: { controller: 'removals', 6 | action: 'animationend->removals#remove click->removals#remove_on_click' } do %> 7 | 8 | 9 | <% if notice %> 10 | 12 | 14 | <% elsif alert %> 15 | 17 | 19 | 20 | <% end %> 21 | 22 |
<%= content_tag :span, notice || alert %>
23 | <% end %> 24 | <% end %> 25 |
26 | -------------------------------------------------------------------------------- /app/views/layouts/_footer.html.erb: -------------------------------------------------------------------------------- 1 | 60 | -------------------------------------------------------------------------------- /app/views/layouts/_navbar.html.erb: -------------------------------------------------------------------------------- 1 | 2 |
3 |
5 | 36 |
37 | <%= link_to root_path do %> 38 | African Ruby Community 39 | <%= image_tag('arc_logo_coloured.png', alt: "Community Logo",class: "h-8 w-auto sm:h-7") %> 40 | <% end %> 41 |
42 | 70 | <% if user_signed_in? %> 71 | 72 | 131 | <% else %> 132 | 137 | <% end %> 138 |
139 |
140 |
-------------------------------------------------------------------------------- /app/views/layouts/application.html.erb: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | ArcPlatform <%= " - " + yield(:title) if content_for?(:title)%> 5 | > 6 | 7 | <%= csrf_meta_tags %> 8 | <%= csp_meta_tag %> 9 | <%= favicon_link_tag 'favicon.ico' %> 10 | 11 | <%= stylesheet_link_tag "application", "data-turbo-track": "reload" %> 12 | <%= javascript_include_tag "application", "data-turbo-track": "reload", defer: true %> 13 | 14 | 15 | 16 |
17 | 18 | <%= render 'layouts/navbar' %> 19 | 20 |
21 | <%= yield %> 22 |
23 | 24 | <%= render 'layouts/flash_messages' %> 25 | <%= render 'layouts/footer' %> 26 |
27 | 28 | 29 | -------------------------------------------------------------------------------- /app/views/layouts/mailer.html.erb: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | <%= stylesheet_link_tag 'mailgun_mails', media: 'all', 'data-turbolinks-track' => false %> 7 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 36 | 37 | 38 |
17 |
18 | 20 | <%= yield %> 21 |
22 | 34 |
35 |
39 | 40 | 41 | -------------------------------------------------------------------------------- /app/views/layouts/mailer.text.erb: -------------------------------------------------------------------------------- 1 | <%= yield %> 2 | -------------------------------------------------------------------------------- /app/views/projects/_project.html.erb: -------------------------------------------------------------------------------- 1 |
2 |

3 | Name: 4 | <%= project.name %> 5 |

6 | 7 |

8 | Description: 9 | <%= project.description %> 10 |

11 | 12 |

13 | Chapter: 14 | <%= project.chapter_id %> 15 |

16 | 17 |

18 | Start date: 19 | <%= project.start_date %> 20 |

21 | 22 |

23 | End date: 24 | <%= project.end_date %> 25 |

26 | 27 |
28 | -------------------------------------------------------------------------------- /app/views/projects/index.html.erb: -------------------------------------------------------------------------------- 1 |

<%= notice %>

2 | 3 |

Projects

4 | 5 |
6 | <% @projects.each do |project| %> 7 | <%= render project %> 8 |

9 | <%= link_to "Show this project", project %> 10 |

11 | <% end %> 12 |
13 | -------------------------------------------------------------------------------- /app/views/projects/show.html.erb: -------------------------------------------------------------------------------- 1 |

<%= notice %>

2 | 3 | <%= render @project %> 4 | 5 |
6 | <%= link_to "Back to projects", projects_path %> 7 |
8 | -------------------------------------------------------------------------------- /bin/bundle: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | # 5 | # This file was generated by Bundler. 6 | # 7 | # The application 'bundle' is installed as part of a gem, and 8 | # this file is here to facilitate running it. 9 | # 10 | 11 | require "rubygems" 12 | 13 | m = Module.new do 14 | module_function 15 | 16 | def invoked_as_script? 17 | File.expand_path($0) == File.expand_path(__FILE__) 18 | end 19 | 20 | def env_var_version 21 | ENV["BUNDLER_VERSION"] 22 | end 23 | 24 | def cli_arg_version 25 | return unless invoked_as_script? # don't want to hijack other binstubs 26 | return unless "update".start_with?(ARGV.first || " ") # must be running `bundle update` 27 | bundler_version = nil 28 | update_index = nil 29 | ARGV.each_with_index do |a, i| 30 | if update_index && update_index.succ == i && a =~ Gem::Version::ANCHORED_VERSION_PATTERN 31 | bundler_version = a 32 | end 33 | next unless a =~ /\A--bundler(?:[= ](#{Gem::Version::VERSION_PATTERN}))?\z/ 34 | bundler_version = $1 35 | update_index = i 36 | end 37 | bundler_version 38 | end 39 | 40 | def gemfile 41 | gemfile = ENV["BUNDLE_GEMFILE"] 42 | return gemfile if gemfile && !gemfile.empty? 43 | 44 | File.expand_path("../../Gemfile", __FILE__) 45 | end 46 | 47 | def lockfile 48 | lockfile = 49 | case File.basename(gemfile) 50 | when "gems.rb" then gemfile.sub(/\.rb$/, gemfile) 51 | else "#{gemfile}.lock" 52 | end 53 | File.expand_path(lockfile) 54 | end 55 | 56 | def lockfile_version 57 | return unless File.file?(lockfile) 58 | lockfile_contents = File.read(lockfile) 59 | return unless lockfile_contents =~ /\n\nBUNDLED WITH\n\s{2,}(#{Gem::Version::VERSION_PATTERN})\n/ 60 | Regexp.last_match(1) 61 | end 62 | 63 | def bundler_requirement 64 | @bundler_requirement ||= 65 | env_var_version || cli_arg_version || 66 | bundler_requirement_for(lockfile_version) 67 | end 68 | 69 | def bundler_requirement_for(version) 70 | return "#{Gem::Requirement.default}.a" unless version 71 | 72 | bundler_gem_version = Gem::Version.new(version) 73 | 74 | requirement = bundler_gem_version.approximate_recommendation 75 | 76 | return requirement unless Gem.rubygems_version < Gem::Version.new("2.7.0") 77 | 78 | requirement += ".a" if bundler_gem_version.prerelease? 79 | 80 | requirement 81 | end 82 | 83 | def load_bundler! 84 | ENV["BUNDLE_GEMFILE"] ||= gemfile 85 | 86 | activate_bundler 87 | end 88 | 89 | def activate_bundler 90 | gem_error = activation_error_handling do 91 | gem "bundler", bundler_requirement 92 | end 93 | return if gem_error.nil? 94 | require_error = activation_error_handling do 95 | require "bundler/version" 96 | end 97 | return if require_error.nil? && Gem::Requirement.new(bundler_requirement).satisfied_by?(Gem::Version.new(Bundler::VERSION)) 98 | warn "Activating bundler (#{bundler_requirement}) failed:\n#{gem_error.message}\n\nTo install the version of bundler this project requires, run `gem install bundler -v '#{bundler_requirement}'`" 99 | exit 42 100 | end 101 | 102 | def activation_error_handling 103 | yield 104 | nil 105 | rescue StandardError, LoadError => e 106 | e 107 | end 108 | end 109 | 110 | m.load_bundler! 111 | 112 | if m.invoked_as_script? 113 | load Gem.bin_path("bundler", "bundle") 114 | end 115 | -------------------------------------------------------------------------------- /bin/dev: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | if ! command -v foreman &> /dev/null 4 | then 5 | echo "Installing foreman..." 6 | gem install foreman 7 | fi 8 | 9 | foreman start -f Procfile.dev "$@" 10 | -------------------------------------------------------------------------------- /bin/docker-entrypoint: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | 3 | # If running the rails server then create or migrate existing database 4 | if [ "${*}" == "./bin/rails server" ]; then 5 | ./bin/rails db:prepare 6 | fi 7 | 8 | exec "${@}" 9 | -------------------------------------------------------------------------------- /bin/rails: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | APP_PATH = File.expand_path("../config/application", __dir__) 3 | require_relative "../config/boot" 4 | require "rails/commands" 5 | -------------------------------------------------------------------------------- /bin/rake: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require_relative "../config/boot" 3 | require "rake" 4 | Rake.application.run 5 | -------------------------------------------------------------------------------- /bin/setup: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require "fileutils" 3 | 4 | # path to your application root. 5 | APP_ROOT = File.expand_path("..", __dir__) 6 | 7 | def system!(*args) 8 | system(*args) || abort("\n== Command #{args} failed ==") 9 | end 10 | 11 | FileUtils.chdir APP_ROOT do 12 | # This script is a way to set up or update your development environment automatically. 13 | # This script is idempotent, so that you can run it at any time and get an expectable outcome. 14 | # Add necessary setup steps to this file. 15 | 16 | puts "== Installing dependencies ==" 17 | system! "gem install bundler --conservative" 18 | system("bundle check") || system!("bundle install") 19 | 20 | # puts "\n== Copying sample files ==" 21 | # unless File.exist?("config/database.yml") 22 | # FileUtils.cp "config/database.yml.sample", "config/database.yml" 23 | # end 24 | 25 | puts "\n== Preparing database ==" 26 | system! "bin/rails db:prepare" 27 | 28 | puts "\n== Removing old logs and tempfiles ==" 29 | system! "bin/rails log:clear tmp:clear" 30 | 31 | puts "\n== Restarting application server ==" 32 | system! "bin/rails restart" 33 | end 34 | -------------------------------------------------------------------------------- /config.ru: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # This file is used by Rack-based servers to start the application. 4 | 5 | require_relative 'config/environment' 6 | 7 | run Rails.application 8 | Rails.application.load_server 9 | -------------------------------------------------------------------------------- /config/application.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative 'boot' 4 | 5 | require 'rails/all' 6 | 7 | # Require the gems listed in Gemfile, including any gems 8 | # you've limited to :test, :development, or :production. 9 | Bundler.require(*Rails.groups) 10 | 11 | module ArcPlatform 12 | class Application < Rails::Application 13 | # Initialize configuration defaults for originally generated Rails version. 14 | config.load_defaults 7.0 15 | 16 | # Configuration for the application, engines, and railties goes here. 17 | # 18 | # These settings can be overridden in specific environments using the files 19 | # in config/environments, which are processed later. 20 | # 21 | # config.time_zone = "Central Time (US & Canada)" 22 | # config.eager_load_paths << Rails.root.join("extras") 23 | end 24 | end 25 | -------------------------------------------------------------------------------- /config/boot.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__) 4 | 5 | require 'bundler/setup' # Set up gems listed in the Gemfile. 6 | require 'bootsnap/setup' # Speed up boot time by caching expensive operations. 7 | -------------------------------------------------------------------------------- /config/cable.yml: -------------------------------------------------------------------------------- 1 | development: 2 | adapter: redis 3 | url: redis://localhost:6379/1 4 | 5 | test: 6 | adapter: test 7 | 8 | production: 9 | adapter: redis 10 | url: <%= ENV.fetch("REDIS_URL") { "redis://localhost:6379/1" } %> 11 | channel_prefix: arc_platform_production 12 | -------------------------------------------------------------------------------- /config/credentials.yml.enc: -------------------------------------------------------------------------------- 1 | /QITpptG/SWJrbZsDVVBQpbRSfWlT7LzpwAwWJor02o3Fvl/qxJ+aYk9yuWHRzWcSruQHyKynZlUFofra+GVuca53GOQA0YrkqQ++wykYuuMfohAiZNuwO2X2Uq3Y/Chk6co7F6pdGCwev4iw7bv/HeGeUt9BzOW1pdt7JSv3Di2fEYNI2L+J3Fh8xeDYDWzgLjtCbtRh7X3H5roPitkNJLNqExdbggcPNOunfAUj+7VnrsbNTxRlSCaLU/i862kSI6SRcTqxR6PY+rv0GB0p6kSWOuEG6nftsv8IQd+RPcpgOlBtrV2QIXVYpSahcnSb93JH+GKhlww4o4ujCiXEkT0mfucykJKAh2aTZ66+Drurh0Z5W/Oy8QtkBXzFVg+R1tDunIab1nnNuRvMuvXytHs2mHcqXvLPcH2--mkpHSrBo2zgAuXYA--BgMvyyxPUISDOmFDwLx8Wg== -------------------------------------------------------------------------------- /config/credentials/production.yml.enc: -------------------------------------------------------------------------------- 1 | +4t9FK5l0vNoTP4UlxXqOVdLhJPNY8DnA4CmiBU0KBN9sUlVM7GXQpQtwAV0kWQmYqMXUWt2M2HGbaZVFHs/UXHZ2pyt+ARyWmx09vHb4Rj76sFyTxcZDK3aOhrl1Js4Z2Uqn2tRoLXcy0jPuySoGeMwHkFNzBAT9VgdamlzmQdBqp+DkpfWw+5+gbJ8Gop3ERid9MMYsiu4X/HF2y9WfFjUoDgi/kL+4r6efpw4N7uPqFah/V5wBTXLiDHgm/u3SUTapqTZB++DC34hRj3cIhxaQSwFTsYFRo4jruourO9iCWx2tLcacd22rGcE8P4EZefbolzOMT15OI7McxIX0AQgrppJ+BH4UiFvP0Dwjb7QfKapywcAMcpiMuoJC1St914Op7L5v/XvjSroR3Y+kog8a6DTdOUJ5FCxHOYNnZpkSOba/V172Rp/JZIxuk0jp8ePL7kr8g6wwbOmDPWxhf/a/80io+aDMuB50OoKPMsMwbcqIBsbgAlnzhyzF9lsjzjs6c5AGSkCA8TTE8vd7c1vZ9wyYmlY4rrtfn2UbFssRM2j6nWMio6PMHEPSjuMZOuIOXBWRQz2gtaIL3tZoN5mK0rmG/MBRqc=--0ArdIzaG4Ohig3qf--BG51pqm3TaDdJBYcujlTrQ== -------------------------------------------------------------------------------- /config/database.yml: -------------------------------------------------------------------------------- 1 | # PostgreSQL. Versions 9.3 and up are supported. 2 | # 3 | # Install the pg driver: 4 | # gem install pg 5 | # On macOS with Homebrew: 6 | # gem install pg -- --with-pg-config=/usr/local/bin/pg_config 7 | # On Windows: 8 | # gem install pg 9 | # Choose the win32 build. 10 | # Install PostgreSQL and put its /bin directory on your path. 11 | # 12 | # Configure Using Gemfile 13 | # gem "pg" 14 | # 15 | default: &default 16 | adapter: postgresql 17 | encoding: unicode 18 | # For details on connection pooling, see Rails configuration guide 19 | # https://guides.rubyonrails.org/configuring.html#database-pooling 20 | pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> 21 | <% if ENV["DB_HOST"] %> 22 | host: <%= ENV["DB_HOST"] %> 23 | username: postgres 24 | password: postgres 25 | <% end %> 26 | 27 | 28 | development: 29 | <<: *default 30 | database: arc_platform_development 31 | 32 | # The specified database role being used to connect to PostgreSQL. 33 | # To create additional roles in PostgreSQL see `$ createuser --help`. 34 | # When left blank, PostgreSQL will use the default role. This is 35 | # the same name as the operating system user running Rails. 36 | #username: arc_platform 37 | 38 | # The password associated with the PostgreSQL role (username). 39 | #password: 40 | 41 | # Connect on a TCP socket. Omitted by default since the client uses a 42 | # domain socket that doesn't need configuration. Windows does not have 43 | # domain sockets, so uncomment these lines. 44 | #host: localhost 45 | 46 | # The TCP port the server listens on. Defaults to 5432. 47 | # If your server runs on a different port number, change accordingly. 48 | #port: 5432 49 | 50 | # Schema search path. The server defaults to $user,public 51 | #schema_search_path: myapp,sharedapp,public 52 | 53 | # Minimum log levels, in increasing order: 54 | # debug5, debug4, debug3, debug2, debug1, 55 | # log, notice, warning, error, fatal, and panic 56 | # Defaults to warning. 57 | #min_messages: notice 58 | 59 | # Warning: The database defined as "test" will be erased and 60 | # re-generated from your development database when you run "rake". 61 | # Do not set this db to the same as development or production. 62 | test: 63 | <<: *default 64 | database: arc_platform_test 65 | 66 | # As with config/credentials.yml, you never want to store sensitive information, 67 | # like your database password, in your source code. If your source code is 68 | # ever seen by anyone, they now have access to your database. 69 | # 70 | # Instead, provide the password or a full connection URL as an environment 71 | # variable when you boot the app. For example: 72 | # 73 | # DATABASE_URL="postgres://myuser:mypass@localhost/somedatabase" 74 | # 75 | # If the connection URL is provided in the special DATABASE_URL environment 76 | # variable, Rails will automatically merge its configuration values on top of 77 | # the values provided in this file. Alternatively, you can specify a connection 78 | # URL environment variable explicitly: 79 | # 80 | # production: 81 | # url: <%= ENV["MY_APP_DATABASE_URL"] %> 82 | # 83 | # Read https://guides.rubyonrails.org/configuring.html#configuring-a-database 84 | # for a full overview on how database connection configuration can be specified. 85 | # 86 | production: 87 | <<: *default 88 | database: arc_platform_production 89 | username: arc_platform 90 | password: <%= ENV["ARC_PLATFORM_DATABASE_PASSWORD"] %> 91 | -------------------------------------------------------------------------------- /config/deploy.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # config valid for current version and patch releases of Capistrano 4 | lock '~> 3.17.2' 5 | 6 | set :user, 'ubuntu' 7 | 8 | set :application, 'arc_platform' 9 | set :repo_url, 'git@github.com:banta/arc_platform.git' 10 | 11 | # Default branch is :master 12 | # ask :branch, `git rev-parse --abbrev-ref HEAD`.chomp 13 | 14 | # Default deploy_to directory is /var/www/my_app_name 15 | set :deploy_to, "/var/www/#{fetch :application}" 16 | 17 | # Default value for :format is :airbrussh. 18 | # set :format, :airbrussh 19 | 20 | # You can configure the Airbrussh format using :format_options. 21 | # These are the defaults. 22 | # set :format_options, command_output: true, log_file: "log/capistrano.log", color: :auto, truncate: :auto 23 | 24 | # Default value for :pty is false 25 | # set :pty, true 26 | 27 | # Default value for :linked_files is [] 28 | set :linked_files, %w[config/database.yml config/credentials/production.key] 29 | set :linked_dirs, %w[ vendor/bundle public/system log tmp/pids tmp/cache tmp/sockets 30 | public/packs .bundle node_modules ] 31 | 32 | # Default value for default_env is {} 33 | # set :default_env, { path: "/opt/ruby/bin:$PATH" } 34 | 35 | # Default value for local_user is ENV['USER'] 36 | # set :local_user, -> { `git config user.name`.chomp } 37 | 38 | # Default value for keep_releases is 5 39 | set :keep_releases, 5 40 | 41 | # Uncomment the following to require manually verifying the host key before first deploy. 42 | # set :ssh_options, verify_host_key: :secure 43 | 44 | namespace :deploy do 45 | desc 'Restart application' 46 | task :restart do 47 | on roles(:app), in: :sequence, wait: 5 do 48 | execute :touch, release_path.join('tmp/restart.txt') 49 | end 50 | end 51 | 52 | after :restart, :clear_cache do 53 | on roles(:web), in: :groups, limit: 3, wait: 10 do 54 | # within release_path do 55 | # execute :rake, 'cache:clear' 56 | # end 57 | end 58 | end 59 | 60 | after :finishing, 'deploy:cleanup' 61 | after :finishing, 'deploy:restart' 62 | end 63 | -------------------------------------------------------------------------------- /config/deploy/production.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | set :stage, :production 4 | set :branch, 'main' 5 | 6 | server '207.154.236.227', user: 'ubuntu', roles: %w[app db web] 7 | -------------------------------------------------------------------------------- /config/dockerfile.yml: -------------------------------------------------------------------------------- 1 | # generated by dockerfile-rails 2 | 3 | --- 4 | options: 5 | label: 6 | fly_launch_runtime: rails 7 | -------------------------------------------------------------------------------- /config/environment.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Load the Rails application. 4 | require_relative 'application' 5 | 6 | # Initialize the Rails application. 7 | Rails.application.initialize! 8 | -------------------------------------------------------------------------------- /config/environments/development.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'active_support/core_ext/integer/time' 4 | 5 | Rails.application.configure do 6 | # Settings specified here will take precedence over those in config/application.rb. 7 | 8 | # In the development environment your application's code is reloaded any time 9 | # it changes. This slows down response time but is perfect for development 10 | # since you don't have to restart the web server when you make code changes. 11 | config.cache_classes = false 12 | 13 | # Do not eager load code on boot. 14 | config.eager_load = false 15 | 16 | # Show full error reports. 17 | config.consider_all_requests_local = true 18 | 19 | # Enable server timing 20 | config.server_timing = true 21 | 22 | # Enable/disable caching. By default caching is disabled. 23 | # Run rails dev:cache to toggle caching. 24 | if Rails.root.join('tmp/caching-dev.txt').exist? 25 | config.action_controller.perform_caching = true 26 | config.action_controller.enable_fragment_cache_logging = true 27 | 28 | config.cache_store = :memory_store 29 | config.public_file_server.headers = { 30 | 'Cache-Control' => "public, max-age=#{2.days.to_i}" 31 | } 32 | else 33 | config.action_controller.perform_caching = false 34 | 35 | config.cache_store = :null_store 36 | end 37 | 38 | # Store uploaded files on the local file system (see config/storage.yml for options). 39 | config.active_storage.service = :local 40 | 41 | # Don't care if the mailer can't send. 42 | config.action_mailer.delivery_method = :letter_opener 43 | config.action_mailer.perform_deliveries = true 44 | config.action_mailer.raise_delivery_errors = true 45 | config.action_mailer.default_url_options = { host: 'localhost', port: 3000 } 46 | 47 | # Sendgrid mailer settings 48 | # config.action_mailer.delivery_method = :sendgrid_actionmailer 49 | # config.action_mailer.sendgrid_actionmailer_settings = { 50 | # api_key: ENV['SENDGRID_API_KEY'], 51 | # raise_delivery_errors: true 52 | # } 53 | 54 | config.action_mailer.perform_caching = false 55 | 56 | # Print deprecation notices to the Rails logger. 57 | config.active_support.deprecation = :log 58 | 59 | # Raise exceptions for disallowed deprecations. 60 | config.active_support.disallowed_deprecation = :raise 61 | 62 | # Tell Active Support which deprecation messages to disallow. 63 | config.active_support.disallowed_deprecation_warnings = [] 64 | 65 | # Raise an error on page load if there are pending migrations. 66 | config.active_record.migration_error = :page_load 67 | 68 | # Highlight code that triggered database queries in logs. 69 | config.active_record.verbose_query_logs = true 70 | 71 | # Suppress logger output for asset requests. 72 | config.assets.quiet = true 73 | 74 | # Raises error for missing translations. 75 | # config.i18n.raise_on_missing_translations = true 76 | 77 | # Annotate rendered view with file names. 78 | # config.action_view.annotate_rendered_view_with_filenames = true 79 | 80 | # Uncomment if you wish to allow Action Cable access from any origin. 81 | # config.action_cable.disable_request_forgery_protection = true 82 | 83 | config.hosts << /.*/ 84 | end 85 | -------------------------------------------------------------------------------- /config/environments/production.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'active_support/core_ext/integer/time' 4 | 5 | Rails.application.configure do 6 | # Settings specified here will take precedence over those in config/application.rb. 7 | 8 | # Code is not reloaded between requests. 9 | config.cache_classes = true 10 | 11 | # Eager load code on boot. This eager loads most of Rails and 12 | # your application in memory, allowing both threaded web servers 13 | # and those relying on copy on write to perform better. 14 | # Rake tasks automatically ignore this option for performance. 15 | config.eager_load = true 16 | 17 | # Full error reports are disabled and caching is turned on. 18 | config.consider_all_requests_local = false 19 | config.action_controller.perform_caching = true 20 | 21 | # Ensures that a master key has been made available in either ENV["RAILS_MASTER_KEY"] 22 | # or in config/master.key. This key is used to decrypt credentials (and other encrypted files). 23 | # config.require_master_key = true 24 | 25 | # Disable serving static files from the `/public` folder by default since 26 | # Apache or NGINX already handles this. 27 | config.public_file_server.enabled = ENV['RAILS_SERVE_STATIC_FILES'].present? 28 | 29 | # Compress CSS using a preprocessor. 30 | # config.assets.css_compressor = :sass 31 | 32 | # Do not fallback to assets pipeline if a precompiled asset is missed. 33 | config.assets.compile = false 34 | 35 | # Enable serving of images, stylesheets, and JavaScripts from an asset server. 36 | # config.asset_host = "http://assets.example.com" 37 | 38 | # Specifies the header that your server uses for sending files. 39 | # config.action_dispatch.x_sendfile_header = "X-Sendfile" # for Apache 40 | # config.action_dispatch.x_sendfile_header = "X-Accel-Redirect" # for NGINX 41 | 42 | # Store uploaded files on the local file system (see config/storage.yml for options). 43 | config.active_storage.service = :digitalocean 44 | 45 | # Mount Action Cable outside main process or domain. 46 | # config.action_cable.mount_path = nil 47 | # config.action_cable.url = "wss://example.com/cable" 48 | # config.action_cable.allowed_request_origins = [ "http://example.com", /http:\/\/example.*/ ] 49 | 50 | # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies. 51 | # config.force_ssl = true 52 | 53 | # Include generic and useful information about system operation, but avoid logging too much 54 | # information to avoid inadvertent exposure of personally identifiable information (PII). 55 | config.log_level = :info 56 | 57 | # Prepend all log lines with the following tags. 58 | config.log_tags = [:request_id] 59 | 60 | # Use a different cache store in production. 61 | # config.cache_store = :mem_cache_store 62 | 63 | # Use a real queuing backend for Active Job (and separate queues per environment). 64 | # config.active_job.queue_adapter = :resque 65 | # config.active_job.queue_name_prefix = "arc_platform_production" 66 | 67 | config.action_mailer.perform_caching = false 68 | 69 | # Ignore bad email addresses and do not raise email delivery errors. 70 | # Set this to true and configure the email server for immediate delivery to raise delivery errors. 71 | # config.action_mailer.raise_delivery_errors = false 72 | 73 | # Enable locale fallbacks for I18n (makes lookups for any locale fall back to 74 | # the I18n.default_locale when a translation cannot be found). 75 | config.i18n.fallbacks = true 76 | 77 | # Don't log any deprecations. 78 | config.active_support.report_deprecations = false 79 | 80 | # Use default logging formatter so that PID and timestamp are not suppressed. 81 | config.log_formatter = Logger::Formatter.new 82 | 83 | # Use a different logger for distributed setups. 84 | # require "syslog/logger" 85 | # config.logger = ActiveSupport::TaggedLogging.new(Syslog::Logger.new "app-name") 86 | 87 | if ENV['RAILS_LOG_TO_STDOUT'].present? 88 | logger = ActiveSupport::Logger.new($stdout) 89 | logger.formatter = config.log_formatter 90 | config.logger = ActiveSupport::TaggedLogging.new(logger) 91 | end 92 | 93 | # Do not dump schema after migrations. 94 | config.active_record.dump_schema_after_migration = false 95 | 96 | # Sendgrid mailer settings 97 | config.action_mailer.perform_deliveries = true 98 | config.action_mailer.default_url_options = { host: 'https://rubycommunity.africa' } 99 | config.action_mailer.delivery_method = :sendgrid_actionmailer 100 | config.action_mailer.sendgrid_actionmailer_settings = { 101 | api_key: Rails.application.credentials.sendgrid_api_key, 102 | raise_delivery_errors: true 103 | } 104 | end 105 | -------------------------------------------------------------------------------- /config/environments/test.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'active_support/core_ext/integer/time' 4 | 5 | # The test environment is used exclusively to run your application's 6 | # test suite. You never need to work with it otherwise. Remember that 7 | # your test database is "scratch space" for the test suite and is wiped 8 | # and recreated between test runs. Don't rely on the data there! 9 | 10 | Rails.application.configure do 11 | # Settings specified here will take precedence over those in config/application.rb. 12 | 13 | # Turn false under Spring and add config.action_view.cache_template_loading = true. 14 | config.cache_classes = true 15 | 16 | # Eager loading loads your whole application. When running a single test locally, 17 | # this probably isn't necessary. It's a good idea to do in a continuous integration 18 | # system, or in some way before deploying your code. 19 | config.eager_load = ENV['CI'].present? 20 | 21 | # Configure public file server for tests with Cache-Control for performance. 22 | config.public_file_server.enabled = true 23 | config.public_file_server.headers = { 24 | 'Cache-Control' => "public, max-age=#{1.hour.to_i}" 25 | } 26 | 27 | # Show full error reports and disable caching. 28 | config.consider_all_requests_local = true 29 | config.action_controller.perform_caching = false 30 | config.cache_store = :null_store 31 | 32 | # Raise exceptions instead of rendering exception templates. 33 | config.action_dispatch.show_exceptions = false 34 | 35 | # Disable request forgery protection in test environment. 36 | config.action_controller.allow_forgery_protection = false 37 | 38 | # Store uploaded files on the local file system in a temporary directory. 39 | config.active_storage.service = :test 40 | 41 | config.action_mailer.perform_caching = false 42 | 43 | # Tell Action Mailer not to deliver emails to the real world. 44 | # The :test delivery method accumulates sent emails in the 45 | # ActionMailer::Base.deliveries array. 46 | config.action_mailer.delivery_method = :test 47 | 48 | # Print deprecation notices to the stderr. 49 | config.active_support.deprecation = :stderr 50 | 51 | # Raise exceptions for disallowed deprecations. 52 | config.active_support.disallowed_deprecation = :raise 53 | 54 | # Tell Active Support which deprecation messages to disallow. 55 | config.active_support.disallowed_deprecation_warnings = [] 56 | 57 | # Raises error for missing translations. 58 | # config.i18n.raise_on_missing_translations = true 59 | 60 | # Annotate rendered view with file names. 61 | # config.action_view.annotate_rendered_view_with_filenames = true 62 | end 63 | -------------------------------------------------------------------------------- /config/initializers/assets.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Be sure to restart your server when you modify this file. 4 | 5 | # Version of your assets, change this if you want to expire all your assets. 6 | Rails.application.config.assets.version = '1.0' 7 | 8 | # Add additional assets to the asset load path. 9 | # Rails.application.config.assets.paths << Emoji.images_path 10 | 11 | # Precompile additional assets. 12 | # application.js, application.css, and all non-JS/CSS in the app/assets 13 | # folder are already added. 14 | # Rails.application.config.assets.precompile += %w( admin.js admin.css ) 15 | -------------------------------------------------------------------------------- /config/initializers/content_security_policy.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | # Be sure to restart your server when you modify this file. 3 | 4 | # Define an application-wide content security policy. 5 | # See the Securing Rails Applications Guide for more information: 6 | # https://guides.rubyonrails.org/security.html#content-security-policy-header 7 | 8 | # Rails.application.configure do 9 | # config.content_security_policy do |policy| 10 | # policy.default_src :self, :https 11 | # policy.font_src :self, :https, :data 12 | # policy.img_src :self, :https, :data 13 | # policy.object_src :none 14 | # policy.script_src :self, :https 15 | # policy.style_src :self, :https 16 | # # Specify URI for violation reports 17 | # # policy.report_uri "/csp-violation-report-endpoint" 18 | # end 19 | # 20 | # # Generate session nonces for permitted importmap and inline scripts 21 | # config.content_security_policy_nonce_generator = ->(request) { request.session.id.to_s } 22 | # config.content_security_policy_nonce_directives = %w(script-src) 23 | # 24 | # # Report violations without enforcing the policy. 25 | # # config.content_security_policy_report_only = true 26 | # end 27 | -------------------------------------------------------------------------------- /config/initializers/filter_parameter_logging.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Be sure to restart your server when you modify this file. 4 | 5 | # Configure parameters to be filtered from the log file. Use this to limit dissemination of 6 | # sensitive information. See the ActiveSupport::ParameterFilter documentation for supported 7 | # notations and behaviors. 8 | Rails.application.config.filter_parameters += %i[ 9 | passw secret token _key crypt salt certificate otp ssn 10 | ] 11 | -------------------------------------------------------------------------------- /config/initializers/inflections.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | # Be sure to restart your server when you modify this file. 3 | 4 | # Add new inflection rules using the following format. Inflections 5 | # are locale specific, and you may define rules for as many different 6 | # locales as you wish. All of these examples are active by default: 7 | # ActiveSupport::Inflector.inflections(:en) do |inflect| 8 | # inflect.plural /^(ox)$/i, "\\1en" 9 | # inflect.singular /^(ox)en/i, "\\1" 10 | # inflect.irregular "person", "people" 11 | # inflect.uncountable %w( fish sheep ) 12 | # end 13 | 14 | # These inflection rules are supported but not enabled by default: 15 | # ActiveSupport::Inflector.inflections(:en) do |inflect| 16 | # inflect.acronym "RESTful" 17 | # end 18 | -------------------------------------------------------------------------------- /config/initializers/permissions_policy.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | # Define an application-wide HTTP permissions policy. For further 3 | # information see https://developers.google.com/web/updates/2018/06/feature-policy 4 | # 5 | # Rails.application.config.permissions_policy do |f| 6 | # f.camera :none 7 | # f.gyroscope :none 8 | # f.microphone :none 9 | # f.usb :none 10 | # f.fullscreen :self 11 | # f.payment :self, "https://secure.example.com" 12 | # end 13 | -------------------------------------------------------------------------------- /config/locales/devise.en.yml: -------------------------------------------------------------------------------- 1 | # Additional translations at https://github.com/heartcombo/devise/wiki/I18n 2 | 3 | en: 4 | devise: 5 | confirmations: 6 | confirmed: "Your email address has been successfully confirmed." 7 | send_instructions: "You will receive an email with instructions for how to confirm your email address in a few minutes." 8 | send_paranoid_instructions: "If your email address exists in our database, you will receive an email with instructions for how to confirm your email address in a few minutes." 9 | failure: 10 | already_authenticated: "You are already signed in." 11 | inactive: "Your account is not activated yet." 12 | invalid: "Invalid %{authentication_keys} or password." 13 | locked: "Your account is locked." 14 | last_attempt: "You have one more attempt before your account is locked." 15 | not_found_in_database: "Invalid %{authentication_keys} or password." 16 | timeout: "Your session expired. Please sign in again to continue." 17 | unauthenticated: "You need to sign in or sign up before continuing." 18 | unconfirmed: "You have to confirm your email address before continuing." 19 | mailer: 20 | confirmation_instructions: 21 | subject: "Confirmation instructions" 22 | reset_password_instructions: 23 | subject: "Reset password instructions" 24 | unlock_instructions: 25 | subject: "Unlock instructions" 26 | email_changed: 27 | subject: "Email Changed" 28 | password_change: 29 | subject: "Password Changed" 30 | omniauth_callbacks: 31 | failure: "Could not authenticate you from %{kind} because \"%{reason}\"." 32 | success: "Successfully authenticated from %{kind} account." 33 | passwords: 34 | no_token: "You can't access this page without coming from a password reset email. If you do come from a password reset email, please make sure you used the full URL provided." 35 | send_instructions: "You will receive an email with instructions on how to reset your password in a few minutes." 36 | send_paranoid_instructions: "If your email address exists in our database, you will receive a password recovery link at your email address in a few minutes." 37 | updated: "Your password has been changed successfully. You are now signed in." 38 | updated_not_active: "Your password has been changed successfully." 39 | registrations: 40 | destroyed: "Bye! Your account has been successfully cancelled. We hope to see you again soon." 41 | signed_up: "Welcome! You have signed up successfully." 42 | signed_up_but_inactive: "You have signed up successfully. However, we could not sign you in because your account is not yet activated." 43 | signed_up_but_locked: "You have signed up successfully. However, we could not sign you in because your account is locked." 44 | signed_up_but_unconfirmed: "A message with a confirmation link has been sent to your email address. Please follow the link to activate your account." 45 | update_needs_confirmation: "You updated your account successfully, but we need to verify your new email address. Please check your email and follow the confirmation link to confirm your new email address." 46 | updated: "Your account has been updated successfully." 47 | updated_but_not_signed_in: "Your account has been updated successfully, but since your password was changed, you need to sign in again." 48 | sessions: 49 | signed_in: "Signed in successfully." 50 | signed_out: "Signed out successfully." 51 | already_signed_out: "Signed out successfully." 52 | unlocks: 53 | send_instructions: "You will receive an email with instructions for how to unlock your account in a few minutes." 54 | send_paranoid_instructions: "If your account exists, you will receive an email with instructions for how to unlock it in a few minutes." 55 | unlocked: "Your account has been unlocked successfully. Please sign in to continue." 56 | errors: 57 | messages: 58 | already_confirmed: "was already confirmed, please try signing in" 59 | confirmation_period_expired: "needs to be confirmed within %{period}, please request a new one" 60 | expired: "has expired, please request a new one" 61 | not_found: "not found" 62 | not_locked: "was not locked" 63 | not_saved: 64 | one: "1 error prohibited this %{resource} from being saved:" 65 | other: "%{count} errors prohibited this %{resource} from being saved:" 66 | -------------------------------------------------------------------------------- /config/locales/en.yml: -------------------------------------------------------------------------------- 1 | # To learn more, please read the Rails Internationalization guide 2 | # available at https://guides.rubyonrails.org/i18n.html. 3 | 4 | en: 5 | unauthorized: 6 | sign_in: 'Please sign in to perform the action' 7 | 8 | chapters: 9 | create: 10 | success: 'Chapter was successfully created.' 11 | update: 12 | success: 'Chapter was successfully updated.' 13 | destroy: 14 | success: 'Chapter was successfully destroyed.' 15 | 16 | countries: 17 | create: 18 | success: 'Country was successfully created.' 19 | update: 20 | success: 'Country was successfully updated.' 21 | destroy: 22 | success: 'Country was successfully destroyed.' 23 | 24 | projects: 25 | create: 26 | success: 'Project was successfully created.' 27 | update: 28 | success: 'Project was successfully updated.' 29 | destroy: 30 | success: 'Project was successfully destroyed.' 31 | 32 | 33 | -------------------------------------------------------------------------------- /config/locales/simple_form.en.yml: -------------------------------------------------------------------------------- 1 | en: 2 | simple_form: 3 | "yes": 'Yes' 4 | "no": 'No' 5 | required: 6 | text: 'required' 7 | mark: '*' 8 | # You can uncomment the line below if you need to overwrite the whole required html. 9 | # When using html, text and mark won't be used. 10 | # html: '*' 11 | error_notification: 12 | default_message: "Please review the problems below:" 13 | # Examples 14 | # labels: 15 | # defaults: 16 | # password: 'Password' 17 | # user: 18 | # new: 19 | # email: 'E-mail to sign in.' 20 | # edit: 21 | # email: 'E-mail.' 22 | # hints: 23 | # defaults: 24 | # username: 'User name to sign in.' 25 | # password: 'No special characters, please.' 26 | # include_blanks: 27 | # defaults: 28 | # age: 'Rather not say' 29 | # prompts: 30 | # defaults: 31 | # age: 'Select your age' 32 | -------------------------------------------------------------------------------- /config/motor.yml: -------------------------------------------------------------------------------- 1 | --- 2 | engine_version: 0.4.7 3 | file_version: 2023-03-09 16:16:17.698355000 Z 4 | resources: 5 | - name: chapter 6 | preferences: 7 | columns: 8 | - column_type: richtext 9 | name: description 10 | updated_at: 2023-03-05 09:31:13.962854000 +00:00 11 | - name: feature_flag 12 | preferences: 13 | columns: 14 | - column_type: richtext 15 | name: description 16 | updated_at: 2023-03-09 16:16:17.698355000 +00:00 17 | configs: 18 | - key: header.links 19 | value: 20 | - name: Reports 21 | link_type: reports 22 | - name: Forms 23 | link_type: forms 24 | - conditions: [] 25 | type: header 26 | name: Exit admin portal 27 | path: "/" 28 | link_type: header 29 | updated_at: 2023-03-05 09:37:51.799389000 +00:00 30 | queries: [] 31 | dashboards: [] 32 | forms: [] 33 | alerts: [] 34 | api_configs: 35 | - id: 1 36 | name: origin 37 | url: "/" 38 | preferences: {} 39 | description: 40 | updated_at: 2023-03-05 08:41:14.200426000 +00:00 41 | -------------------------------------------------------------------------------- /config/puma.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Puma can serve each request in a thread from an internal thread pool. 4 | # The `threads` method setting takes two numbers: a minimum and maximum. 5 | # Any libraries that use thread pools should be configured to match 6 | # the maximum value specified for Puma. Default is set to 5 threads for minimum 7 | # and maximum; this matches the default thread size of Active Record. 8 | # 9 | max_threads_count = ENV.fetch('RAILS_MAX_THREADS', 5) 10 | min_threads_count = ENV.fetch('RAILS_MIN_THREADS') { max_threads_count } 11 | threads min_threads_count, max_threads_count 12 | 13 | # Specifies the `worker_timeout` threshold that Puma will use to wait before 14 | # terminating a worker in development environments. 15 | # 16 | worker_timeout 3600 if ENV.fetch('RAILS_ENV', 'development') == 'development' 17 | 18 | # Specifies the `port` that Puma will listen on to receive requests; default is 3000. 19 | # 20 | port ENV.fetch('PORT', 3000) 21 | 22 | # Specifies the `environment` that Puma will run in. 23 | # 24 | environment ENV.fetch('RAILS_ENV', 'development') 25 | 26 | # Specifies the `pidfile` that Puma will use. 27 | pidfile ENV.fetch('PIDFILE', 'tmp/pids/server.pid') 28 | 29 | # Specifies the number of `workers` to boot in clustered mode. 30 | # Workers are forked web server processes. If using threads and workers together 31 | # the concurrency of the application would be max `threads` * `workers`. 32 | # Workers do not work on JRuby or Windows (both of which do not support 33 | # processes). 34 | # 35 | # workers ENV.fetch("WEB_CONCURRENCY") { 2 } 36 | 37 | # Use the `preload_app!` method when specifying a `workers` number. 38 | # This directive tells Puma to first boot the application and load code 39 | # before forking the application. This takes advantage of Copy On Write 40 | # process behavior so workers use less memory. 41 | # 42 | # preload_app! 43 | 44 | # Allow puma to be restarted by `bin/rails restart` command. 45 | plugin :tmp_restart 46 | -------------------------------------------------------------------------------- /config/routes.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | Rails.application.routes.draw do 4 | authenticate :user do 5 | mount Motor::Admin => '/admin' 6 | end 7 | resources :projects, only: %i[index show] 8 | resources :chapters, only: %i[index show] 9 | resources :countries, only: %i[index show] 10 | devise_for :users, controllers: { 11 | registrations: 'users/registrations' # Override devise registration controller 12 | } 13 | # Define your application routes per the DSL in https://guides.rubyonrails.org/routing.html 14 | 15 | # Defines the root path route ("/") 16 | root 'landing#index' 17 | 18 | get 'about_us', to: 'landing#about', as: :landing_about 19 | get 'learn', to: 'landing#learn', as: :landing_learn 20 | end 21 | -------------------------------------------------------------------------------- /config/sitemap.rb: -------------------------------------------------------------------------------- 1 | # Set the host name for URL creation 2 | SitemapGenerator::Sitemap.default_host = "https://rubycommunity.africa" 3 | SitemapGenerator::Sitemap.compress = false 4 | 5 | SitemapGenerator::Sitemap.create do 6 | # Put links creation logic here. 7 | # 8 | # The root path '/' and sitemap index file are added automatically for you. 9 | # Links are added to the Sitemap in the order they are specified. 10 | # 11 | # Usage: add(path, options={}) 12 | # (default options are used if you don't specify) 13 | # 14 | # Defaults: :priority => 0.5, :changefreq => 'weekly', 15 | # :lastmod => Time.now, :host => default_host 16 | # 17 | # Examples: 18 | # 19 | # Add '/articles' 20 | # 21 | # add articles_path, :priority => 0.7, :changefreq => 'daily' 22 | # 23 | # Add all articles: 24 | # 25 | # Article.find_each do |article| 26 | # add article_path(article), :lastmod => article.updated_at 27 | # end 28 | 29 | add '/about_us', 30 | changefreq: 'monthly', 31 | priority: 0.9 32 | add '/learn', 33 | changefreq: 'monthly', 34 | priority: 0.9 35 | add '/chapters', 36 | changefreq: 'monthly', 37 | priority: 0.9 38 | 39 | Chapter.find_each do |chapter| 40 | add chapter_path(chapter), :lastmod => chapter.updated_at 41 | end 42 | 43 | add '/users/sign_up', 44 | changefreq: 'monthly', 45 | priority: 0.8 46 | 47 | add '/users/sign_in', 48 | changefreq: 'monthly', 49 | priority: 0.8 50 | end 51 | -------------------------------------------------------------------------------- /config/storage.yml: -------------------------------------------------------------------------------- 1 | test: 2 | service: Disk 3 | root: <%= Rails.root.join("tmp/storage") %> 4 | 5 | local: 6 | service: Disk 7 | root: <%= Rails.root.join("storage") %> 8 | 9 | # Use bin/rails credentials:edit to set the AWS secrets (as aws:access_key_id|secret_access_key) 10 | amazon: 11 | service: S3 12 | access_key_id: <%= Rails.application.credentials.dig(:aws, :access_key_id) %> 13 | secret_access_key: <%= Rails.application.credentials.dig(:aws, :secret_access_key) %> 14 | region: us-east-1 15 | bucket: rubycommunity_africa-<%= Rails.env %> 16 | 17 | digitalocean: 18 | service: S3 19 | endpoint: <%= Rails.application.credentials.dig(:digitalocean, :endpoint) %> 20 | access_key_id: <%= Rails.application.credentials.dig(:digitalocean, :access_key_id) %> 21 | secret_access_key: <%= Rails.application.credentials.dig(:digitalocean, :secret_access_key) %> 22 | bucket: <%= Rails.application.credentials.dig(:digitalocean, :space_name) %> 23 | region: <%= Rails.application.credentials.dig(:digitalocean, :region) %> 24 | 25 | 26 | # Remember not to checkin your GCS keyfile to a repository 27 | # google: 28 | # service: GCS 29 | # project: your_project 30 | # credentials: <%= Rails.root.join("path/to/gcs.keyfile") %> 31 | # bucket: your_own_bucket-<%= Rails.env %> 32 | 33 | # Use bin/rails credentials:edit to set the Azure Storage secret (as azure_storage:storage_access_key) 34 | # microsoft: 35 | # service: AzureStorage 36 | # storage_account_name: your_account_name 37 | # storage_access_key: <%= Rails.application.credentials.dig(:azure_storage, :storage_access_key) %> 38 | # container: your_container_name-<%= Rails.env %> 39 | 40 | # mirror: 41 | # service: Mirror 42 | # primary: local 43 | # mirrors: [ amazon, google, microsoft ] 44 | -------------------------------------------------------------------------------- /db/migrate/20221118122721_devise_create_users.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class DeviseCreateUsers < ActiveRecord::Migration[7.0] 4 | def change 5 | create_table :users do |t| 6 | ## Database authenticatable 7 | t.string :email, null: false, default: "" 8 | t.string :encrypted_password, null: false, default: "" 9 | 10 | ## Recoverable 11 | t.string :reset_password_token 12 | t.datetime :reset_password_sent_at 13 | 14 | ## Rememberable 15 | t.datetime :remember_created_at 16 | 17 | ## Trackable 18 | t.integer :sign_in_count, default: 0, null: false 19 | t.datetime :current_sign_in_at 20 | t.datetime :last_sign_in_at 21 | t.string :current_sign_in_ip 22 | t.string :last_sign_in_ip 23 | 24 | ## Confirmable 25 | t.string :confirmation_token 26 | t.datetime :confirmed_at 27 | t.datetime :confirmation_sent_at 28 | t.string :unconfirmed_email # Only if using reconfirmable 29 | 30 | ## Lockable 31 | t.integer :failed_attempts, default: 0, null: false # Only if lock strategy is :failed_attempts 32 | t.string :unlock_token # Only if unlock strategy is :email or :both 33 | t.datetime :locked_at 34 | 35 | 36 | t.timestamps null: false 37 | end 38 | 39 | add_index :users, :email, unique: true 40 | add_index :users, :reset_password_token, unique: true 41 | add_index :users, :confirmation_token, unique: true 42 | add_index :users, :unlock_token, unique: true 43 | end 44 | end 45 | -------------------------------------------------------------------------------- /db/migrate/20221227125811_create_countries.rb: -------------------------------------------------------------------------------- 1 | class CreateCountries < ActiveRecord::Migration[7.0] 2 | def change 3 | create_table :countries do |t| 4 | t.string :name 5 | 6 | t.timestamps 7 | end 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /db/migrate/20230117033124_create_chapters.rb: -------------------------------------------------------------------------------- 1 | class CreateChapters < ActiveRecord::Migration[7.0] 2 | def change 3 | create_table :chapters do |t| 4 | t.string :name 5 | t.string :location 6 | t.text :description 7 | t.belongs_to :country 8 | 9 | t.timestamps 10 | end 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /db/migrate/20230212202017_create_projects.rb: -------------------------------------------------------------------------------- 1 | class CreateProjects < ActiveRecord::Migration[7.0] 2 | def change 3 | create_table :projects do |t| 4 | t.string :name 5 | t.text :description 6 | t.references :chapter, null: false, foreign_key: true 7 | t.datetime :start_date 8 | t.datetime :end_date 9 | 10 | t.timestamps 11 | end 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /db/migrate/20230225213826_add_role_to_users.rb: -------------------------------------------------------------------------------- 1 | class AddRoleToUsers < ActiveRecord::Migration[7.0] 2 | def change 3 | add_column :users, :role, :integer 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20230225222048_create_users_chapters.rb: -------------------------------------------------------------------------------- 1 | class CreateUsersChapters < ActiveRecord::Migration[7.0] 2 | def change 3 | create_table :users_chapters do |t| 4 | t.belongs_to :chapter, null: false, foreign_key: true 5 | t.belongs_to :user, null: false, foreign_key: true 6 | t.boolean :main_chapter, default: false 7 | 8 | t.timestamps 9 | end 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /db/migrate/20230226063248_add_extra_fields_to_users.rb: -------------------------------------------------------------------------------- 1 | class AddExtraFieldsToUsers < ActiveRecord::Migration[7.0] 2 | def change 3 | add_column :users, :name, :string 4 | add_column :users, :phone_number, :string 5 | add_column :users, :github_username, :string 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /db/migrate/20230305235848_create_active_storage_tables.active_storage.rb: -------------------------------------------------------------------------------- 1 | # This migration comes from active_storage (originally 20170806125915) 2 | class CreateActiveStorageTables < ActiveRecord::Migration[5.2] 3 | def change 4 | # Use Active Record's configured type for primary and foreign keys 5 | primary_key_type, foreign_key_type = primary_and_foreign_key_types 6 | 7 | create_table :active_storage_blobs, id: primary_key_type do |t| 8 | t.string :key, null: false 9 | t.string :filename, null: false 10 | t.string :content_type 11 | t.text :metadata 12 | t.string :service_name, null: false 13 | t.bigint :byte_size, null: false 14 | t.string :checksum 15 | 16 | if connection.supports_datetime_with_precision? 17 | t.datetime :created_at, precision: 6, null: false 18 | else 19 | t.datetime :created_at, null: false 20 | end 21 | 22 | t.index [ :key ], unique: true 23 | end 24 | 25 | create_table :active_storage_attachments, id: primary_key_type do |t| 26 | t.string :name, null: false 27 | t.references :record, null: false, polymorphic: true, index: false, type: foreign_key_type 28 | t.references :blob, null: false, type: foreign_key_type 29 | 30 | if connection.supports_datetime_with_precision? 31 | t.datetime :created_at, precision: 6, null: false 32 | else 33 | t.datetime :created_at, null: false 34 | end 35 | 36 | t.index [ :record_type, :record_id, :name, :blob_id ], name: :index_active_storage_attachments_uniqueness, unique: true 37 | t.foreign_key :active_storage_blobs, column: :blob_id 38 | end 39 | 40 | create_table :active_storage_variant_records, id: primary_key_type do |t| 41 | t.belongs_to :blob, null: false, index: false, type: foreign_key_type 42 | t.string :variation_digest, null: false 43 | 44 | t.index [ :blob_id, :variation_digest ], name: :index_active_storage_variant_records_uniqueness, unique: true 45 | t.foreign_key :active_storage_blobs, column: :blob_id 46 | end 47 | end 48 | 49 | private 50 | def primary_and_foreign_key_types 51 | config = Rails.configuration.generators 52 | setting = config.options[config.orm][:primary_key_type] 53 | primary_key_type = setting || :primary_key 54 | foreign_key_type = setting || :bigint 55 | [primary_key_type, foreign_key_type] 56 | end 57 | end 58 | -------------------------------------------------------------------------------- /db/migrate/20230309154521_create_feature_flags.rb: -------------------------------------------------------------------------------- 1 | class CreateFeatureFlags < ActiveRecord::Migration[7.0] 2 | def change 3 | create_table :feature_flags do |t| 4 | t.string :feature 5 | t.text :description 6 | t.boolean :enabled 7 | 8 | t.timestamps 9 | end 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /db/migrate/20230313002939_rename_feature_to_name_for_feature_flags.rb: -------------------------------------------------------------------------------- 1 | class RenameFeatureToNameForFeatureFlags < ActiveRecord::Migration[7.0] 2 | def change 3 | rename_column :feature_flags, :feature, :name 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20230531154135_add_index_to_columns.rb: -------------------------------------------------------------------------------- 1 | class AddIndexToColumns < ActiveRecord::Migration[7.0] 2 | def change 3 | add_index :chapters, :name, unique: true 4 | add_index :users, :github_username, unique: true 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /db/seeds.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | # This file should contain all the record creation needed to seed the database with its default values. 3 | # The data can then be loaded with the bin/rails db:seed command (or created alongside the database with db:setup). 4 | # 5 | # Examples: 6 | # 7 | # movies = Movie.create([{ name: "Star Wars" }, { name: "Lord of the Rings" }]) 8 | # Character.create(name: "Luke", movie: movies.first) 9 | -------------------------------------------------------------------------------- /dev-docker-entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -e 4 | 5 | echo "Environment: $RAILS_ENV" 6 | 7 | # install missing gems 8 | bundle check || bundle install --jobs 20 --retry 5 9 | 10 | # Remove pre-existing puma/passenger server.pid 11 | rm -f $APP_PATH/tmp/pids/server.pid 12 | 13 | # run passed commands 14 | bundle exec ${@} -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | networks: 3 | development: 4 | test: 5 | volumes: 6 | db_data: 7 | gem_cache: 8 | shared_data: 9 | services: 10 | arc_redis: 11 | image: redis:4.0-alpine 12 | command: redis-server 13 | networks: 14 | - development 15 | - test 16 | volumes: 17 | - shared_data:/var/shared/redis 18 | db: 19 | image: postgres:12.5-alpine 20 | container_name: arc_db 21 | volumes: 22 | - db_data:/var/lib/postgresql/data 23 | - shared_data:/var/shared 24 | networks: 25 | - development 26 | - test 27 | environment: 28 | POSTGRES_USER: postgres 29 | POSTGRES_PASSWORD: password 30 | ports: 31 | - 5099:5432 32 | web: 33 | build: 34 | context: . 35 | dockerfile: Dockerfile 36 | container_name: arc_app 37 | volumes: 38 | - .:/var/app 39 | - shared_data:/var/shared 40 | - gem_cache:/usr/local/bundle/gems 41 | networks: 42 | - development 43 | ports: 44 | - 3000:3000 45 | stdin_open: true 46 | tty: true 47 | env_file: .env.development 48 | entrypoint: dev-entrypoint.sh 49 | command: ['rails', 'server', '-p', '3000', '-b', '0.0.0.0'] 50 | environment: 51 | RAILS_ENV: development 52 | depends_on: 53 | - db 54 | -------------------------------------------------------------------------------- /fly.toml: -------------------------------------------------------------------------------- 1 | # fly.toml file generated for arc-platform on 2023-03-25T13:02:42+03:00 2 | 3 | app = "arc-platform" 4 | kill_signal = "SIGINT" 5 | kill_timeout = 5 6 | primary_region = "jnb" 7 | processes = [] 8 | 9 | [env] 10 | 11 | [experimental] 12 | auto_rollback = true 13 | 14 | [[services]] 15 | http_checks = [] 16 | internal_port = 3000 17 | processes = ["app"] 18 | protocol = "tcp" 19 | script_checks = [] 20 | [services.concurrency] 21 | hard_limit = 25 22 | soft_limit = 20 23 | type = "connections" 24 | 25 | [[services.ports]] 26 | force_https = true 27 | handlers = ["http"] 28 | port = 80 29 | 30 | [[services.ports]] 31 | handlers = ["tls", "http"] 32 | port = 443 33 | 34 | [[services.tcp_checks]] 35 | grace_period = "1s" 36 | interval = "15s" 37 | restart_limit = 0 38 | timeout = "2s" 39 | 40 | [[statics]] 41 | guest_path = "/rails/public" 42 | url_prefix = "/" 43 | -------------------------------------------------------------------------------- /lib/assets/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/African-Ruby-Community/arc_platform/c77a4f421418b59f00b462a04269f720dc73f1dd/lib/assets/.keep -------------------------------------------------------------------------------- /lib/tasks/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/African-Ruby-Community/arc_platform/c77a4f421418b59f00b462a04269f720dc73f1dd/lib/tasks/.keep -------------------------------------------------------------------------------- /lib/tasks/auto_annotate_models.rake: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # NOTE: only doing this in development as some production environments (Heroku) 4 | # NOTE: are sensitive to local FS writes, and besides -- it's just not proper 5 | # NOTE: to have a dev-mode tool do its thing in production. 6 | if Rails.env.development? 7 | require 'annotate' 8 | # rubocop:disable Metrics/BlockLength 9 | task set_annotation_options: :environment do 10 | # You can override any of these by setting an environment variable of the 11 | # same name. 12 | Annotate.set_defaults( 13 | 'active_admin' => 'false', 14 | 'additional_file_patterns' => [], 15 | 'routes' => 'false', 16 | 'models' => 'true', 17 | 'position_in_routes' => 'before', 18 | 'position_in_class' => 'before', 19 | 'position_in_test' => 'before', 20 | 'position_in_fixture' => 'before', 21 | 'position_in_factory' => 'before', 22 | 'position_in_serializer' => 'before', 23 | 'show_foreign_keys' => 'true', 24 | 'show_complete_foreign_keys' => 'false', 25 | 'show_indexes' => 'true', 26 | 'simple_indexes' => 'false', 27 | 'model_dir' => 'app/models', 28 | 'root_dir' => '', 29 | 'include_version' => 'false', 30 | 'require' => '', 31 | 'exclude_tests' => 'false', 32 | 'exclude_fixtures' => 'false', 33 | 'exclude_factories' => 'false', 34 | 'exclude_serializers' => 'false', 35 | 'exclude_scaffolds' => 'true', 36 | 'exclude_controllers' => 'true', 37 | 'exclude_helpers' => 'true', 38 | 'exclude_sti_subclasses' => 'false', 39 | 'ignore_model_sub_dir' => 'false', 40 | 'ignore_columns' => nil, 41 | 'ignore_routes' => nil, 42 | 'ignore_unknown_models' => 'false', 43 | 'hide_limit_column_types' => 'integer,bigint,boolean', 44 | 'hide_default_column_types' => 'json,jsonb,hstore', 45 | 'skip_on_db_migrate' => 'false', 46 | 'format_bare' => 'true', 47 | 'format_rdoc' => 'false', 48 | 'format_yard' => 'false', 49 | 'format_markdown' => 'false', 50 | 'sort' => 'false', 51 | 'force' => 'false', 52 | 'frozen' => 'false', 53 | 'classified_sort' => 'true', 54 | 'trace' => 'false', 55 | 'wrapper_open' => nil, 56 | 'wrapper_close' => nil, 57 | 'with_comment' => 'true' 58 | ) 59 | end 60 | # rubocop:enable Metrics/BlockLength 61 | 62 | Annotate.load_tasks 63 | end 64 | -------------------------------------------------------------------------------- /lib/templates/erb/scaffold/_form.html.erb: -------------------------------------------------------------------------------- 1 | <%# frozen_string_literal: true %> 2 | <%%= simple_form_for(@<%= singular_table_name %>) do |f| %> 3 | <%%= f.error_notification %> 4 | <%%= f.error_notification message: f.object.errors[:base].to_sentence if f.object.errors[:base].present? %> 5 | 6 |
7 | <%- attributes.each do |attribute| -%> 8 | <%%= f.<%= attribute.reference? ? :association : :input %> :<%= attribute.name %> %> 9 | <%- end -%> 10 |
11 | 12 |
13 | <%%= f.button :submit %> 14 |
15 | <%% end %> 16 | -------------------------------------------------------------------------------- /log/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/African-Ruby-Community/arc_platform/c77a4f421418b59f00b462a04269f720dc73f1dd/log/.keep -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "app", 3 | "private": "true", 4 | "dependencies": { 5 | "@hotwired/stimulus": "^3.0.1", 6 | "@hotwired/turbo-rails": "^7.1.3", 7 | "@tailwindcss/typography": "^0.5.8", 8 | "autoprefixer": "^10.4.7", 9 | "daisyui": "^2.46.0", 10 | "esbuild": "^0.14.41", 11 | "postcss": "^8.4.14", 12 | "tailwindcss": "^3.3.1" 13 | }, 14 | "scripts": { 15 | "build": "esbuild app/javascript/*.* --bundle --sourcemap --outdir=app/assets/builds", 16 | "build:css": "tailwindcss -i ./app/assets/stylesheets/application.tailwind.css -o ./app/assets/builds/application.css --minify" 17 | }, 18 | "packageManager": "yarn@1.22.19" 19 | } 20 | -------------------------------------------------------------------------------- /public/404.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | The page you were looking for doesn't exist (404) 5 | 6 | 55 | 56 | 57 | 58 | 59 |
60 |
61 |

The page you were looking for doesn't exist.

62 |

You may have mistyped the address or the page may have moved.

63 |
64 |

If you are the application owner check the logs for more information.

65 |
66 | 67 | 68 | -------------------------------------------------------------------------------- /public/422.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | The change you wanted was rejected (422) 5 | 6 | 55 | 56 | 57 | 58 | 59 |
60 |
61 |

The change you wanted was rejected.

62 |

Maybe you tried to change something you didn't have access to.

63 |
64 |

If you are the application owner check the logs for more information.

65 |
66 | 67 | 68 | -------------------------------------------------------------------------------- /public/500.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | We're sorry, but something went wrong (500) 5 | 6 | 55 | 56 | 57 | 58 | 59 |
60 |
61 |

We're sorry, but something went wrong.

62 |
63 |

If you are the application owner check the logs for more information.

64 |
65 | 66 | 67 | -------------------------------------------------------------------------------- /public/apple-touch-icon-precomposed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/African-Ruby-Community/arc_platform/c77a4f421418b59f00b462a04269f720dc73f1dd/public/apple-touch-icon-precomposed.png -------------------------------------------------------------------------------- /public/apple-touch-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/African-Ruby-Community/arc_platform/c77a4f421418b59f00b462a04269f720dc73f1dd/public/apple-touch-icon.png -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/African-Ruby-Community/arc_platform/c77a4f421418b59f00b462a04269f720dc73f1dd/public/favicon.ico -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | # See https://www.robotstxt.org/robotstxt.html for documentation on how to use the robots.txt file 2 | User-agent: * 3 | 4 | Disallow: /admin 5 | Disallow: /chapters/new 6 | Disallow: /chapters/edit 7 | Disallow: /countries/new 8 | Disallow: /countries/edit 9 | Disallow: /projects/new 10 | Disallow: /projects/edit 11 | Disallow: /users/ 12 | # Overriding /users route to add the sign in and sign up page to be indexed 13 | Allow: /users/sign_up 14 | Allow: /users/sign_in 15 | 16 | 17 | Sitemap: https://rubycommunity.africa/sitemap.xml -------------------------------------------------------------------------------- /public/sitemap.xml: -------------------------------------------------------------------------------- 1 | https://rubycommunity.africa2023-10-14T14:11:33+03:00weekly1.0https://rubycommunity.africa/about_us2023-10-14T14:11:33+03:00monthly0.9https://rubycommunity.africa/learn2023-10-14T14:11:33+03:00monthly0.9https://rubycommunity.africa/chapters2023-10-14T14:11:33+03:00monthly0.9https://rubycommunity.africa/users/sign_up2023-10-14T14:11:33+03:00monthly0.8https://rubycommunity.africa/users/sign_in2023-10-14T14:11:33+03:00monthly0.8 -------------------------------------------------------------------------------- /storage/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/African-Ruby-Community/arc_platform/c77a4f421418b59f00b462a04269f720dc73f1dd/storage/.keep -------------------------------------------------------------------------------- /tailwind.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | content: [ 3 | './app/views/**/*.html.erb', 4 | './app/helpers/**/*.rb', 5 | './app/assets/stylesheets/**/*.css', 6 | './app/javascript/**/*.js' 7 | ], 8 | theme: { 9 | extend: { 10 | fontFamily: { 11 | inter: ['Inter', 'sans-serif'], 12 | }, 13 | }, 14 | }, 15 | daisyui: { 16 | themes: [{ 17 | mytheme: { 18 | "primary": "#D82028", 19 | "secondary": "#F000B8", 20 | "accent": "#37CDBE", 21 | "neutral": "#3D4451", 22 | "base-100": "#FFFFFF", 23 | "info": "#3ABFF8", 24 | "success": "#36D399", 25 | "warning": "#FBBD23", 26 | "error": "#F87272", 27 | }, 28 | },], 29 | }, 30 | screens: { 31 | xs: '576', 32 | sm: '640px', 33 | md: '768px', 34 | lg: '1024px', 35 | xl: '1280px', 36 | '2xl': '1536px', 37 | }, 38 | plugins: [require("@tailwindcss/typography"), require("daisyui")], 39 | } 40 | -------------------------------------------------------------------------------- /test-docker-entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -e 4 | 5 | echo "Environment: $RAILS_ENV" 6 | 7 | # Check if we need to install new gems 8 | bundle check || bundle install --jobs 20 --retry 5 9 | 10 | # Then run any passed command 11 | bundle exec ${@} -------------------------------------------------------------------------------- /test/application_system_test_case.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'test_helper' 4 | 5 | class ApplicationSystemTestCase < ActionDispatch::SystemTestCase 6 | if ENV['CAPYBARA_SERVER_PORT'] 7 | served_by host: 'rails-app', port: ENV['CAPYBARA_SERVER_PORT'] 8 | 9 | driven_by :selenium, using: :headless_chrome, screen_size: [1400, 1400], options: { 10 | browser: :remote, 11 | url: "http://#{ENV.fetch('SELENIUM_HOST', nil)}:4444" 12 | } 13 | else 14 | driven_by :selenium, using: :headless_chrome, screen_size: [1400, 1400] 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /test/channels/application_cable/connection_test.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'test_helper' 4 | 5 | module ApplicationCable 6 | class ConnectionTest < ActionCable::Connection::TestCase 7 | # test "connects with cookies" do 8 | # cookies.signed[:user_id] = 42 9 | # 10 | # connect 11 | # 12 | # assert_equal connection.user_id, "42" 13 | # end 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /test/controllers/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/African-Ruby-Community/arc_platform/c77a4f421418b59f00b462a04269f720dc73f1dd/test/controllers/.keep -------------------------------------------------------------------------------- /test/controllers/chapters_controller_test.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'test_helper' 4 | 5 | class ChaptersControllerTest < ActionDispatch::IntegrationTest 6 | setup do 7 | @chapter = chapters(:one) 8 | @country = countries(:one) 9 | end 10 | 11 | test 'should get index' do 12 | get chapters_url 13 | assert_response :success 14 | end 15 | 16 | test 'should show chapter' do 17 | get chapter_url(@chapter) 18 | assert_response :success 19 | end 20 | end 21 | -------------------------------------------------------------------------------- /test/controllers/countries_controller_test.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'test_helper' 4 | 5 | class CountriesControllerTest < ActionDispatch::IntegrationTest 6 | setup do 7 | @country = countries(:one) 8 | @user = users(:organization_admin) # Create and organization_admin user 9 | @user.confirm 10 | sign_in(@user) # Sign in user 11 | end 12 | 13 | test 'should get index' do 14 | get countries_url 15 | assert_response :success 16 | end 17 | 18 | test 'should show country' do 19 | get country_url(@country) 20 | assert_response :success 21 | end 22 | end 23 | -------------------------------------------------------------------------------- /test/controllers/projects_controller_test.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'test_helper' 4 | 5 | class ProjectsControllerTest < ActionDispatch::IntegrationTest 6 | setup do 7 | @project = projects(:one) 8 | 9 | @user = users(:organization_admin) # Create and organization_admin user 10 | @user.confirm 11 | sign_in(@user) # Sign in user 12 | end 13 | 14 | test 'should get index' do 15 | get projects_url 16 | assert_response :success 17 | end 18 | 19 | test 'should show project' do 20 | get project_url(@project) 21 | assert_response :success 22 | end 23 | end 24 | -------------------------------------------------------------------------------- /test/fixtures/chapters.yml: -------------------------------------------------------------------------------- 1 | # == Schema Information 2 | # 3 | # Table name: chapters 4 | # 5 | # id :bigint not null, primary key 6 | # description :text 7 | # location :string 8 | # name :string 9 | # created_at :datetime not null 10 | # updated_at :datetime not null 11 | # country_id :bigint 12 | # 13 | # Indexes 14 | # 15 | # index_chapters_on_country_id (country_id) 16 | # index_chapters_on_name (name) UNIQUE 17 | # 18 | 19 | one: 20 | name: Chapter One 21 | location: MyString 22 | description: MyText 23 | 24 | two: 25 | name: Chapter two 26 | location: MyString 27 | description: MyText 28 | -------------------------------------------------------------------------------- /test/fixtures/countries.yml: -------------------------------------------------------------------------------- 1 | # == Schema Information 2 | # 3 | # Table name: countries 4 | # 5 | # id :bigint not null, primary key 6 | # name :string 7 | # created_at :datetime not null 8 | # updated_at :datetime not null 9 | # 10 | 11 | one: 12 | name: Kenya 13 | 14 | two: 15 | name: Rwanda 16 | -------------------------------------------------------------------------------- /test/fixtures/feature_flags.yml: -------------------------------------------------------------------------------- 1 | # == Schema Information 2 | # 3 | # Table name: feature_flags 4 | # 5 | # id :bigint not null, primary key 6 | # description :text 7 | # enabled :boolean 8 | # name :string 9 | # created_at :datetime not null 10 | # updated_at :datetime not null 11 | # 12 | 13 | one: 14 | name: MyString 15 | description: MyText 16 | enabled: false 17 | 18 | two: 19 | name: MyString 20 | description: MyText 21 | enabled: false 22 | -------------------------------------------------------------------------------- /test/fixtures/files/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/African-Ruby-Community/arc_platform/c77a4f421418b59f00b462a04269f720dc73f1dd/test/fixtures/files/.keep -------------------------------------------------------------------------------- /test/fixtures/projects.yml: -------------------------------------------------------------------------------- 1 | # == Schema Information 2 | # 3 | # Table name: projects 4 | # 5 | # id :bigint not null, primary key 6 | # description :text 7 | # end_date :datetime 8 | # name :string 9 | # start_date :datetime 10 | # created_at :datetime not null 11 | # updated_at :datetime not null 12 | # chapter_id :bigint not null 13 | # 14 | # Indexes 15 | # 16 | # index_projects_on_chapter_id (chapter_id) 17 | # 18 | # Foreign Keys 19 | # 20 | # fk_rails_... (chapter_id => chapters.id) 21 | # 22 | 23 | one: 24 | name: MyString 25 | description: MyText 26 | chapter: one 27 | start_date: 2023-02-12 20:20:17 28 | end_date: 2023-02-12 20:20:17 29 | 30 | two: 31 | name: MyString 32 | description: MyText 33 | chapter: two 34 | start_date: 2023-02-12 20:20:17 35 | end_date: 2023-02-12 20:20:17 36 | -------------------------------------------------------------------------------- /test/fixtures/users.yml: -------------------------------------------------------------------------------- 1 | # == Schema Information 2 | # 3 | # Table name: users 4 | # 5 | # id :bigint not null, primary key 6 | # confirmation_sent_at :datetime 7 | # confirmation_token :string 8 | # confirmed_at :datetime 9 | # current_sign_in_at :datetime 10 | # current_sign_in_ip :string 11 | # email :string default(""), not null 12 | # encrypted_password :string default(""), not null 13 | # failed_attempts :integer default(0), not null 14 | # github_username :string 15 | # last_sign_in_at :datetime 16 | # last_sign_in_ip :string 17 | # locked_at :datetime 18 | # name :string 19 | # phone_number :string 20 | # remember_created_at :datetime 21 | # reset_password_sent_at :datetime 22 | # reset_password_token :string 23 | # role :integer 24 | # sign_in_count :integer default(0), not null 25 | # unconfirmed_email :string 26 | # unlock_token :string 27 | # created_at :datetime not null 28 | # updated_at :datetime not null 29 | # 30 | # Indexes 31 | # 32 | # index_users_on_confirmation_token (confirmation_token) UNIQUE 33 | # index_users_on_email (email) UNIQUE 34 | # index_users_on_github_username (github_username) UNIQUE 35 | # index_users_on_reset_password_token (reset_password_token) UNIQUE 36 | # index_users_on_unlock_token (unlock_token) UNIQUE 37 | # 38 | 39 | # This model initially had no columns defined. If you add columns to the 40 | # model remove the "{}" from the fixture names and add the columns immediately 41 | # below each fixture, per the syntax in the comments below 42 | # 43 | member: 44 | email: user1@example.com 45 | role: member1 46 | name: John Smith1 47 | phone_number: 2547111111111 48 | github_username: user1 49 | encrypted_password: <%= Devise::Encryptor.digest(User, 'password') %> 50 | 51 | chapter_admin: 52 | email: user2@example.com 53 | role: organization_admin 54 | name: John Doe 55 | phone_number: 254711111112 56 | github_username: user2 57 | encrypted_password: <%= Devise::Encryptor.digest(User, 'password') %> 58 | 59 | organization_admin: 60 | email: user3@example.com 61 | role: organization_admin 62 | name: Jane Doe 63 | phone_number: 254711111113 64 | github_username: user3 65 | encrypted_password: <%= Devise::Encryptor.digest(User, 'password') %> 66 | -------------------------------------------------------------------------------- /test/fixtures/users_chapters.yml: -------------------------------------------------------------------------------- 1 | # == Schema Information 2 | # 3 | # Table name: users_chapters 4 | # 5 | # id :bigint not null, primary key 6 | # main_chapter :boolean default(FALSE) 7 | # created_at :datetime not null 8 | # updated_at :datetime not null 9 | # chapter_id :bigint not null 10 | # user_id :bigint not null 11 | # 12 | # Indexes 13 | # 14 | # index_users_chapters_on_chapter_id (chapter_id) 15 | # index_users_chapters_on_user_id (user_id) 16 | # 17 | # Foreign Keys 18 | # 19 | # fk_rails_... (chapter_id => chapters.id) 20 | # fk_rails_... (user_id => users.id) 21 | # 22 | 23 | one: 24 | chapter: one 25 | user: member 26 | main_chapter: false 27 | 28 | two: 29 | chapter: two 30 | user: member 31 | main_chapter: false 32 | -------------------------------------------------------------------------------- /test/helpers/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/African-Ruby-Community/arc_platform/c77a4f421418b59f00b462a04269f720dc73f1dd/test/helpers/.keep -------------------------------------------------------------------------------- /test/integration/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/African-Ruby-Community/arc_platform/c77a4f421418b59f00b462a04269f720dc73f1dd/test/integration/.keep -------------------------------------------------------------------------------- /test/mailers/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/African-Ruby-Community/arc_platform/c77a4f421418b59f00b462a04269f720dc73f1dd/test/mailers/.keep -------------------------------------------------------------------------------- /test/models/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/African-Ruby-Community/arc_platform/c77a4f421418b59f00b462a04269f720dc73f1dd/test/models/.keep -------------------------------------------------------------------------------- /test/models/chapter_test.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # == Schema Information 4 | # 5 | # Table name: chapters 6 | # 7 | # id :bigint not null, primary key 8 | # description :text 9 | # location :string 10 | # name :string 11 | # created_at :datetime not null 12 | # updated_at :datetime not null 13 | # country_id :bigint 14 | # 15 | # Indexes 16 | # 17 | # index_chapters_on_country_id (country_id) 18 | # index_chapters_on_name (name) UNIQUE 19 | # 20 | require 'test_helper' 21 | 22 | class ChapterTest < ActiveSupport::TestCase 23 | # test "the truth" do 24 | # assert true 25 | # end 26 | end 27 | -------------------------------------------------------------------------------- /test/models/country_test.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # == Schema Information 4 | # 5 | # Table name: countries 6 | # 7 | # id :bigint not null, primary key 8 | # name :string 9 | # created_at :datetime not null 10 | # updated_at :datetime not null 11 | # 12 | require 'test_helper' 13 | 14 | class CountryTest < ActiveSupport::TestCase 15 | # test "the truth" do 16 | # assert true 17 | # end 18 | end 19 | -------------------------------------------------------------------------------- /test/models/feature_flag_test.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # == Schema Information 4 | # 5 | # Table name: feature_flags 6 | # 7 | # id :bigint not null, primary key 8 | # description :text 9 | # enabled :boolean 10 | # name :string 11 | # created_at :datetime not null 12 | # updated_at :datetime not null 13 | # 14 | require 'test_helper' 15 | 16 | class FeatureFlagTest < ActiveSupport::TestCase 17 | # test "the truth" do 18 | # assert true 19 | # end 20 | end 21 | -------------------------------------------------------------------------------- /test/models/project_test.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # == Schema Information 4 | # 5 | # Table name: projects 6 | # 7 | # id :bigint not null, primary key 8 | # description :text 9 | # end_date :datetime 10 | # name :string 11 | # start_date :datetime 12 | # created_at :datetime not null 13 | # updated_at :datetime not null 14 | # chapter_id :bigint not null 15 | # 16 | # Indexes 17 | # 18 | # index_projects_on_chapter_id (chapter_id) 19 | # 20 | # Foreign Keys 21 | # 22 | # fk_rails_... (chapter_id => chapters.id) 23 | # 24 | require 'test_helper' 25 | 26 | class ProjectTest < ActiveSupport::TestCase 27 | # test "the truth" do 28 | # assert true 29 | # end 30 | end 31 | -------------------------------------------------------------------------------- /test/models/user_test.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # == Schema Information 4 | # 5 | # Table name: users 6 | # 7 | # id :bigint not null, primary key 8 | # confirmation_sent_at :datetime 9 | # confirmation_token :string 10 | # confirmed_at :datetime 11 | # current_sign_in_at :datetime 12 | # current_sign_in_ip :string 13 | # email :string default(""), not null 14 | # encrypted_password :string default(""), not null 15 | # failed_attempts :integer default(0), not null 16 | # github_username :string 17 | # last_sign_in_at :datetime 18 | # last_sign_in_ip :string 19 | # locked_at :datetime 20 | # name :string 21 | # phone_number :string 22 | # remember_created_at :datetime 23 | # reset_password_sent_at :datetime 24 | # reset_password_token :string 25 | # role :integer 26 | # sign_in_count :integer default(0), not null 27 | # unconfirmed_email :string 28 | # unlock_token :string 29 | # created_at :datetime not null 30 | # updated_at :datetime not null 31 | # 32 | # Indexes 33 | # 34 | # index_users_on_confirmation_token (confirmation_token) UNIQUE 35 | # index_users_on_email (email) UNIQUE 36 | # index_users_on_github_username (github_username) UNIQUE 37 | # index_users_on_reset_password_token (reset_password_token) UNIQUE 38 | # index_users_on_unlock_token (unlock_token) UNIQUE 39 | # 40 | require 'test_helper' 41 | 42 | class UserTest < ActiveSupport::TestCase 43 | # test "the truth" do 44 | # assert true 45 | # end 46 | end 47 | -------------------------------------------------------------------------------- /test/models/users_chapter_test.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # == Schema Information 4 | # 5 | # Table name: users_chapters 6 | # 7 | # id :bigint not null, primary key 8 | # main_chapter :boolean default(FALSE) 9 | # created_at :datetime not null 10 | # updated_at :datetime not null 11 | # chapter_id :bigint not null 12 | # user_id :bigint not null 13 | # 14 | # Indexes 15 | # 16 | # index_users_chapters_on_chapter_id (chapter_id) 17 | # index_users_chapters_on_user_id (user_id) 18 | # 19 | # Foreign Keys 20 | # 21 | # fk_rails_... (chapter_id => chapters.id) 22 | # fk_rails_... (user_id => users.id) 23 | # 24 | require 'test_helper' 25 | 26 | class UsersChapterTest < ActiveSupport::TestCase 27 | # test "the truth" do 28 | # assert true 29 | # end 30 | end 31 | -------------------------------------------------------------------------------- /test/system/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/African-Ruby-Community/arc_platform/c77a4f421418b59f00b462a04269f720dc73f1dd/test/system/.keep -------------------------------------------------------------------------------- /test/system/chapters_test.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'application_system_test_case' 4 | 5 | class ChaptersTest < ApplicationSystemTestCase 6 | setup do 7 | @chapter = chapters(:one) 8 | end 9 | 10 | test 'visiting the index' do 11 | visit chapters_url 12 | assert_selector 'h1', text: 'Chapters' 13 | end 14 | 15 | test 'should create chapter' do 16 | visit chapters_url 17 | click_on 'New chapter' 18 | 19 | fill_in 'Description', with: @chapter.description 20 | fill_in 'Location', with: @chapter.location 21 | fill_in 'Name', with: @chapter.name 22 | click_on 'Create Chapter' 23 | 24 | assert_text 'Chapter was successfully created' 25 | click_on 'Back' 26 | end 27 | 28 | test 'should update Chapter' do 29 | visit chapter_url(@chapter) 30 | click_on 'Edit this chapter', match: :first 31 | 32 | fill_in 'Description', with: @chapter.description 33 | fill_in 'Location', with: @chapter.location 34 | fill_in 'Name', with: @chapter.name 35 | click_on 'Update Chapter' 36 | 37 | assert_text 'Chapter was successfully updated' 38 | click_on 'Back' 39 | end 40 | 41 | test 'should destroy Chapter' do 42 | visit chapter_url(@chapter) 43 | click_on 'Destroy this chapter', match: :first 44 | 45 | assert_text 'Chapter was successfully destroyed' 46 | end 47 | end 48 | -------------------------------------------------------------------------------- /test/system/countries_test.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'application_system_test_case' 4 | 5 | class CountriesTest < ApplicationSystemTestCase 6 | setup do 7 | @country = countries(:one) 8 | end 9 | 10 | test 'visiting the index' do 11 | visit countries_url 12 | assert_selector 'h1', text: 'Countries' 13 | end 14 | 15 | test 'should create country' do 16 | visit countries_url 17 | click_on 'New country' 18 | 19 | fill_in 'Name', with: @country.name 20 | click_on 'Create Country' 21 | 22 | assert_text 'Country was successfully created' 23 | click_on 'Back' 24 | end 25 | 26 | test 'should update Country' do 27 | visit country_url(@country) 28 | click_on 'Edit this country', match: :first 29 | 30 | fill_in 'Name', with: @country.name 31 | click_on 'Update Country' 32 | 33 | assert_text 'Country was successfully updated' 34 | click_on 'Back' 35 | end 36 | 37 | test 'should destroy Country' do 38 | visit country_url(@country) 39 | click_on 'Destroy this country', match: :first 40 | 41 | assert_text 'Country was successfully destroyed' 42 | end 43 | end 44 | -------------------------------------------------------------------------------- /test/system/projects_test.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'application_system_test_case' 4 | 5 | class ProjectsTest < ApplicationSystemTestCase 6 | setup do 7 | @project = projects(:one) 8 | end 9 | 10 | test 'visiting the index' do 11 | visit projects_url 12 | assert_selector 'h1', text: 'Projects' 13 | end 14 | 15 | test 'should create project' do 16 | visit projects_url 17 | click_on 'New project' 18 | 19 | fill_in 'Chapter', with: @project.chapter_id 20 | fill_in 'Description', with: @project.description 21 | fill_in 'End date', with: @project.end_date 22 | fill_in 'Name', with: @project.name 23 | fill_in 'Start date', with: @project.start_date 24 | click_on 'Create Project' 25 | 26 | assert_text 'Project was successfully created' 27 | click_on 'Back' 28 | end 29 | 30 | test 'should update Project' do 31 | visit project_url(@project) 32 | click_on 'Edit this project', match: :first 33 | 34 | fill_in 'Chapter', with: @project.chapter_id 35 | fill_in 'Description', with: @project.description 36 | fill_in 'End date', with: @project.end_date 37 | fill_in 'Name', with: @project.name 38 | fill_in 'Start date', with: @project.start_date 39 | click_on 'Update Project' 40 | 41 | assert_text 'Project was successfully updated' 42 | click_on 'Back' 43 | end 44 | 45 | test 'should destroy Project' do 46 | visit project_url(@project) 47 | click_on 'Destroy this project', match: :first 48 | 49 | assert_text 'Project was successfully destroyed' 50 | end 51 | end 52 | -------------------------------------------------------------------------------- /test/test_helper.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # simple coverage test tool 4 | require 'simplecov' 5 | SimpleCov.start 6 | 7 | ENV['RAILS_ENV'] ||= 'test' 8 | require_relative '../config/environment' 9 | require 'rails/test_help' 10 | 11 | module ActiveSupport 12 | class TestCase 13 | # Run tests in parallel with specified workers 14 | parallelize(workers: :number_of_processors) 15 | 16 | # Setup all fixtures in test/fixtures/*.yml for all tests in alphabetical order. 17 | fixtures :all 18 | 19 | # Add more helper methods to be used by all tests here... 20 | include Devise::Test::IntegrationHelpers # Include devise test module 21 | end 22 | end 23 | -------------------------------------------------------------------------------- /tmp/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/African-Ruby-Community/arc_platform/c77a4f421418b59f00b462a04269f720dc73f1dd/tmp/.keep -------------------------------------------------------------------------------- /tmp/pids/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/African-Ruby-Community/arc_platform/c77a4f421418b59f00b462a04269f720dc73f1dd/tmp/pids/.keep -------------------------------------------------------------------------------- /tmp/storage/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/African-Ruby-Community/arc_platform/c77a4f421418b59f00b462a04269f720dc73f1dd/tmp/storage/.keep -------------------------------------------------------------------------------- /vendor/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/African-Ruby-Community/arc_platform/c77a4f421418b59f00b462a04269f720dc73f1dd/vendor/.keep --------------------------------------------------------------------------------