├── log
└── .gitkeep
├── lib
├── tasks
│ ├── .gitkeep
│ └── tddium.rake
├── assets
│ └── .gitkeep
└── templates
│ └── erb
│ └── scaffold
│ └── _form.html.erb
├── spec
├── lib
│ ├── .gitkeep
│ └── spam_checker_spec.rb
├── helpers
│ ├── .gitkeep
│ └── application_helper_spec.rb
├── models
│ ├── .gitkeep
│ ├── comment_spec.rb
│ ├── gravatar_spec.rb
│ └── country_sort_criteria_spec.rb
├── support
│ ├── .gitkeep
│ ├── mixins
│ │ └── .gitkeep
│ ├── matchers
│ │ ├── .gitkeep
│ │ ├── email_matchers.rb
│ │ └── flash.rb
│ ├── shared_examples
│ │ └── .gitkeep
│ ├── fixtures
│ │ ├── 1.JPG
│ │ ├── 1.pdf
│ │ ├── 2.JPG
│ │ ├── 3.JPG
│ │ └── מדהים.png
│ ├── view_stubs.rb
│ ├── fake_data.rb
│ ├── pagination.rb
│ ├── fake_user_factory.rb
│ ├── locale_fix.rb
│ ├── fake_mailer.rb
│ ├── aws_s3_mock_factory.rb
│ └── feed.xml
├── views
│ ├── .gitkeep
│ ├── header_views_spec.rb
│ ├── funded_projects_views_spec.rb
│ ├── layout_views_spec.rb
│ └── finalists_views_spec.rb
├── controllers
│ ├── .gitkeep
│ ├── pages_controller_spec.rb
│ ├── acceptances_controller_spec.rb
│ └── users_controller_spec.rb
├── features
│ ├── step_definitions
│ │ ├── page_steps.rb
│ │ ├── pagination_steps.rb
│ │ ├── dean_steps.rb
│ │ ├── dean_edits_project_steps.rb
│ │ ├── guest_views_project_steps.rb
│ │ ├── dean_manages_promotions_steps.rb
│ │ ├── guest_views_chapter.rb
│ │ ├── admin_manages_promotions_steps.rb
│ │ ├── export_steps.rb
│ │ ├── guest_views_chapter_steps.rb
│ │ └── role_steps.rb
│ ├── admin_edits_user.feature
│ ├── dean_deletes_spam.feature
│ ├── dean_creates_custom_application_intro.feature
│ ├── trustee_filters_funded_projects.feature
│ ├── guest_views_homepage.feature
│ ├── dean_views_projects.feature
│ ├── dean_generates_shortlist_report.feature.pending
│ ├── dean_creates_additional_questions_for_application.feature
│ ├── admin_dean_manage_chapters.feature
│ ├── dean_edits_project.feature
│ ├── trustee_edits_profile.feature
│ ├── admin_views_project_submissions.feature
│ ├── guest_views_project.feature
│ ├── admin_exports_projects.feature
│ └── admin_manages_promotions.feature
├── requests
│ └── routing_spec.rb
└── mailers
│ └── project_mailer_spec.rb
├── .ruby-version
├── app
├── mailers
│ ├── .gitkeep
│ ├── project_mailer.rb
│ └── invitation_mailer.rb
├── models
│ ├── .gitkeep
│ ├── funded_project.rb
│ ├── application_record.rb
│ ├── callbacks
│ │ └── url_normalizer.rb
│ ├── vote.rb
│ ├── project_moderation.rb
│ ├── guest.rb
│ └── role.rb
├── views
│ ├── pages
│ │ ├── .gitkeep
│ │ ├── faq.html.erb
│ │ └── about_us.html.erb
│ ├── locales
│ │ ├── _dmca.en.md
│ │ ├── _start_a_chapter_blurb.en.md
│ │ ├── _start_a_chapter_blurb.ru.md
│ │ ├── _start_a_chapter_blurb.pt.md
│ │ ├── _contact.pt.md
│ │ ├── _contact.en.md
│ │ ├── _contact.ru.md
│ │ ├── _contact.bg.md
│ │ ├── _contact.fr.md
│ │ ├── _contact.hy.md
│ │ └── _contact.es.md
│ ├── comments
│ │ └── create.js.erb
│ ├── shared
│ │ ├── _flashes.html.erb
│ │ ├── _javascript.html.erb
│ │ ├── _lightbox.html.erb
│ │ ├── _rssfeed.html.erb
│ │ └── _analytics.html.erb
│ ├── passwords
│ │ ├── create.html.erb
│ │ ├── new.html.erb
│ │ └── edit.html.erb
│ ├── errors
│ │ └── not_found.html.erb
│ ├── layouts
│ │ └── _locales.html.erb
│ ├── users
│ │ ├── edit.html.erb
│ │ ├── index.csv.erb
│ │ ├── _form.html.erb
│ │ └── index.html.erb
│ ├── chapters
│ │ ├── new.html.erb
│ │ ├── edit.html.erb
│ │ ├── index.html.erb
│ │ └── _chapter.html.erb
│ ├── projects
│ │ ├── _comments_js.html.erb
│ │ ├── _image_form.html.erb
│ │ ├── hide.turbo_stream.erb
│ │ ├── edit.html.erb
│ │ ├── _funded_date.html.erb
│ │ ├── _project_actions_js.html.erb
│ │ ├── _project.html.erb
│ │ ├── _image_form_element.html.erb
│ │ ├── new.html.erb
│ │ ├── show.html.erb
│ │ ├── success.html.erb
│ │ ├── _project_hidden.html.erb
│ │ └── _image_upload.html.erb
│ ├── funded_projects
│ │ ├── _1up_gallery.html.erb
│ │ ├── _2up_gallery.html.erb
│ │ ├── _3up_gallery.html.erb
│ │ └── _4up_gallery.html.erb
│ ├── sessions
│ │ ├── new.html.erb
│ │ └── _form.html.erb
│ ├── acceptances
│ │ └── new.html.erb
│ ├── invitation_mailer
│ │ └── invite_trustee.text.erb
│ ├── winners
│ │ ├── edit.html.erb
│ │ └── _form.html.erb
│ ├── invitations
│ │ └── new.html.erb
│ └── project_mailer
│ │ └── new_application.text.erb
├── assets
│ ├── javascripts
│ │ ├── components
│ │ │ └── .keep
│ │ ├── components.js
│ │ ├── chapters.js.coffee
│ │ ├── acceptances.js.coffee
│ │ ├── invitations.js.coffee
│ │ ├── server_rendering.js
│ │ ├── project-gallery.js
│ │ ├── owl.carousel.scroll.js
│ │ ├── tagline.js
│ │ ├── application-js.js
│ │ └── awesome_react.js
│ ├── images
│ │ ├── fb.png
│ │ ├── blog.png
│ │ ├── idea.png
│ │ ├── logo.png
│ │ ├── mail.png
│ │ ├── apply.png
│ │ ├── blog-2.png
│ │ ├── money.png
│ │ ├── rails.png
│ │ ├── twitter.png
│ │ ├── dean-hat.png
│ │ ├── instagram.png
│ │ ├── mini_map.png
│ │ ├── worldmap.png
│ │ ├── arrow_left.png
│ │ ├── arrow_right.png
│ │ ├── chapter_bg.png
│ │ ├── info-graphic.png
│ │ ├── info_graphic.png
│ │ ├── jagged_edge.png
│ │ ├── logo-160x160.png
│ │ ├── logo-800x800.png
│ │ ├── map_texture.png
│ │ ├── social_icons.png
│ │ ├── tagline_bg.png
│ │ ├── logo-1500x750.png
│ │ ├── no-image-index.png
│ │ ├── no-image-main.png
│ │ ├── hamburger-small.png
│ │ ├── no-image-original.png
│ │ ├── small_arrow_left.png
│ │ ├── small_arrow_right.png
│ │ ├── awesome-news-banner.png
│ │ ├── location_pin_small.png
│ │ ├── logo-banner-1680x626.png
│ │ ├── no-image-small_square.png
│ │ ├── no-image-large_rectangle.png
│ │ └── start-a-chapter
│ │ │ ├── book-icon.png
│ │ │ ├── globe-icon.png
│ │ │ ├── people-icon.png
│ │ │ ├── plane-icon.png
│ │ │ ├── tada-icon.png
│ │ │ ├── start-a-chapter-0.jpg
│ │ │ ├── start-a-chapter-1.jpg
│ │ │ └── start-a-chapter-2.jpg
│ ├── stylesheets
│ │ ├── _funded-projects.scss
│ │ ├── _projects-edit.scss
│ │ ├── _projects.scss
│ │ ├── _chapters.scss
│ │ ├── _chapters-new.scss
│ │ ├── acceptances.css.scss
│ │ ├── _winners.scss
│ │ ├── _shared-feed.scss
│ │ ├── _buttons.scss
│ │ ├── _base-mixins.scss
│ │ ├── _base-extends.scss
│ │ ├── _invitations-new.scss
│ │ ├── _shared-flash-messages.scss
│ │ ├── _base-variables.scss
│ │ ├── _shared-footer.scss
│ │ ├── _owl.theme.default.min.css
│ │ ├── _faq.scss
│ │ └── _finalists.scss
│ └── config
│ │ └── manifest.js
├── extras
│ ├── domain_constraint.rb
│ ├── gravatar.rb
│ ├── country_options.rb
│ ├── subdomain_constraint.rb
│ ├── country_sort_criteria.rb
│ └── spam_checker.rb
├── javascript
│ ├── application.js
│ └── controllers
│ │ ├── hamburger_controller.js
│ │ ├── application.js
│ │ ├── js_controller.js
│ │ ├── revealer_controller.js
│ │ ├── jump_controller.js
│ │ ├── menu_toggle_controller.js
│ │ ├── index.js
│ │ └── toggler_controller.js
├── controllers
│ ├── sessions_controller.rb
│ ├── home_controller.rb
│ ├── errors_controller.rb
│ ├── roles_controller.rb
│ ├── acceptances_controller.rb
│ ├── admins_controller.rb
│ ├── promotions_controller.rb
│ ├── votes_controller.rb
│ ├── subdomains_controller.rb
│ └── comments_controller.rb
├── jobs
│ ├── direct_upload_job.rb
│ └── project_mailer_job.rb
├── validators
│ ├── email_validator.rb
│ └── url_validator.rb
└── helpers
│ ├── project_nav_helper.rb
│ └── invitations_helper.rb
├── db
├── migrate
│ ├── .gitkeep
│ ├── 20221017040918_add_shrine.rb
│ ├── 20120605132131_add_index_to_photo.rb
│ ├── 20220304205611_add_votes_chapter.rb
│ ├── 20221026065913_add_photo_caption.rb
│ ├── 20250204080047_add_funded_projects_index.rb
│ ├── 20120221203310_add_country_to_chapters.rb
│ ├── 20120223155120_project_rss_feed_url.rb
│ ├── 20120208135332_add_rss_feed_to_chapters.rb
│ ├── 20120208182547_add_funded_on_to_projects.rb
│ ├── 20190215232536_add_chapters_instagram.rb
│ ├── 20201018204124_add_application_intro.rb
│ ├── 20120601153734_add_email_address_to_chapter.rb
│ ├── 20130925010702_add_chapter_time_zone.rb
│ ├── 20120213202939_last_chapter_user_is_viewing.rb
│ ├── 20141016030734_add_photo_direct_upload_url.rb
│ ├── 20150519013053_add_inactive_chapter.rb
│ ├── 20160721212739_add_chapter_locale.rb
│ ├── 20120828150909_ensure_lowercase_slugs.rb
│ ├── 20120605132113_add_index_to_invitation.rb
│ ├── 20190510033512_add_invitation_role_name.rb
│ ├── 20170706232725_add_submission_response_email_to_chapters.rb
│ ├── 20190215211018_add_chapters_hide_trustees.rb
│ ├── 20120126190545_rename_submissions_to_projects.rb
│ ├── 20251116063511_add_metadata_to_projects.rb
│ ├── 20120223145132_add_sort_order_to_photos.rb
│ ├── 20120124210428_add_first_and_last_names_to_invitations.rb
│ ├── 20151010182141_add_hiding_to_projects.rb
│ ├── 20120227152649_remove_extra_urls_from_user.rb
│ ├── 20120206183303_create_votes.rb
│ ├── 20120221183925_create_photos.rb
│ ├── 20250204072748_add_funded_projects_full_text_indexes.rb
│ ├── 20190430194718_fix_photos_field_lengths.rb
│ ├── 20200118195058_create_comments.rb
│ ├── 20120124154733_create_invitations.rb
│ ├── 20120913183115_add_funded_description.rb
│ ├── 20120123213411_create_roles.rb
│ ├── 20120427130615_change_project_info_column_names.rb
│ ├── 20120202133816_ensure_uniqueness_of_roles_and_invitations.rb
│ ├── 20120522140401_add_slugs_to_chapters.rb
│ ├── 20121025015059_add_full_text_index_to_projects.rb
│ ├── 20120131180550_change_chapters.rb
│ ├── 20251116230500_create_project_moderations.rb
│ ├── 20120131193919_remove_extra_fields_from_users.rb
│ └── 20120214161129_extra_questions_on_applications.rb
└── seeds.rb
├── public
├── images
│ └── .gitkeep
├── blog
│ └── awesome_foundation
│ │ ├── comments.php
│ │ ├── sidebar.php
│ │ ├── 404.php
│ │ ├── stylesheets
│ │ └── sass
│ │ │ ├── screen.scss
│ │ │ ├── bourbon
│ │ │ ├── lib
│ │ │ │ ├── bourbon
│ │ │ │ │ ├── sass_extensions.rb
│ │ │ │ │ └── sass_extensions
│ │ │ │ │ │ ├── functions
│ │ │ │ │ │ └── compact.rb
│ │ │ │ │ │ └── functions.rb
│ │ │ │ └── bourbon.rb
│ │ │ ├── css3
│ │ │ │ ├── _box-sizing.scss
│ │ │ │ ├── _user-select.scss
│ │ │ │ ├── _appearance.scss
│ │ │ │ ├── _inline-block.scss
│ │ │ │ ├── _box-shadow.scss
│ │ │ │ ├── _background-size.scss
│ │ │ │ └── _transform.scss
│ │ │ ├── functions
│ │ │ │ ├── _tint-shade.scss
│ │ │ │ ├── _grid-width.scss
│ │ │ │ ├── _render-gradients.scss
│ │ │ │ ├── _radial-gradient.scss
│ │ │ │ └── _linear-gradient.scss
│ │ │ ├── addons
│ │ │ │ ├── _font-family.scss
│ │ │ │ ├── _clearfix.scss
│ │ │ │ └── _position.scss
│ │ │ └── _bourbon.scss
│ │ │ ├── _base-variables.scss
│ │ │ └── _sidebar.scss
│ │ ├── searchform.php
│ │ ├── style.css
│ │ ├── header-head.php
│ │ ├── README
│ │ ├── footer.php
│ │ ├── functions.php
│ │ ├── loop-single.php
│ │ ├── page.php
│ │ ├── index.php
│ │ ├── archive.php
│ │ ├── header-nav.php
│ │ └── loop-category.php
├── favicon.ico
├── favicon-1.ico
├── favicon-3.ico
└── robots.txt
├── vendor
├── javascript
│ └── .keep
├── assets
│ └── stylesheets
│ │ └── .gitkeep
└── lightgallery
│ ├── fonts
│ ├── lg.eot
│ ├── lg.ttf
│ └── lg.woff
│ └── img
│ ├── lg-loading.gif
│ ├── video-play.png
│ ├── vimeo-play.png
│ └── youtube-play.png
├── .rspec
├── config
├── initializers
│ ├── csv.rb
│ ├── rss.rb
│ ├── locales.rb
│ ├── magickly.rb
│ ├── session_store.rb
│ ├── mime_types.rb
│ ├── rack-attack.rb
│ ├── safe_join_fix.rb
│ ├── application_controller_renderer.rb
│ ├── cookies_serializer.rb
│ ├── clearance.rb
│ ├── time_formats.rb
│ ├── tus.rb
│ ├── email.rb
│ ├── filter_parameter_logging.rb
│ ├── markdown_handler.rb
│ ├── permissions_policy.rb
│ ├── wrap_parameters.rb
│ ├── backtrace_silencers.rb
│ ├── inflections.rb
│ ├── assets.rb
│ ├── errors.rb
│ ├── rack-cors.rb
│ └── content_security_policy.rb
├── database.travis.yml
├── spring.rb
├── environment.rb
├── boot.rb
├── cable.yml
├── importmap.rb
├── cucumber.yml
├── configs
│ └── spam_config.rb
└── database.yml
├── Procfile
├── features
├── step_definitions
│ ├── factory_bot_steps.rb
│ └── trustee_steps.rb
└── clearance
│ ├── visitor_signs_out.feature
│ ├── visitor_signs_up.feature
│ └── visitor_signs_in.feature
├── doc
├── awesomebits-docker-compose-up.gif
└── awesomebits-docker-compose-rails-console.gif
├── config.ru
├── docker-runapp.sh
├── .gitignore
├── script
├── rails
└── cucumber
├── Dockerfile
├── Rakefile
├── .travis.yml
├── docker-compose.yml
└── .github
└── workflows
└── build.yaml
/log/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/lib/tasks/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/spec/lib/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/.ruby-version:
--------------------------------------------------------------------------------
1 | 3.3.6
2 |
--------------------------------------------------------------------------------
/app/mailers/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/app/models/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/db/migrate/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/lib/assets/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/public/images/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/spec/helpers/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/spec/models/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/spec/support/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/spec/views/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/vendor/javascript/.keep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/app/views/pages/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/spec/controllers/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/spec/support/mixins/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/spec/support/matchers/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/.rspec:
--------------------------------------------------------------------------------
1 | --colour -r turnip/rspec
2 |
--------------------------------------------------------------------------------
/spec/support/shared_examples/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/vendor/assets/stylesheets/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/app/assets/javascripts/components/.keep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/public/blog/awesome_foundation/comments.php:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/config/initializers/csv.rb:
--------------------------------------------------------------------------------
1 | require 'csv'
2 |
--------------------------------------------------------------------------------
/app/assets/javascripts/components.js:
--------------------------------------------------------------------------------
1 | //= require_tree ./components
2 |
--------------------------------------------------------------------------------
/Procfile:
--------------------------------------------------------------------------------
1 | web: bundle exec puma -C config/puma.rb
2 | release: rake db:migrate
3 |
--------------------------------------------------------------------------------
/config/initializers/rss.rb:
--------------------------------------------------------------------------------
1 | MAIN_AWESOME_RSS = "http://blog.awesomefoundation.org/feed/"
2 |
--------------------------------------------------------------------------------
/features/step_definitions/factory_bot_steps.rb:
--------------------------------------------------------------------------------
1 | require 'factory_bot/step_definitions'
2 |
--------------------------------------------------------------------------------
/config/initializers/locales.rb:
--------------------------------------------------------------------------------
1 | I18n.available_locales = [:bg, :en, :es, :fr, :hy, :pt, :ru]
2 |
--------------------------------------------------------------------------------
/config/initializers/magickly.rb:
--------------------------------------------------------------------------------
1 | ENV['MAGICKLY_HOST'] ||= "http://img.awesomefoundation.org"
2 |
--------------------------------------------------------------------------------
/features/step_definitions/trustee_steps.rb:
--------------------------------------------------------------------------------
1 | step 'I am logged in as a trustee' do
2 |
3 | end
4 |
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/awesomefoundation/awesomebits/HEAD/public/favicon.ico
--------------------------------------------------------------------------------
/app/views/locales/_dmca.en.md:
--------------------------------------------------------------------------------
1 | For copyright concerns, view our [DMCA policy](<%= ENV["DMCA_URL"] %>).
2 |
--------------------------------------------------------------------------------
/public/favicon-1.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/awesomefoundation/awesomebits/HEAD/public/favicon-1.ico
--------------------------------------------------------------------------------
/public/favicon-3.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/awesomefoundation/awesomebits/HEAD/public/favicon-3.ico
--------------------------------------------------------------------------------
/app/assets/images/fb.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/awesomefoundation/awesomebits/HEAD/app/assets/images/fb.png
--------------------------------------------------------------------------------
/app/models/funded_project.rb:
--------------------------------------------------------------------------------
1 | class FundedProject < Project
2 | validates :funded_on, presence: true
3 | end
4 |
--------------------------------------------------------------------------------
/app/assets/images/blog.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/awesomefoundation/awesomebits/HEAD/app/assets/images/blog.png
--------------------------------------------------------------------------------
/app/assets/images/idea.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/awesomefoundation/awesomebits/HEAD/app/assets/images/idea.png
--------------------------------------------------------------------------------
/app/assets/images/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/awesomefoundation/awesomebits/HEAD/app/assets/images/logo.png
--------------------------------------------------------------------------------
/app/assets/images/mail.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/awesomefoundation/awesomebits/HEAD/app/assets/images/mail.png
--------------------------------------------------------------------------------
/app/assets/stylesheets/_funded-projects.scss:
--------------------------------------------------------------------------------
1 | @import 'funded-projects-index';
2 | @import 'funded-projects-show';
3 |
--------------------------------------------------------------------------------
/app/assets/stylesheets/_projects-edit.scss:
--------------------------------------------------------------------------------
1 | #old-photos {
2 | li span {
3 | position: absolute;
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/app/views/comments/create.js.erb:
--------------------------------------------------------------------------------
1 | CommentStore.setComments(<%= @comments.to_json.html_safe %>, <%= @project.id %>);
2 |
--------------------------------------------------------------------------------
/app/assets/images/apply.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/awesomefoundation/awesomebits/HEAD/app/assets/images/apply.png
--------------------------------------------------------------------------------
/app/assets/images/blog-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/awesomefoundation/awesomebits/HEAD/app/assets/images/blog-2.png
--------------------------------------------------------------------------------
/app/assets/images/money.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/awesomefoundation/awesomebits/HEAD/app/assets/images/money.png
--------------------------------------------------------------------------------
/app/assets/images/rails.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/awesomefoundation/awesomebits/HEAD/app/assets/images/rails.png
--------------------------------------------------------------------------------
/app/assets/images/twitter.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/awesomefoundation/awesomebits/HEAD/app/assets/images/twitter.png
--------------------------------------------------------------------------------
/app/models/application_record.rb:
--------------------------------------------------------------------------------
1 | class ApplicationRecord < ActiveRecord::Base
2 | self.abstract_class = true
3 | end
4 |
--------------------------------------------------------------------------------
/spec/support/fixtures/1.JPG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/awesomefoundation/awesomebits/HEAD/spec/support/fixtures/1.JPG
--------------------------------------------------------------------------------
/spec/support/fixtures/1.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/awesomefoundation/awesomebits/HEAD/spec/support/fixtures/1.pdf
--------------------------------------------------------------------------------
/spec/support/fixtures/2.JPG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/awesomefoundation/awesomebits/HEAD/spec/support/fixtures/2.JPG
--------------------------------------------------------------------------------
/spec/support/fixtures/3.JPG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/awesomefoundation/awesomebits/HEAD/spec/support/fixtures/3.JPG
--------------------------------------------------------------------------------
/app/assets/images/dean-hat.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/awesomefoundation/awesomebits/HEAD/app/assets/images/dean-hat.png
--------------------------------------------------------------------------------
/app/assets/images/instagram.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/awesomefoundation/awesomebits/HEAD/app/assets/images/instagram.png
--------------------------------------------------------------------------------
/app/assets/images/mini_map.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/awesomefoundation/awesomebits/HEAD/app/assets/images/mini_map.png
--------------------------------------------------------------------------------
/app/assets/images/worldmap.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/awesomefoundation/awesomebits/HEAD/app/assets/images/worldmap.png
--------------------------------------------------------------------------------
/app/assets/stylesheets/_projects.scss:
--------------------------------------------------------------------------------
1 | @import 'projects-index';
2 | @import 'projects-new';
3 | @import 'projects-edit';
4 |
--------------------------------------------------------------------------------
/config/database.travis.yml:
--------------------------------------------------------------------------------
1 | test:
2 | adapter: postgresql
3 | database: awesomefoundation_test
4 | username: postgres
5 |
--------------------------------------------------------------------------------
/spec/features/step_definitions/page_steps.rb:
--------------------------------------------------------------------------------
1 | step 'I am on the admin homepage' do
2 | visit admin_dashboard_path
3 | end
4 |
--------------------------------------------------------------------------------
/spec/support/fixtures/מדהים.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/awesomefoundation/awesomebits/HEAD/spec/support/fixtures/מדהים.png
--------------------------------------------------------------------------------
/app/assets/images/arrow_left.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/awesomefoundation/awesomebits/HEAD/app/assets/images/arrow_left.png
--------------------------------------------------------------------------------
/app/assets/images/arrow_right.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/awesomefoundation/awesomebits/HEAD/app/assets/images/arrow_right.png
--------------------------------------------------------------------------------
/app/assets/images/chapter_bg.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/awesomefoundation/awesomebits/HEAD/app/assets/images/chapter_bg.png
--------------------------------------------------------------------------------
/app/assets/images/info-graphic.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/awesomefoundation/awesomebits/HEAD/app/assets/images/info-graphic.png
--------------------------------------------------------------------------------
/app/assets/images/info_graphic.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/awesomefoundation/awesomebits/HEAD/app/assets/images/info_graphic.png
--------------------------------------------------------------------------------
/app/assets/images/jagged_edge.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/awesomefoundation/awesomebits/HEAD/app/assets/images/jagged_edge.png
--------------------------------------------------------------------------------
/app/assets/images/logo-160x160.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/awesomefoundation/awesomebits/HEAD/app/assets/images/logo-160x160.png
--------------------------------------------------------------------------------
/app/assets/images/logo-800x800.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/awesomefoundation/awesomebits/HEAD/app/assets/images/logo-800x800.png
--------------------------------------------------------------------------------
/app/assets/images/map_texture.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/awesomefoundation/awesomebits/HEAD/app/assets/images/map_texture.png
--------------------------------------------------------------------------------
/app/assets/images/social_icons.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/awesomefoundation/awesomebits/HEAD/app/assets/images/social_icons.png
--------------------------------------------------------------------------------
/app/assets/images/tagline_bg.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/awesomefoundation/awesomebits/HEAD/app/assets/images/tagline_bg.png
--------------------------------------------------------------------------------
/vendor/lightgallery/fonts/lg.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/awesomefoundation/awesomebits/HEAD/vendor/lightgallery/fonts/lg.eot
--------------------------------------------------------------------------------
/vendor/lightgallery/fonts/lg.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/awesomefoundation/awesomebits/HEAD/vendor/lightgallery/fonts/lg.ttf
--------------------------------------------------------------------------------
/vendor/lightgallery/fonts/lg.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/awesomefoundation/awesomebits/HEAD/vendor/lightgallery/fonts/lg.woff
--------------------------------------------------------------------------------
/app/assets/images/logo-1500x750.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/awesomefoundation/awesomebits/HEAD/app/assets/images/logo-1500x750.png
--------------------------------------------------------------------------------
/app/assets/images/no-image-index.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/awesomefoundation/awesomebits/HEAD/app/assets/images/no-image-index.png
--------------------------------------------------------------------------------
/app/assets/images/no-image-main.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/awesomefoundation/awesomebits/HEAD/app/assets/images/no-image-main.png
--------------------------------------------------------------------------------
/app/assets/images/hamburger-small.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/awesomefoundation/awesomebits/HEAD/app/assets/images/hamburger-small.png
--------------------------------------------------------------------------------
/app/assets/images/no-image-original.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/awesomefoundation/awesomebits/HEAD/app/assets/images/no-image-original.png
--------------------------------------------------------------------------------
/app/assets/images/small_arrow_left.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/awesomefoundation/awesomebits/HEAD/app/assets/images/small_arrow_left.png
--------------------------------------------------------------------------------
/app/assets/images/small_arrow_right.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/awesomefoundation/awesomebits/HEAD/app/assets/images/small_arrow_right.png
--------------------------------------------------------------------------------
/doc/awesomebits-docker-compose-up.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/awesomefoundation/awesomebits/HEAD/doc/awesomebits-docker-compose-up.gif
--------------------------------------------------------------------------------
/vendor/lightgallery/img/lg-loading.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/awesomefoundation/awesomebits/HEAD/vendor/lightgallery/img/lg-loading.gif
--------------------------------------------------------------------------------
/vendor/lightgallery/img/video-play.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/awesomefoundation/awesomebits/HEAD/vendor/lightgallery/img/video-play.png
--------------------------------------------------------------------------------
/vendor/lightgallery/img/vimeo-play.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/awesomefoundation/awesomebits/HEAD/vendor/lightgallery/img/vimeo-play.png
--------------------------------------------------------------------------------
/app/assets/images/awesome-news-banner.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/awesomefoundation/awesomebits/HEAD/app/assets/images/awesome-news-banner.png
--------------------------------------------------------------------------------
/app/assets/images/location_pin_small.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/awesomefoundation/awesomebits/HEAD/app/assets/images/location_pin_small.png
--------------------------------------------------------------------------------
/vendor/lightgallery/img/youtube-play.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/awesomefoundation/awesomebits/HEAD/vendor/lightgallery/img/youtube-play.png
--------------------------------------------------------------------------------
/app/assets/images/logo-banner-1680x626.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/awesomefoundation/awesomebits/HEAD/app/assets/images/logo-banner-1680x626.png
--------------------------------------------------------------------------------
/app/assets/images/no-image-small_square.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/awesomefoundation/awesomebits/HEAD/app/assets/images/no-image-small_square.png
--------------------------------------------------------------------------------
/config/spring.rb:
--------------------------------------------------------------------------------
1 | %w(
2 | .ruby-version
3 | .rbenv-vars
4 | tmp/restart.txt
5 | tmp/caching-dev.txt
6 | ).each { |path| Spring.watch(path) }
7 |
--------------------------------------------------------------------------------
/app/assets/images/no-image-large_rectangle.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/awesomefoundation/awesomebits/HEAD/app/assets/images/no-image-large_rectangle.png
--------------------------------------------------------------------------------
/app/assets/images/start-a-chapter/book-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/awesomefoundation/awesomebits/HEAD/app/assets/images/start-a-chapter/book-icon.png
--------------------------------------------------------------------------------
/app/assets/images/start-a-chapter/globe-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/awesomefoundation/awesomebits/HEAD/app/assets/images/start-a-chapter/globe-icon.png
--------------------------------------------------------------------------------
/app/assets/images/start-a-chapter/people-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/awesomefoundation/awesomebits/HEAD/app/assets/images/start-a-chapter/people-icon.png
--------------------------------------------------------------------------------
/app/assets/images/start-a-chapter/plane-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/awesomefoundation/awesomebits/HEAD/app/assets/images/start-a-chapter/plane-icon.png
--------------------------------------------------------------------------------
/app/assets/images/start-a-chapter/tada-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/awesomefoundation/awesomebits/HEAD/app/assets/images/start-a-chapter/tada-icon.png
--------------------------------------------------------------------------------
/doc/awesomebits-docker-compose-rails-console.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/awesomefoundation/awesomebits/HEAD/doc/awesomebits-docker-compose-rails-console.gif
--------------------------------------------------------------------------------
/spec/support/view_stubs.rb:
--------------------------------------------------------------------------------
1 | RSpec.configure do |config|
2 | config.before(:each, type: :view) do
3 | view.stubs(:embed?).returns(false)
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/config/environment.rb:
--------------------------------------------------------------------------------
1 | # Load the Rails application.
2 | require_relative "application"
3 |
4 | # Initialize the Rails application.
5 | Rails.application.initialize!
6 |
--------------------------------------------------------------------------------
/db/migrate/20221017040918_add_shrine.rb:
--------------------------------------------------------------------------------
1 | class AddShrine < ActiveRecord::Migration[5.2]
2 | def change
3 | add_column :photos, :image_data, :jsonb
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/spec/models/comment_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | RSpec.describe Comment, type: :model do
4 | pending "add some examples to (or delete) #{__FILE__}"
5 | end
6 |
--------------------------------------------------------------------------------
/app/assets/images/start-a-chapter/start-a-chapter-0.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/awesomefoundation/awesomebits/HEAD/app/assets/images/start-a-chapter/start-a-chapter-0.jpg
--------------------------------------------------------------------------------
/app/assets/images/start-a-chapter/start-a-chapter-1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/awesomefoundation/awesomebits/HEAD/app/assets/images/start-a-chapter/start-a-chapter-1.jpg
--------------------------------------------------------------------------------
/app/assets/images/start-a-chapter/start-a-chapter-2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/awesomefoundation/awesomebits/HEAD/app/assets/images/start-a-chapter/start-a-chapter-2.jpg
--------------------------------------------------------------------------------
/app/views/shared/_flashes.html.erb:
--------------------------------------------------------------------------------
1 |
2 | <% flash.each do |key, value| -%>
3 |
<%= value %>
4 | <% end -%>
5 |
6 |
--------------------------------------------------------------------------------
/db/migrate/20120605132131_add_index_to_photo.rb:
--------------------------------------------------------------------------------
1 | class AddIndexToPhoto < ActiveRecord::Migration[4.2]
2 | def change
3 | add_index :photos, :project_id
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/db/migrate/20220304205611_add_votes_chapter.rb:
--------------------------------------------------------------------------------
1 | class AddVotesChapter < ActiveRecord::Migration[5.2]
2 | def change
3 | add_reference :votes, :chapter
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/app/views/passwords/create.html.erb:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
--------------------------------------------------------------------------------
/db/migrate/20221026065913_add_photo_caption.rb:
--------------------------------------------------------------------------------
1 | class AddPhotoCaption < ActiveRecord::Migration[5.2]
2 | def change
3 | add_column :photos, :caption, :text
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/public/blog/awesome_foundation/sidebar.php:
--------------------------------------------------------------------------------
1 |
8 |
--------------------------------------------------------------------------------
/public/blog/awesome_foundation/404.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | 404
6 | Custom 404 page
7 |
8 |
9 |
--------------------------------------------------------------------------------
/public/blog/awesome_foundation/stylesheets/sass/screen.scss:
--------------------------------------------------------------------------------
1 | @import 'bourbon/bourbon';
2 |
3 | @import 'base-variables';
4 | @import 'base';
5 | @import 'post';
6 | @import 'sidebar';
7 |
--------------------------------------------------------------------------------
/app/extras/domain_constraint.rb:
--------------------------------------------------------------------------------
1 | class DomainConstraint
2 | def self.matches?(request)
3 | ENV['CANONICAL_HOST'].present? && request.host != ENV['CANONICAL_HOST']
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/config.ru:
--------------------------------------------------------------------------------
1 | # This file is used by Rack-based servers to start the application.
2 |
3 | require_relative "config/environment"
4 |
5 | run Rails.application
6 | Rails.application.load_server
7 |
--------------------------------------------------------------------------------
/db/migrate/20250204080047_add_funded_projects_index.rb:
--------------------------------------------------------------------------------
1 | class AddFundedProjectsIndex < ActiveRecord::Migration[6.1]
2 | def change
3 | add_index :projects, :funded_on
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/config/initializers/session_store.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | Rails.application.config.session_store :cookie_store, key: '_awesomefoundation_session'
4 |
--------------------------------------------------------------------------------
/db/migrate/20120221203310_add_country_to_chapters.rb:
--------------------------------------------------------------------------------
1 | class AddCountryToChapters < ActiveRecord::Migration[4.2]
2 | def change
3 | add_column :chapters, :country, :string
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/db/migrate/20120223155120_project_rss_feed_url.rb:
--------------------------------------------------------------------------------
1 | class ProjectRssFeedUrl < ActiveRecord::Migration[4.2]
2 | def change
3 | add_column :projects, :rss_feed_url, :string
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/db/migrate/20120208135332_add_rss_feed_to_chapters.rb:
--------------------------------------------------------------------------------
1 | class AddRssFeedToChapters < ActiveRecord::Migration[4.2]
2 | def change
3 | add_column :chapters, :rss_feed_url, :string
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/db/migrate/20120208182547_add_funded_on_to_projects.rb:
--------------------------------------------------------------------------------
1 | class AddFundedOnToProjects < ActiveRecord::Migration[4.2]
2 | def change
3 | add_column :projects, :funded_on, :date
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/db/migrate/20190215232536_add_chapters_instagram.rb:
--------------------------------------------------------------------------------
1 | class AddChaptersInstagram < ActiveRecord::Migration[4.2]
2 | def change
3 | add_column :chapters, :instagram_url, :string
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/db/migrate/20201018204124_add_application_intro.rb:
--------------------------------------------------------------------------------
1 | class AddApplicationIntro < ActiveRecord::Migration[5.2]
2 | def change
3 | add_column :chapters, :application_intro, :text
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/config/initializers/mime_types.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # Add new mime types for use in respond_to blocks:
4 | # Mime::Type.register "text/richtext", :rtf
5 |
--------------------------------------------------------------------------------
/db/migrate/20120601153734_add_email_address_to_chapter.rb:
--------------------------------------------------------------------------------
1 | class AddEmailAddressToChapter < ActiveRecord::Migration[4.2]
2 | def change
3 | add_column :chapters, :email_address, :string
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/db/migrate/20130925010702_add_chapter_time_zone.rb:
--------------------------------------------------------------------------------
1 | class AddChapterTimeZone < ActiveRecord::Migration[4.2]
2 | def change
3 | add_column 'chapters', 'time_zone', :string, :limit => 50
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/db/migrate/20120213202939_last_chapter_user_is_viewing.rb:
--------------------------------------------------------------------------------
1 | class LastChapterUserIsViewing < ActiveRecord::Migration[4.2]
2 | def change
3 | add_column :users, :last_viewed_chapter_id, :int
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/db/migrate/20141016030734_add_photo_direct_upload_url.rb:
--------------------------------------------------------------------------------
1 | class AddPhotoDirectUploadUrl < ActiveRecord::Migration[4.2]
2 | def change
3 | add_column 'photos', 'direct_upload_url', :string
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/db/migrate/20150519013053_add_inactive_chapter.rb:
--------------------------------------------------------------------------------
1 | class AddInactiveChapter < ActiveRecord::Migration[4.2]
2 | def change
3 | add_column 'chapters', 'inactive_at', :timestamp, :default => nil
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/db/migrate/20160721212739_add_chapter_locale.rb:
--------------------------------------------------------------------------------
1 | class AddChapterLocale < ActiveRecord::Migration[4.2]
2 | def change
3 | add_column :chapters, :locale, :string, :null => false, :default => "en"
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/docker-runapp.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | set -e
4 |
5 | rm -f tmp/pids/server.pid
6 |
7 | bundle install
8 | bundle exec rake db:migrate
9 | bundle exec rake db:seed
10 | bundle exec rails s -p 3000 -b '0.0.0.0'
11 |
--------------------------------------------------------------------------------
/app/assets/stylesheets/_chapters.scss:
--------------------------------------------------------------------------------
1 | @import 'chapters-show';
2 | @import 'chapters-index';
3 | @import 'chapters-new';
4 |
5 | body.chapters-show {
6 | section.container {
7 | width: 100%;
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/app/views/errors/not_found.html.erb:
--------------------------------------------------------------------------------
1 |
2 | The page you were looking for doesn't exist.
3 | You may have mistyped the address or the page may have moved.
4 |
5 |
--------------------------------------------------------------------------------
/app/views/layouts/_locales.html.erb:
--------------------------------------------------------------------------------
1 | <% I18n.available_locales.each do |locale| %>
2 | <%= tag("link", :rel => "alternate", :hreflang => locale, :href => url_for(:locale => locale, :only_path => false)) %>
3 | <% end %>
4 |
--------------------------------------------------------------------------------
/db/migrate/20120828150909_ensure_lowercase_slugs.rb:
--------------------------------------------------------------------------------
1 | class EnsureLowercaseSlugs < ActiveRecord::Migration[4.2]
2 | def up
3 | execute("UPDATE chapters SET slug=LOWER(slug)")
4 | end
5 |
6 | def down
7 | end
8 | end
9 |
--------------------------------------------------------------------------------
/app/assets/stylesheets/_chapters-new.scss:
--------------------------------------------------------------------------------
1 | .chapter-form {
2 | form {
3 | .chapter-admin {
4 | padding-bottom: 10px;
5 | border-bottom: 1px solid rgb(200,200,200);
6 | margin-bottom: 25px;
7 | }
8 | }
9 | }
--------------------------------------------------------------------------------
/app/assets/stylesheets/acceptances.css.scss:
--------------------------------------------------------------------------------
1 | // Place all the styles related to the acceptances controller here.
2 | // They will automatically be included in application.css.
3 | // You can use Sass (SCSS) here: http://sass-lang.com/
4 |
--------------------------------------------------------------------------------
/app/javascript/application.js:
--------------------------------------------------------------------------------
1 | // Configure your import map in config/importmap.rb. Read more: https://github.com/rails/importmap-rails
2 | import "controllers"
3 | import "@hotwired/turbo-rails"
4 |
5 | Turbo.session.drive = false
6 |
--------------------------------------------------------------------------------
/config/boot.rb:
--------------------------------------------------------------------------------
1 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__)
2 |
3 | require "bundler/setup" # Set up gems listed in the Gemfile.
4 | require "bootsnap/setup" # Speed up boot time by caching expensive operations.
5 |
--------------------------------------------------------------------------------
/db/migrate/20120605132113_add_index_to_invitation.rb:
--------------------------------------------------------------------------------
1 | class AddIndexToInvitation < ActiveRecord::Migration[4.2]
2 | def change
3 | add_index :invitations, :invitee_id
4 | add_index :invitations, :inviter_id
5 | end
6 | end
7 |
--------------------------------------------------------------------------------
/db/migrate/20190510033512_add_invitation_role_name.rb:
--------------------------------------------------------------------------------
1 | class AddInvitationRoleName < ActiveRecord::Migration[5.2]
2 | def change
3 | add_column :invitations, :role_name, :string, null: false, default: "trustee"
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/public/blog/awesome_foundation/stylesheets/sass/bourbon/lib/bourbon/sass_extensions.rb:
--------------------------------------------------------------------------------
1 | module Bourbon::SassExtensions
2 | end
3 |
4 | require "sass"
5 |
6 | require File.join(File.dirname(__FILE__), "/sass_extensions/functions")
7 |
--------------------------------------------------------------------------------
/spec/features/step_definitions/pagination_steps.rb:
--------------------------------------------------------------------------------
1 | step 'I follow the link to the next page' do
2 | go_to_next_page
3 | end
4 |
5 | step 'I should see pagination links' do
6 | expect(page).to have_css('div.pagination')
7 | end
8 |
--------------------------------------------------------------------------------
/app/controllers/sessions_controller.rb:
--------------------------------------------------------------------------------
1 | class SessionsController < Clearance::SessionsController
2 | def url_after_create
3 | submissions_path
4 | end
5 |
6 | def url_after_destroy
7 | root_path
8 | end
9 | end
10 |
--------------------------------------------------------------------------------
/public/robots.txt:
--------------------------------------------------------------------------------
1 | # See https://www.robotstxt.org/robotstxt.html for documentation on how to use the robots.txt file
2 | #
3 | # To ban all spiders from the entire site uncomment the next two lines:
4 | # User-Agent: *
5 | # Disallow: /
6 |
--------------------------------------------------------------------------------
/spec/features/step_definitions/dean_steps.rb:
--------------------------------------------------------------------------------
1 | step 'there is a dean in the system' do
2 | @dean_role = FactoryBot.create(:role, :name => 'dean')
3 | @dean = @dean_role.user
4 | @dean_chapter = @dean_role.chapter
5 | end
6 |
--------------------------------------------------------------------------------
/app/javascript/controllers/hamburger_controller.js:
--------------------------------------------------------------------------------
1 | import { Controller } from "@hotwired/stimulus"
2 |
3 | export default class extends Controller {
4 | toggle() {
5 | this.element.parentElement.classList.toggle('shownav')
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/db/migrate/20170706232725_add_submission_response_email_to_chapters.rb:
--------------------------------------------------------------------------------
1 | class AddSubmissionResponseEmailToChapters < ActiveRecord::Migration[4.2]
2 | def change
3 | add_column :chapters, :submission_response_email, :text
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/db/migrate/20190215211018_add_chapters_hide_trustees.rb:
--------------------------------------------------------------------------------
1 | class AddChaptersHideTrustees < ActiveRecord::Migration[4.2]
2 | def change
3 | add_column :chapters, :hide_trustees, :boolean, :null => false, :default => false
4 | end
5 | end
6 |
--------------------------------------------------------------------------------
/public/blog/awesome_foundation/stylesheets/sass/bourbon/css3/_box-sizing.scss:
--------------------------------------------------------------------------------
1 | @mixin box-sizing ($box) {
2 | // content-box | border-box | inherit
3 | -webkit-box-sizing: $box;
4 | -moz-box-sizing: $box;
5 | box-sizing: $box;
6 | }
7 |
--------------------------------------------------------------------------------
/public/blog/awesome_foundation/stylesheets/sass/bourbon/css3/_user-select.scss:
--------------------------------------------------------------------------------
1 | @mixin user-select($arg: none) {
2 | -webkit-user-select: $arg;
3 | -moz-user-select: $arg;
4 | -ms-user-select: $arg;
5 | user-select: $arg;
6 | }
7 |
--------------------------------------------------------------------------------
/app/views/users/edit.html.erb:
--------------------------------------------------------------------------------
1 | <% provide(:page_title, t(".title")) %>
2 |
3 |
7 |
8 |
--------------------------------------------------------------------------------
/config/initializers/rack-attack.rb:
--------------------------------------------------------------------------------
1 | class Rack::Attack
2 | blocklist_ips = ENV['BLOCKLIST_IPS'] ? ENV['BLOCKLIST_IPS'].split(/,\s*/) : []
3 |
4 | blocklist("blacklisted ips") do |request|
5 | blocklist_ips.include? request.ip
6 | end
7 | end
8 |
--------------------------------------------------------------------------------
/app/controllers/home_controller.rb:
--------------------------------------------------------------------------------
1 | class HomeController < ApplicationController
2 | def index
3 | @chapters = Chapter.active.visitable.for_display
4 | @projects = Project.recent_winners.preload(:primary_photo, :chapter).limit(15)
5 | end
6 | end
7 |
--------------------------------------------------------------------------------
/db/migrate/20120126190545_rename_submissions_to_projects.rb:
--------------------------------------------------------------------------------
1 | class RenameSubmissionsToProjects < ActiveRecord::Migration[4.2]
2 | def change
3 | rename_table :projects, :accepted_projects
4 | rename_table :submissions, :projects
5 | end
6 | end
7 |
--------------------------------------------------------------------------------
/app/jobs/direct_upload_job.rb:
--------------------------------------------------------------------------------
1 | class DirectUploadJob
2 | include SuckerPunch::Job
3 |
4 | def perform(target)
5 | ActiveRecord::Base.connection_pool.with_connection do
6 | target.transfer_from_direct_upload
7 | end
8 | end
9 | end
10 |
--------------------------------------------------------------------------------
/app/views/chapters/new.html.erb:
--------------------------------------------------------------------------------
1 | <% provide(:page_title, t(".title")) %>
2 |
3 |
7 |
8 |
--------------------------------------------------------------------------------
/config/cable.yml:
--------------------------------------------------------------------------------
1 | development:
2 | adapter: async
3 |
4 | test:
5 | adapter: test
6 |
7 | production:
8 | adapter: redis
9 | url: <%= ENV.fetch("REDIS_URL") { "redis://localhost:6379/1" } %>
10 | channel_prefix: awesomefoundation_production
11 |
--------------------------------------------------------------------------------
/db/migrate/20251116063511_add_metadata_to_projects.rb:
--------------------------------------------------------------------------------
1 | class AddMetadataToProjects < ActiveRecord::Migration[7.2]
2 | def change
3 | add_column :projects, :metadata, :jsonb, default: {}
4 | add_index :projects, :metadata, using: :gin
5 | end
6 | end
7 |
--------------------------------------------------------------------------------
/config/initializers/safe_join_fix.rb:
--------------------------------------------------------------------------------
1 | # TODO Rails 3.2.22.3 introduced a change that makes this required.
2 | # When upgrading Rails, see if this is still required.
3 | class ActionView::Helpers::InstanceTag
4 | include ActionView::Helpers::OutputSafetyHelper
5 | end
6 |
--------------------------------------------------------------------------------
/db/migrate/20120223145132_add_sort_order_to_photos.rb:
--------------------------------------------------------------------------------
1 | class AddSortOrderToPhotos < ActiveRecord::Migration[4.2]
2 | def change
3 | add_column :photos, :sort_order, :integer, :default => 9999, :null => false
4 | add_index :photos, :sort_order
5 | end
6 | end
7 |
--------------------------------------------------------------------------------
/app/views/projects/_comments_js.html.erb:
--------------------------------------------------------------------------------
1 | <% content_for :javascript do %>
2 | <% javascript_tag do %>
3 | window.addEventListener("load", function () {
4 | CommentStore.setComments(<%= comments.to_json.html_safe %>);
5 | });
6 | <% end %>
7 | <% end %>
8 |
--------------------------------------------------------------------------------
/app/assets/javascripts/chapters.js.coffee:
--------------------------------------------------------------------------------
1 | # Place all the behaviors and hooks related to the matching controller here.
2 | # All this logic will automatically be available in application.js.
3 | # You can use CoffeeScript in this file: http://jashkenas.github.com/coffee-script/
4 |
--------------------------------------------------------------------------------
/app/assets/javascripts/acceptances.js.coffee:
--------------------------------------------------------------------------------
1 | # Place all the behaviors and hooks related to the matching controller here.
2 | # All this logic will automatically be available in application.js.
3 | # You can use CoffeeScript in this file: http://jashkenas.github.com/coffee-script/
4 |
--------------------------------------------------------------------------------
/app/assets/javascripts/invitations.js.coffee:
--------------------------------------------------------------------------------
1 | # Place all the behaviors and hooks related to the matching controller here.
2 | # All this logic will automatically be available in application.js.
3 | # You can use CoffeeScript in this file: http://jashkenas.github.com/coffee-script/
4 |
--------------------------------------------------------------------------------
/db/migrate/20120124210428_add_first_and_last_names_to_invitations.rb:
--------------------------------------------------------------------------------
1 | class AddFirstAndLastNamesToInvitations < ActiveRecord::Migration[4.2]
2 | def change
3 | add_column :invitations, :first_name, :string
4 | add_column :invitations, :last_name, :string
5 | end
6 | end
7 |
--------------------------------------------------------------------------------
/public/blog/awesome_foundation/stylesheets/sass/bourbon/css3/_appearance.scss:
--------------------------------------------------------------------------------
1 | @mixin appearance ($value) {
2 | -webkit-appearance: $value;
3 | -moz-appearance: $value;
4 | -ms-appearance: $value;
5 | -o-appearance: $value;
6 | appearance: $value;
7 | }
8 |
--------------------------------------------------------------------------------
/app/assets/javascripts/server_rendering.js:
--------------------------------------------------------------------------------
1 | //= require react-server
2 | //= require react_ujs
3 | //= require ./components
4 | //
5 | // By default, this file is loaded for server-side rendering.
6 | // It should require your components and any dependencies.
7 | //= require ./awesome_react
8 |
--------------------------------------------------------------------------------
/app/assets/javascripts/project-gallery.js:
--------------------------------------------------------------------------------
1 | /* Launches project gallery lightbox from button on project show pages */
2 |
3 | $("#launch-gallery").on("click", function(event) {
4 | event.preventDefault();
5 | document.getElementById('project-gallery').querySelector('.image').click();
6 | });
7 |
--------------------------------------------------------------------------------
/config/initializers/application_controller_renderer.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # ActiveSupport::Reloader.to_prepare do
4 | # ApplicationController.renderer.defaults.merge!(
5 | # http_host: 'example.org',
6 | # https: false
7 | # )
8 | # end
9 |
--------------------------------------------------------------------------------
/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/views/chapters/edit.html.erb:
--------------------------------------------------------------------------------
1 | <% provide(:page_title, [t(".title"), @chapter.display_name].join(" - ")) %>
2 |
3 |
7 |
8 |
--------------------------------------------------------------------------------
/config/initializers/cookies_serializer.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # Specify a serializer for the signed and encrypted cookie jars.
4 | # Valid options are :json, :marshal, and :hybrid.
5 | Rails.application.config.action_dispatch.cookies_serializer = :hybrid
6 |
--------------------------------------------------------------------------------
/public/blog/awesome_foundation/searchform.php:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/app/mailers/project_mailer.rb:
--------------------------------------------------------------------------------
1 | class ProjectMailer < ActionMailer::Base
2 | default :from => DO_NOT_REPLY
3 |
4 | def new_application(project)
5 | @project = project
6 | mail(:to => project.email,
7 | :subject => "[Awesome] #{t("emails.application.subject")}")
8 | end
9 | end
10 |
--------------------------------------------------------------------------------
/db/migrate/20151010182141_add_hiding_to_projects.rb:
--------------------------------------------------------------------------------
1 | class AddHidingToProjects < ActiveRecord::Migration[4.2]
2 | def change
3 | add_column :projects, :hidden_reason, :string
4 | add_column :projects, :hidden_by_user_id, :integer
5 | add_column :projects, :hidden_at, :timestamp
6 | end
7 | end
8 |
--------------------------------------------------------------------------------
/app/validators/email_validator.rb:
--------------------------------------------------------------------------------
1 | class EmailValidator < ActiveModel::EachValidator
2 | def validate_each(record, attribute, value)
3 | unless value =~ /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\z/i
4 | record.errors[attribute] << (options[:message] || "is not an email")
5 | end
6 | end
7 | end
8 |
--------------------------------------------------------------------------------
/config/initializers/clearance.rb:
--------------------------------------------------------------------------------
1 | Clearance.configure do |config|
2 | config.allow_sign_up = false
3 | config.password_strategy = Clearance::PasswordStrategies::SHA1
4 | config.mailer_sender = 'do-not-reply@awesomefoundation.org'
5 | config.rotate_csrf_on_sign_in = true
6 | config.routes = false
7 | end
8 |
--------------------------------------------------------------------------------
/app/controllers/errors_controller.rb:
--------------------------------------------------------------------------------
1 | class ErrorsController < ApplicationController
2 | def not_found
3 | render_404
4 | end
5 |
6 | def internal_server_error
7 | render status: :internal_server_error, file: File.join(Rails.root, "public", "500.html"), content_type: :html
8 | end
9 | end
10 |
--------------------------------------------------------------------------------
/app/controllers/roles_controller.rb:
--------------------------------------------------------------------------------
1 | class RolesController < ApplicationController
2 | before_action { |c| c.must_be_able_to_manage_chapter_users(params[:id]) }
3 |
4 | def destroy
5 | role = Role.find(params[:id])
6 | role.destroy
7 | render :json => { :role_id => role.id }
8 | end
9 | end
10 |
--------------------------------------------------------------------------------
/public/blog/awesome_foundation/style.css:
--------------------------------------------------------------------------------
1 | /*
2 | Theme Name: awesome_foundation
3 | Theme URI: http://awesomefoundation.org/
4 | Description: The theme for The Awesome Foundation website.
5 | Version: 1.0
6 | Author: thoughbot
7 | Author URI: http://www.thoughbot.com
8 | */
9 |
--------------------------------------------------------------------------------
/spec/support/matchers/email_matchers.rb:
--------------------------------------------------------------------------------
1 | RSpec::Matchers.define :have_delivered_email do |expected|
2 | chain :to do |address|
3 | @address = address
4 | end
5 |
6 | match do |actual|
7 | emails = actual.delivery_to(expected, @address)
8 | expect(emails.length).to eq(1)
9 | end
10 | end
11 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .ruby-gemset
2 | .bundle
3 | .env
4 | .envrc
5 | db/*.sqlite3
6 | log/*.log
7 | tmp/
8 | .sass-cache/
9 | db/schema.rb
10 | public/system
11 | *.DS_Store
12 | coverage/*
13 | *.swp
14 | *~
15 | rerun.txt
16 | tags
17 | !.keep
18 | vendor/bundler_gems
19 | bin
20 | .tddium*
21 | .tddium
22 | .tm_properties
23 |
--------------------------------------------------------------------------------
/app/views/funded_projects/_1up_gallery.html.erb:
--------------------------------------------------------------------------------
1 |
2 | <%= image_tag(project.display_images[0].url(:large_rectangle)) %>
3 |
--------------------------------------------------------------------------------
/script/rails:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 | # This command will automatically be run when you run "rails" with Rails 3 gems installed from the root of your application.
3 |
4 | APP_PATH = File.expand_path('../../config/application', __FILE__)
5 | require File.expand_path('../../config/boot', __FILE__)
6 | require 'rails/commands'
7 |
--------------------------------------------------------------------------------
/spec/features/admin_edits_user.feature:
--------------------------------------------------------------------------------
1 | Feature: Admin edits a user
2 |
3 | Scenario: Admin edits a user's email address
4 | Given I am logged in as an admin
5 | And there is a trustee in the system
6 | When I edit that trustee's email address
7 | Then I should see the change reflected in the list of all users
8 |
--------------------------------------------------------------------------------
/app/extras/gravatar.rb:
--------------------------------------------------------------------------------
1 | class Gravatar
2 | attr_reader :email
3 |
4 | def initialize(email)
5 | @email = email
6 | end
7 |
8 | def hash
9 | Digest::MD5.hexdigest(email.to_s.strip.downcase)
10 | end
11 |
12 | def url
13 | "https://www.gravatar.com/avatar/#{hash}?d=retro&s=134"
14 | end
15 | end
16 |
--------------------------------------------------------------------------------
/config/initializers/time_formats.rb:
--------------------------------------------------------------------------------
1 | # {
2 | # :short_date => "%x", # 04/13/10
3 | # :long_date => "%a, %b %d, %Y" # Tue, Apr 13, 2010
4 | # }.each do |format_name, format_string|
5 | # Time::DATE_FORMATS[format_name] = format_string
6 | # end
7 |
8 | Time::DATE_FORMATS[:long_with_zone] = "%B %d, %Y %H:%M %Z"
9 |
--------------------------------------------------------------------------------
/db/migrate/20120227152649_remove_extra_urls_from_user.rb:
--------------------------------------------------------------------------------
1 | class RemoveExtraUrlsFromUser < ActiveRecord::Migration[4.2]
2 | def change
3 | remove_column :users, :chapter_id
4 | remove_column :users, :twitter_username
5 | remove_column :users, :facebook_url
6 | remove_column :users, :linkedin_url
7 | end
8 | end
9 |
--------------------------------------------------------------------------------
/app/extras/country_options.rb:
--------------------------------------------------------------------------------
1 | class CountryOptions
2 | def self.countries_for_select(options = nil)
3 | ApplicationController.helpers.options_for_select(["Worldwide", separator] + COUNTRIES, { disabled: separator }.merge(options))
4 | end
5 |
6 | private
7 | def self.separator
8 | "-" * 20
9 | end
10 | end
11 |
--------------------------------------------------------------------------------
/app/javascript/controllers/js_controller.js:
--------------------------------------------------------------------------------
1 | import { Controller } from "@hotwired/stimulus"
2 |
3 | // https://gist.github.com/adrienpoly/862846f5882796fdeb4fc85b260b3c5a
4 | export default class extends Controller {
5 | static values = { loaded: false }
6 |
7 | connect() {
8 | this.loadedValue = true
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/app/assets/stylesheets/_winners.scss:
--------------------------------------------------------------------------------
1 | .center-form__cancel {
2 | text-align: center;
3 | }
4 |
5 | .center-form__cancel-link {
6 | color: $lighter-base-font-color !important;
7 | font-size: .85em;
8 |
9 | text-decoration: none !important;
10 |
11 | &:hover {
12 | text-decoration: underline !important;
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/spec/features/dean_deletes_spam.feature:
--------------------------------------------------------------------------------
1 | Feature: Deleting projects
2 |
3 | Scenario: Projects are spam, and the dean deletes it
4 | Given I am logged in as a dean
5 | And someone has submitted spam to my chapter
6 | When I go to the projects list
7 | And I delete the project
8 | Then I should not see the project anymore
9 |
--------------------------------------------------------------------------------
/config/initializers/tus.rb:
--------------------------------------------------------------------------------
1 | unless ENV["AWS_BUCKET"]
2 | require "tus/server"
3 | require "tus/storage/filesystem"
4 |
5 | if Rails.env.test?
6 | Tus::Server.opts[:storage] = Tus::Storage::Filesystem.new("tmp/tus-test")
7 | else
8 | Tus::Server.opts[:storage] = Tus::Storage::Filesystem.new("tmp/tus")
9 | end
10 | end
11 |
--------------------------------------------------------------------------------
/db/migrate/20120206183303_create_votes.rb:
--------------------------------------------------------------------------------
1 | class CreateVotes < ActiveRecord::Migration[4.2]
2 | def change
3 | create_table :votes do |t|
4 | t.references :user
5 | t.references :project
6 |
7 | t.timestamps
8 | end
9 |
10 | add_index :votes, [:user_id, :project_id], :unique => true
11 | end
12 | end
13 |
--------------------------------------------------------------------------------
/spec/features/step_definitions/dean_edits_project_steps.rb:
--------------------------------------------------------------------------------
1 | step 'I set the winning date to be February 2008' do
2 | fill_in("project_funded_on", :with => "2008-02-01")
3 | click_button("Save")
4 | end
5 |
6 | step 'I should see the project was funded in February 2008' do
7 | expect(find('.funded-on').text).to eq("(February 2008)")
8 | end
9 |
--------------------------------------------------------------------------------
/app/views/locales/_start_a_chapter_blurb.en.md:
--------------------------------------------------------------------------------
1 | # Start a Chapter
2 |
3 | The Awesome Foundation is driven by hundreds of volunteers around the world who organize, launch, and run chapters that give out monthly grants. It's simple and a lot of fun. Interested in getting one started up in your own community? [Find out more](<%= start_a_chapter_path %>).
4 |
--------------------------------------------------------------------------------
/public/blog/awesome_foundation/stylesheets/sass/bourbon/functions/_tint-shade.scss:
--------------------------------------------------------------------------------
1 | // Add percentage of white to a color
2 | @function tint($color, $percent){
3 | @return mix(white, $color, $percent);
4 | }
5 |
6 | // Add percentage of black to a color
7 | @function shade($color, $percent){
8 | @return mix(black, $color, $percent);
9 | }
10 |
--------------------------------------------------------------------------------
/app/views/locales/_start_a_chapter_blurb.ru.md:
--------------------------------------------------------------------------------
1 | # Основать раздел
2 |
3 | Фонд Awesome управляется сотнями добровольцев по всему миру, которые организуют, запускают и управляют разделами, которые выдают ежемесячные гранты. Это просто и очень весело. Заинтересованы в том, чтобы начать работу в своем сообществе? [Узнайте больше](<%= start_a_chapter_path %>).
4 |
--------------------------------------------------------------------------------
/app/javascript/controllers/revealer_controller.js:
--------------------------------------------------------------------------------
1 | import { Controller } from "@hotwired/stimulus"
2 |
3 | export default class extends Controller {
4 | static values = {
5 | expandedClass: 'expanded',
6 | }
7 |
8 | reveal(event) {
9 | this.element.classList.add(this.expandedClassValue)
10 | event.preventDefault()
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/spec/support/matchers/flash.rb:
--------------------------------------------------------------------------------
1 | RSpec::Matchers.define :show_the_flash do |expected|
2 | match do |actual|
3 | expect(actual).to have_selector("#flash #flash_#{expected}")
4 | end
5 |
6 | failure_message do |actual|
7 | %[Expected this content:\n#{actual.body}\n to have an element matching "#flash #flash_#{expected}"]
8 | end
9 | end
10 |
--------------------------------------------------------------------------------
/script/cucumber:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 |
3 | vendored_cucumber_bin = Dir["#{File.dirname(__FILE__)}/../vendor/{gems,plugins}/cucumber*/bin/cucumber"].first
4 | if vendored_cucumber_bin
5 | load File.expand_path(vendored_cucumber_bin)
6 | else
7 | require 'rubygems' unless ENV['NO_RUBYGEMS']
8 | require 'cucumber'
9 | load Cucumber::BINARY
10 | end
11 |
--------------------------------------------------------------------------------
/public/blog/awesome_foundation/stylesheets/sass/bourbon/css3/_inline-block.scss:
--------------------------------------------------------------------------------
1 | // Legacy support for inline-block in IE7 (maybe IE6)
2 | @mixin inline-block {
3 | display: -moz-inline-box;
4 | -moz-box-orient: vertical;
5 | display: inline-block;
6 | vertical-align: baseline;
7 | zoom: 1;
8 | *display: inline;
9 | *vertical-align: auto;
10 | }
11 |
--------------------------------------------------------------------------------
/app/views/sessions/new.html.erb:
--------------------------------------------------------------------------------
1 |
14 |
--------------------------------------------------------------------------------
/app/views/shared/_javascript.html.erb:
--------------------------------------------------------------------------------
1 |
4 |
5 | <%= javascript_include_tag "application-js" %>
6 |
7 | <%= render 'shared/analytics' %>
8 |
9 | <%= yield :javascript %>
10 |
11 | <% if Rails.env.test? %>
12 | <%= javascript_tag do %>
13 | $.ajaxSetup({ async: false });
14 | <% end %>
15 | <% end %>
16 |
--------------------------------------------------------------------------------
/app/extras/subdomain_constraint.rb:
--------------------------------------------------------------------------------
1 | class SubdomainConstraint
2 | def self.matches?(request)
3 | if ENV['CANONICAL_HOST'].present?
4 | return false if request.host == ENV['CANONICAL_HOST']
5 | end
6 |
7 | case request.subdomains.first
8 | when 'www', '', nil, ENV['SUBDOMAIN']
9 | false
10 | else
11 | true
12 | end
13 | end
14 | end
15 |
--------------------------------------------------------------------------------
/config/importmap.rb:
--------------------------------------------------------------------------------
1 | # Pin npm packages by running ./bin/importmap
2 |
3 | pin "application", preload: true
4 | pin "@hotwired/stimulus", to: "stimulus.min.js", preload: true
5 | pin "@hotwired/stimulus-loading", to: "stimulus-loading.js", preload: true
6 | pin_all_from "app/javascript/controllers", under: "controllers"
7 | pin "@hotwired/turbo-rails", to: "turbo.min.js", preload: true
8 |
--------------------------------------------------------------------------------
/lib/tasks/tddium.rake:
--------------------------------------------------------------------------------
1 | namespace :tddium do
2 | desc "Setup the database for tddium. https://gist.github.com/1519804"
3 | task :db_hook do
4 | Rake::Task["db:create"].invoke
5 | if File.exists?(File.join(Rails.root, "db", "schema.rb"))
6 | Rake::Task['db:schema:load'].invoke
7 | else
8 | Rake::Task['db:migrate'].invoke
9 | end
10 | end
11 | end
12 |
--------------------------------------------------------------------------------
/app/views/locales/_start_a_chapter_blurb.pt.md:
--------------------------------------------------------------------------------
1 | # Comece um Capítulo
2 |
3 | A Fundação Awesome é construída por centenas de voluntários em todo o mundo que organizam, fundam e gerenciam capítulos (grupos ou “filiais”) que financiam projetos incríveis todos os meses. É simples e divertido. Você tem interesse em começar um capítulo em sua cidade? [Descubra mais](<%= start_a_chapter_path %>).
4 |
--------------------------------------------------------------------------------
/db/migrate/20120221183925_create_photos.rb:
--------------------------------------------------------------------------------
1 | class CreatePhotos < ActiveRecord::Migration[4.2]
2 | def change
3 | create_table :photos do |t|
4 | t.timestamps
5 | t.string :image_file_name
6 | t.string :image_content_type
7 | t.integer :image_file_size
8 | t.datetime :image_updated_at
9 | t.references :project
10 | end
11 | end
12 | end
13 |
--------------------------------------------------------------------------------
/app/assets/stylesheets/_shared-feed.scss:
--------------------------------------------------------------------------------
1 | //*****************************************************
2 | //RSS and Events Sidebar Feed
3 | //*****************************************************
4 |
5 | ol.feed {
6 | margin: 0px;
7 |
8 | li {
9 | list-style: none;
10 | margin-bottom: 10px;
11 |
12 | &:last-child {
13 | margin: 0px;
14 | }
15 | }
16 | }
17 |
18 |
--------------------------------------------------------------------------------
/public/blog/awesome_foundation/stylesheets/sass/bourbon/addons/_font-family.scss:
--------------------------------------------------------------------------------
1 | $georgia: Georgia, Cambria, "Times New Roman", Times, serif;
2 | $helvetica: "Helvetica Neue", Helvetica, Arial, sans-serif;
3 | $lucida-grande: "Lucida Grande", Tahoma, Verdana, Arial, sans-serif;
4 | $monospace: "Bitstream Vera Sans Mono", Consolas, Courier, monospace;
5 | $verdana: Verdana, Geneva, sans-serif;
6 |
--------------------------------------------------------------------------------
/app/helpers/project_nav_helper.rb:
--------------------------------------------------------------------------------
1 | module ProjectNavHelper
2 | def project_winning_siblings(project)
3 | prev_project = project.chapter.winning_projects.where(Project.arel_table[:funded_on].gt(project.funded_on)).last
4 | next_project = project.chapter.winning_projects.where(Project.arel_table[:funded_on].lt(project.funded_on)).first
5 |
6 | [prev_project, next_project]
7 | end
8 | end
9 |
--------------------------------------------------------------------------------
/config/initializers/email.rb:
--------------------------------------------------------------------------------
1 | DO_NOT_REPLY = "do-not-reply@awesomefoundation.org"
2 |
3 | ActionMailer::Base.smtp_settings = {
4 | :address => "smtp.sendgrid.net",
5 | :port => "25",
6 | :authentication => :plain,
7 | :user_name => ENV['SENDGRID_USERNAME'],
8 | :password => ENV['SENDGRID_PASSWORD'],
9 | :domain => ENV['SENDGRID_DOMAIN']
10 | }
11 |
--------------------------------------------------------------------------------
/db/migrate/20250204072748_add_funded_projects_full_text_indexes.rb:
--------------------------------------------------------------------------------
1 | class AddFundedProjectsFullTextIndexes < ActiveRecord::Migration[6.1]
2 | def change
3 | add_index :projects, %{to_tsvector('english', email)}, using: :gin
4 | add_index :projects, %{to_tsvector('english', url)}, using: :gin
5 | add_index :projects, %{to_tsvector('english', funded_description)}, using: :gin
6 | end
7 | end
8 |
--------------------------------------------------------------------------------
/db/migrate/20190430194718_fix_photos_field_lengths.rb:
--------------------------------------------------------------------------------
1 | class FixPhotosFieldLengths < ActiveRecord::Migration[5.2]
2 | def up
3 | change_column :photos, :image_file_name, :text
4 | change_column :photos, :direct_upload_url, :text
5 | end
6 |
7 | def down
8 | change_column :photos, :image_file_name, :string
9 | change_column :photos, :direct_upload_url, :string
10 | end
11 | end
12 |
--------------------------------------------------------------------------------
/db/migrate/20200118195058_create_comments.rb:
--------------------------------------------------------------------------------
1 | class CreateComments < ActiveRecord::Migration[5.2]
2 | def change
3 | create_table :comments do |t|
4 | t.integer :user_id
5 | t.integer :project_id
6 | t.integer :viewable_chapter_id
7 | t.text :body
8 | t.string :viewable_by, length: 20, null: false, index: true
9 | t.timestamps
10 | end
11 | end
12 | end
13 |
--------------------------------------------------------------------------------
/features/clearance/visitor_signs_out.feature:
--------------------------------------------------------------------------------
1 | Feature: Sign out
2 |
3 | In order to protect my account from unauthorized access
4 | As a signed in user
5 | I want to sign out
6 |
7 | Scenario: User signs out
8 | Given I am signed up as "email@example.com"
9 | When I sign in as "email@example.com"
10 | Then I should be signed in
11 | When I sign out
12 | Then I should be signed out
13 |
--------------------------------------------------------------------------------
/app/javascript/controllers/jump_controller.js:
--------------------------------------------------------------------------------
1 | import { Controller } from "@hotwired/stimulus"
2 |
3 | export default class extends Controller {
4 | static values = {
5 | scroll: false
6 | }
7 |
8 | scrollValueChanged() {
9 | if (this.scrollValue === true)
10 | this.scroll()
11 | }
12 |
13 | scroll() {
14 | this.element.scrollIntoView(true)
15 | this.scrollValue = false
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/app/validators/url_validator.rb:
--------------------------------------------------------------------------------
1 | class UrlValidator < ActiveModel::EachValidator
2 | def validate_each(record, attribute, value)
3 | valid = begin
4 | URI.parse(value).kind_of?(URI::HTTP)
5 | rescue URI::InvalidURIError
6 | false
7 | end
8 |
9 | unless valid
10 | record.errors.add(attribute, options[:message] || :invalid)
11 | end
12 | end
13 | end
14 |
--------------------------------------------------------------------------------
/db/migrate/20120124154733_create_invitations.rb:
--------------------------------------------------------------------------------
1 | class CreateInvitations < ActiveRecord::Migration[4.2]
2 | def change
3 | create_table :invitations do |t|
4 | t.string :email, :null => false
5 | t.references :chapter
6 | t.references :invitee
7 | t.references :inviter
8 | t.boolean :accepted, :default => false, :null => false
9 |
10 | t.timestamps
11 | end
12 | end
13 | end
14 |
--------------------------------------------------------------------------------
/db/migrate/20120913183115_add_funded_description.rb:
--------------------------------------------------------------------------------
1 | class AddFundedDescription < ActiveRecord::Migration[4.2]
2 | def up
3 | add_column "projects", "funded_description", :text
4 | Project.reset_column_information
5 | execute("UPDATE projects SET funded_description=about_project WHERE funded_on IS NOT NULL")
6 | end
7 |
8 | def down
9 | remove_column "projects", "funded_description"
10 | end
11 | end
12 |
--------------------------------------------------------------------------------
/app/models/callbacks/url_normalizer.rb:
--------------------------------------------------------------------------------
1 | class UrlNormalizer
2 | def initialize(*url_fields)
3 | @url_fields = url_fields
4 | end
5 |
6 | def before_validation(record)
7 | @url_fields.each do |url_field|
8 | url = record[url_field]
9 |
10 | if url.present? && ! url.match(/:\/\//) && ! url.match(/^mailto:/)
11 | record[url_field] = "http://#{url}"
12 | end
13 | end
14 | end
15 | end
16 |
--------------------------------------------------------------------------------
/app/assets/javascripts/owl.carousel.scroll.js:
--------------------------------------------------------------------------------
1 | /* Prevents vertical scrolling of Owl carousel when on mobile/touch devices */
2 |
3 | var carousel = document.getElementById('owl-carousel');
4 |
5 | if (carousel != null) {
6 | carousel.addEventListener('touchmove', function(e) {
7 | e.preventDefault();
8 | }, false);
9 |
10 | if ('ontouchstart' in window) {
11 | $(carousel).addClass("touch-device");
12 | }
13 |
14 | }
--------------------------------------------------------------------------------
/public/blog/awesome_foundation/header-head.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/app/views/locales/_contact.pt.md:
--------------------------------------------------------------------------------
1 | # Contato
2 |
3 | Tem uma ideia irada? [Concorra ao nosso prêmio!](<%= new_submission_path %>)
4 |
5 | Para contatar um capítulo específico, favor escrever para o e-mail que aparece no topo da página do capítulo em questão, em baixo da sessão Capítulos aqui do site. Para perguntas para a comunidade global, é só escrever para contact@awesomefoundation.org. Não é possível dar notícias sobre a sua proposta neste endereço.
6 |
--------------------------------------------------------------------------------
/spec/features/dean_creates_custom_application_intro.feature:
--------------------------------------------------------------------------------
1 | Feature: A dean adds custom application intro text
2 |
3 | @javascript
4 | Scenario: Application intro
5 | Given I am logged in as a dean
6 | When I attempt to edit my chapter
7 | And I update a chapter with custom application intro text
8 | When I am on the submission page
9 | And I select the chapter to apply to
10 | Then I should see custom intro text
11 |
--------------------------------------------------------------------------------
/app/views/pages/faq.html.erb:
--------------------------------------------------------------------------------
1 | <% provide(:page_title, t(".title_tag")) %>
2 | <% content_for(:extra_body_classes, 'pages-about_us') %>
3 |
4 |
5 |
6 | <%= t(".headline") %>
7 |
8 |
9 |
10 |
11 | <%= render("locales/faq").html_safe %>
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/app/views/projects/_image_form.html.erb:
--------------------------------------------------------------------------------
1 |
9 |
--------------------------------------------------------------------------------
/app/views/locales/_contact.en.md:
--------------------------------------------------------------------------------
1 | # Contact
2 |
3 | Got an awesome idea? [Apply for a grant!](<%= new_submission_path %>)
4 |
5 | To reach a specific chapter, please use the e-mail link at the top of the chapter's page, under the Chapters section of this site. Or, for general global inquiries, you can drop us a line at contact@awesomefoundation.org. Please note that we are unable to provide updates or feedback with regard to applications at this address.
6 |
7 |
8 |
--------------------------------------------------------------------------------
/app/views/projects/hide.turbo_stream.erb:
--------------------------------------------------------------------------------
1 | <% if @error_message.present? || @display_project_even_if_hidden %>
2 | <%= turbo_stream.replace_all "#project#{project.id} .filtering" do %>
3 | <%= render "projects/hide_form", project: project, error_message: @error_message, expanded: true %>
4 | <% end %>
5 | <% else %>
6 | <%= turbo_stream.replace "project#{project.id}" do %>
7 | <%= render @project, scroll: true %>
8 | <% end %>
9 | <% end %>
10 |
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM ruby:3.3.6-alpine
2 |
3 | RUN apk update && \
4 | apk upgrade && \
5 | apk add --no-cache linux-headers libxml2-dev make gcc libc-dev libc6-compat nodejs tzdata postgresql-dev postgresql && \
6 | apk add --virtual build-packages --no-cache build-base curl-dev
7 |
8 | WORKDIR /app
9 | ADD Gemfile /app/Gemfile
10 | ADD Gemfile.lock /app/Gemfile.lock
11 | RUN bundle install
12 | ADD . /app
13 |
14 | CMD ["/app/docker-runapp.sh"]
15 |
--------------------------------------------------------------------------------
/app/extras/country_sort_criteria.rb:
--------------------------------------------------------------------------------
1 | class CountrySortCriteria
2 |
3 | def initialize(country_priority)
4 | @country_priority = country_priority
5 | end
6 |
7 | def to_proc
8 | proc do |chapter|
9 | if(@country_priority.include? chapter.country)
10 | "#{@country_priority.index(chapter.country)} #{chapter.name}"
11 | else
12 | "#{chapter.country} #{chapter.name}"
13 | end
14 | end
15 | end
16 |
17 | end
18 |
--------------------------------------------------------------------------------
/app/helpers/invitations_helper.rb:
--------------------------------------------------------------------------------
1 | module InvitationsHelper
2 |
3 | def show_chapters_dropdown?
4 | if Chapter.invitable_by(current_user).count > 1 || current_user.admin
5 | true
6 | else
7 | false
8 | end
9 | end
10 |
11 | def invitable_chapters
12 | Chapter.invitable_by(current_user).order(:name)
13 | end
14 |
15 | def primary_invitable_chapter
16 | Chapter.invitable_by(current_user).first
17 | end
18 |
19 | end
20 |
--------------------------------------------------------------------------------
/app/assets/config/manifest.js:
--------------------------------------------------------------------------------
1 | // app/assets/config/manifest.js
2 |
3 | // legacy asset pipeline links
4 | //= link_tree ../images
5 | //= link application.css
6 | //= link application-js.js
7 |
8 | // importmap links
9 | //= link application.js
10 | //= link_tree ../../../vendor/javascript .js
11 | //= link_tree ../../javascript .js
12 |
13 | // To render React components in production, precompile the server rendering manifest
14 | //= link server_rendering.js
15 |
--------------------------------------------------------------------------------
/app/views/users/index.csv.erb:
--------------------------------------------------------------------------------
1 | <%= CSV.generate_line %w[id first_name last_name email url chapter_name role created_at updated_at chapter_active] -%>
2 | <%- @users.each do |user| -%>
3 | <%= CSV.generate_line([user.id, user.first_name, user.last_name, user.email, user.url, user.chapter_name, user.role_name, user.created_at.to_fs(:iso8601), user.updated_at.to_fs(:iso8601), (user.chapter_name.blank? ? nil : user.chapter_inactive_at.blank?)]).html_safe -%>
4 | <%- end -%>
5 |
--------------------------------------------------------------------------------
/public/blog/awesome_foundation/stylesheets/sass/_base-variables.scss:
--------------------------------------------------------------------------------
1 | $gw-column: 60px;
2 | $gw-gutter: 20px;
3 |
4 | $serif: Georgia, Cambria, serif;
5 | $sans-serif: 'museo-sans', 'brandon-grotesque', 'proxima-nova', 'Open Sans', 'helvetica neue', sans-serif;
6 |
7 | $base-font-color: rgb(55,55,55);
8 | $lighter-base-font-color: rgb(100,100,100);
9 |
10 | $pink: rgb(255, 75, 126);
11 | $button-pink: rgb(252, 103, 147);
12 |
13 | $blue: rgb(34,122,255); //blue
14 |
--------------------------------------------------------------------------------
/app/assets/javascripts/tagline.js:
--------------------------------------------------------------------------------
1 | $(document).ready(function() {
2 |
3 | function size_tagline() {
4 | var window_width = $(window).outerWidth() - 10;
5 | var height = 105.6;
6 |
7 | if (window_width >= 940) {
8 | var inner_width = window_width * 0.2;
9 | height = (inner_width - 10) * 0.6;
10 | }
11 |
12 | $('.tagline').height(height);
13 |
14 | };
15 |
16 | size_tagline();
17 |
18 | $(window).resize(size_tagline);
19 |
20 | });
21 |
--------------------------------------------------------------------------------
/app/assets/stylesheets/_buttons.scss:
--------------------------------------------------------------------------------
1 | .button--pill {
2 | @include button(pill, $button-pink);
3 | margin: 6px;
4 | text-decoration: none;
5 | color: white;
6 |
7 | &:visited {
8 | color: white;
9 | }
10 |
11 | &:link {
12 | color: white;
13 | text-decoration: none;
14 | }
15 |
16 | &:hover, &:hover:not(:disabled) {
17 | text-decoration: none;
18 | }
19 | }
20 |
21 | .button--small {
22 | padding: 7px 12px 6px;
23 | font-size: 0.8em;
24 | }
25 |
--------------------------------------------------------------------------------
/app/views/projects/edit.html.erb:
--------------------------------------------------------------------------------
1 | <% provide(:page_title, @project.title) %>
2 |
3 |
9 |
10 |
--------------------------------------------------------------------------------
/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 |
5 |
6 | <%- attributes.each do |attribute| -%>
7 | <%%= f.<%= attribute.reference? ? :association : :input %> :<%= attribute.name %> %>
8 | <%- end -%>
9 |
10 |
11 |
12 | <%%= f.button :submit %>
13 |
14 | <%% end %>
15 |
--------------------------------------------------------------------------------
/config/cucumber.yml:
--------------------------------------------------------------------------------
1 | <%
2 | rerun = File.file?('rerun.txt') ? IO.read('rerun.txt') : ""
3 | rerun_opts = rerun.to_s.strip.empty? ? "--format #{ENV['CUCUMBER_FORMAT'] || 'progress'} features" : "--format #{ENV['CUCUMBER_FORMAT'] || 'pretty'} #{rerun}"
4 | std_opts = "--format #{ENV['CUCUMBER_FORMAT'] || 'pretty'} --strict --tags ~@wip"
5 | %>
6 | default: <%= std_opts %> features
7 | wip: --tags @wip:3 --wip features
8 | rerun: <%= rerun_opts %> --format rerun --out rerun.txt --strict --tags ~@wip
9 |
--------------------------------------------------------------------------------
/public/blog/awesome_foundation/stylesheets/sass/bourbon/lib/bourbon/sass_extensions/functions/compact.rb:
--------------------------------------------------------------------------------
1 | # Compact function pulled from compass
2 | module Bourbon::SassExtensions::Functions::Compact
3 |
4 | def compact(*args)
5 | sep = :comma
6 | if args.size == 1 && args.first.is_a?(Sass::Script::List)
7 | args = args.first.value
8 | sep = args.first.separator
9 | end
10 | Sass::Script::List.new(args.reject{|a| !a.to_bool}, sep)
11 | end
12 |
13 | end
14 |
--------------------------------------------------------------------------------
/app/views/funded_projects/_2up_gallery.html.erb:
--------------------------------------------------------------------------------
1 |
2 | <%= image_tag(project.display_images[0].url(:large_square)) %>
3 |
4 |
5 | <%= image_tag(project.display_images[1].url(:large_square)) %>
6 |
7 |
--------------------------------------------------------------------------------
/app/views/shared/_lightbox.html.erb:
--------------------------------------------------------------------------------
1 | <% content_for :javascript do %>
2 | <% javascript_tag do %>
3 | $(document).ready(function() {
4 | $('.gallery').each(function() {
5 | $(this).magnificPopup({
6 | delegate: 'a',
7 | type: 'image',
8 | gallery: {
9 | enabled: true
10 | },
11 | image: {
12 | titleSrc: 'title'
13 | }
14 | });
15 | });
16 | });
17 | <% end %>
18 | <% end %>
19 |
--------------------------------------------------------------------------------
/app/views/passwords/new.html.erb:
--------------------------------------------------------------------------------
1 |
17 |
--------------------------------------------------------------------------------
/db/migrate/20120123213411_create_roles.rb:
--------------------------------------------------------------------------------
1 | class CreateRoles < ActiveRecord::Migration[4.2]
2 | def up
3 | create_table :roles do |t|
4 | t.references :user, :null => false
5 | t.references :chapter, :null => false
6 | t.string :name, :null => false, :default => "trustee"
7 | end
8 | add_index :roles, [:user_id, :chapter_id]
9 | end
10 |
11 | def down
12 | remove_index :roles, :column => [:user_id, :chapter_id]
13 | drop_table :roles
14 | end
15 | end
16 |
--------------------------------------------------------------------------------
/config/initializers/filter_parameter_logging.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # Configure parameters to be partially matched (e.g. passw matches password) and filtered from the log file.
4 | # Use this to limit dissemination of sensitive information.
5 | # See the ActiveSupport::ParameterFilter documentation for supported notations and behaviors.
6 | Rails.application.config.filter_parameters += [
7 | :passw, :secret, :token, :_key, :crypt, :salt, :certificate, :otp, :ssn
8 | ]
9 |
--------------------------------------------------------------------------------
/config/initializers/markdown_handler.rb:
--------------------------------------------------------------------------------
1 | module MarkdownHandler
2 | def self.erb
3 | @erb ||= ActionView::Template.registered_template_handler(:erb)
4 | end
5 |
6 | def self.call(template, source)
7 | compiled_source = erb.call(template, source)
8 | "Redcarpet::Markdown.new(Redcarpet::Render::HTML.new, no_intra_emphasis: true, autolink: true).render(begin;#{compiled_source};end.to_s).html_safe"
9 | end
10 | end
11 |
12 | ActionView::Template.register_template_handler :md, MarkdownHandler
13 |
--------------------------------------------------------------------------------
/db/migrate/20120427130615_change_project_info_column_names.rb:
--------------------------------------------------------------------------------
1 | class ChangeProjectInfoColumnNames < ActiveRecord::Migration[4.2]
2 | def up
3 | rename_column :projects, :description, :about_me
4 | rename_column :projects, :use, :about_project
5 | add_column :projects, :use_for_money, :text
6 | end
7 |
8 | def down
9 | remove_column :projects, :use_for_money
10 | rename_column :projects, :about_project, :use
11 | rename_column :projects, :about_me, :description
12 | end
13 | end
14 |
--------------------------------------------------------------------------------
/public/blog/awesome_foundation/stylesheets/sass/bourbon/lib/bourbon/sass_extensions/functions.rb:
--------------------------------------------------------------------------------
1 | module Bourbon::SassExtensions::Functions
2 | end
3 |
4 | require File.join(File.dirname(__FILE__), "/functions/compact")
5 |
6 | module Sass::Script::Functions
7 | include Bourbon::SassExtensions::Functions::Compact
8 | end
9 |
10 | # Wierd that this has to be re-included to pick up sub-modules. Ruby bug?
11 | class Sass::Script::Functions::EvaluationContext
12 | include Sass::Script::Functions
13 | end
14 |
--------------------------------------------------------------------------------
/spec/views/header_views_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | describe 'shared/_navigation' do
4 | let!(:chapter) { FactoryBot.create(:chapter) }
5 | let!(:inactive_chapter) { FactoryBot.create(:inactive_chapter) }
6 |
7 | it 'only displays active chapters in the chapter list' do
8 | view.stubs(:signed_in?).returns(false)
9 |
10 | render
11 |
12 | expect(rendered).to have_content(chapter.name)
13 | expect(rendered).not_to have_content(inactive_chapter.name)
14 | end
15 | end
16 |
--------------------------------------------------------------------------------
/app/assets/stylesheets/_base-mixins.scss:
--------------------------------------------------------------------------------
1 | @mixin af-button() {
2 | @include background-image(linear-gradient(top, rgb(106, 189, 255), rgb(65, 165, 255)));
3 | border: 1px solid $blue;
4 | border-radius: 3px;
5 | color: $base-font-color;
6 | font: normal 16px/20px $sans-serif;
7 | margin-bottom: 15px;
8 | padding: 10px 15px;
9 | text-align: center;
10 | text-decoration: none;
11 | text-shadow: 0 1px rgba(255,255,255, 0.3);
12 |
13 | &:hover {
14 | }
15 |
16 | &:active {
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/app/controllers/acceptances_controller.rb:
--------------------------------------------------------------------------------
1 | class AcceptancesController < ApplicationController
2 | def new
3 | @invitation = Invitation.find(params[:invitation_id])
4 | end
5 |
6 | def create
7 | @invitation = Invitation.find(params[:invitation_id])
8 | if @invitation.accept(params[:invitation])
9 | flash[:notice] = t(".success")
10 | redirect_to sign_in_path
11 | else
12 | flash[:notice] = t("flash.acceptances.cannot")
13 | render :new
14 | end
15 | end
16 | end
17 |
--------------------------------------------------------------------------------
/public/blog/awesome_foundation/stylesheets/sass/bourbon/lib/bourbon.rb:
--------------------------------------------------------------------------------
1 | require "bourbon/generator"
2 |
3 | module Bourbon
4 | if defined?(Rails)
5 | class Engine < ::Rails::Engine
6 | require 'bourbon/engine'
7 | end
8 |
9 | module Rails
10 | class Railtie < ::Rails::Railtie
11 | rake_tasks do
12 | load "tasks/install.rake"
13 | end
14 | end
15 | end
16 | end
17 | end
18 |
19 | require File.join(File.dirname(__FILE__), "/bourbon/sass_extensions")
20 |
--------------------------------------------------------------------------------
/spec/features/trustee_filters_funded_projects.feature:
--------------------------------------------------------------------------------
1 | Feature: A trustee can filter projects by funded status
2 |
3 | Scenario: Trustee can filter projects based on funded status
4 | Given I am logged in as a trustee
5 | And a project was created on each of the last 7 days for my chapter
6 | And there is 1 winning project in my chapter
7 | When I am looking at the list of projects
8 | Then I should see only 8 projects
9 | When I view only funded projects
10 | Then I should see only 1 project
11 |
--------------------------------------------------------------------------------
/spec/views/funded_projects_views_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | describe 'funded_projects/show' do
4 | let!(:funded_project) { FactoryBot.create(:project, funded_on: Time.zone.now.to_date, funded_description: "I am a funded project") }
5 |
6 | it 'displays the funded description for a funded project' do
7 | assign(:project, funded_project)
8 | view.stubs(:current_user).returns(Guest.new)
9 |
10 | render
11 | expect(rendered).to have_content(funded_project.funded_description)
12 | end
13 | end
14 |
--------------------------------------------------------------------------------
/spec/features/guest_views_homepage.feature:
--------------------------------------------------------------------------------
1 | Feature: A guest views the homepage
2 |
3 | Scenario: Viewing the homepage
4 | Given there are 5 winning projects
5 | And those projects' chapters are in 4 countries total
6 | When I am on the homepage
7 | Then I should see those 5 chapters
8 | And I should see those 5 winning projects in their proper order
9 | And I should see that 5 projects have been funded for $5000
10 | And I should see that the 5 chapters, not including Any, are spread across 4 countries
11 |
--------------------------------------------------------------------------------
/public/blog/awesome_foundation/stylesheets/sass/bourbon/functions/_grid-width.scss:
--------------------------------------------------------------------------------
1 | @function grid-width($n) {
2 | @return $n * $gw-column + ($n - 1) * $gw-gutter;
3 | }
4 |
5 | // The $gw-column and $gw-gutter variables must be defined in your base stylesheet to properly use the grid-width function.
6 | //
7 | // $gw-column: 100px; // Column Width
8 | // $gw-gutter: 40px; // Gutter Width
9 | //
10 | // div {
11 | // width: grid-width(4); // returns 520px;
12 | // margin-left: $gw-gutter; // returns 40px;
13 | // }
14 |
--------------------------------------------------------------------------------
/spec/models/gravatar_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | describe Gravatar do
4 | context 'given an email' do
5 | let(:gravatar) { Gravatar.new("HELLO@example.com ") }
6 | it 'should generate the hash that gravatar needs' do
7 | expect(gravatar.hash).to eq("cb8419c1d471d55fbca0d63d1fb2b6ac")
8 | end
9 |
10 | it 'should generate the url that will get the gravatar' do
11 | expect(gravatar.url).to eq("https://www.gravatar.com/avatar/cb8419c1d471d55fbca0d63d1fb2b6ac?d=retro&s=134")
12 | end
13 | end
14 | end
15 |
--------------------------------------------------------------------------------
/app/views/projects/_funded_date.html.erb:
--------------------------------------------------------------------------------
1 |
2 | <%= form.input :funded_on, as: :string, input_html: { class: "datepicker", autocomplete: "off" }, required: local_assigns[:required], hint: local_assigns[:hint] %>
3 |
4 |
5 | <% content_for :javascript do %>
6 | <%= javascript_tag do %>
7 | $(window).load(function(){
8 | $('.datepicker').datepicker({
9 | dateFormat: 'yy-mm-dd',
10 | onClose: function(){ $('.datepicker').blur() }
11 | });
12 | });
13 | <% end %>
14 | <% end %>
15 |
--------------------------------------------------------------------------------
/app/jobs/project_mailer_job.rb:
--------------------------------------------------------------------------------
1 | class ProjectMailerJob
2 | include SuckerPunch::Job
3 |
4 | def perform(project_id)
5 | ActiveRecord::Base.connection_pool.with_connection do
6 | project = Project.find_by(id: project_id)
7 | return unless project
8 |
9 | if project.not_pending_moderation?
10 | project.mailer.new_application(project).deliver_now
11 | else
12 | Rails.logger.info "SUSPECTED SPAM: Project #{project.id} pending moderation - new_application mail not sent"
13 | end
14 | end
15 | end
16 | end
17 |
--------------------------------------------------------------------------------
/config/initializers/permissions_policy.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # Define an application-wide HTTP permissions policy. For further
4 | # information see: https://developers.google.com/web/updates/2018/06/feature-policy
5 |
6 | # Rails.application.config.permissions_policy do |policy|
7 | # policy.camera :none
8 | # policy.gyroscope :none
9 | # policy.microphone :none
10 | # policy.usb :none
11 | # policy.fullscreen :self
12 | # policy.payment :self, "https://secure.example.com"
13 | # end
14 |
--------------------------------------------------------------------------------
/public/blog/awesome_foundation/README:
--------------------------------------------------------------------------------
1 | This is the wordpress theme for the Awesome Foundation blog.
2 |
3 | The theme must link to the awesomefoundation.org stylesheet in the header-head.php file before it links to the theme's own style sheet.
4 |
5 | The source for the logo in the header of the wordpress theme is also the awesomefoundation.org site.
6 |
7 | Any changes made to the .php or .scss files stored here in the awesomefoundation.org rails site in the public/blog/awesome_foundation directory must be copied to the theme that is actually installed in the wordpress blog.
8 |
--------------------------------------------------------------------------------
/spec/controllers/pages_controller_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | describe HighVoltage::PagesController, '#show' do
4 | render_views
5 |
6 | %w(about_us faq start_a_chapter).each do |page|
7 | %w(bg en es fr hy pt ru).each do |locale|
8 | context "on GET to /#{locale}/#{page}" do
9 | before do
10 | get :show, params: { id: page, locale: locale }
11 | end
12 |
13 | it { is_expected.to respond_with(:success) }
14 | it { is_expected.to render_template(page) }
15 | end
16 | end
17 | end
18 | end
19 |
--------------------------------------------------------------------------------
/app/views/sessions/_form.html.erb:
--------------------------------------------------------------------------------
1 | <%= form_for :session, :url => session_path do |form| %>
2 |
3 | <%= form.label :email %>
4 | <%= form.text_field :email, type: "email", value: params[:session] && params[:session][:email], autofocus: params[:session].blank? || params[:session][:email].blank? %>
5 |
6 |
7 |
8 | <%= form.label :password %>
9 | <%= form.password_field :password, autofocus: params[:session] && params[:session][:email].present? %>
10 |
11 |
12 | <%= form.submit %>
13 | <% end %>
14 |
--------------------------------------------------------------------------------
/app/mailers/invitation_mailer.rb:
--------------------------------------------------------------------------------
1 | class InvitationMailer < ActionMailer::Base
2 | default :from => DO_NOT_REPLY
3 |
4 | def invite_trustee(invitation)
5 | @invitation = invitation
6 | mail(:to => invitation.email,
7 | :subject => "[Awesome] #{t('emails.invitation.subject', :name => invitation.chapter.name)}")
8 | end
9 |
10 | def welcome_trustee(invitation)
11 | @invitation = invitation
12 | mail(:to => invitation.email,
13 | :subject => "[Awesome] #{t('emails.welcome.subject', :name => invitation.chapter.name)}")
14 | end
15 | end
16 |
--------------------------------------------------------------------------------
/app/views/projects/_project_actions_js.html.erb:
--------------------------------------------------------------------------------
1 | <% content_for :javascript do %>
2 | <% javascript_tag do %>
3 | const projectNavigator = new ProjectNavigator();
4 |
5 | document.addEventListener("keydown", (event) => {
6 | if (event.target.tagName == "INPUT" || event.target.tagName == "TEXTAREA") {
7 | return;
8 | }
9 |
10 | if (event.key == "d") {
11 | projectNavigator.nextProject();
12 | } else if (event.key == "a") {
13 | projectNavigator.previousProject();
14 | }
15 | });
16 | <% end %>
17 | <% end %>
18 |
--------------------------------------------------------------------------------
/config/initializers/wrap_parameters.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # This file contains settings for ActionController::ParamsWrapper which
4 | # is enabled by default.
5 |
6 | # Enable parameter wrapping for JSON. You can disable this by setting :format to an empty array.
7 | ActiveSupport.on_load(:action_controller) do
8 | wrap_parameters format: [:json]
9 | end
10 |
11 | # To enable root element in JSON for ActiveRecord objects.
12 | # ActiveSupport.on_load(:active_record) do
13 | # self.include_root_in_json = true
14 | # end
15 |
--------------------------------------------------------------------------------
/spec/features/step_definitions/guest_views_project_steps.rb:
--------------------------------------------------------------------------------
1 | step 'there is a project with :count photo(s)' do |count|
2 | @chapter = FactoryBot.create(:chapter)
3 | @project = FactoryBot.create(:project, :chapter => @chapter, :funded_on => 1.days.ago)
4 | FactoryBot.create_list(:photo, count.to_i, :project => @project)
5 | end
6 |
7 | step 'I view the project' do
8 | visit funded_project_path(@project)
9 | end
10 |
11 | step 'I should see the placeholder image' do
12 | expect(page).to have_css('#project-gallery img[src^="/assets/no-image-large_rectangle"]')
13 | end
14 |
--------------------------------------------------------------------------------
/app/javascript/controllers/menu_toggle_controller.js:
--------------------------------------------------------------------------------
1 | import { Controller } from "@hotwired/stimulus"
2 |
3 | export default class extends Controller {
4 | static values = { target: String }
5 |
6 | toggle(event) {
7 | if (event.metaKey || event.ctrlKey || event.shiftKey) {
8 | return
9 | }
10 |
11 | event.preventDefault()
12 | const targetElement = document.querySelector(this.targetValue)
13 | if (targetElement) {
14 | targetElement.classList.toggle("expanded")
15 | event.currentTarget.classList.toggle("active")
16 | }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/public/blog/awesome_foundation/stylesheets/sass/bourbon/css3/_box-shadow.scss:
--------------------------------------------------------------------------------
1 | // Box-Shadow Mixin Requires Sass v3.1.1+
2 | @mixin box-shadow ($shadow-1,
3 | $shadow-2: false, $shadow-3: false,
4 | $shadow-4: false, $shadow-5: false,
5 | $shadow-6: false, $shadow-7: false,
6 | $shadow-8: false, $shadow-9: false)
7 | {
8 | $full: compact($shadow-1, $shadow-2, $shadow-3, $shadow-4,
9 | $shadow-5, $shadow-6, $shadow-7, $shadow-8, $shadow-9);
10 |
11 | -webkit-box-shadow: $full;
12 | -moz-box-shadow: $full;
13 | box-shadow: $full;
14 | }
15 |
--------------------------------------------------------------------------------
/Rakefile:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env rake
2 | # Add your own tasks in files placed in lib/tasks ending in .rake,
3 | # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
4 |
5 | require File.expand_path('../config/application', __FILE__)
6 |
7 | Awesomefoundation::Application.load_tasks
8 | task(:default).clear
9 | task :default => [:spec, "spec:features"]
10 |
11 | if defined?(RSpec)
12 | namespace :spec do
13 | RSpec::Core::RakeTask.new(:features => ["db:test:prepare"]) do |t|
14 | t.pattern = "./spec/**/*.feature"
15 | end
16 | end
17 | end
18 |
--------------------------------------------------------------------------------
/db/migrate/20120202133816_ensure_uniqueness_of_roles_and_invitations.rb:
--------------------------------------------------------------------------------
1 | class EnsureUniquenessOfRolesAndInvitations < ActiveRecord::Migration[4.2]
2 | def up
3 | add_index :invitations, [:email, :chapter_id], :unique => true
4 | remove_index :roles, :column => [:user_id, :chapter_id]
5 | add_index :roles, [:user_id, :chapter_id], :unique => true
6 | end
7 |
8 | def down
9 | remove_index :roles, :column => [:user_id, :chapter_id]
10 | add_index :roles, [:user_id, :chapter_id]
11 | remove_index :invitations, :column => [:email, :chapter_id]
12 | end
13 | end
14 |
--------------------------------------------------------------------------------
/public/blog/awesome_foundation/footer.php:
--------------------------------------------------------------------------------
1 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/config/initializers/backtrace_silencers.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces.
4 | # Rails.backtrace_cleaner.add_silencer { |line| /my_noisy_library/.match?(line) }
5 |
6 | # You can also remove all the silencers if you're trying to debug a problem that might stem from framework code
7 | # by setting BACKTRACE=1 before calling your invocation, like "BACKTRACE=1 ./bin/rails runner 'MyClass.perform'".
8 | Rails.backtrace_cleaner.remove_silencers! if ENV["BACKTRACE"]
9 |
--------------------------------------------------------------------------------
/public/blog/awesome_foundation/functions.php:
--------------------------------------------------------------------------------
1 | read more →';
13 | }
14 | add_filter('excerpt_length', 'excerpt_length');
15 | add_filter('excerpt_more', 'excerpt_more');
16 |
17 | if ( function_exists('register_sidebar') )
18 | register_sidebar();
19 | ?>
20 |
--------------------------------------------------------------------------------
/public/blog/awesome_foundation/stylesheets/sass/bourbon/functions/_render-gradients.scss:
--------------------------------------------------------------------------------
1 | // User for linear and radial gradients within background-image or border-image properties
2 |
3 | @function render-gradients($gradients, $gradient-type, $vendor: false) {
4 | $vendor-gradients: false;
5 | @if $vendor {
6 | $vendor-gradients: -#{$vendor}-#{$gradient-type}-gradient($gradients);
7 | }
8 |
9 | @else if $vendor == false {
10 | $vendor-gradients: "#{$gradient-type}-gradient(#{$gradients})";
11 | $vendor-gradients: unquote($vendor-gradients);
12 | }
13 | @return $vendor-gradients;
14 | }
15 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | sudo: false
2 | language: ruby
3 | cache: bundler
4 | bundler_args: --without production
5 | rvm:
6 | - 2.5.5
7 | services:
8 | # https://docs.travis-ci.com/user/gui-and-headless-browsers/#using-xvfb-to-run-tests-that-require-a-gui
9 | - xvfb
10 | before_install:
11 | # To keep using bundler < 2.0
12 | - gem uninstall -v '>= 2' -i $(rvm gemdir)@global -ax bundler || true
13 | - gem install bundler -v '< 2'
14 | before_script:
15 | - RAILS_ENV=test bundle exec rake db:create
16 | - RAILS_ENV=test bundle exec rake db:migrate --trace
17 | addons:
18 | postgresql: "9.4"
19 | chrome: stable
20 |
--------------------------------------------------------------------------------
/app/assets/stylesheets/_base-extends.scss:
--------------------------------------------------------------------------------
1 | .active-link {
2 | border-bottom: 3px solid $pink;
3 | color: rgb(255,255,255);
4 | }
5 |
6 |
7 | .user-avatar {
8 | @include background-image(linear-gradient(90deg, rgb(240,240,240), rgb(250,250,250)));
9 | border: 1px solid rgb(200,200,200);
10 | border-radius: 70px;
11 | display: block;
12 | height: 122px;
13 | margin: 0 auto;
14 | overflow: hidden;
15 | position: relative;
16 | padding: 5px;
17 | width: 122px;
18 | z-index: 2;
19 |
20 | img {
21 | border-radius: 70px;
22 | display: block;
23 | max-width: 122px;
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/app/views/chapters/index.html.erb:
--------------------------------------------------------------------------------
1 |
2 |
3 | <%= t ".title" %>
4 |
5 |
6 | <%= render @chapters %>
7 |
8 |
9 |
10 |
11 | <% if params[:include_inactive].present? %>
12 | <%= link_to t(".show_active_chapters"), :include_inactive => nil %>
13 | <% else %>
14 | <%= link_to t(".show_inactive_chapters"), :include_inactive => true %>
15 | <% end %>
16 |
17 |
18 |
--------------------------------------------------------------------------------
/db/migrate/20120522140401_add_slugs_to_chapters.rb:
--------------------------------------------------------------------------------
1 | class AddSlugsToChapters < ActiveRecord::Migration[4.2]
2 | def up
3 | add_column :chapters, :slug, :string
4 | select_all("SELECT id, name FROM chapters").each do |chapter|
5 | id = chapter["id"]
6 | slug = chapter["name"].downcase.gsub(/[^a-z]+/, "-")
7 | execute("UPDATE chapters SET slug = '#{slug}' WHERE id = #{id}")
8 | end
9 | change_column :chapters, :slug, :string, :null => false
10 | add_index :chapters, :slug, unique: true
11 | end
12 |
13 | def down
14 | remove_column :chapters, :slug
15 | end
16 | end
17 |
--------------------------------------------------------------------------------
/app/assets/stylesheets/_invitations-new.scss:
--------------------------------------------------------------------------------
1 | .invitation-form {
2 | form {
3 | p {
4 | font: bold 14px/16px $sans-serif;
5 | margin-bottom: 35px;
6 |
7 | span {
8 | border-bottom: 1px dotted rgb(60,60,60);
9 | font: 300 16px/18px $sans-serif;
10 | margin-left: 10px;
11 | padding-bottom: 3px;
12 | }
13 | }
14 |
15 | div.input {
16 | &.select {
17 | border: {
18 | bottom: 1px solid rgb(200,200,200);
19 | }
20 | margin-bottom: 20px;
21 | padding: 0px 0px 20px 0px;
22 | }
23 | }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/public/blog/awesome_foundation/loop-single.php:
--------------------------------------------------------------------------------
1 | ';
5 | echo '';
6 | echo '';
7 | echo ''; the_date(); echo '
';
8 | echo ' ';
9 | the_content();
10 | echo '';
11 |
12 | echo '';
15 |
16 | endwhile;
17 |
18 | echo '';
19 | ?>
20 |
--------------------------------------------------------------------------------
/app/views/shared/_rssfeed.html.erb:
--------------------------------------------------------------------------------
1 | <%= javascript_tag do %>
2 | jQuery(function($) {
3 | $("#rss-feeds").rss("<%= rss_feed_url %>",
4 | {
5 | ssl: true,
6 | limit: 6,
7 | layoutTemplate: '{entries} ',
8 | entryTemplate: '{formatted_date} {title} ',
9 | tokens: {
10 | formatted_date: function(entry, tokens) {
11 | date = (new Date(tokens.date)) || Date.now();
12 | return date.toString('yyyy-MM-dd');
13 | }
14 | }
15 | }
16 | )
17 | })
18 | <% end -%>
19 |
--------------------------------------------------------------------------------
/config/configs/spam_config.rb:
--------------------------------------------------------------------------------
1 | class SpamConfig < Anyway::Config
2 | attr_config(
3 | threshold: 0.85,
4 | weight_missing_js_metadata: 0.2,
5 | weight_short_time_on_page: 0.3,
6 | weight_no_referrer: 0.2,
7 | weight_suspicious_user_agent: 0.8,
8 | weight_low_form_interactions: 0.4,
9 | weight_high_paste_ratio: 0.3,
10 | weight_bot_screen_resolution: 0.2,
11 | weight_gibberish_fields: 0.5,
12 | weight_identical_fields: 0.8,
13 | time_on_page_threshold_ms: 10000,
14 | min_form_interactions: 2,
15 | gibberish_field_threshold: 3,
16 | paste_ratio_threshold: 0.5
17 | )
18 | end
19 |
--------------------------------------------------------------------------------
/db/migrate/20121025015059_add_full_text_index_to_projects.rb:
--------------------------------------------------------------------------------
1 | class AddFullTextIndexToProjects < ActiveRecord::Migration[4.2]
2 |
3 | COLUMN = [:name, :title, :about_me, :about_project, :use_for_money,
4 | :extra_answer_1, :extra_answer_2, :extra_answer_3]
5 |
6 | def up
7 | COLUMN.each do |column|
8 | execute("create index index_projects_to_tsvector_on_#{column} on projects using gin(to_tsvector('english', #{column}))")
9 | end
10 | end
11 |
12 | def down
13 | COLUMN.each do |column|
14 | execute("drop index index_projects_to_tsvector_on_#{column}")
15 | end
16 | end
17 |
18 | end
19 |
--------------------------------------------------------------------------------
/app/views/users/_form.html.erb:
--------------------------------------------------------------------------------
1 | <%= simple_form_for user do |form| %>
2 | <%= hidden_field_tag :return_to, params[:return_to] %>
3 | <%= form.input :first_name %>
4 | <%= form.input :last_name %>
5 | <%= form.input :email %>
6 | <%= form.input :url %>
7 | <%= form.input :new_password, :as => :password, :label => t(:'simple_form.labels.user.new_password') %>
8 |
9 | <%= form.label t(:'simple_form.labels.user.user_image') %>
10 | <%= image_tag(user.gravatar_url) %>
11 | <%= form.hint t(:'simple_form.hints.user.user_image', :email => h(user.email)).html_safe %>
12 |
13 | <%= form.button :submit %>
14 | <% end %>
15 |
--------------------------------------------------------------------------------
/features/clearance/visitor_signs_up.feature:
--------------------------------------------------------------------------------
1 | Feature: Sign up
2 |
3 | In order to access protected sections of the site
4 | As a visitor
5 | I want to sign up
6 |
7 | Scenario: Visitor signs up with invalid email
8 | When I sign up with "invalidemail" and "password"
9 | Then I am told to enter a valid email address
10 |
11 | Scenario: Visitor signs up with blank password
12 | When I sign up with "email@example.com" and ""
13 | Then I am told to enter a password
14 |
15 | Scenario: Visitor signs up with valid data
16 | When I sign up with "email@example.com" and "password"
17 | Then I should be signed in
18 |
--------------------------------------------------------------------------------
/public/blog/awesome_foundation/stylesheets/sass/bourbon/css3/_background-size.scss:
--------------------------------------------------------------------------------
1 | @mixin background-size ($length-1,
2 | $length-2: false, $length-3: false,
3 | $length-4: false, $length-5: false,
4 | $length-6: false, $length-7: false,
5 | $length-8: false, $length-9: false)
6 | {
7 | $full: compact($length-1, $length-2, $length-3, $length-4,
8 | $length-5, $length-6, $length-7, $length-8, $length-9);
9 |
10 | -webkit-background-size: $full;
11 | -moz-background-size: $full;
12 | -ms-background-size: $full;
13 | -o-background-size: $full;
14 | background-size: $full;
15 | }
16 |
--------------------------------------------------------------------------------
/public/blog/awesome_foundation/page.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/app/javascript/controllers/index.js:
--------------------------------------------------------------------------------
1 | // Import and register all your controllers from the importmap under controllers/*
2 |
3 | import { application } from "controllers/application"
4 |
5 | // Eager load all controllers defined in the import map under controllers/**/*_controller
6 | import { eagerLoadControllersFrom } from "@hotwired/stimulus-loading"
7 | eagerLoadControllersFrom("controllers", application)
8 |
9 | // Lazy load controllers as they appear in the DOM (remember not to preload controllers in import map!)
10 | // import { lazyLoadControllersFrom } from "@hotwired/stimulus-loading"
11 | // lazyLoadControllersFrom("controllers", application)
12 |
--------------------------------------------------------------------------------
/app/views/passwords/edit.html.erb:
--------------------------------------------------------------------------------
1 |
21 |
--------------------------------------------------------------------------------
/app/views/shared/_analytics.html.erb:
--------------------------------------------------------------------------------
1 | <% if Rails.env.production? %>
2 |
15 |
16 | <% else %>
17 |
18 | <% end %>
19 |
--------------------------------------------------------------------------------
/public/blog/awesome_foundation/index.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/public/blog/awesome_foundation/stylesheets/sass/bourbon/functions/_radial-gradient.scss:
--------------------------------------------------------------------------------
1 | // This function is required and used by the background-image mixin.
2 | @function radial-gradient($pos, $shape-size,
3 | $G1, $G2,
4 | $G3: false, $G4: false,
5 | $G5: false, $G6: false,
6 | $G7: false, $G8: false,
7 | $G9: false, $G10: false) {
8 |
9 | $type: radial;
10 | $gradient: compact($pos, $shape-size, $G1, $G2, $G3, $G4, $G5, $G6, $G7, $G8, $G9, $G10);
11 | $type-gradient: append($type, $gradient, comma);
12 |
13 | @return $type-gradient;
14 | }
15 |
16 |
--------------------------------------------------------------------------------
/app/views/acceptances/new.html.erb:
--------------------------------------------------------------------------------
1 |
14 |
--------------------------------------------------------------------------------
/app/views/projects/_project.html.erb:
--------------------------------------------------------------------------------
1 | <%= "winner" if project.winner? %>" id="project<%= project.id %>" data-id="<%= project.id %>" data-controller="jump" data-jump-scroll-value="<%= local_assigns[:scroll] == true %>">
2 | <% if !project.hidden? || @display_project_even_if_hidden %>
3 | <%= render "projects/project_details", project: project, moderation: local_assigns[:moderation] %>
4 | <% else %>
5 | <%= render "projects/project_hidden", project: project, moderation: local_assigns[:moderation] %>
6 | <% end %>
7 |
8 | <%= render "projects/hide_form", project: project %>
9 |
10 |
--------------------------------------------------------------------------------
/spec/support/fake_data.rb:
--------------------------------------------------------------------------------
1 | module FakeData
2 | module_function
3 |
4 | def fixture_file(filename)
5 | File.open(Rails.root.join("spec", "support", "fixtures", filename), binmode: true)
6 | end
7 |
8 | def shrine_uploaded_file(filename, storage: :store)
9 | file = fixture_file(filename)
10 | mime_type = Rack::Mime.mime_type(File.extname(filename))
11 |
12 | uploaded_file = Shrine.upload(file, storage, metadata: false)
13 | uploaded_file.metadata.merge!(
14 | "size" => File.size(file.path),
15 | "mime_type" => Rack::Mime.mime_type(File.extname(filename)),
16 | "filename" => filename
17 | )
18 |
19 | uploaded_file
20 | end
21 | end
22 |
--------------------------------------------------------------------------------
/app/javascript/controllers/toggler_controller.js:
--------------------------------------------------------------------------------
1 | import { Controller } from "@hotwired/stimulus"
2 |
3 | export default class extends Controller {
4 | static targets = [ "toggleable" ]
5 | static values = { spin: Boolean }
6 |
7 | toggle(event) {
8 | this.toggleableTarget.classList.toggle('hidden')
9 |
10 | if (this.spinValue) {
11 | const content = event.currentTarget.querySelector('*')
12 | if (content) {
13 | content.classList.add('icon-spin')
14 | setTimeout(() => {
15 | content.classList.remove('icon-spin')
16 | }, 500)
17 | }
18 | }
19 |
20 | event.target.blur()
21 | event.preventDefault()
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/spec/features/step_definitions/dean_manages_promotions_steps.rb:
--------------------------------------------------------------------------------
1 | step "there is a :role_name for my chapter in the system" do |role_name|
2 | instance_variable_set("@#{role_name}_role", FactoryBot.create(:role, :name => role_name, :chapter => @current_chapter))
3 | instance_variable_set("@#{role_name}", instance_variable_get("@#{role_name}_role").user)
4 | instance_variable_set("@#{role_name}_chapter", instance_variable_get("@#{role_name}_role").chapter)
5 | end
6 |
7 | step 'I remove trustee from my chapter' do
8 | visit chapter_users_path(@current_chapter)
9 | accept_confirm { click_link("Remove") }
10 | page.evaluate_script('window.confirm = function() { return true; }')
11 | end
12 |
--------------------------------------------------------------------------------
/app/views/pages/about_us.html.erb:
--------------------------------------------------------------------------------
1 | <% provide(:page_title, t(".title_tag")) %>
2 | <% content_for(:extra_body_classes, 'pages-about_us') %>
3 |
4 |
5 |
6 | <%= render("locales/about_us").html_safe %>
7 |
8 |
18 |
19 |
--------------------------------------------------------------------------------
/spec/features/step_definitions/guest_views_chapter.rb:
--------------------------------------------------------------------------------
1 | step 'there are 5 trustees' do
2 | @trustees = (1..5).map { FactoryBot.create(:user) }
3 | @trustees.each do |trustee|
4 | FactoryBot.create(:role,
5 | :user => trustee,
6 | :name => 'trustee',
7 | :chapter => @current_chapter)
8 | end
9 | end
10 |
11 | step 'I should see the trustees' do
12 | @trustees.each do |trustee|
13 | expect(page).to have_selector(".trustee-details h3", :text => "#{trustee.first_name} #{trustee.last_name}")
14 | end
15 | end
16 |
17 | step 'I should not see the trustees' do
18 | expect(page).to_not have_selector('.trustees')
19 | end
20 |
--------------------------------------------------------------------------------
/app/models/vote.rb:
--------------------------------------------------------------------------------
1 | class Vote < ApplicationRecord
2 | belongs_to :user
3 | belongs_to :project
4 | belongs_to :chapter
5 |
6 | validates_presence_of :user_id
7 | validates_presence_of :project_id
8 | validates_presence_of :chapter_id
9 |
10 | validates_uniqueness_of :user_id, :scope => :project_id
11 |
12 | validate :ensure_chapter
13 |
14 | def self.by(user)
15 | where(:user_id => user.id)
16 | end
17 |
18 | def self.for(project)
19 | where(:project_id => project.id)
20 | end
21 |
22 | private
23 |
24 | def ensure_chapter
25 | unless user && user.chapters.include?(chapter)
26 | self.errors.add(:chapter_id, :invalid_for_user)
27 | end
28 | end
29 | end
30 |
--------------------------------------------------------------------------------
/spec/features/dean_views_projects.feature:
--------------------------------------------------------------------------------
1 | Feature: Dean views all projects
2 |
3 | Scenario: Dean views first page of results by default
4 | Given I am logged in as a dean
5 | And there are enough winning projects in my chapter to spread over two pages
6 | When I am looking at the list of projects for the current chapter
7 | Then I should see only 30 projects
8 |
9 | Scenario: Dean can view second page
10 | Given I am logged in as a dean
11 | And there are enough winning projects in my chapter to spread over two pages
12 | When I am looking at the list of projects for the current chapter
13 | And I follow the link to the next page
14 | Then I should see only 1 project
15 |
--------------------------------------------------------------------------------
/app/assets/stylesheets/_shared-flash-messages.scss:
--------------------------------------------------------------------------------
1 | #flash {
2 | #flash_thanks {
3 | background: $pink;
4 | border: none;
5 | border-radius: 0;
6 | color: rgb(255,255,255);
7 | font: bold 18px/22px $sans-serif;
8 | padding: 15px 0px;
9 | text-align: center;
10 | text-transform: uppercase;
11 | }
12 |
13 | #flash_notice, #flash_alert {
14 | background: rgb(90,90,90);
15 | border: 1px solid rgb(60,60,60);
16 | border-radius: 4px;
17 | box-shadow: 0 1px 0 0 rgba(255,255,255, 0.75);
18 | color: rgb(255,255,255);
19 | font: bold 14px/16px $sans-serif;
20 | padding: 10px 0px;
21 | text-align: center;
22 | text-transform: uppercase;
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/spec/support/pagination.rb:
--------------------------------------------------------------------------------
1 | module PaginationHelpers
2 | def go_to_next_page
3 | find('a.next_page[rel="next"]').click
4 | end
5 | end
6 |
7 | RSpec.configure do |c|
8 | c.include PaginationHelpers
9 |
10 | # rspec-rails 3 will no longer automatically infer an example group's spec type
11 | # from the file location. You can explicitly opt-in to the feature using this
12 | # config option.
13 | # To explicitly tag specs without using automatic inference, set the `:type`
14 | # metadata manually:
15 | #
16 | # describe ThingsController, :type => :controller do
17 | # # Equivalent to being in spec/controllers
18 | # end
19 | c.infer_spec_type_from_file_location!
20 | end
21 |
--------------------------------------------------------------------------------
/app/views/invitation_mailer/invite_trustee.text.erb:
--------------------------------------------------------------------------------
1 | Hi <%= @invitation.first_name %> <%= @invitation.last_name %>!
2 |
3 | You have been invited to join AwesomeFoundation.org as a <%= @invitation.role_name %> of the
4 | <%= @invitation.chapter.display_name %> chapter! Yay!
5 |
6 | <%= new_invitation_acceptance_url(@invitation, :locale => I18n.locale) %>
7 |
8 | Once you accept the invitation, you’ll be listed as a trustee on the
9 | chapter’s website. You’ll also be able to read and create personal
10 | shortlists for your chapter’s applications. It’ll be a really good time, we
11 | promise.
12 |
13 | If you have any questions about the site, please contact the Awesome Web team:
14 | webmaster@awesomefoundation.org
15 |
--------------------------------------------------------------------------------
/app/assets/javascripts/application-js.js:
--------------------------------------------------------------------------------
1 | // This is a manifest file that'll be compiled into including all the files listed below.
2 | // Add new JavaScript/Coffee code in separate files in this directory and they'll automatically
3 | // be included in the compiled file accessible from http://example.com/assets/application.js
4 | // It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
5 | // the compiled file.
6 | //
7 | //= require jquery
8 | //= require jquery_ujs
9 | //= require jquery.ui.all
10 | //= require magnific-popup
11 | //= require lightgallery
12 | //= require lg-zoom
13 | //= require react
14 | //= require react_ujs
15 | //= require components
16 | //= require_tree .
17 |
--------------------------------------------------------------------------------
/public/blog/awesome_foundation/stylesheets/sass/bourbon/addons/_clearfix.scss:
--------------------------------------------------------------------------------
1 | // Micro clearfix provides an easy way to contain floats without adding additional markup
2 | //
3 | // Example usage:
4 | //
5 | // // Contain all floats within .wrapper
6 | // .wrapper {
7 | // @include clearfix;
8 | // .content,
9 | // .sidebar {
10 | // float : left;
11 | // }
12 | // }
13 |
14 | @mixin clearfix {
15 | zoom: 1;
16 |
17 | &:before,
18 | &:after {
19 | content: "";
20 | display: table;
21 | }
22 |
23 | &:after {
24 | clear: both;
25 | }
26 | }
27 |
28 | // Acknowledgements
29 | // Micro clearfix: [Nicolas Gallagher](http://nicolasgallagher.com/micro-clearfix-hack/)
30 |
--------------------------------------------------------------------------------
/public/blog/awesome_foundation/stylesheets/sass/bourbon/addons/_position.scss:
--------------------------------------------------------------------------------
1 | @mixin position ($position: relative, $coordinates: 0 0 0 0) {
2 |
3 | @if type-of($position) == list {
4 | $coordinates: $position;
5 | $position: relative;
6 | }
7 |
8 | $top: nth($coordinates, 1);
9 | $right: nth($coordinates, 2);
10 | $bottom: nth($coordinates, 3);
11 | $left: nth($coordinates, 4);
12 |
13 | position: $position;
14 |
15 | @if not(unitless($top)) {
16 | top: $top;
17 | }
18 |
19 | @if not(unitless($right)) {
20 | right: $right;
21 | }
22 |
23 | @if not(unitless($bottom)) {
24 | bottom: $bottom;
25 | }
26 |
27 | @if not(unitless($left)) {
28 | left: $left;
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/app/views/locales/_contact.ru.md:
--------------------------------------------------------------------------------
1 | # Связаться с нами
2 |
3 | Вы можете связаться с нами по имейлу contact@awesomefoundation.org , подписаться на наш Twitter @awesomefound или следить за обновлениями на Facebook here . Если Вы хотите связаться с определенным разделом, используйте ссылку на имейл наверху главной страницы раздела "Chapters".
4 |
5 | Если Вы хотите создать новый раздел, для чего нужно собрать группу из десяти "trustees", которые хотят вносить по $100 в месяц для гранта ($1000), пожалуйста, свяжитесь по имейлу join@awesomefoundation.org .
--------------------------------------------------------------------------------
/public/blog/awesome_foundation/stylesheets/sass/bourbon/css3/_transform.scss:
--------------------------------------------------------------------------------
1 | @mixin transform($property: none) {
2 | // none |
3 | -webkit-transform: $property;
4 | -moz-transform: $property;
5 | -ms-transform: $property;
6 | -o-transform: $property;
7 | transform: $property;
8 | }
9 |
10 | @mixin transform-origin($axes: 50%) {
11 | // x-axis - left | center | right | length | %
12 | // y-axis - top | center | bottom | length | %
13 | // z-axis - length
14 | -webkit-transform-origin: $axes;
15 | -moz-transform-origin: $axes;
16 | -ms-transform-origin: $axes;
17 | -o-transform-origin: $axes;
18 | transform-origin: $axes;
19 | }
20 |
--------------------------------------------------------------------------------
/config/initializers/inflections.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # Add new inflection rules using the following format. Inflections
4 | # are locale specific, and you may define rules for as many different
5 | # locales as you wish. All of these examples are active by default:
6 | # ActiveSupport::Inflector.inflections(:en) do |inflect|
7 | # inflect.plural /^(ox)$/i, "\\1en"
8 | # inflect.singular /^(ox)en/i, "\\1"
9 | # inflect.irregular "person", "people"
10 | # inflect.uncountable %w( fish sheep )
11 | # end
12 |
13 | # These inflection rules are supported but not enabled by default:
14 | # ActiveSupport::Inflector.inflections(:en) do |inflect|
15 | # inflect.acronym "RESTful"
16 | # end
17 |
--------------------------------------------------------------------------------
/spec/lib/spam_checker_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | describe SpamChecker do
4 | context "Project" do
5 | let(:checker) { SpamChecker::Project }
6 | it "updates the blocklist from the SPAM_REGEXP environment variable" do
7 | ENV['SPAM_REGEXP'] = "bob|felix"
8 |
9 | expect(checker.new(Project.new(about_me: "bob is a spammer")).spam?).to be true
10 | expect(checker.new(Project.new(about_me: "felix is a spammer")).spam?).to be true
11 | expect(checker.new(Project.new(about_me: "sandy is not a spammer")).spam?).to be false
12 | end
13 |
14 | it "functions without the SPAM_REGEXP environment variable" do
15 | expect(checker.new(Project.new).spam?).to be false
16 | end
17 | end
18 | end
19 |
--------------------------------------------------------------------------------
/spec/support/fake_user_factory.rb:
--------------------------------------------------------------------------------
1 | class FakeUserFactory
2 | attr_accessor :errors
3 |
4 | def initialize
5 | @users = []
6 | @return_value = true
7 | end
8 |
9 | def users
10 | @users
11 | end
12 |
13 | def user
14 | @users.last
15 | end
16 |
17 | def role
18 | Role.new(user: user, chapter: @chapter, name: @role_name)
19 | end
20 |
21 | def new(attributes)
22 | @attributes = attributes
23 |
24 | @chapter = @attributes.delete(:chapter)
25 | @role_name = @attributes.delete(:role_name)
26 |
27 | self
28 | end
29 |
30 | def fail!
31 | @return_value = false
32 | end
33 |
34 | def create
35 | @users << User.new(@attributes)
36 | @return_value
37 | end
38 | end
39 |
--------------------------------------------------------------------------------
/spec/support/locale_fix.rb:
--------------------------------------------------------------------------------
1 | module DefaultUrlOptionsWithLocale
2 | def default_url_options(options = {})
3 | super({ locale: I18n.locale }.merge(options))
4 | end
5 | end
6 |
7 | ActionDispatch::Integration::Session.send(:prepend, DefaultUrlOptionsWithLocale)
8 |
9 | # https://github.com/rspec/rspec-rails/issues/255#issuecomment-20727452
10 | module CallWithLocaleFix
11 | def call(t, method_name, args, inner_options, url_strategy)
12 | original_options = @options
13 | @options = { locale: I18n.locale }.merge(@options)
14 | result = super
15 | @options = original_options
16 | result
17 | end
18 | end
19 |
20 | ActionDispatch::Routing::RouteSet::NamedRouteCollection::UrlHelper.send(:prepend, CallWithLocaleFix)
21 |
--------------------------------------------------------------------------------
/db/seeds.rb:
--------------------------------------------------------------------------------
1 | # This file should contain all the record creation needed to seed the database with its default values.
2 | # The data can then be loaded with the rake db:seed (or created alongside the db with db:setup).
3 | #
4 | # Examples:
5 | #
6 | # cities = City.create([{ name: 'Chicago' }, { name: 'Copenhagen' }])
7 | # Mayor.create(name: 'Emanuel', city: cities.first)
8 |
9 | # Set up the admin user
10 | user = User.where(first_name: "Awesome", last_name: "Admin", email: "admin@awesomefoundation.org").first_or_create
11 | user.update_attribute(:admin, true)
12 | user.update_password("gnarly")
13 |
14 | # Set up the "Any" Chapter
15 | Chapter.where(name: "Any").first_or_create(description: "Any Chapter", country: COUNTRY_PRIORITY.first)
16 |
--------------------------------------------------------------------------------
/spec/support/fake_mailer.rb:
--------------------------------------------------------------------------------
1 | class FakeMailer
2 | def initialize
3 | @emails = []
4 | end
5 |
6 | def method_missing(method, *args, &block)
7 | @emails << FakeEmail.new(method)
8 | @emails.last
9 | end
10 |
11 | def delivery_to(email_name, to = nil)
12 | @emails.select do |mail|
13 | res = mail.name == email_name
14 | res &&= (to.nil? || mail.to.include?(to))
15 | res &&= mail.delivered?
16 | res
17 | end
18 | end
19 |
20 | class FakeEmail
21 | def initialize(name)
22 | @name = name
23 | end
24 |
25 | attr_reader :name
26 |
27 | def deliver_now
28 | @delivered = true
29 | end
30 |
31 | def delivered?
32 | @delivered
33 | end
34 | end
35 |
36 | end
37 |
--------------------------------------------------------------------------------
/app/views/locales/_contact.bg.md:
--------------------------------------------------------------------------------
1 | # Контакти
2 |
3 | Имате страхотна идея? [Кандидатствайте за микро грант!](<%= new_submission_path %>)
4 |
5 |
6 | За да се свържете с определен Епизод, моля използвайте имейла, който се вижда горе на страницата, в секцията където са изброени Епизодите. Ако имате общи въпроси, може да ни пишете на contact@awesomefoundation.org (на този адрес не даваме информация относно подадени апликации). Можете да ни следвате в [Twitter](https://twitter.com/awesomefound) и [Facebook](https://www.facebook.com/awesomefoundation).
7 |
8 |
9 | Ако искате да започнете нов Епизод, който да включва не по-малко от 10 пазителя, който са готови да дарят поне $100 ( или еквивалент в местна валута) всеки месец, моля да ни пишете на join@awesomefoundation.org.
10 |
--------------------------------------------------------------------------------
/app/views/projects/_image_form_element.html.erb:
--------------------------------------------------------------------------------
1 |
2 | remove
3 | <%= image_tag(photo.url(:small_square), title: photo.original_filename, class: "form__image-element-image") %>
4 | <%= f.input :caption, as: :string, input_html: { class: "form__image-element-caption", autocomplete: "off" } %>
5 | <%= f.input(:image, as: :hidden, input_html: { value: f.object.cached_image_data, class: "js-image-data" }) unless photo.persisted? %>
6 | <%= f.input :sort_order, as: :hidden, input_html: { class: "js-uploader__sort-field" } %>
7 | <%= f.input :_destroy, as: :hidden, input_html: { class: "js-uploader__destroy-field" } %>
8 |
9 |
--------------------------------------------------------------------------------
/app/controllers/admins_controller.rb:
--------------------------------------------------------------------------------
1 | class AdminsController < ApplicationController
2 | before_action :must_be_admin
3 |
4 | def create
5 | user = User.find(params[:user_id])
6 | user.admin = true
7 | user.save
8 | if user.save
9 | render :json => { :admin => true, :user_id => user.id }
10 | else
11 | render :json => { :message => I18n.t("users.user.error-admin-promotion") }, :status => 400
12 | end
13 | end
14 |
15 | def destroy
16 | user = User.find(params[:user_id])
17 | user.admin = false
18 | user.save
19 | if user.save
20 | render :json => { :admin => false, :user_id => user.id }
21 | else
22 | render :json => { :message => I18n.t("users.user.error-admin-demotion") }, :status => 400
23 | end
24 | end
25 | end
26 |
--------------------------------------------------------------------------------
/app/views/funded_projects/_3up_gallery.html.erb:
--------------------------------------------------------------------------------
1 |
2 | <%= image_tag(project.display_images[0].url(:large_square)) %>
3 |
4 |
5 |
6 | <%= image_tag(project.display_images[1].url(:small_rectangle)) %>
7 |
8 |
9 | <%= image_tag(project.display_images[2].url(:small_rectangle)) %>
10 |
11 |
12 |
--------------------------------------------------------------------------------
/config/initializers/assets.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # Version of your assets, change this if you want to expire all your assets.
4 | Rails.application.config.assets.version = "1.0"
5 |
6 | # Add additional assets to the asset load path.
7 | # Rails.application.config.assets.paths << Emoji.images_path
8 | # Add Yarn node_modules folder to the asset load path.
9 | Rails.application.config.assets.paths << Rails.root.join('node_modules')
10 | Rails.application.config.assets.paths += Dir[Rails.root.join('vendor', 'lightgallery', '*')]
11 |
12 | # Precompile additional assets.
13 | # application.js, application.css, and all non-JS/CSS in the app/assets
14 | # folder are already added.
15 | # Rails.application.config.assets.precompile += %w[ admin.js admin.css ]
16 |
--------------------------------------------------------------------------------
/spec/controllers/acceptances_controller_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | describe AcceptancesController do
4 | let(:invitation) { FactoryBot.create(:invitation) }
5 |
6 | context 'not logged in' do
7 | context 'GET to #new' do
8 | before do
9 | get :new, params: { invitation_id: invitation.id }
10 | end
11 |
12 | it { is_expected.to respond_with(:success) }
13 | end
14 |
15 | context 'accepting without a password' do
16 | before do
17 | post :create, params: { invitation_id: invitation.id, invitation: { password: "" } }
18 | end
19 |
20 | it { is_expected.to respond_with(:success) }
21 | it { is_expected.to render_template('new') }
22 | it { expect(flash[:notice]).not_to be_blank }
23 | end
24 | end
25 | end
26 |
--------------------------------------------------------------------------------
/app/views/chapters/_chapter.html.erb:
--------------------------------------------------------------------------------
1 |
2 |
3 |
<%= link_to chapter.display_name, chapter_path(chapter) %>
4 |
5 | <%= link_to "", chapter.twitter_url, :class => :twitter_url, :title => Chapter.human_attribute_name(:twitter_url) if chapter.twitter_url.present? %>
6 | <%= link_to "", chapter.facebook_url, :class => :facebook_url, :title => Chapter.human_attribute_name(:facebook_url) if chapter.facebook_url.present? %>
7 | <%= link_to "", chapter.instagram_url, :class => :instagram_url, :title => Chapter.human_attribute_name(:instagram_url) if chapter.instagram_url.present? %>
8 |
9 |
10 | <%= chapter.country %>
11 |
12 |
--------------------------------------------------------------------------------
/public/blog/awesome_foundation/archive.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/spec/features/step_definitions/admin_manages_promotions_steps.rb:
--------------------------------------------------------------------------------
1 | step 'I promote the trustee to admin' do
2 | @current_chapter = FactoryBot.create(:chapter)
3 | visit chapter_projects_path(@current_chapter)
4 | click_link("View all Users")
5 | page.find(:css, "tr[data-user-id='#{@trustee.id}'].non_admin td.promote-demote-admin a.promote-user").click
6 | end
7 |
8 | step 'I remove trustee from a chapter' do
9 | visit users_path
10 | accept_confirm { click_link("Remove") }
11 | page.evaluate_script('window.confirm = function() { return true; }')
12 | end
13 |
14 | step 'I should see the deactivated user' do
15 | expect(page).to have_selector(".remove-trustee", :text => '-')
16 | end
17 |
18 | step 'I should see the new admin' do
19 | expect(page).to have_css("tr[data-user-id='#{@trustee.id}'].admin")
20 | end
21 |
--------------------------------------------------------------------------------
/app/controllers/promotions_controller.rb:
--------------------------------------------------------------------------------
1 | class PromotionsController < ApplicationController
2 | before_action { |c| c.must_be_able_to_manage_chapter_users(params[:role_id]) }
3 |
4 | def create
5 | role = Role.find(params[:role_id])
6 | role.name = 'dean'
7 | if role.save
8 | render :json => { :role => role.name, :role_id => role.id }
9 | else
10 | render :json => { :message => I18n.t("users.user.error_dean_promotion") }, :status => 400
11 | end
12 | end
13 |
14 | def destroy
15 | role = Role.find(params[:role_id])
16 | role.name = 'trustee'
17 | if role.save
18 | render :json => { :role => role.name, :role_id => role.id }
19 | else
20 | render :json => { :message => I18n.t("users.user.error_dean_demotion") }, :status => 400
21 | end
22 | end
23 |
24 | end
25 |
--------------------------------------------------------------------------------
/db/migrate/20120131180550_change_chapters.rb:
--------------------------------------------------------------------------------
1 | class ChangeChapters < ActiveRecord::Migration[4.2]
2 | def up
3 | remove_column :chapters, :slug
4 | rename_column :chapters, :body, :description
5 | remove_column :chapters, :tagline
6 | remove_column :chapters, :submission_form_url
7 | add_column :chapters, :twitter_url, :string
8 | add_column :chapters, :facebook_url, :string
9 | add_column :chapters, :blog_url, :string
10 | end
11 |
12 | def down
13 | remove_column :chapters, :blog_url
14 | remove_column :chapters, :facebook_url
15 | remove_column :chapters, :twitter_url
16 | add_column :chapters, :submission_form_url, :string
17 | add_column :chapters, :tagline, :string
18 | rename_column :chapters, :description, :body
19 | add_column :chapters, :slug, :string
20 | end
21 | end
22 |
--------------------------------------------------------------------------------
/db/migrate/20251116230500_create_project_moderations.rb:
--------------------------------------------------------------------------------
1 | class CreateProjectModerations < ActiveRecord::Migration[7.2]
2 | def change
3 | create_table :project_moderations do |t|
4 | t.references :project, null: false, foreign_key: true
5 | t.string :status, null: false, default: "unreviewed"
6 | t.string :moderation_type, null: false, default: "spam"
7 | t.jsonb :signals, null: false, default: {}
8 | t.references :reviewed_by, null: true, foreign_key: { to_table: :users }
9 | t.datetime :reviewed_at
10 |
11 | t.timestamps
12 | end
13 |
14 | add_index :project_moderations, :status
15 | add_index :project_moderations, :moderation_type
16 | add_index :project_moderations, :signals, using: :gin
17 | # project_id index is automatically created by foreign key
18 | end
19 | end
20 |
--------------------------------------------------------------------------------
/config/initializers/errors.rb:
--------------------------------------------------------------------------------
1 | require 'net/smtp'
2 | # Example:
3 | # begin
4 | # some http call
5 | # rescue *HTTP_ERRORS => error
6 | # notify_hoptoad error
7 | # end
8 |
9 | HTTP_ERRORS = [Timeout::Error,
10 | Errno::EINVAL,
11 | Errno::ECONNRESET,
12 | EOFError,
13 | Net::HTTPBadResponse,
14 | Net::HTTPHeaderSyntaxError,
15 | Net::ProtocolError]
16 |
17 | SMTP_SERVER_ERRORS = [Timeout::Error,
18 | IOError,
19 | Net::SMTPUnknownError,
20 | Net::SMTPServerBusy,
21 | Net::SMTPAuthenticationError]
22 |
23 | SMTP_CLIENT_ERRORS = [Net::SMTPFatalError,
24 | Net::SMTPSyntaxError]
25 |
26 | SMTP_ERRORS = SMTP_SERVER_ERRORS + SMTP_CLIENT_ERRORS
27 |
--------------------------------------------------------------------------------
/docker-compose.yml:
--------------------------------------------------------------------------------
1 | services:
2 | db:
3 | image: postgres
4 | volumes:
5 | - postgresqldata:/var/lib/postgresql/data
6 | environment:
7 | POSTGRES_USER: "postgres"
8 | POSTGRES_PASSWORD: "mysecretpassword"
9 |
10 | web:
11 | build: .
12 | volumes:
13 | - .:/app
14 | ports:
15 | - "3000:3000"
16 | environment:
17 | APPLICATION_IMAGE_PREVIEWS: true
18 | DB_NAME: postgres
19 | DEFAULT_URL: http://host.docker.internal:3000
20 | IMGPROXY_HOST: //localhost:8080
21 | POSTGRES_HOST: db
22 | POSTGRES_USER: postgres
23 | POSTGRES_PASSWORD: mysecretpassword
24 | SHRINE_UPLOADS:
25 | depends_on:
26 | - db
27 |
28 | imgproxy:
29 | image: darthsim/imgproxy:v3.8
30 | ports:
31 | - 8080:8080
32 |
33 | volumes:
34 | postgresqldata:
35 |
--------------------------------------------------------------------------------
/app/views/projects/new.html.erb:
--------------------------------------------------------------------------------
1 | <% provide(:page_title, t(".title")) %>
2 |
3 | <% unless embed? %>
4 |
5 | <%= t ".title" %>
6 | <%= t ".description" %>
7 |
8 | <% end %>
9 |
10 |
16 |
17 |
--------------------------------------------------------------------------------
/spec/support/aws_s3_mock_factory.rb:
--------------------------------------------------------------------------------
1 | class AwsS3MockFactory
2 | def initialize(shrine_s3)
3 | @shrine_s3 = shrine_s3
4 | end
5 |
6 | def client
7 | @shrine_s3.client
8 | end
9 |
10 | def create_mock_file(options = {})
11 | obj = OpenStruct.new(
12 | key: options[:key] || "#{SecureRandom.uuid}.png",
13 | content_length: Random.rand(10..50000),
14 | content_type: options[:content_type] || "image/png",
15 | last_modified: options[:last_modified] || 1.minute.ago
16 | )
17 |
18 | client.stub_responses(:head_object, {
19 | content_length: obj.content_length,
20 | content_type: obj.content_type,
21 | last_modified: obj.last_modified
22 | })
23 |
24 | @shrine_s3.object(obj.key)
25 | end
26 | end
27 |
--------------------------------------------------------------------------------
/config/initializers/rack-cors.rb:
--------------------------------------------------------------------------------
1 | # This is needed to ensure that fonts (and other assets) that are served
2 | # directly by the Rails app on Heroku and then served via a CDN (Cloudfront)
3 | # will serve the correct headers and will let the browsers load them properly
4 | # https://devcenter.heroku.com/articles/using-amazon-cloudfront-cdn#cors
5 | Rails.configuration.middleware.insert_before 0, Rack::Cors do
6 | allow do
7 | if ENV['CANONICAL_HOST'].present?
8 | origins "https://#{ENV['CANONICAL_HOST']}",
9 | "http://#{ENV['CANONICAL_HOST']}"
10 | else
11 | origins "https://#{ ENV['SUBDOMAIN'] || "www" }.awesomefoundation.org",
12 | "http://#{ ENV['SUBDOMAIN'] || "www" }.awesomefoundation.org"
13 | end
14 |
15 | resource '/assets/*', headers: :any, methods: [:get, :post, :options]
16 | end
17 | end
18 |
--------------------------------------------------------------------------------
/public/blog/awesome_foundation/header-nav.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | The Awesome Foundation
6 |
7 |
8 |
9 | Home
10 |
11 |
12 | About Us
13 |
14 |
15 | Chapters
16 |
17 |
18 | Apply
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/app/views/winners/edit.html.erb:
--------------------------------------------------------------------------------
1 | <% provide(:page_title, t(".title")) %>
2 |
3 |
4 |
5 | <%= t(".title") %>
6 | <%= simple_format t(".description") %>
7 |
8 |
9 |
19 |
20 |
--------------------------------------------------------------------------------
/app/views/locales/_contact.fr.md:
--------------------------------------------------------------------------------
1 | # Contacts
2 |
3 | Vous avez une idée géniale ? [Postulez à une bourse !](<%= new_submission_path %>)
4 |
5 | Pour contacter une branche en particulier, merci d’utiliser le lien e-mail qui figure en haut de la page de la branche, dans la partie Branches de ce site. Pour les demandes globales, envoyez-nous un mot à contact@awesomefoundation.org (nous ne pouvons pas vous donner d’informations et de retours sur les candidatures à cette adresse). Vous pouvez aussi nous rejoindre sur [Twitter](https://twitter.com/awesomefound) et [Facebook](https://www.facebook.com/awesomefoundation).
6 |
7 | Si vous souhaitez créer votre propre branche, ce qui implique de réunir un groupe d’au moins 10 « membres » prêts à donner chacun 100$ (ou l’équivalent en monnaie locale) tous les mois pour constituer la bourse, merci de nous contacter à join@awesomefoundation.org.
8 |
--------------------------------------------------------------------------------
/app/views/projects/show.html.erb:
--------------------------------------------------------------------------------
1 | <% provide(:page_title, @project.title) %>
2 | <% provide(:meta_viewport, 'width=device-width, initial-scale=1, maximum-scale=1') %>
3 |
4 | <% content_for(:extra_body_classes, 'projects-index') %>
5 |
6 |
7 | <%= render 'shared/sidebar', :chapter => @project.chapter %>
8 |
9 |
10 |
11 | <%= t "projects.index.title", :name => @project.chapter.display_name, :count => 1 %>
12 |
13 |
14 | <%= raw t ".back-to", :name => @project.chapter.display_name, :url => chapter_projects_path(@project.chapter) %>
15 |
16 |
17 | <%= render @project, full_view: true %>
18 |
19 |
20 |
21 | <%= render "shared/lightbox" %>
22 | <% render "project_actions_js" %>
23 | <%= render partial: "comments_js", locals: { comments: @initial_comments } %>
24 |
--------------------------------------------------------------------------------
/config/database.yml:
--------------------------------------------------------------------------------
1 | production: &default
2 | adapter: postgresql
3 | database: awesomefoundation_production
4 | pool: <%= ENV['DB_POOL'] || ENV['RAILS_MAX_THREADS'] || 5 %>
5 | timeout: 5000
6 |
7 | <% if Rails.env.development? %>
8 | development: &default
9 | adapter: postgresql
10 | database: <%= ENV['DB_NAME'] || 'awesomefoundation_development' %>
11 | pool: 5
12 | timeout: 5000
13 | host: <%= ENV['POSTGRES_HOST'] || 'localhost' %>
14 | username: <%= ENV['POSTGRES_USER'] || '' %>
15 | password: <%= ENV['POSTGRES_PASSWORD'] || '' %>
16 | <% end %>
17 |
18 | test: &test
19 | <<: *default
20 | database: awesomefoundation_test
21 | host: <%= ENV['POSTGRES_HOST'] || 'localhost' %>
22 | username: <%= ENV['POSTGRES_USER'] || '' %>
23 | password: <%= ENV['POSTGRES_PASSWORD'] || '' %>
24 | min_messages: warning
25 |
26 | cucumber:
27 | <<: *test
28 |
--------------------------------------------------------------------------------
/spec/features/step_definitions/export_steps.rb:
--------------------------------------------------------------------------------
1 | HEADER_COUNT = 1
2 |
3 | step 'I visit a chapters projects page' do
4 | visit chapter_projects_path Chapter.last
5 | end
6 |
7 | step 'I export all projects' do
8 | click_link 'Export All From Date Range'
9 | end
10 |
11 | step 'I should not see the export all link' do
12 | expect(page).not_to have_css('p', :text => 'Export All From Date Range')
13 | end
14 |
15 | step 'I filter to the last :num_days day(s)' do |num_days|
16 | fill_in("start date", with: (num_days.to_i.days.ago).utc.strftime("%Y-%m-%d"))
17 | fill_in("end date", with: Time.now.utc.strftime("%Y-%m-%d"))
18 | click_button "Filter"
19 | end
20 |
21 | step 'I should receive a CSV file with :num_projects projects' do |num_projects|
22 | csv = CSV.parse(page.source, :col_sep => ",")
23 | expect(csv.count).to eq(HEADER_COUNT + num_projects.to_i)
24 | end
25 |
--------------------------------------------------------------------------------
/db/migrate/20120131193919_remove_extra_fields_from_users.rb:
--------------------------------------------------------------------------------
1 | class RemoveExtraFieldsFromUsers < ActiveRecord::Migration[4.2]
2 | def up
3 | remove_column :users, :login_count
4 | remove_column :users, :failed_login_count
5 | remove_column :users, :last_request_at
6 | remove_column :users, :current_login_at
7 | remove_column :users, :last_login_at
8 | remove_column :users, :current_login_ip
9 | remove_column :users, :last_login_ip
10 | end
11 |
12 | def down
13 | add_column :users, :last_login_ip, :string
14 | add_column :users, :current_login_ip, :string
15 | add_column :users, :last_login_at, :datetime
16 | add_column :users, :current_login_at, :datetime
17 | add_column :users, :last_request_at, :datetime
18 | add_column :users, :failed_login_count, :integer
19 | add_column :users, :login_count, :integer
20 | end
21 | end
22 |
--------------------------------------------------------------------------------
/app/views/projects/success.html.erb:
--------------------------------------------------------------------------------
1 | <% provide :page_title, t(".title") %>
2 |
3 |
4 |
5 | <%= t ".title" %>
6 | <%= t(".description", chapter: @chapter.name) %>
7 |
8 | <% unless embed? %>
9 | <%= link_to t(".explore-projects"), projects_path %>
10 | <% end %>
11 |
12 |
13 | <%= link_to t(".share-on-twitter"), "https://twitter.com/intent/tweet?text=#{t('.i-just-applied-tweet', twitter: @twitter_account || '@awesomefound')}&url=#{@share_url}&related=#{@twitter_account},@awesomefound", class: "button--pill button--small", target: "_blank" %>
14 | <%= link_to t(".share-on-facebook"), "https://www.facebook.com/sharer.php?u=#{@share_url}", class: "button--pill button--small", target: "_blank" %>
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/app/views/locales/_contact.hy.md:
--------------------------------------------------------------------------------
1 | # Կապ
2 |
3 | Ունե՞ք հիանալի (օսմ) գաղափար... [դիմե՛քդրամաշնորհի համար](<%= new_submission_path %>)
4 |
5 | Որևէ մասնաճյուղի հետ կապ հաստատելու համար, խնդրում ենք օգտվել տվյալ մասնաճյուղի էջի վերևի հատվածում նշված էլեկտրոնային հասցեից: Մասնաճյուղերի էջերը կարող եք գտնել այս վեբկայքի «Մասնաճյուղեր» բաժնում: Ընդհանուր բնույթի հարցերի համար կարող եք մեզ գրել contact@awesomefoundation.org հասցեով (այս հասցեով մենք չենք տրամադրում դիմումների մասին տեղեկություններ):
6 | Մեր գործունեությանը ծանոթանալու համար կարող եք հետևել մեզ [Twitter-ում](https://twitter.com/awesomefound) եւ [Facebook-ում](https://www.facebook.com/awesomefoundation)։
7 |
8 | Եթե հետաքրքրված եք հիմնելու նոր մասնաճյուղ և հավաքագրել եք նվազագույնը 10 «հոգաբարձուների» խումբ, ովքեր պատրաստ են տրամադրել $100 (կամ տեղական համարժեք դրամ) ամենամսյա ֆինանսավորման համար, ապա կապվեք մեզ հետ join@awesomefoundation.org հասցեով:
9 |
--------------------------------------------------------------------------------
/app/views/locales/_contact.es.md:
--------------------------------------------------------------------------------
1 | # Contacto
2 |
3 | ¿Tienes una idea impresionante? [¡Solicita un beca!](<%= new_submission_path %>)
4 |
5 | Para llegarle a un capítulo específico, por favor usa el enlace de correo electrónico en la parte superior de la página del capítulo, bajo la sección Capítulos en este sitio web. O, para preguntals globales generales, puedes enviarnos un mensaje a contact@awesomefoundation.org (no podemos proveer actualizaciones o detalles con respecto a las solicitudes en esa dirección.) También puedes comunicarte con nosotros en [Twitter](https://twitter.com/awesomefound) y [Facebook](https://www.facebook.com/awesomefoundation).
6 |
7 | Si estás interesado en comenzar tu propio capítulo, lo cual incluye reunir un grupo de por lo menos diez "administradores" dispuestos a contribuir $100 cada uno (o su equivalente local) mensualmente para la beca, por favor comunícate con join@awesomefoundation.org.
--------------------------------------------------------------------------------
/public/blog/awesome_foundation/loop-category.php:
--------------------------------------------------------------------------------
1 |
2 | results for ', get_search_query(), '';
5 |
6 | while (have_posts()) : the_post();
7 |
8 | echo '';
9 | echo '
';
13 | if ( has_post_thumbnail() ) {
14 | echo '
';
15 | echo get_the_post_thumbnail(get_the_ID(), 'thumbnail');
16 | echo '
';
17 | };
18 | the_excerpt();
19 | echo '
';
20 |
21 | endwhile;
22 |
23 | echo '';
24 | ?>
25 |
26 |
--------------------------------------------------------------------------------
/spec/features/dean_generates_shortlist_report.feature.pending:
--------------------------------------------------------------------------------
1 | Feature: A dean can generate a report of all shortlisted projects for a specified time period
2 |
3 | Scenario: dean generates shortlist
4 | Given I am logged in as a dean
5 | And trustees in my chapter have shortlisted projects submtted in the past 7 days
6 | When I generate a report of projects that have been submitted in the past 3 days and shorlisted
7 | Then I see a list of projects that were submitted in the last 3 days and have been shortlisted
8 | And I should not see any non-shortlisted projects
9 | And I should not see any projects that were submitted 4 days ago
10 |
11 | Scenario: dean exports short list
12 | Given I am logged in as a dean
13 | And I have generated a report of shortlisted projects
14 | When I export the report as a CSV
15 | Then I should get a conformation taht the report has exported
16 |
--------------------------------------------------------------------------------
/spec/features/dean_creates_additional_questions_for_application.feature:
--------------------------------------------------------------------------------
1 | Feature: A dean adds additional questions to the application process
2 |
3 | @javascript
4 | Scenario: Additional Questions
5 | Given I am logged in as a dean
6 | When I attempt to edit my chapter
7 | And I enter new questions for applicants to answer
8 | And I submit a project to the "Boston" chapter with the extra questions answered
9 | Then I should be thanked
10 | And I should get an email telling me the application went through
11 |
12 | When I view the project in the admin area
13 | Then I should see the questions and my answers to them
14 |
15 | When I attempt to edit my chapter
16 | And I enter different questions for applicants to answer
17 | Then I should see them on the application form
18 | When I go to the recently submitted project
19 | Then I should see the questions and my answers to them
20 |
--------------------------------------------------------------------------------
/app/extras/spam_checker.rb:
--------------------------------------------------------------------------------
1 | module SpamChecker
2 | class Project
3 | attr_accessor :project
4 |
5 | def initialize(project)
6 | @project = project
7 | end
8 |
9 | def call
10 | if spam?
11 | project.errors.add(:base, :spam_detected)
12 | true
13 | end
14 | end
15 |
16 | def spam?
17 | if fields_to_check.all? { |field| field.present? } && fields_to_check.uniq.size == 1
18 | true
19 | elsif [project.about_me, project.about_project, project.use_for_money].any? { |field| field&.match?(blocklist) }
20 | true
21 | else
22 | false
23 | end
24 | end
25 |
26 | private
27 |
28 | def fields_to_check
29 | [project.about_me, project.about_project, project.use_for_money]
30 | end
31 |
32 | def blocklist
33 | ["--test-spam-string--", ENV['SPAM_REGEXP']].reject(&:blank?).join("|")
34 | end
35 | end
36 | end
37 |
--------------------------------------------------------------------------------
/spec/requests/routing_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | describe 'Routes for the blog' do
4 | it 'should redirect the contact page' do
5 | get '/blog/contact/'
6 | expect(response).to redirect_to('/en/contact')
7 | end
8 |
9 | it 'should redirect the about page' do
10 | get '/blog/about/'
11 | expect(response).to redirect_to('/en/about_us')
12 | end
13 |
14 | it 'should redirect the main blog page' do
15 | get '/blog/'
16 | expect(response).to redirect_to('http://blog.awesomefoundation.org')
17 | end
18 |
19 | it 'should redirect a specific blog page' do
20 | get '/blog/2012/01/01/post-name'
21 | expect(response).to redirect_to('http://blog.awesomefoundation.org/2012/01/01/post-name')
22 | end
23 | end
24 |
25 | describe 'Routes for submissions' do
26 | it 'should redirect the apply page' do
27 | get '/apply'
28 | expect(response).to redirect_to('/en/submissions/new')
29 | end
30 | end
31 |
--------------------------------------------------------------------------------
/app/assets/stylesheets/_base-variables.scss:
--------------------------------------------------------------------------------
1 | $gw-column: 60px;
2 | $gw-gutter: 20px;
3 |
4 | $serif: Georgia, Cambria, serif;
5 | $sans-serif: 'museo-sans', 'proxima-nova', $helvetica;
6 |
7 | $base-font-color: rgb(55,55,55);
8 | $lighter-base-font-color: rgb(46,46,46);
9 | $muted-color: #ccc;
10 |
11 | $pink: rgb(255, 75, 126);
12 | $button-pink: rgb(252, 103, 147);
13 |
14 | $blue: rgb(34,122,255); //blue
15 |
16 | /***
17 | * Responsiveness Sizes
18 | *
19 | * Three distinct stop points are defined:
20 | * maximum-width: largest size the main body of the page grows to
21 | * mobile-standard: for layout changes on average mobile phone screens
22 | * mobile-small: for additional changes that accommdate very small screens like iPhone 5S
23 | ***/
24 |
25 | $maximum-width: 60em; // Equivalent to 969px;
26 | $tablet-standard: 60em;
27 | $mobile-standard: 30em; // Equivalent to 480px;
28 | $mobile-small: 20em; // Equivalent to 320px;
29 |
--------------------------------------------------------------------------------
/spec/features/admin_dean_manage_chapters.feature:
--------------------------------------------------------------------------------
1 | Feature: Manage Chapters
2 | An admin can create and modify chapters
3 | A dean of a chapter can modify the chapter
4 |
5 | Scenario: An admin creates a chapter
6 | Given I am logged in as an admin
7 | When I create a new chapter
8 | And I go to the chapters index
9 | Then I should see this new chapter
10 |
11 | Scenario: An admin tries to create an invalid chapter
12 | Given I am logged in as an admin
13 | When I go to create a new chapter
14 | But I just submit the form
15 | Then I should see the new chapter form with errors
16 |
17 | Scenario: A dean edits a chapter
18 | Given I am logged in as a dean
19 | When I edit a chapter
20 | Then I should see the updated chapter
21 |
22 | Scenario: A trustee attempts to edit a chapter
23 | Given I am logged in as a trustee
24 | When I attempt to edit a chapter
25 | Then I should see a permissions error
26 |
--------------------------------------------------------------------------------
/spec/helpers/application_helper_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | describe ApplicationHelper, '#display_country?' do
4 |
5 | let(:chapter1) { FactoryBot.create(:chapter, :country => 'Australia') }
6 | let(:chapter2) { FactoryBot.create(:chapter, :country => 'Australia') }
7 | let(:chapter3) { FactoryBot.create(:chapter, :country => 'America') }
8 |
9 | it 'returns true/false based on current/previous chapters country' do
10 | expect(helper.display_country?(chapter1.country)).to be_truthy
11 | expect(helper.display_country?(chapter2.country)).to be_falsey
12 | expect(helper.display_country?(chapter3.country)).to be_truthy
13 | end
14 |
15 | end
16 |
17 | describe ApplicationHelper, '#markdown' do
18 | it 'returns markdown converted text' do
19 | expect(helper.markdown('*Test*')).to eq("Test
\n")
20 | end
21 |
22 | it 'returns html_safe text' do
23 | expect(helper.markdown('test')).to be_html_safe
24 | end
25 | end
26 |
--------------------------------------------------------------------------------
/public/blog/awesome_foundation/stylesheets/sass/bourbon/functions/_linear-gradient.scss:
--------------------------------------------------------------------------------
1 | @function linear-gradient($pos: top, $G1: false, $G2: false,
2 | $G3: false, $G4: false,
3 | $G5: false, $G6: false,
4 | $G7: false, $G8: false,
5 | $G9: false, $G10: false) {
6 |
7 | // Detect what type of value exists in $pos
8 | $pos-type: type-of(nth($pos, 1));
9 |
10 | // If $pos is missing from mixin, reassign vars and add default position
11 | @if ($pos-type == color) or (nth($pos, 1) == "transparent") {
12 | $G10: $G9; $G9: $G8; $G8: $G7; $G7: $G6; $G6: $G5;
13 | $G5: $G4; $G4: $G3; $G3: $G2; $G2: $G1; $G1: $pos;
14 | $pos: top; // Default position
15 | }
16 |
17 | $type: linear;
18 | $gradient: compact($pos, $G1, $G2, $G3, $G4, $G5, $G6, $G7, $G8, $G9, $G10);
19 | $type-gradient: append($type, $gradient, comma);
20 |
21 | @return $type-gradient;
22 | }
23 |
24 |
--------------------------------------------------------------------------------
/spec/features/dean_edits_project.feature:
--------------------------------------------------------------------------------
1 | Feature: Dean edits a project
2 |
3 | @javascript
4 | Scenario: Dean adds and rearranges some photos to a project
5 | Given I am logged in as a dean
6 | And there is 1 winning project in my chapter
7 | When I edit that winning project
8 | And I attach 3 photos
9 | And I go to the public page for that project
10 | Then I should see 3 project images on the page
11 |
12 | When I edit that winning project
13 | And I set the last image to be first
14 | Then I should see that last image when I load the page
15 |
16 | @javascript
17 | Scenario: Dean sets the funding date for a winning project
18 | Given I am logged in as a dean
19 | And there is 1 winning project in my chapter
20 | When I edit that winning project
21 | And I set the winning date to be February 2008
22 | And I go to the public page for that project
23 | Then I should see the project was funded in February 2008
24 |
--------------------------------------------------------------------------------
/app/controllers/votes_controller.rb:
--------------------------------------------------------------------------------
1 | class VotesController < ApplicationController
2 | before_action :must_be_logged_in
3 |
4 | def create
5 | @project = Project.find(params[:project_id])
6 | @user = current_user
7 | @vote = Vote.new(user: @user, project: @project, chapter_id: params[:chapter_id])
8 | if @vote.save
9 | render json: {shortlisted: true, project_id: @project.id, chapter_id: params[:chapter_id]}
10 | else
11 | render :json => {:message => t("flash.votes.already-voted")}, :status => 400
12 | end
13 | end
14 |
15 | def destroy
16 | @project = Project.find(params[:project_id])
17 | @user = current_user
18 | if @vote = @user.votes.find_by(project: @project)
19 | @vote.destroy
20 | render json: {shortlisted: false, project_id: @project.id, chapter_id: params[:chapter_id]}
21 | else
22 | render :json => {:message => t("flash.votes.already-deleted")}, :status => 400
23 | end
24 | end
25 | end
26 |
--------------------------------------------------------------------------------
/spec/features/step_definitions/guest_views_chapter_steps.rb:
--------------------------------------------------------------------------------
1 | step 'there are 5 trustees' do
2 | @trustees = (1..5).map { FactoryBot.create(:user) }
3 | @trustees.each do |trustee|
4 | FactoryBot.create(:role,
5 | :user => trustee,
6 | :name => 'trustee',
7 | :chapter => @current_chapter)
8 | end
9 | end
10 |
11 | step 'I should see the trustees' do
12 | @trustees.each do |trustee|
13 | expect(page).to have_selector(".trustee-details h3", :text => "#{trustee.first_name} #{trustee.last_name}")
14 | end
15 | end
16 |
17 | step 'there is a trustee' do
18 | @chapter = FactoryBot.create(:chapter)
19 | @trustee = FactoryBot.create(:user, :url => 'http://www.myawesomeblog.com')
20 | @role = FactoryBot.create(:role, :user => @trustee, :chapter => @chapter)
21 | end
22 |
23 | step 'I should be able to click on a trustee' do
24 | visit chapter_path(@chapter)
25 | expect(page).to have_css("a.avatar[href='#{@trustee.url}']")
26 | end
27 |
--------------------------------------------------------------------------------
/spec/models/country_sort_criteria_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | describe CountrySortCriteria do
4 |
5 | let(:chapter1) { FactoryBot.create(:chapter, :name => 'Salzburg', :country => 'Austria') }
6 | let(:chapter2) { FactoryBot.create(:chapter, :name => 'Los Angeles', :country => 'United States') }
7 | let(:chapter3) { FactoryBot.create(:chapter, :name => 'Sydney', :country => 'Australia') }
8 | let(:chapter4) { FactoryBot.create(:chapter, :name => 'Boston', :country => 'United States') }
9 | let(:chapter5) { FactoryBot.create(:chapter, :name => 'Awesome Without Borders', :country => 'Worldwide') }
10 | let(:chapters) { [chapter1, chapter2, chapter3, chapter4, chapter5] }
11 |
12 | context "given an array of chapters" do
13 | it "should be sorted based on priorty and country name" do
14 | expect(chapters.sort_by(&CountrySortCriteria.new(COUNTRY_PRIORITY))).to eq([chapter5, chapter3, chapter1, chapter4, chapter2])
15 | end
16 | end
17 |
18 | end
19 |
--------------------------------------------------------------------------------
/spec/features/trustee_edits_profile.feature:
--------------------------------------------------------------------------------
1 | Feature: As a trustee I can edit my profile
2 |
3 | Scenario: Trustee changes account information
4 | Given I am logged in as a trustee
5 | When I change my profile information
6 | Then my profile is updated
7 | And I am on the projects page of my last viewed chapter
8 |
9 | Scenario: Trustee tries to change another users account
10 | Given I am logged in as a trustee
11 | And there is another trustee in the system
12 | When I try to change the other trustees information
13 | Then I should see an update user permission error
14 |
15 | Scenario: Trustee changes password
16 | Given I am logged in as a trustee
17 | When I update my password
18 | And I log out
19 | Then I should be able to log in with updated password
20 |
21 | Scenario: Trustee is not associated with a chpater
22 | Given I log in as a trustee with no chapter
23 | Then I should see an error about not having a chapter
24 |
--------------------------------------------------------------------------------
/features/clearance/visitor_signs_in.feature:
--------------------------------------------------------------------------------
1 | Feature: Sign in
2 |
3 | In order to get access to protected sections of the site
4 | As a visitor
5 | I want to sign in
6 |
7 | Scenario: Visitor is not signed up
8 | When I sign in as "unknown.email@example.com"
9 | Then I am told email or password is bad
10 | And I should be signed out
11 |
12 | Scenario: Visitor enters wrong password
13 | Given I am signed up as "email@example.com"
14 | When I sign in as "email@example.com" and "badpassword"
15 | Then I am told email or password is bad
16 | And I should be signed out
17 |
18 | Scenario: Visitor signs in successfully
19 | Given I am signed up as "email@example.com"
20 | When I sign in as "email@example.com"
21 | Then I should be signed in
22 |
23 | Scenario: Visitor signs in successfully with uppercase email
24 | Given I am signed up as "email@example.com"
25 | When I sign in as "Email@example.com"
26 | Then I should be signed in
27 |
--------------------------------------------------------------------------------
/spec/mailers/project_mailer_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | describe ProjectMailer, :type => :mailer do
4 | let(:project) { FactoryBot.create(:project, :chapter => chapter) }
5 | let(:mail) { ProjectMailer.new_application(project) }
6 |
7 | describe 'in a chapter without custom email response' do
8 | let(:chapter) { FactoryBot.create(:chapter) }
9 |
10 | it 'includes the default email text' do
11 | # No idea why this works with "include" and not "match" and
12 | # mail.body.to_s but not mail.body.encoded
13 | expect(mail.body.to_s).to include(Chapter::DEFAULT_SUBMISSION_RESPONSE_EMAIL)
14 | end
15 | end
16 |
17 | describe 'in a chapter with a custom email response' do
18 | let(:chapter) { FactoryBot.create(:chapter, :submission_response_email => "This is a custom email response") }
19 |
20 | it 'includes the custom response' do
21 | expect(mail.body.encoded).to match("This is a custom email response")
22 | end
23 | end
24 | end
25 |
--------------------------------------------------------------------------------
/spec/features/admin_views_project_submissions.feature:
--------------------------------------------------------------------------------
1 | Feature: Admin can view any chapter
2 |
3 | Scenario: Admin uses the chapter selection dropdown to view a chapter
4 | Given I am logged in as an admin
5 | And a project was created on each of the last 7 days for one chapter
6 | And a project was created on each of the last 7 days for a different chapter
7 | And a project was created on each of the last 7 days for any chapter
8 | When I am looking at the list of projects for the first chapter
9 | And I want to see my projects for the past 3 days
10 | Then I should see my projects for the past 3 days
11 | And I should not see projects that are not mine
12 | And I should not see any projects that are 4 or more days old
13 |
14 | When I look at the projects for the "Any" chapter
15 | Then I should see its projects for the past 3 days
16 |
17 | When I look at the projects for the other chapter
18 | Then I should see its projects for the past 3 days
19 |
--------------------------------------------------------------------------------
/spec/support/feed.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | -
4 |
New Melbourne Chapter
5 | http://awesomefoundation.org/blog/2012/02/12/awesome-squared-welcome-to-melbourne/
6 | Mon, 13 Feb 2012 04:03:56 +0000
7 |
8 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/spec/features/guest_views_project.feature:
--------------------------------------------------------------------------------
1 | Feature: Guest views a project's page
2 |
3 | Scenario: Guest views a project
4 | Given there is 1 winning project
5 | And I am on the homepage
6 | When I click on that project
7 | Then I should see the page describing it and all its details
8 |
9 | Scenario: Guest views project with no image
10 | Given there is a project with 0 photos
11 | And I am on the homepage
12 | When I view the project
13 | Then I should see 1 project image on the page
14 | And I should see the placeholder image
15 |
16 | Scenario: Guest views project with one image
17 | Given there is a project with 1 photo
18 | And I am on the homepage
19 | When I view the project
20 | Then I should see 1 project image on the page
21 |
22 | Scenario: Guest views a project with multiple images
23 | Given there is a project with 3 photos
24 | And I am on the homepage
25 | When I view the project
26 | Then I should see 3 project images on the page
27 |
--------------------------------------------------------------------------------
/app/models/project_moderation.rb:
--------------------------------------------------------------------------------
1 | class ProjectModeration < ApplicationRecord
2 | belongs_to :project
3 | belongs_to :reviewed_by, class_name: "User", optional: true
4 |
5 | validates :project_id, uniqueness: true
6 |
7 | enum :status, %w[unreviewed suspected confirmed_spam confirmed_legit].index_by(&:itself)
8 | enum :moderation_type, %w[spam missing_metadata other].index_by(&:itself)
9 |
10 | store_accessor :signals, :score, :triggered
11 |
12 | scope :pending, -> { where(status: %w[unreviewed suspected]) }
13 | scope :approved, -> { where(status: %w[confirmed_legit]) }
14 |
15 | def mark_confirmed_spam!(user)
16 | update!(
17 | status: :confirmed_spam,
18 | reviewed_by: user,
19 | reviewed_at: Time.current
20 | )
21 | end
22 |
23 | def mark_confirmed_legit!(user)
24 | update!(
25 | status: :confirmed_legit,
26 | reviewed_by: user,
27 | reviewed_at: Time.current
28 | )
29 | end
30 |
31 | def reviewed?
32 | reviewed_by.present?
33 | end
34 | end
35 |
--------------------------------------------------------------------------------
/app/assets/stylesheets/_shared-footer.scss:
--------------------------------------------------------------------------------
1 | footer {
2 | height: 100px;
3 | max-width: $maximum-width;
4 | width: 100%;
5 |
6 | p {
7 | padding: 10px 0;
8 | text-align: center;
9 | margin-left: 1.5em;
10 | margin-right: 1.5em;
11 |
12 | &:first-child {
13 | padding-top: 20px;
14 | border-top: 1px solid rgb(200,200,200);
15 | }
16 |
17 | a:link, a:visited {
18 | color: $lighter-base-font-color;
19 | font: normal 12px/14px $sans-serif;
20 | margin: 0 10px;
21 | padding-bottom: 3px;
22 | text-decoration: none;
23 | text-transform: uppercase;
24 | white-space: nowrap;
25 |
26 | &:hover {
27 | border-bottom: 3px solid $pink;
28 | }
29 | }
30 |
31 | span {
32 | margin: 0 10px;
33 | }
34 | }
35 |
36 | ol {
37 | li {
38 | float: left;
39 | list-style: none;
40 | margin-right: 10px;
41 |
42 | &:last-child {
43 | margin-right: 0px;
44 | }
45 | }
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/app/assets/stylesheets/_owl.theme.default.min.css:
--------------------------------------------------------------------------------
1 | /**
2 | * Owl Carousel v2.3.4
3 | * Copyright 2013-2018 David Deutsch
4 | * Licensed under: SEE LICENSE IN https://github.com/OwlCarousel2/OwlCarousel2/blob/master/LICENSE
5 | */
6 | .owl-theme .owl-dots,.owl-theme .owl-nav{text-align:center;-webkit-tap-highlight-color:transparent}.owl-theme .owl-nav{margin-top:10px}.owl-theme .owl-nav [class*=owl-]{color:#FFF;font-size:14px;margin:5px;padding:4px 7px;background:#D6D6D6;display:inline-block;cursor:pointer;border-radius:3px}.owl-theme .owl-nav [class*=owl-]:hover{background:#869791;color:#FFF;text-decoration:none}.owl-theme .owl-nav .disabled{opacity:.5;cursor:default}.owl-theme .owl-nav.disabled+.owl-dots{margin-top:10px}.owl-theme .owl-dots .owl-dot{display:inline-block;zoom:1}.owl-theme .owl-dots .owl-dot span{width:10px;height:10px;margin:5px 7px;background:#D6D6D6;display:block;-webkit-backface-visibility:visible;transition:opacity .2s ease;border-radius:30px}.owl-theme .owl-dots .owl-dot.active span,.owl-theme .owl-dots .owl-dot:hover span{background:#869791}
--------------------------------------------------------------------------------
/app/models/guest.rb:
--------------------------------------------------------------------------------
1 | class Guest
2 | def logged_in?
3 | false
4 | end
5 |
6 | def trustee?
7 | false
8 | end
9 |
10 | def dean?
11 | false
12 | end
13 |
14 | def admin?
15 | false
16 | end
17 |
18 | def gravatar_url
19 | Gravatar.new(nil).url
20 | end
21 |
22 | def can_manage_chapter?(chapter)
23 | false
24 | end
25 |
26 | def can_manage_users?(chapter)
27 | false
28 | end
29 |
30 | def can_manage_permissions?
31 | false
32 | end
33 |
34 | def can_create_chapters?
35 | false
36 | end
37 |
38 | def can_invite?
39 | false
40 | end
41 |
42 | def can_invite_to_chapter?(chapter)
43 | false
44 | end
45 |
46 | def can_view_finalists_for?(chapter)
47 | false
48 | end
49 |
50 | def can_mark_winner?(project)
51 | false
52 | end
53 |
54 | def can_edit_project?(project)
55 | false
56 | end
57 |
58 | def can_edit_profile?(user_id)
59 | false
60 | end
61 |
62 | def mark_last_viewed_chapter(chapter_id)
63 | false
64 | end
65 | end
66 |
--------------------------------------------------------------------------------
/app/views/users/index.html.erb:
--------------------------------------------------------------------------------
1 | <% provide(:page_title, t(".title")) %>
2 |
3 | <%= t(".title") %>
4 |
5 |
6 |
7 |
8 |
9 |
10 | <%= t(".name") %>
11 | <%= t(".email") %>
12 | <% if current_user.can_edit_all_profiles? %>
13 | <%= t(".edit") %>
14 | <% end %>
15 | <%= t(".chapter") %>
16 | <%= t(".role") %>
17 | <% if current_user.can_manage_users?(current_chapter) %>
18 | <%= t(".dean") %>
19 | <% end %>
20 | <% if current_user.can_manage_permissions? %>
21 | <%= t(".admin") %>
22 | <% end %>
23 | <% if current_user.can_manage_users?(current_chapter) %>
24 | <%= t(".remove") %>
25 | <% end %>
26 |
27 | <%= render @users %>
28 |
29 |
30 |
31 |
32 | <%= will_paginate(@users) %>
33 |
--------------------------------------------------------------------------------
/app/views/funded_projects/_4up_gallery.html.erb:
--------------------------------------------------------------------------------
1 |
2 | <%= image_tag(project.display_images[0].url(:large_square)) %>
3 |
4 |
5 |
6 | <%= image_tag(project.display_images[1].url(:small_rectangle)) %>
7 |
8 |
9 |
10 | <%= image_tag(project.display_images[2].url(:small_square)) %>
11 |
12 |
13 | <%= image_tag(project.display_images[3].url(:small_square)) %>
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/public/blog/awesome_foundation/stylesheets/sass/_sidebar.scss:
--------------------------------------------------------------------------------
1 | aside {
2 | //background: rgb(240,240,240);
3 | //@include border-radius(4px);
4 | border-left: 1px solid rgb(210,210,210);
5 | float: left;
6 | width: grid-width(3) - 1;
7 |
8 | .inner-wrapper {
9 | padding: 0px 0px 0px 15px;
10 | }
11 |
12 | ul {
13 | li {
14 | list-style: none;
15 | margin-bottom: 30px;
16 |
17 | h2 {
18 | font: normal 18px/22px $sans-serif;
19 | margin-bottom: 15px;
20 | text-transform: uppercase;
21 | }
22 |
23 | ul {
24 | li {
25 | margin-bottom: 5px;
26 |
27 | a:link, a:visited {
28 | color: rgb(180,180,180);
29 | font: bold 12px/16px $sans-serif;
30 | text-decoration: none;
31 |
32 | &:hover {
33 | color: $pink;
34 | //text-decoration: underline;
35 | }
36 | }
37 | }
38 | }
39 | }
40 | }
41 |
42 | form {
43 | label {
44 | display: none;
45 | }
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/.github/workflows/build.yaml:
--------------------------------------------------------------------------------
1 | name: Build
2 |
3 | on: [push, pull_request]
4 |
5 | jobs:
6 | build:
7 | runs-on: ubuntu-24.04
8 |
9 | env:
10 | PGHOST: localhost
11 | PGUSER: postgres
12 | PGPASSWORD: postgres
13 | RAILS_ENV: test
14 |
15 | services:
16 | postgres:
17 | image: postgres:14
18 | env:
19 | POSTGRES_PASSWORD: postgres
20 | ports:
21 | - 5432:5432
22 | options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5
23 |
24 | steps:
25 | - uses: actions/checkout@v3
26 |
27 | - name: Install Postgres Libraries
28 | run: |
29 | sudo apt-get install -yqq libpq-dev
30 |
31 | - name: Set up Ruby
32 | uses: ruby/setup-ruby@v1
33 | with:
34 | bundler-cache: true # runs 'bundle install' and caches installed gems
35 |
36 | - name: Set up database
37 | run: |
38 | bundle exec rake db:create
39 | bundle exec rake db:migrate --trace
40 |
41 | - name: Build and test
42 | run: bundle exec rake
43 |
--------------------------------------------------------------------------------
/app/assets/javascripts/awesome_react.js:
--------------------------------------------------------------------------------
1 | var CommentStore = {
2 | items: [],
3 | subscribers: [],
4 |
5 | subscribe: function(callback) {
6 | this.subscribers.push(callback);
7 | },
8 |
9 | unsubscribe: function(callback) {
10 | this.subscribers = this.subscribers.filter(subscriber => (subscriber !== callback));
11 | },
12 |
13 | notifySubscribers: function() {
14 | this.subscribers.map((subscriber) => {
15 | subscriber();
16 | });
17 | },
18 |
19 | getComments: function(projectId) {
20 | return this.items.filter(comment => comment.project_id == projectId);
21 | },
22 |
23 | setComments: function(comments, projectId) {
24 | if (projectId !== null) {
25 | this.items = this.items.filter(item => item.project_id != projectId);
26 | this.items = this.items.concat(comments);
27 |
28 | } else {
29 | this.items = comments;
30 | }
31 |
32 | this.notifySubscribers();
33 | },
34 |
35 | removeComment: function(commentId) {
36 | this.items = this.items.filter(item => item.id != commentId);
37 |
38 | this.notifySubscribers();
39 | }
40 | };
41 |
--------------------------------------------------------------------------------
/app/assets/stylesheets/_faq.scss:
--------------------------------------------------------------------------------
1 | .faq-wrapper {
2 | margin-right: 1.5em;
3 | margin-left: 1.5em;
4 |
5 | header {
6 | h1 {
7 | color: $base-font-color;
8 | font: bold 38px/44px $sans-serif;
9 | margin: 0;
10 | padding-bottom: 5px;
11 | text-align: center;
12 | text-transform: uppercase;
13 | }
14 | }
15 |
16 | .faq-answers {
17 | max-width: 45em;
18 |
19 | article {
20 | &:target {
21 | h3 {
22 | color: $pink;
23 | }
24 | }
25 |
26 | h3 {
27 | color: $base-font-color;
28 | font: normal 18px/22px $sans-serif;
29 | margin-bottom: 10px;
30 | margin-top: 40px;
31 | text-transform: uppercase;
32 | }
33 |
34 | p {
35 | color: $lighter-base-font-color;
36 | font: normal 14px/20px $sans-serif;
37 | }
38 |
39 | a {
40 | color: $pink;
41 | font: normal 14px/20px $sans-serif;
42 | text-decoration: none;
43 |
44 | &:hover {
45 | text-decoration: underline;
46 | }
47 | }
48 | }
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/db/migrate/20120214161129_extra_questions_on_applications.rb:
--------------------------------------------------------------------------------
1 | class ExtraQuestionsOnApplications < ActiveRecord::Migration[4.2]
2 | def up
3 | add_column :chapters, :extra_question_1, :string
4 | add_column :chapters, :extra_question_2, :string
5 | add_column :chapters, :extra_question_3, :string
6 | add_column :projects, :extra_question_1, :string
7 | add_column :projects, :extra_question_2, :string
8 | add_column :projects, :extra_question_3, :string
9 | add_column :projects, :extra_answer_1, :text
10 | add_column :projects, :extra_answer_2, :text
11 | add_column :projects, :extra_answer_3, :text
12 | end
13 |
14 | def down
15 | remove_column :projects, :extra_answer_3
16 | remove_column :projects, :extra_answer_2
17 | remove_column :projects, :extra_answer_1
18 | remove_column :projects, :extra_question_3
19 | remove_column :projects, :extra_question_2
20 | remove_column :projects, :extra_question_1
21 | remove_column :chapters, :extra_question_3
22 | remove_column :chapters, :extra_question_2
23 | remove_column :chapters, :extra_question_1
24 | end
25 | end
26 |
--------------------------------------------------------------------------------
/app/models/role.rb:
--------------------------------------------------------------------------------
1 | class Role < ApplicationRecord
2 | NAMES = %w(dean trustee)
3 |
4 | belongs_to :user
5 | belongs_to :chapter
6 |
7 | validates_uniqueness_of :user_id, :scope => :chapter_id
8 |
9 | validates :name, inclusion: { in: NAMES }
10 |
11 | def self.can_invite?
12 | where(:name => "dean").any?
13 | end
14 |
15 | def self.can_invite_to_chapter?(chapter)
16 | where(:name => "dean", :chapter_id => chapter).any?
17 | end
18 |
19 | def self.can_mark_winner?(project)
20 | where(:name => "dean", :chapter_id => project.chapter).any?
21 | end
22 |
23 | def self.can_edit_project?(project)
24 | where(:name => "dean", :chapter_id => project.chapter).any?
25 | end
26 |
27 | def self.can_manage_chapter?(chapter)
28 | where(:name => "dean", :chapter_id => chapter).any?
29 | end
30 |
31 | def self.can_manage_users?(chapter)
32 | where(:name => "dean", :chapter_id => chapter).any?
33 | end
34 |
35 | def self.can_view_finalists_for?(chapter)
36 | where(:chapter_id => chapter).any?
37 | end
38 |
39 | def trustee?
40 | true
41 | end
42 |
43 | def dean?
44 | name == "dean"
45 | end
46 | end
47 |
--------------------------------------------------------------------------------
/app/views/projects/_project_hidden.html.erb:
--------------------------------------------------------------------------------
1 |
2 |
3 | <%= link_to project.title, chapter_project_path(project.chapter, project), :class => "title" %>
4 | <% if local_assigns[:moderation].present? && project.project_moderation %>
5 | <%= render "projects/moderation", project: project %>
6 | <% end %>
7 |
8 |
9 |
16 |
17 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/spec/features/admin_exports_projects.feature:
--------------------------------------------------------------------------------
1 | Feature: Export projects
2 |
3 | In order to download projects
4 | As an Admin
5 | I want to export a CSV of projects
6 |
7 | Scenario: admin exports all projects
8 | Given I am logged in as an admin
9 | And a project was created on each of the last 7 days for a different chapter
10 | And a project was created on each of the last 7 days for any chapter
11 | When I visit a chapters projects page
12 | And I export all projects
13 | Then I should receive a CSV file with 14 projects
14 |
15 | Scenario: admin exports a date range of projects
16 | Given I am logged in as an admin
17 | And a project was created on each of the last 7 days for a different chapter
18 | And a project was created on each of the last 7 days for any chapter
19 | When I visit a chapters projects page
20 | And I filter to the last 1 days
21 | And I export all projects
22 | Then I should receive a CSV file with 4 projects
23 |
24 | Scenario: dean attempts to export all
25 | Given I am logged in as a dean
26 | When I visit a chapters projects page
27 | Then I should not see the export all link
28 |
--------------------------------------------------------------------------------
/app/views/invitations/new.html.erb:
--------------------------------------------------------------------------------
1 | <% provide(:page_title, t(".title")) %>
2 |
27 |
--------------------------------------------------------------------------------
/app/views/project_mailer/new_application.text.erb:
--------------------------------------------------------------------------------
1 | Hi <%= @project.name %>!
2 |
3 | <% if @project.chapter.submission_response_email.present? %>
4 | <%= @project.chapter.submission_response_email %>
5 | <% else %>
6 | <%= Chapter::DEFAULT_SUBMISSION_RESPONSE_EMAIL %>
7 | <% end %>
8 |
9 | Your application, for reference:
10 |
11 | Your name: <%= @project.name %>
12 | Your email: <%= @project.email %>
13 | Your phone number: <%= @project.phone %>
14 | Project title: <%= @project.title %>
15 | Project website: <%= @project.url %>
16 | Chapter: <%= @project.chapter.display_name %>
17 |
18 | About me:
19 | <%= @project.about_me %>
20 |
21 | About the project:
22 | <%= @project.about_project %>
23 |
24 | How you will use the money:
25 | <%= @project.use_for_money %>
26 |
27 | <% if @project.extra_question_1.present? -%>
28 | <%= @project.extra_question_1 %>:
29 | <%= @project.extra_answer_1 %>
30 |
31 | <% end -%>
32 | <% if @project.extra_question_2.present? -%>
33 | <%= @project.extra_question_2 %>:
34 | <%= @project.extra_answer_2 %>
35 |
36 | <% end -%>
37 | <% if @project.extra_question_3.present? -%>
38 | <%= @project.extra_question_3 %>:
39 | <%= @project.extra_answer_3 %>
40 | <% end -%>
41 |
--------------------------------------------------------------------------------
/public/blog/awesome_foundation/stylesheets/sass/bourbon/_bourbon.scss:
--------------------------------------------------------------------------------
1 | // Custom Functions
2 | @import "functions/deprecated-webkit-gradient";
3 | @import "functions/flex-grid";
4 | @import "functions/grid-width";
5 | @import "functions/linear-gradient";
6 | @import "functions/modular-scale";
7 | @import "functions/radial-gradient";
8 | @import "functions/render-gradients";
9 | @import "functions/tint-shade";
10 |
11 | // CSS3 Mixins
12 | @import "css3/animation";
13 | @import "css3/appearance";
14 | @import "css3/background-image";
15 | @import "css3/background-size";
16 | @import "css3/border-image";
17 | @import "css3/border-radius";
18 | @import "css3/box-shadow";
19 | @import "css3/box-sizing";
20 | @import "css3/columns";
21 | @import "css3/flex-box";
22 | @import "css3/inline-block";
23 | @import "css3/linear-gradient";
24 | @import "css3/radial-gradient";
25 | @import "css3/transform";
26 | @import "css3/transition";
27 | @import "css3/user-select";
28 |
29 | // Addons & other mixins
30 | @import "addons/button";
31 | @import "addons/clearfix";
32 | @import "addons/font-family";
33 | @import "addons/html5-input-types";
34 | @import "addons/position";
35 | @import "addons/timing-functions";
36 |
--------------------------------------------------------------------------------
/spec/views/layout_views_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | describe 'layouts/application' do
4 | before(:each) do
5 | controller.request.path_parameters[:controller] = "home"
6 | controller.request.path_parameters[:action] = "index"
7 | end
8 |
9 | context 'the html tag' do
10 | it 'includes the default language locale' do
11 | view.stubs(:signed_in?).returns(false)
12 |
13 | render
14 |
15 | expect(rendered).to have_selector('html[lang="en"]')
16 | end
17 |
18 | it 'includes an alternate language locale' do
19 | I18n.locale = 'fr'
20 |
21 | view.stubs(:signed_in?).returns(false)
22 |
23 | render
24 |
25 | expect(rendered).to have_selector('html[lang="fr"]')
26 | end
27 | end
28 |
29 | context 'the header' do
30 | it 'includes all of the alternate language versions including itself' do
31 | view.stubs(:signed_in?).returns(false)
32 |
33 | render
34 |
35 | # Can't figure out why have_selector isn't working here
36 | I18n.available_locales.each do |locale|
37 | expect(rendered).to include("rel=\"alternate\" hreflang=\"#{locale}\"")
38 | end
39 | end
40 | end
41 | end
42 |
--------------------------------------------------------------------------------
/app/views/projects/_image_upload.html.erb:
--------------------------------------------------------------------------------
1 |
2 | <%= render partial: "projects/image_form", locals: { form: form, upload_mechanism: :s3, image_notes: local_assigns[:image_notes] } %>
3 |
4 |
5 | <%= form.simple_fields_for :photos, Photo.new do |photo_fields| %>
6 | <%= render "projects/image_form_element", photo: Photo.new, f: photo_fields %>
7 | <% end %>
8 |
9 |
10 |
11 |
12 | <% if form.object.photos.present? %>
13 | <% form.object.photos.each do |photo| %>
14 | <%= form.simple_fields_for :photos, photo do |photo_fields| %>
15 | <%= render "projects/image_form_element", photo: photo, f: photo_fields %>
16 | <% end %>
17 | <% end %>
18 | <% end %>
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/config/initializers/content_security_policy.rb:
--------------------------------------------------------------------------------
1 | # Be sure to restart your server when you modify this file.
2 |
3 | # Define an application-wide content security policy.
4 | # See the Securing Rails Applications Guide for more information:
5 | # https://guides.rubyonrails.org/security.html#content-security-policy-header
6 |
7 | # Rails.application.configure do
8 | # config.content_security_policy do |policy|
9 | # policy.default_src :self, :https
10 | # policy.font_src :self, :https, :data
11 | # policy.img_src :self, :https, :data
12 | # policy.object_src :none
13 | # policy.script_src :self, :https
14 | # policy.style_src :self, :https
15 | # # Specify URI for violation reports
16 | # # policy.report_uri "/csp-violation-report-endpoint"
17 | # end
18 | #
19 | # # Generate session nonces for permitted importmap, inline scripts, and inline styles.
20 | # config.content_security_policy_nonce_generator = ->(request) { request.session.id.to_s }
21 | # config.content_security_policy_nonce_directives = %w(script-src style-src)
22 | #
23 | # # Report violations without enforcing the policy.
24 | # # config.content_security_policy_report_only = true
25 | # end
26 |
--------------------------------------------------------------------------------
/spec/features/step_definitions/role_steps.rb:
--------------------------------------------------------------------------------
1 | step 'I promote the trustee to dean' do
2 | visit(chapter_users_path(@trustee_chapter))
3 | page.find(:css, "span[data-role-id='#{@trustee_role.id}'] a.promote-user").click
4 | end
5 |
6 | step 'I demote the dean to trustee' do
7 | visit(chapter_users_path(@dean_chapter))
8 | page.find(:css, "span[data-role-id='#{@dean_role.id}'] a.demote-user").click
9 | end
10 |
11 | step 'I should see the new trustee' do
12 | expect(page).to have_css("span[data-role-id='#{@dean_role.id}'] a.promote-user")
13 | end
14 |
15 | step 'I should see the new dean' do
16 | expect(page).to have_css("span[data-role-id='#{@trustee_role.id}'] a.demote-user")
17 | end
18 |
19 | step 'I try to promote a user' do
20 | visit(chapter_users_path(@trustee_chapter))
21 | end
22 |
23 | step 'I should not see promotion links' do
24 | expect(page).to have_no_css(".demote-user")
25 | expect(page).to have_no_css(".promote-user")
26 | end
27 |
28 | step 'I am a trustee for another chapter as well' do
29 | @other_current_chapter = FactoryBot.create(:chapter)
30 | FactoryBot.create(:role, :chapter => @other_current_chapter,
31 | :user => @current_user)
32 | end
33 |
--------------------------------------------------------------------------------
/spec/views/finalists_views_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | describe 'finalists/index' do
4 | let!(:user) { FactoryBot.create(:user_with_dean_role) }
5 | let!(:project1) { FactoryBot.create(:project, chapter: user.chapters.first) }
6 | let!(:project2) { FactoryBot.create(:project) }
7 |
8 | before(:each) do
9 | controller.request.params[:chapter_id] = project1.chapter
10 | end
11 |
12 | describe 'when a project from another chapter has votes from our trustees' do
13 | it 'displays the name of the other chapter next to that project title' do
14 | Vote.create(user: user, project: project1, chapter: project1.chapter)
15 | Vote.create(user: user, project: project2, chapter: project1.chapter)
16 |
17 | assign(:chapter, project1.chapter)
18 | assign(:projects, Project.with_votes_for_chapter(project1.chapter).by_vote_count)
19 | view.stubs(:current_user).returns(user)
20 |
21 | render
22 |
23 | expect(rendered).not_to have_css("tr[data-id=\"#{project1.id}\"] td em", text: project1.chapter.display_name)
24 | expect(rendered).to have_css("tr[data-id=\"#{project2.id}\"] td em", text: project2.chapter.display_name)
25 | end
26 | end
27 | end
28 |
--------------------------------------------------------------------------------
/app/assets/stylesheets/_finalists.scss:
--------------------------------------------------------------------------------
1 | body.finalists-index {
2 | section.container {
3 | @extend .clearfix;
4 | }
5 |
6 | @media all and (max-width: $maximum-width) {
7 | section.container {
8 | margin-top: 0.5em !important;
9 | }
10 | }
11 | }
12 |
13 | section.applications {
14 | table {
15 | font-family: $sans-serif;
16 | font-size: 0.8em;
17 |
18 | tr {
19 | td, th {
20 | &:first-child {
21 | width: 75%;
22 | }
23 |
24 | &:nth-child(2) {
25 | width: 15%;
26 | }
27 |
28 | &:nth-child(3) {
29 | width: 10%;
30 | }
31 |
32 | &.vote-count {
33 | text-align: center;
34 | }
35 |
36 | a {
37 | font-weight: bold;
38 | color: rgb(55,55,55);
39 | text-decoration: none;
40 |
41 | &:hover {
42 | color: $pink;
43 | }
44 | }
45 | .winner {
46 | color: $pink;
47 | }
48 | .sorted:after {
49 | content: ' \21c5';
50 | }
51 |
52 | }
53 | th {
54 | white-space: nowrap;
55 | }
56 | }
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/app/controllers/subdomains_controller.rb:
--------------------------------------------------------------------------------
1 | class SubdomainsController < ApplicationController
2 | before_action :find_chapter
3 |
4 | def chapter
5 | if @chapter
6 | redirect_to(chapter_url(@chapter.slug, url_parts), allow_other_host: true)
7 |
8 | else
9 | redirect_to(root_url(url_parts), allow_other_host: true)
10 | end
11 | end
12 |
13 | def apply
14 | redirect_to(new_submission_url({ chapter: @chapter }.merge(url_parts)), allow_other_host: true)
15 | end
16 |
17 | def canonical
18 | redirect_to({ locale: nil }.merge(url_parts), status: :moved_permanently, allow_other_host: true)
19 | end
20 |
21 | protected
22 |
23 | def url_parts
24 | if ENV['CANONICAL_HOST'].present?
25 | { host: ENV['CANONICAL_HOST'] }
26 | else
27 | { subdomain: @subdomain }
28 | end
29 | end
30 |
31 | def find_chapter
32 | subdomains = request.subdomains
33 | subdomain = subdomains.shift
34 |
35 | begin
36 | @chapter = Chapter.find(subdomain)
37 | I18n.locale = @chapter.locale
38 |
39 | rescue ActiveRecord::RecordNotFound
40 | @chapter = nil
41 | end
42 |
43 | @subdomain = subdomains.unshift("www").join(".")
44 | end
45 | end
46 |
--------------------------------------------------------------------------------
/app/views/winners/_form.html.erb:
--------------------------------------------------------------------------------
1 | <%= hidden_field_tag :return_to, params[:return_to] %>
2 |
3 | <%= form.input :chapter_id, collection: winnable_chapters_for(form.object), label: t(".chapter_id"), include_blank: false, disabled: !(form.object.in_any_chapter? || current_user.admin?), hint: t(".hints.chapter_id") %>
4 |
5 |
6 | <%= form.input :title, maxlength: 50 %>
7 | <%= render partial: "projects/funded_date", locals: { form: form, required: true, hint: t(".hints.funded_on") } %>
8 |
9 | <%= render partial: "projects/image_upload", locals: { form: form, image_notes: t(".image-notes") } %>
10 |
11 | <%= form.input :funded_description, required: true %>
12 |
13 |
14 | <%= form.input :name, label: t(".name") %>
15 | <%= form.input :url %>
16 | <%= form.input :rss_feed_url %>
17 |
18 |
19 | <% content_for :javascript do %>
20 | <%= javascript_include_tag "https://releases.transloadit.com/uppy/v3.2.1/uppy.min.js" %>
21 | <% end %>
22 |
23 | <% content_for :head do %>
24 | <%= stylesheet_link_tag "https://releases.transloadit.com/uppy/v3.2.1/uppy.min.css" %>
25 | <% end %>
26 |
--------------------------------------------------------------------------------
/spec/features/admin_manages_promotions.feature:
--------------------------------------------------------------------------------
1 | Feature: Manage Promotions
2 | As an admin I can modify roles and admin status
3 | In order to promote a trustee to a dean or admin
4 |
5 | @javascript
6 | Scenario: As an admin, I can promote a trustee to an admin
7 | Given I am logged in as an admin
8 | And there is a trustee in the system
9 | When I promote the trustee to admin
10 | Then I should see the new admin
11 |
12 | @javascript
13 | Scenario: As an admin, I can promote a trustee of a chapter to be a dean
14 | Given I am logged in as an admin
15 | And there is a trustee in the system
16 | When I promote the trustee to dean
17 | Then I should see the new dean
18 |
19 | @javascript
20 | Scenario: As an admin, I can demote dean back to trustee
21 | Given I am logged in as an admin
22 | And there is a dean in the system
23 | When I demote the dean to trustee
24 | Then I should see the new trustee
25 |
26 | @javascript
27 | Scenario: As an admin, I can remove trustee from chapter
28 | Given I am logged in as an admin
29 | And there is a trustee in the system
30 | When I remove trustee from a chapter
31 | Then I should see the deactivated user
32 |
--------------------------------------------------------------------------------
/spec/controllers/users_controller_spec.rb:
--------------------------------------------------------------------------------
1 | require 'spec_helper'
2 |
3 | describe UsersController, type: :controller do
4 | context "signed in as admin user" do
5 | render_views
6 |
7 | let(:user) { FactoryBot.create(:user, :admin => true) }
8 | before do
9 | sign_in_as user
10 | end
11 |
12 | context "fetching an HTML file" do
13 | before { get :index }
14 | it { is_expected.to respond_with(:success) }
15 | it { should render_template("index") }
16 | end
17 |
18 | context "fetching a CSV file" do
19 | before { get :index, format: "csv" }
20 | it { is_expected.to respond_with(:success) }
21 | it { should render_template("index") }
22 | end
23 | end
24 | context "signed in as non-admin user" do
25 | let(:role) { FactoryBot.create(:role) }
26 | let(:user) { role.user }
27 | let(:chapter) { role.chapter }
28 | before do
29 | sign_in_as user
30 | get :index
31 | end
32 | it { is_expected.to redirect_to(chapter_users_path(chapter)) }
33 | end
34 | context "signed out" do
35 | before do
36 | sign_out
37 | get :index
38 | end
39 | it { is_expected.to redirect_to(sign_in_path) }
40 | end
41 | end
42 |
--------------------------------------------------------------------------------
/app/controllers/comments_controller.rb:
--------------------------------------------------------------------------------
1 | class CommentsController < ApplicationController
2 | before_action :must_be_logged_in
3 | before_action :find_project
4 |
5 | def create
6 | @comment = @project.comments.build(comment_params)
7 | @comment.user = current_user
8 |
9 | if @comment.save
10 | @comments = @project.comments.viewable_by(user: current_user, chapter: @project.chapter).by_date
11 |
12 | render json: { comments: @comments, project_id: @project.id }
13 | else
14 | render status: 400, json: { message: @comment.errors.full_messages.join(", ") }
15 | end
16 | end
17 |
18 | def destroy
19 | @comment = @project.comments.find(params[:id])
20 |
21 | unless current_user == @comment.user || current_user.can_edit_project?(@project)
22 | head :forbidden and return
23 | end
24 |
25 | if @comment.destroy
26 | head :ok
27 | else
28 | render status: 400, json: { message: @comment.errors.full_messages.join(", ") }
29 | end
30 | end
31 |
32 | private
33 |
34 | def find_project
35 | @project = Project.find(params[:project_id])
36 | end
37 |
38 | def comment_params
39 | params.require(:comment).permit(:viewable_by, :body)
40 | end
41 | end
42 |
--------------------------------------------------------------------------------