├── .codeclimate.yml ├── .dockerignore ├── .github ├── FUNDING.yml ├── dependabot.yml └── workflows │ └── ruby.yml ├── .gitignore ├── .rspec ├── .rubocop.yml ├── .ruby-version ├── CONTRIBUTING.md ├── Dockerfile ├── Gemfile ├── Gemfile.lock ├── ISSUE_TEMPLATE.md ├── LICENSE ├── Makefile ├── Procfile ├── README.md ├── Rakefile ├── app ├── assets │ ├── config │ │ └── manifest.js │ ├── images │ │ ├── .keep │ │ ├── GitHub_Logo_White.png │ │ ├── Icon-128.png │ │ ├── Icon-196.png │ │ ├── benevity-logo.png │ │ ├── bg.jpg │ │ ├── codebar-girl.gif │ │ ├── codebar-stories-banner.png │ │ ├── collaboration.png │ │ ├── favicon.ico │ │ ├── festival │ │ │ └── codebar-festival-logo-light.png │ │ ├── give-as-you-live.png │ │ ├── how-to-support-us │ │ │ ├── become-a-coach.jpg │ │ │ ├── become-an-organiser.jpg │ │ │ ├── codebar-festival-2023.jpg │ │ │ ├── hackney-half.jpeg │ │ │ └── volunteer.jpg │ │ ├── logo-square.png │ │ ├── logo.png │ │ ├── nyc-workshop.jpg │ │ ├── ok.png │ │ ├── open-collective-logo.png │ │ ├── sponsors │ │ │ ├── 8th-Light.png │ │ │ ├── StreetTeam.png │ │ │ ├── bloomberg.png │ │ │ ├── gds-logo.png │ │ │ ├── google.png │ │ │ ├── mozilla.png │ │ │ ├── pivotal.png │ │ │ ├── shutl_logo.png │ │ │ ├── softwire.png │ │ │ ├── the-guardian.png │ │ │ ├── ticketmaster.png │ │ │ └── ustwo.png │ │ ├── star-rating.gif │ │ ├── twitter-summary-card-image.png │ │ └── uncodebar-group.jpeg │ ├── javascripts │ │ ├── analytics.js │ │ ├── application.js │ │ ├── gosquared.js │ │ ├── invitations.js │ │ ├── jsimple-star-rating.min.js │ │ ├── payments.js │ │ └── subscriptions-toggle.js │ └── stylesheets │ │ ├── _bootstrap-custom.scss │ │ ├── animations.scss │ │ ├── application.scss │ │ ├── email.css │ │ ├── main.scss │ │ └── partials │ │ ├── _colors.sass │ │ ├── _hero.scss │ │ ├── _layout.scss │ │ ├── _screen_readers.scss │ │ ├── _social_media.scss │ │ └── _star-rating.scss ├── controllers │ ├── admin │ │ ├── announcements_controller.rb │ │ ├── application_controller.rb │ │ ├── bans_controller.rb │ │ ├── chapters │ │ │ ├── feedback_controller.rb │ │ │ └── organisers_controller.rb │ │ ├── chapters_controller.rb │ │ ├── contacts_controller.rb │ │ ├── events_controller.rb │ │ ├── feedback_controller.rb │ │ ├── groups_controller.rb │ │ ├── invitation_controller.rb │ │ ├── invitations_controller.rb │ │ ├── meeting_invitations_controller.rb │ │ ├── meetings_controller.rb │ │ ├── member_notes_controller.rb │ │ ├── members_controller.rb │ │ ├── portal_controller.rb │ │ ├── sponsors_controller.rb │ │ ├── testimonials_controller.rb │ │ └── workshops_controller.rb │ ├── application_controller.rb │ ├── auth_services_controller.rb │ ├── auth_sessions_controller.rb │ ├── chapter_controller.rb │ ├── concerns │ │ ├── admin │ │ │ ├── sponsor_concerns.rb │ │ │ └── workshop_concerns.rb │ │ ├── invitation_controller_concerns.rb │ │ ├── mailing_list_concerns.rb │ │ ├── member_concerns.rb │ │ └── workshop_invitation_concerns.rb │ ├── contact_preferences_controller.rb │ ├── dashboard_controller.rb │ ├── donations_controller.rb │ ├── events_controller.rb │ ├── feedback_controller.rb │ ├── invitation_controller.rb │ ├── invitations_controller.rb │ ├── mailing_lists_controller.rb │ ├── meetings_controller.rb │ ├── member │ │ └── details_controller.rb │ ├── members_controller.rb │ ├── pages_controller.rb │ ├── payments_controller.rb │ ├── sponsors_controller.rb │ ├── subscriptions_controller.rb │ ├── super_admin │ │ └── application_controller.rb │ ├── terms_and_conditions_controller.rb │ ├── waiting_lists_controller.rb │ └── workshops_controller.rb ├── form_models │ ├── mailing_list_form.rb │ └── terms_and_conditions_form.rb ├── helpers │ ├── README.md │ ├── application_helper.rb │ ├── email_header_helper.rb │ ├── email_helper.rb │ └── event_helper.rb ├── jobs │ └── application_job.rb ├── mailers │ ├── application_mailer.rb │ ├── contact_mailer.rb │ ├── event_invitation_mailer.rb │ ├── feedback_request_mailer.rb │ ├── meeting_invitation_mailer.rb │ ├── member_mailer.rb │ ├── virtual_workshop_invitation_mailer.rb │ └── workshop_invitation_mailer.rb ├── models │ ├── README.md │ ├── address.rb │ ├── announcement.rb │ ├── application_record.rb │ ├── attendance_warning.rb │ ├── auth_service.rb │ ├── ban.rb │ ├── chapter.rb │ ├── concerns │ │ ├── .keep │ │ ├── date_time_concerns.rb │ │ ├── invitable.rb │ │ ├── invitation_concerns.rb │ │ ├── listable.rb │ │ ├── permissions.rb │ │ └── workshop_invitation_manager_concerns.rb │ ├── contact.rb │ ├── eligibility_inquiry.rb │ ├── event.rb │ ├── feedback.rb │ ├── feedback_request.rb │ ├── group.rb │ ├── group_announcement.rb │ ├── invitation.rb │ ├── invitation_manager.rb │ ├── meeting.rb │ ├── meeting_invitation.rb │ ├── meeting_talk.rb │ ├── member.rb │ ├── member_note.rb │ ├── permission.rb │ ├── role.rb │ ├── sponsor.rb │ ├── sponsors_search.rb │ ├── sponsorship.rb │ ├── subscription.rb │ ├── testimonial.rb │ ├── tutorial.rb │ ├── waiting_list.rb │ ├── workshop.rb │ ├── workshop_calendar.rb │ ├── workshop_invitation.rb │ └── workshop_sponsor.rb ├── policies │ ├── admin_portal_policy.rb │ ├── application_policy.rb │ ├── chapter_policy.rb │ ├── contact_policy.rb │ ├── event_policy.rb │ ├── group_policy.rb │ ├── member_note_policy.rb │ ├── organiser_policy.rb │ ├── sponsor_policy.rb │ ├── testimonial_policy.rb │ └── workshop_policy.rb ├── presenters │ ├── address_presenter.rb │ ├── base_presenter.rb │ ├── chapter_presenter.rb │ ├── contact_presenter.rb │ ├── event_presenter.rb │ ├── invitation_presenter.rb │ ├── meeting_presenter.rb │ ├── member_presenter.rb │ ├── sponsor_presenter.rb │ ├── virtual_workshop_presenter.rb │ ├── waiting_list_presenter.rb │ └── workshop_presenter.rb ├── services │ └── auditor.rb ├── uploaders │ ├── avatar_uploader.rb │ └── image_uploader.rb └── views │ ├── admin │ ├── announcements │ │ ├── edit.html.haml │ │ ├── index.html.haml │ │ └── new.html.haml │ ├── attendance_warnings │ │ └── _attendance_warning.html.haml │ ├── bans │ │ ├── _ban.html.haml │ │ └── new.html.haml │ ├── chapters │ │ ├── edit.html.haml │ │ ├── new.html.haml │ │ ├── organisers │ │ │ └── index.html.haml │ │ └── show.html.haml │ ├── contacts │ │ └── index.html.haml │ ├── eligibility_inquiries │ │ └── _eligibility_inquiry.html.haml │ ├── events │ │ ├── _attendances.html.haml │ │ ├── _event.html.haml │ │ ├── _form.html.haml │ │ ├── _invitation_management.html.haml │ │ ├── edit.html.haml │ │ ├── new.html.haml │ │ └── show.html.haml │ ├── feedback │ │ └── index.html.haml │ ├── groups │ │ ├── new.html.haml │ │ └── show.html.haml │ ├── meetings │ │ ├── _form.html.haml │ │ ├── _invitation_management.html.haml │ │ ├── _meeting.html.haml │ │ ├── edit.html.haml │ │ ├── new.html.haml │ │ └── show.html.haml │ ├── member_notes │ │ └── _member_note.html.haml │ ├── members │ │ ├── _actions.html.haml │ │ ├── _note.html.haml │ │ ├── _profile.html.haml │ │ ├── events.html.haml │ │ ├── index.html.haml │ │ └── show.html.haml │ ├── portal │ │ ├── guide.html.haml │ │ └── index.html.haml │ ├── shared │ │ └── _title.html.haml │ ├── sponsors │ │ ├── _contact_fields.html.haml │ │ ├── _form.html.haml │ │ ├── edit.html.haml │ │ ├── index.html.haml │ │ ├── new.html.haml │ │ └── show.html.haml │ ├── subscriptions │ │ └── _index.html.haml │ ├── testimonials │ │ └── index.html.haml │ ├── workshop │ │ ├── _attendances.html.haml │ │ └── _waiting_list.html.haml │ └── workshops │ │ ├── _activity.html.haml │ │ ├── _edit_form.html.haml │ │ ├── _form.html.haml │ │ ├── _invitation_management.html.haml │ │ ├── _shared_form.html.haml │ │ ├── _virtual_workshop_fields.html.haml │ │ ├── _workshop.html.haml │ │ ├── changes.html.haml │ │ ├── edit.html.haml │ │ ├── index.html.haml │ │ ├── new.html.haml │ │ ├── send_invites.html.haml │ │ └── show.html.haml │ ├── chapter │ ├── _subscriptions.html.haml │ └── show.html.haml │ ├── coach │ └── _coach.html.haml │ ├── contact_mailer │ └── subscription_notification.html.haml │ ├── contact_preferences │ └── show.html.haml │ ├── dashboard │ ├── attendance_policy.html.haml │ ├── code.html.haml │ ├── dashboard.html.haml │ ├── effective-teacher-guide.html.haml │ ├── faq.html.haml │ ├── participant_guide.html.haml │ ├── show.html.haml │ └── wall_of_fame.html.haml │ ├── errors │ ├── error.html.haml │ └── not_found.html.haml │ ├── event_invitation_mailer │ ├── attending.html.haml │ ├── invite_coach.html.haml │ └── invite_student.html.haml │ ├── events │ ├── _event.html.haml │ ├── _event_actions.html.haml │ ├── _event_sponsors.html.haml │ ├── _events.html.haml │ ├── _faq.html.haml │ ├── index.html.haml │ └── show.html.haml │ ├── feedback │ └── show.html.haml │ ├── feedback_request_mailer │ └── request_feedback.html.haml │ ├── invitation │ ├── _coach.html.haml │ ├── _student.html.haml │ ├── _waiting_list.html.haml │ └── show.html.haml │ ├── invitations │ ├── index.html.haml │ └── show.html.haml │ ├── layouts │ ├── _admin_menu.html.haml │ ├── _footer.html.haml │ ├── _member_menu.html.haml │ ├── _messages.html.haml │ ├── _meta.html.haml │ ├── _navigation.html.haml │ ├── _organiser_menu.html.haml │ ├── application.html.haml │ ├── email.html.erb │ ├── mailer.html.erb │ └── mailer.text.erb │ ├── meeting_invitation_mailer │ ├── _agenda.html.haml │ ├── _cancel_attendance.html.haml │ ├── approve_from_waitlist.html.haml │ ├── attendance_reminder.html.haml │ ├── attending.html.haml │ └── invite.html.haml │ ├── meetings │ ├── _meeting.html.haml │ ├── _meeting_actions.html.haml │ └── show.html.haml │ ├── member │ └── details │ │ └── edit.html.haml │ ├── member_mailer │ ├── attendance_warning.html.haml │ ├── ban.html.haml │ ├── eligibility_check.html.haml │ ├── welcome_coach.html.haml │ └── welcome_student.html.haml │ ├── members │ ├── _avatar_listing.html.haml │ ├── _coach_invite_subscriptions.html.haml │ ├── _new.html.haml │ ├── _organisers_grid.html.haml │ ├── _student_invite_subscriptions.html.haml │ ├── _testimonials.html.haml │ ├── edit.html.haml │ ├── new.html.haml │ ├── show.html.haml │ └── step2.html.haml │ ├── pages │ ├── breach-code-of-conduct.html.haml │ ├── codebar-stories-podcast.html.haml │ ├── cookie-policy.html.haml │ ├── how-to-support-us.html.haml │ └── privacy-policy.html.haml │ ├── public_activity │ └── sponsor │ │ ├── _admin_contact_subscribe.html.haml │ │ ├── _admin_contact_unsubscribe.html.haml │ │ ├── _contact_subscribe.html.haml │ │ └── _contact_unsubscribe.html.haml │ ├── shared │ ├── _announcements.html.haml │ ├── _donation_platforms.html.haml │ ├── _festival_banner.html.haml │ ├── _newsletter.html.haml │ ├── _pagination.html.haml │ ├── _social_media.html.haml │ ├── _sponsors.html.haml │ └── _venue.html.haml │ ├── shared_mailers │ ├── _body_header.html.haml │ ├── _footer.html.haml │ ├── _header.html.haml │ ├── _social.html.haml │ └── _venue.html.haml │ ├── sponsors │ └── index.html.haml │ ├── subscriptions │ └── index.html.haml │ ├── terms_and_conditions │ └── show.html.haml │ ├── virtual_workshop_invitation_mailer │ ├── _how_to_join_info.html.haml │ ├── attending.html.haml │ ├── attending_reminder.html.haml │ ├── invite_coach.html.haml │ ├── invite_student.html.haml │ └── waiting_list_reminder.html.haml │ ├── virtual_workshops │ ├── _meta_tags.html.haml │ └── show.html.haml │ ├── workshop_invitation_mailer │ ├── attending.html.haml │ ├── attending_reminder.html.haml │ ├── invite_coach.html.haml │ ├── invite_student.html.haml │ ├── notify_waiting_list.html.haml │ └── waiting_list_reminder.html.haml │ └── workshops │ ├── _actions.html.haml │ ├── _meta_tags.html.haml │ ├── _workshop.html.haml │ └── show.html.haml ├── bin ├── bundle ├── dadmin ├── ddown ├── delayed_job ├── dexec ├── drails ├── drake ├── drspec ├── dserver ├── dstart ├── dstop ├── dup ├── rails ├── rake ├── setup └── update ├── config.ru ├── config ├── application.rb ├── boot.rb ├── database.yml ├── environment.rb ├── environments │ ├── development.rb │ ├── production.rb │ └── test.rb ├── initializers │ ├── application_controller_renderer.rb │ ├── assets.rb │ ├── backtrace_silencers.rb │ ├── carrier_wave.rb │ ├── commonmarker.rb │ ├── content_security_policy.rb │ ├── cookies_serializer.rb │ ├── delayed_job.rb │ ├── filter_parameter_logging.rb │ ├── flodesk.rb │ ├── haml_markdown.rb │ ├── inflections.rb │ ├── locale.rb │ ├── mime_types.rb │ ├── new_framework_defaults_5_2.rb │ ├── new_framework_defaults_6_1.rb │ ├── new_framework_defaults_7_0.rb │ ├── omniauth.rb │ ├── pagy.rb │ ├── permissions_policy.rb │ ├── premailer.rb │ ├── rolify.rb │ ├── rollbar.rb │ ├── secret_token.rb │ ├── session_store.rb │ ├── simple_form.rb │ ├── simple_form_bootstrap.rb │ ├── stripe.rb │ ├── twitter.rb │ └── wrap_parameters.rb ├── locales │ ├── admin.de.yml │ ├── admin.en.yml │ ├── admin.en_AU.yml │ ├── admin.en_GB.yml │ ├── admin.en_US.yml │ ├── admin.es.yml │ ├── admin.fi.yml │ ├── admin.fr.yml │ ├── admin.no.yml │ ├── de.yml │ ├── en.rb │ ├── en.yml │ ├── en_AU.yml │ ├── en_GB.yml │ ├── en_US.yml │ ├── es.yml │ ├── fi.yml │ ├── fr.yml │ ├── no.yml │ ├── simple_form.de.yml │ ├── simple_form.en.yml │ └── simple_form.fr.yml ├── newrelic.yml ├── puma.rb ├── routes.rb └── storage.yml ├── crowdin.yml ├── db ├── migrate │ ├── 20131017221407_create_members.rb │ ├── 20131020223957_create_sessions.rb │ ├── 20131020235644_create_invitations.rb │ ├── 20131021011352_add_token_to_invitation.rb │ ├── 20131021011859_add_index_to_invitation_token.rb │ ├── 20131021040356_add_unsubscribed_to_member.rb │ ├── 20131021182241_add_seats_to_session.rb │ ├── 20131024223507_create_roles.rb │ ├── 20131024224307_create_member_role.rb │ ├── 20131029210620_create_courses.rb │ ├── 20131102132756_create_sponsors.rb │ ├── 20131102141049_create_address.rb │ ├── 20131103174325_create_sponsor_sessions.rb │ ├── 20131103210723_rename_invitations_to_session_invitations.rb │ ├── 20131103212835_create_course_invitations.rb │ ├── 20131104030726_create_reminders.rb │ ├── 20131107182457_add_avatar_to_sponsor.rb │ ├── 20131110220757_add_website_to_sponsor.rb │ ├── 20131111024701_add_role_to_session_invitations.rb │ ├── 20131112221451_remove_seats_from_sessions.rb │ ├── 20131112221641_add_seats_to_sponsor.rb │ ├── 20131130211001_create_tutorials.rb │ ├── 20131130211305_create_feedbacks.rb │ ├── 20131201091346_rename_tutorials_table_name_column_to_title.rb │ ├── 20131208030221_create_meetings.rb │ ├── 20131208030336_create_meeting_talks.rb │ ├── 20131208141447_create_auth_services.rb │ ├── 20131208145950_add_can_log_in_to_users.rb │ ├── 20131221204400_add_token_to_feedbacks.rb │ ├── 20131222160002_add_rating_to_feedbacks.rb │ ├── 20140119093708_create_feedback_requests.rb │ ├── 20140202112853_remove_token_from_feedbacks.rb │ ├── 20140329201235_add_phone_number_to_members.rb │ ├── 20140403004924_create_course_tutors.rb │ ├── 20140417151614_add_name_to_meeting.rb │ ├── 20140417152406_add_description_to_meeting.rb │ ├── 20140417154809_add_slug_to_meeting.rb │ ├── 20140425155706_add_host_to_course.rb │ ├── 20140425160722_add_ticket_url_to_course.rb │ ├── 20140501015844_add_verified_to_member.rb │ ├── 20140504143819_create_job.rb │ ├── 20140504171455_add_company_to_job.rb │ ├── 20140510232842_add_invitable_to_session.rb │ ├── 20140510234035_add_city_to_address.rb │ ├── 20140610130020_create_chapters.rb │ ├── 20140610133755_create_groups.rb │ ├── 20140610155915_create_subscriptions.rb │ ├── 20140610202421_add_chapter_to_session.rb │ ├── 20140610212001_add_time_to_sessions.rb │ ├── 20140611191143_rolify_create_permissions.rb │ ├── 20140615010338_add_chapter_to_course.rb │ ├── 20140615030540_add_avatar_cache_to_sponsor.rb │ ├── 20140621234319_add_email_to_chapter.rb │ ├── 20140708114919_add_number_of_coaches_to_sponsor.rb │ ├── 20140824234126_drop_reminders.rb │ ├── 20140825005743_add_reminder_at_to_session_invitations.rb │ ├── 20140828194906_create_waiting_lists.rb │ ├── 20140908151822_add_twitter_handle_and_id_to_chapter.rb │ ├── 20140916134752_remove_verified_from_user.rb │ ├── 20141003172945_create_testimonials.rb │ ├── 20141003195205_change_testimonial_string_to_text.rb │ ├── 20141022052135_add_welcome_fields_to_member.rb │ ├── 20141203000909_create_events.rb │ ├── 20141203004824_create_sponsorships.rb │ ├── 20141203012421_add_slug_to_event.rb │ ├── 20141203034740_add_schedule_to_event.rb │ ├── 20141204011642_create_invitations_2.rb │ ├── 20141204164936_add_token_to_invitation_2.rb │ ├── 20141204173228_add_student_and_coach_spaces_to_event.rb │ ├── 20141204181137_add_coach_and_student_questionnaire_to_event.rb │ ├── 20141204181517_add_verified_and_verified_by_to_invitation.rb │ ├── 20141204221303_add_coach_description_to_event.rb │ ├── 20141204232033_add_info_to_event.rb │ ├── 20150130001852_create_member_notes.rb │ ├── 20150211023345_add_rsvp_close_time_to_sessions.rb │ ├── 20150219223111_add_slug_to_chapter.rb │ ├── 20150222110321_add_announce_only_to_event.rb │ ├── 20150224001247_add_mailing_list_id_to_group.rb │ ├── 20150328102113_add_invitable_to_event.rb │ ├── 20150409140851_create_announcements.rb │ ├── 20150409145541_create_group_announcements.rb │ ├── 20150418235316_create_bans.rb │ ├── 20150419004358_create_delayed_jobs.rb │ ├── 20150505133258_add_tito_url_to_event.rb │ ├── 20150505161414_create_chapters_events.rb │ ├── 20150508211109_add_contacts_to_sponsors.rb │ ├── 20150509200835_create_contacts.rb │ ├── 20150629202748_create_eligibility_inquiries.rb │ ├── 20150714194446_create_attendance_warnings.rb │ ├── 20150725165534_create_member_contacts.rb │ ├── 20150801134457_add_map_coords_to_address.rb │ ├── 20150814042120_add_show_faq_to_events.rb │ ├── 20150823215449_acts_as_taggable_on_migration.acts_as_taggable_on_engine.rb │ ├── 20150823215450_add_missing_unique_indices.acts_as_taggable_on_engine.rb │ ├── 20150823215451_add_taggings_counter_cache_to_tags.acts_as_taggable_on_engine.rb │ ├── 20150823215452_add_missing_taggable_index.acts_as_taggable_on_engine.rb │ ├── 20150823215453_change_collation_for_tag_names.acts_as_taggable_on_engine.rb │ ├── 20151110180108_add_togglable_fields_to_event.rb │ ├── 20160123192121_add_approve_by_to_job.rb │ ├── 20160124024112_add_preferred_pronoun_to_member.rb │ ├── 20160124225727_add_active_to_chapter.rb │ ├── 20160201210920_change_meeting_fields.rb │ ├── 20160207151405_create_meeting_invitation.rb │ ├── 20160211182925_change_meeting_description_to_text.rb │ ├── 20160228102639_change_preferred_pronoun_to_pronouns_in_member.rb │ ├── 20160306231907_rename_table_sessions_to_workshop.rb │ ├── 20160306234034_rename_session_ids_to_workshop_ids.rb │ ├── 20160307015747_rename_sponsor_sessions_to_workshop_sponsors.rb │ ├── 20160307223728_rename_permissions_resource_type_value_to_workshop.rb │ ├── 20160320164227_add_attended_to_meeting_invitation.rb │ ├── 20160326003113_add_more_data_to_bans.rb │ ├── 20160424081653_create_chapters_meetings.rb │ ├── 20160424175400_add_invited_flag_to_meetings.rb │ ├── 20160523171604_add_external_event_link_to_event.rb │ ├── 20160523173346_add_more_fields_to_events.rb │ ├── 20160526182452_add_rsvp_time_to_session_invitation.rb │ ├── 20160614203328_add_target_group_to_event.rb │ ├── 20161028141043_add_rsvp_open_time_to_workshops.rb │ ├── 20161228121833_add_workshop_id_to_feedback.rb │ ├── 20180108210921_remove_time_from_workshops.rb │ ├── 20180109024411_add_rsvp_opens_at_to_workshops.rb │ ├── 20180109030511_add_accessibility_info_to_sponsors.rb │ ├── 20180110212924_add_time_zone_to_chapters.rb │ ├── 20180307221521_add_level_to_sponsors.rb │ ├── 20180313165054_rename_table_session_invitations_to_workshop_invitations.rb │ ├── 20180430001328_add_unique_index_to_meeting_slug.rb │ ├── 20180519231943_add_unique_index_to_event_slug.rb │ ├── 20180608010545_add_directions_to_addresses.rb │ ├── 20181002213441_extend_job_model.rb │ ├── 20181012015419_create_friendly_id_slugs.rb │ ├── 20181012015504_add_slug_to_job.rb │ ├── 20181013224547_add_status_to_job.rb │ ├── 20181019002645_add_description_to_chapters.rb │ ├── 20181021014646_add_image_to_chapters.rb │ ├── 20191018175052_add_ends_at_to_workshops.rb │ ├── 20200120111440_add_accepted_toc_at_to_member.rb │ ├── 20200124124311_add_opt_in_newsletter_at_to_member.rb │ ├── 20200311233721_add_virtual_to_workshop.rb │ ├── 20200312172212_add_student_and_coach_spaces_to_workshop.rb │ ├── 20200313211614_add_slack_channel_and_slack_channel_link_to_workshop.rb │ ├── 20200511151348_add_automated_rsvp_to_workshop_invitation.rb │ ├── 20200521151343_add_tutorial_to_workshop_invitation.rb │ ├── 20200522142646_add_email_index_to_member.rb │ ├── 20200721072708_update_contacts.rb │ ├── 20200805104520_add_level_to_sponsorship.rb │ ├── 20200815141515_add_token_to_contact.rb │ ├── 20201102173506_create_activities.rb │ ├── 20201109043756_add_end_dt_to_meetings_courses.rb │ ├── 20201120012424_drop_member_contacts.rb │ ├── 20201120012812_remove_contact_details_from_sponsor.rb │ ├── 20220820180050_add_virtual_to_events.rb │ ├── 20220820215847_add_time_zone_to_events.rb │ ├── 20230722001140_add_missing_indexes_on_taggings.acts_as_taggable_on_engine.rb │ ├── 20230722001141_add_tenant_to_taggings.acts_as_taggable_on_engine.rb │ ├── 20230801074547_add_service_name_to_active_storage_blobs.active_storage.rb │ ├── 20230801074548_create_active_storage_variant_records.active_storage.rb │ ├── 20230803225601_remove_not_null_on_active_storage_blobs_checksum.active_storage.rb │ └── 20231230162506_add_last_overridden_by_id_to_workshop_invitations.rb ├── schema.rb └── seeds.rb ├── docker-compose.env ├── docker-compose.yml ├── lib ├── assets │ └── .keep ├── services │ ├── event_calendar.rb │ ├── flodesk.rb │ ├── mailing_list.rb │ └── ticket.rb ├── tasks │ ├── .keep │ ├── delete_member.rake │ ├── feedback.rake │ ├── mailing_list.rake │ ├── reminders.rake │ ├── rubocop.rake │ ├── seed_tags.rake │ └── workshop.rake ├── templates │ └── erb │ │ └── scaffold │ │ └── _form.html.erb └── verifier.rb ├── log └── .keep ├── native-installation-instructions.md ├── public ├── 404.html ├── 422.html ├── 500.html ├── favicon.ico └── robots.txt ├── spec ├── controllers │ ├── admin │ │ ├── invitations_controller_spec.rb │ │ ├── member_notes_controller_spec.rb │ │ ├── sponsors_controller_spec.rb │ │ └── workshops_controller_spec.rb │ ├── auth_services_controller_spec.rb │ └── members_controller_spec.rb ├── fabricators │ ├── address_fabricator.rb │ ├── announcement_fabricator.rb │ ├── attendance_warning_fabricator.rb │ ├── auth_service_fabricator.rb │ ├── ban_fabricator.rb │ ├── chapter_fabricator.rb │ ├── contact_fabricator.rb │ ├── event_fabricator.rb │ ├── feedback_fabricator.rb │ ├── feedback_request_fabricator.rb │ ├── group_fabricator.rb │ ├── invitation_fabricator.rb │ ├── meeting_fabricator.rb │ ├── meeting_invitation_fabricator.rb │ ├── member_fabricator.rb │ ├── member_note_fabricator.rb │ ├── permission_fabricator.rb │ ├── role_fabricator.rb │ ├── sponsor_fabricator.rb │ ├── sponsorship_fabricator.rb │ ├── subscription_fabricator.rb │ ├── testimonials_fabricator.rb │ ├── tutorial_fabricator.rb │ ├── waiting_list_fabricator.rb │ ├── workshop_fabricator.rb │ ├── workshop_invitation_fabricator.rb │ └── workshop_sponsor_fabricator.rb ├── features │ ├── accepting_invitation_spec.rb │ ├── accepting_terms_and_conditions_spec.rb │ ├── admin │ │ ├── accessing_portal_spec.rb │ │ ├── announcements_spec.rb │ │ ├── chapter │ │ │ └── feedback_spec.rb │ │ ├── chapters_spec.rb │ │ ├── event_spec.rb │ │ ├── feedback_spec.rb │ │ ├── filtering_sponsors_list_spec.rb │ │ ├── groups_spec.rb │ │ ├── manage_event_spec.rb │ │ ├── manage_sponsor_spec.rb │ │ ├── manage_workshop_attendances_spec.rb │ │ ├── managing_meeting_invitations_spec.rb │ │ ├── managing_organisers_spec.rb │ │ ├── managing_testimonials_spec.rb │ │ ├── meeting_spec.rb │ │ ├── members_spec.rb │ │ ├── sponsor_spec.rb │ │ └── workshops_spec.rb │ ├── chapter_spec.rb │ ├── coach_accepting_invitation_spec.rb │ ├── internationalization_spec.rb │ ├── listing_coaches_spec.rb │ ├── listing_events_spec.rb │ ├── manage_contact_preferences_spec.rb │ ├── managing_workshop_attendance_spec.rb │ ├── member │ │ └── login_spec.rb │ ├── member_feedback_spec.rb │ ├── member_joining_spec.rb │ ├── member_portal_spec.rb │ ├── sponsors_spec.rb │ ├── subscribing_to_emails_spec.rb │ ├── subscribing_to_newsletter_spec.rb │ ├── view_event_spec.rb │ ├── viewing_a_meeting_spec.rb │ ├── viewing_a_workshop_invitation_spec.rb │ ├── viewing_a_workshop_spec.rb │ ├── viewing_pages_spec.rb │ └── visiting_homepage_spec.rb ├── helpers │ └── application_helper_spec.rb ├── lib │ ├── services │ │ ├── flodesk_spec.rb │ │ └── mailing_list_spec.rb │ ├── tasks │ │ ├── delete_member_rake_spec.rb │ │ ├── feedback_rake_spec.rb │ │ ├── mailing_list_rake_spec.rb │ │ ├── reminders_meeting_rake_spec.rb │ │ └── reminders_workshop_rake_spec.rb │ └── verifier_spec.rb ├── mailers │ ├── event_invitation_mailer_spec.rb │ ├── feedback_request_mailer_spec.rb │ ├── meeting_invitation_mailer_spec.rb │ ├── member_mailer_spec.rb │ ├── previews │ │ ├── event_invitation_mailer_preview.rb │ │ ├── meeting_invitation_mailer_preview.rb │ │ ├── member_mailer_preview.rb │ │ ├── virtual_workshop_invitation_mailer_preview.rb │ │ └── workshop_invitation_mailer_preview.rb │ ├── virtual_workshop_invitation_mailer_spec.rb │ └── workshop_invitation_mailer_spec.rb ├── models │ ├── address_spec.rb │ ├── attendance_warning_spec.rb │ ├── ban_spec.rb │ ├── chapter_spec.rb │ ├── concerns │ │ ├── listable_spec.rb │ │ └── permissions_spec.rb │ ├── eligibility_inquiry_spec.rb │ ├── event_spec.rb │ ├── feedback_request_spec.rb │ ├── feedback_spec.rb │ ├── group_spec.rb │ ├── invitation_manager_spec.rb │ ├── invitation_spec.rb │ ├── meeting_invitation_spec.rb │ ├── meeting_spec.rb │ ├── meeting_talk_spec.rb │ ├── member_note_spec.rb │ ├── member_spec.rb │ ├── role_spec.rb │ ├── sponsor_spec.rb │ ├── sponsors_search_spec.rb │ ├── tutorial_spec.rb │ ├── waiting_list_spec.rb │ ├── workshop_calendar_spec.rb │ ├── workshop_invitation_spec.rb │ ├── workshop_spec.rb │ └── workshop_sponsor_spec.rb ├── presenters │ ├── address_presenter_spec.rb │ ├── chapter_presenter_spec.rb │ ├── contact_presenter_spec.rb │ ├── event_presenter_spec.rb │ ├── invitation_presenter_spec.rb │ ├── meeting_presenter_spec.rb │ ├── member_presenter_spec.rb │ ├── sponsor_presenter_spec.rb │ ├── virtual_workshop_presenter_spec.rb │ └── workshop_presenter_spec.rb ├── services │ └── auditor_spec.rb ├── spec_helper.rb └── support │ ├── capybara.rb │ ├── chapter-image.png │ ├── codebar-logo.png │ ├── helpers │ └── login_helpers.rb │ ├── omniauth.rb │ ├── rake_tasks.rb │ ├── select_from_chosen.rb │ └── shared_examples │ ├── behaves_like_an_invitation.rb │ ├── behaves_like_an_invitation_route.rb │ ├── behaves_like_date_time_concerns.rb │ ├── behaves_like_invitable.rb │ ├── behaves_like_managing_workshop_attendance.rb │ ├── behaves_like_sending_workshop_emails.rb │ ├── behaves_like_viewing_workshop_actions.rb │ ├── behaves_like_viewing_workshop_details.rb │ └── behaves_link_member_viewing_workshop.rb ├── tmp └── pids │ └── .keep └── vendor └── assets ├── javascripts └── .keep └── stylesheets └── .keep /.codeclimate.yml: -------------------------------------------------------------------------------- 1 | version: "2" 2 | plugins: 3 | rubocop: 4 | enabled: true 5 | channel: rubocop-1-50-2 6 | brakeman: 7 | enabled: true 8 | -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | .git* 2 | log/* 3 | tmp/* 4 | Dockerfile 5 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] 4 | patreon: # Replace with a single Patreon username 5 | open_collective: codebar 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | otechie: # Replace with a single Otechie username 12 | custom: ["https://codebar.enthuse.com/donate/#!/"] 13 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: bundler 4 | directory: "/" 5 | schedule: 6 | interval: weekly 7 | open-pull-requests-limit: 10 8 | ignore: 9 | - dependency-name: pg 10 | versions: 11 | - ">= 1.2.a, < 1.3" 12 | - dependency-name: stripe 13 | versions: 14 | - "> 4.18.1" 15 | 16 | - package-ecosystem: "github-actions" 17 | directory: "/" 18 | schedule: 19 | interval: "weekly" 20 | -------------------------------------------------------------------------------- /.rspec: -------------------------------------------------------------------------------- 1 | --color 2 | -------------------------------------------------------------------------------- /.ruby-version: -------------------------------------------------------------------------------- 1 | 3.2.2 2 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ruby:3.2.2 2 | 3 | # Default node version on apt is old. This makes sure a recent version is installed 4 | # This step also runs apt-get update 5 | RUN curl -fsSL https://deb.nodesource.com/setup_20.x | bash - 6 | RUN apt-get update 7 | RUN apt-get install -y --force-yes build-essential libpq-dev nodejs chromium chromium-driver 8 | 9 | WORKDIR /planner 10 | 11 | COPY . ./ 12 | 13 | RUN bundle install --jobs 4 14 | -------------------------------------------------------------------------------- /ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ## Description of the issue 📄 2 | 3 | ## Screenshots 📷 4 | 5 | ## Steps to fix 🛠 6 | 7 | ## To do 📋 8 | 9 | * [ ] Claim this issue (comment below, or assign yourself if you are part of the codebar org) 10 | * [ ] Fork and clone the repository 11 | * [ ] Update the relevant files. Follow the steps to fix section in this issue. 12 | * [ ] Commit your changes as one commit. Use the title of this issue as your commit message 13 | * [ ] Submit a pull request 14 | * [ ] Mention this issue in the PR description by including it's number 15 | * [ ] Have your pull request reviewed & merged by a codebar team member 16 | -------------------------------------------------------------------------------- /Procfile: -------------------------------------------------------------------------------- 1 | web: bundle exec puma -C config/puma.rb 2 | worker: bundle exec rake jobs:workoff --trace 3 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | # Add your own tasks in files placed in lib/tasks ending in .rake, 2 | # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake. 3 | 4 | require_relative 'config/application' 5 | 6 | Rails.application.load_tasks 7 | -------------------------------------------------------------------------------- /app/assets/config/manifest.js: -------------------------------------------------------------------------------- 1 | //= link_tree ../images 2 | //= link_directory ../javascripts .js 3 | //= link_directory ../stylesheets .css 4 | -------------------------------------------------------------------------------- /app/assets/images/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codebar/planner/1a80f39ba971d16a89d9e1023d401ca6876f7534/app/assets/images/.keep -------------------------------------------------------------------------------- /app/assets/images/GitHub_Logo_White.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codebar/planner/1a80f39ba971d16a89d9e1023d401ca6876f7534/app/assets/images/GitHub_Logo_White.png -------------------------------------------------------------------------------- /app/assets/images/Icon-128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codebar/planner/1a80f39ba971d16a89d9e1023d401ca6876f7534/app/assets/images/Icon-128.png -------------------------------------------------------------------------------- /app/assets/images/Icon-196.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codebar/planner/1a80f39ba971d16a89d9e1023d401ca6876f7534/app/assets/images/Icon-196.png -------------------------------------------------------------------------------- /app/assets/images/benevity-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codebar/planner/1a80f39ba971d16a89d9e1023d401ca6876f7534/app/assets/images/benevity-logo.png -------------------------------------------------------------------------------- /app/assets/images/bg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codebar/planner/1a80f39ba971d16a89d9e1023d401ca6876f7534/app/assets/images/bg.jpg -------------------------------------------------------------------------------- /app/assets/images/codebar-girl.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codebar/planner/1a80f39ba971d16a89d9e1023d401ca6876f7534/app/assets/images/codebar-girl.gif -------------------------------------------------------------------------------- /app/assets/images/codebar-stories-banner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codebar/planner/1a80f39ba971d16a89d9e1023d401ca6876f7534/app/assets/images/codebar-stories-banner.png -------------------------------------------------------------------------------- /app/assets/images/collaboration.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codebar/planner/1a80f39ba971d16a89d9e1023d401ca6876f7534/app/assets/images/collaboration.png -------------------------------------------------------------------------------- /app/assets/images/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codebar/planner/1a80f39ba971d16a89d9e1023d401ca6876f7534/app/assets/images/favicon.ico -------------------------------------------------------------------------------- /app/assets/images/festival/codebar-festival-logo-light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codebar/planner/1a80f39ba971d16a89d9e1023d401ca6876f7534/app/assets/images/festival/codebar-festival-logo-light.png -------------------------------------------------------------------------------- /app/assets/images/give-as-you-live.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codebar/planner/1a80f39ba971d16a89d9e1023d401ca6876f7534/app/assets/images/give-as-you-live.png -------------------------------------------------------------------------------- /app/assets/images/how-to-support-us/become-a-coach.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codebar/planner/1a80f39ba971d16a89d9e1023d401ca6876f7534/app/assets/images/how-to-support-us/become-a-coach.jpg -------------------------------------------------------------------------------- /app/assets/images/how-to-support-us/become-an-organiser.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codebar/planner/1a80f39ba971d16a89d9e1023d401ca6876f7534/app/assets/images/how-to-support-us/become-an-organiser.jpg -------------------------------------------------------------------------------- /app/assets/images/how-to-support-us/codebar-festival-2023.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codebar/planner/1a80f39ba971d16a89d9e1023d401ca6876f7534/app/assets/images/how-to-support-us/codebar-festival-2023.jpg -------------------------------------------------------------------------------- /app/assets/images/how-to-support-us/hackney-half.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codebar/planner/1a80f39ba971d16a89d9e1023d401ca6876f7534/app/assets/images/how-to-support-us/hackney-half.jpeg -------------------------------------------------------------------------------- /app/assets/images/how-to-support-us/volunteer.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codebar/planner/1a80f39ba971d16a89d9e1023d401ca6876f7534/app/assets/images/how-to-support-us/volunteer.jpg -------------------------------------------------------------------------------- /app/assets/images/logo-square.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codebar/planner/1a80f39ba971d16a89d9e1023d401ca6876f7534/app/assets/images/logo-square.png -------------------------------------------------------------------------------- /app/assets/images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codebar/planner/1a80f39ba971d16a89d9e1023d401ca6876f7534/app/assets/images/logo.png -------------------------------------------------------------------------------- /app/assets/images/nyc-workshop.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codebar/planner/1a80f39ba971d16a89d9e1023d401ca6876f7534/app/assets/images/nyc-workshop.jpg -------------------------------------------------------------------------------- /app/assets/images/ok.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codebar/planner/1a80f39ba971d16a89d9e1023d401ca6876f7534/app/assets/images/ok.png -------------------------------------------------------------------------------- /app/assets/images/open-collective-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codebar/planner/1a80f39ba971d16a89d9e1023d401ca6876f7534/app/assets/images/open-collective-logo.png -------------------------------------------------------------------------------- /app/assets/images/sponsors/8th-Light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codebar/planner/1a80f39ba971d16a89d9e1023d401ca6876f7534/app/assets/images/sponsors/8th-Light.png -------------------------------------------------------------------------------- /app/assets/images/sponsors/StreetTeam.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codebar/planner/1a80f39ba971d16a89d9e1023d401ca6876f7534/app/assets/images/sponsors/StreetTeam.png -------------------------------------------------------------------------------- /app/assets/images/sponsors/bloomberg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codebar/planner/1a80f39ba971d16a89d9e1023d401ca6876f7534/app/assets/images/sponsors/bloomberg.png -------------------------------------------------------------------------------- /app/assets/images/sponsors/gds-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codebar/planner/1a80f39ba971d16a89d9e1023d401ca6876f7534/app/assets/images/sponsors/gds-logo.png -------------------------------------------------------------------------------- /app/assets/images/sponsors/google.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codebar/planner/1a80f39ba971d16a89d9e1023d401ca6876f7534/app/assets/images/sponsors/google.png -------------------------------------------------------------------------------- /app/assets/images/sponsors/mozilla.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codebar/planner/1a80f39ba971d16a89d9e1023d401ca6876f7534/app/assets/images/sponsors/mozilla.png -------------------------------------------------------------------------------- /app/assets/images/sponsors/pivotal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codebar/planner/1a80f39ba971d16a89d9e1023d401ca6876f7534/app/assets/images/sponsors/pivotal.png -------------------------------------------------------------------------------- /app/assets/images/sponsors/shutl_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codebar/planner/1a80f39ba971d16a89d9e1023d401ca6876f7534/app/assets/images/sponsors/shutl_logo.png -------------------------------------------------------------------------------- /app/assets/images/sponsors/softwire.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codebar/planner/1a80f39ba971d16a89d9e1023d401ca6876f7534/app/assets/images/sponsors/softwire.png -------------------------------------------------------------------------------- /app/assets/images/sponsors/the-guardian.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codebar/planner/1a80f39ba971d16a89d9e1023d401ca6876f7534/app/assets/images/sponsors/the-guardian.png -------------------------------------------------------------------------------- /app/assets/images/sponsors/ticketmaster.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codebar/planner/1a80f39ba971d16a89d9e1023d401ca6876f7534/app/assets/images/sponsors/ticketmaster.png -------------------------------------------------------------------------------- /app/assets/images/sponsors/ustwo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codebar/planner/1a80f39ba971d16a89d9e1023d401ca6876f7534/app/assets/images/sponsors/ustwo.png -------------------------------------------------------------------------------- /app/assets/images/star-rating.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codebar/planner/1a80f39ba971d16a89d9e1023d401ca6876f7534/app/assets/images/star-rating.gif -------------------------------------------------------------------------------- /app/assets/images/twitter-summary-card-image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codebar/planner/1a80f39ba971d16a89d9e1023d401ca6876f7534/app/assets/images/twitter-summary-card-image.png -------------------------------------------------------------------------------- /app/assets/images/uncodebar-group.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codebar/planner/1a80f39ba971d16a89d9e1023d401ca6876f7534/app/assets/images/uncodebar-group.jpeg -------------------------------------------------------------------------------- /app/assets/javascripts/analytics.js: -------------------------------------------------------------------------------- 1 | (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){ 2 | (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o), 3 | m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m) 4 | })(window,document,'script','//www.google-analytics.com/analytics.js','ga'); 5 | 6 | ga('create', 'UA-45126617-1', 'codebar.io'); 7 | ga('send', 'pageview'); 8 | -------------------------------------------------------------------------------- /app/assets/javascripts/gosquared.js: -------------------------------------------------------------------------------- 1 | !function(g,s,q,r,d){r=g[r]=g[r]||function(){(r.q=r.q||[]).push(arguments)};d=s.createElement(q);q=s.getElementsByTagName(q)[0];d.src='//d1l6p2sc9645hc.cloudfront.net/tracker.js';q.parentNode.insertBefore(d,q)} (window,document,'script','_gs'); 2 | 3 | _gs('GSN-171446-A'); 4 | -------------------------------------------------------------------------------- /app/assets/javascripts/subscriptions-toggle.js: -------------------------------------------------------------------------------- 1 | // Expand/collapse toggling for coach/student group subscriptions. 2 | // Used in the new user signup flow, to stop too many options being 3 | // presented. 4 | 5 | /* global $ */ 6 | 7 | $(() => 8 | $(".subscriptions .codebar-toggle").click(function (e) { 9 | const $section = $(e.target).closest(".subscriptions"); 10 | const $container = $(".group-container", $section); 11 | const $icon = $(".codebar-toggle i", $section); 12 | $container.slideToggle(400, () => $container.toggleClass("codebar-collapsed")); 13 | $icon.toggleClass("fa-chevron-right fa-chevron-down"); 14 | }) 15 | ); 16 | -------------------------------------------------------------------------------- /app/assets/stylesheets/animations.scss: -------------------------------------------------------------------------------- 1 | .spin { 2 | animation: spin 2s infinite linear; 3 | } 4 | 5 | @keyframes spin { 6 | from { 7 | transform: rotate(0deg); 8 | } 9 | to { 10 | transform: rotate(360deg); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /app/assets/stylesheets/main.scss: -------------------------------------------------------------------------------- 1 | /* Show/hide togglable elements are controlled by JavaScript. */ 2 | .codebar-toggle { 3 | cursor: pointer; 4 | } 5 | 6 | .codebar-collapsed { 7 | display: none; 8 | } 9 | 10 | .no-js .codebar-collapsed { 11 | display: block; 12 | } 13 | 14 | img.sponsor { 15 | max-height: 100px; 16 | } 17 | 18 | form .hint { 19 | color: gray; 20 | display: inline-block; 21 | font-size: 0.875em; 22 | margin-bottom: 0.5rem; 23 | } 24 | 25 | .chosen-dropwdown { 26 | margin-bottom: 1.14286rem; 27 | } 28 | 29 | .small-image { 30 | max-height: 100px; 31 | } 32 | 33 | .sponsor-sm { 34 | max-width: 120px; 35 | } 36 | 37 | .announcement p:last-child { 38 | margin-bottom: 0; 39 | } 40 | 41 | .picker { 42 | width: 320px !important; 43 | } 44 | 45 | .festival-banner { 46 | background: #1E1D3B; 47 | } 48 | -------------------------------------------------------------------------------- /app/assets/stylesheets/partials/_colors.sass: -------------------------------------------------------------------------------- 1 | $codebar-green: #19f3be 2 | $codebar-pink: #ff036a 3 | $codebar-blue: #4bafff 4 | 5 | $dark-codebar-blue: #006cc2 6 | 7 | $white: #ffffff 8 | 9 | $primary-color: #596677 10 | $secondary-color: $codebar-blue 11 | -------------------------------------------------------------------------------- /app/assets/stylesheets/partials/_hero.scss: -------------------------------------------------------------------------------- 1 | .homepage-hero { 2 | background-image: image-url("uncodebar-group.jpeg"); 3 | background-position: center center; 4 | background-size: cover; 5 | background-repeat: no-repeat; 6 | height: 350px; 7 | .text { 8 | background-color: rgba(0, 0, 0, 0.6); 9 | p { 10 | color: $white; 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /app/assets/stylesheets/partials/_layout.scss: -------------------------------------------------------------------------------- 1 | @import "partials/colors"; 2 | 3 | #top { 4 | margin-top: 96px; 5 | } 6 | 7 | .main-footer { 8 | background-color: $dark-codebar-blue; 9 | color: $white; 10 | 11 | a { 12 | color: $white; 13 | text-decoration: none; 14 | 15 | &:hover { 16 | color: $codebar-green; 17 | } 18 | } 19 | 20 | .registration { 21 | font-size: 0.75rem; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /app/assets/stylesheets/partials/_screen_readers.scss: -------------------------------------------------------------------------------- 1 | .sr-only { 2 | position: absolute; 3 | width: 1px; 4 | height: 1px; 5 | padding: 0; 6 | overflow: hidden; 7 | clip: rect(0, 0, 0, 0); 8 | white-space: nowrap; 9 | clip-path: inset(50%); 10 | border: 0; 11 | } 12 | -------------------------------------------------------------------------------- /app/assets/stylesheets/partials/_social_media.scss: -------------------------------------------------------------------------------- 1 | .social-icon { 2 | transition: all 0.6s ease; 3 | &:hover { 4 | transform: scale(1.3); 5 | color: $white; 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /app/assets/stylesheets/partials/_star-rating.scss: -------------------------------------------------------------------------------- 1 | .rating { 2 | float: left; 3 | 4 | ul { 5 | list-style: none; 6 | float: left; 7 | padding: 0; 8 | margin: 0; 9 | 10 | li { 11 | float: left; 12 | margin-left: 2px; 13 | background: image-url("star-rating.gif") no-repeat; 14 | width: 25px; 15 | height: 25px; 16 | cursor: pointer; 17 | } 18 | 19 | li:first-child { 20 | margin-left: 0; 21 | } 22 | 23 | li.hover { 24 | background-position: -25px; 25 | } 26 | 27 | li.active { 28 | background-position: -50px; 29 | } 30 | } 31 | 32 | span.less { 33 | cursor: pointer; 34 | background: image-url("star-rating.gif") -75px no-repeat; 35 | display: block; 36 | float: left; 37 | height: 25px; 38 | width: 25px; 39 | } 40 | } -------------------------------------------------------------------------------- /app/controllers/admin/application_controller.rb: -------------------------------------------------------------------------------- 1 | class Admin::ApplicationController < ApplicationController 2 | include Pundit::Authorization 3 | 4 | before_action :authenticate_admin_or_organiser! 5 | end 6 | -------------------------------------------------------------------------------- /app/controllers/admin/bans_controller.rb: -------------------------------------------------------------------------------- 1 | class Admin::BansController < Admin::ApplicationController 2 | before_action :set_member 3 | 4 | def new 5 | @ban = Ban.new 6 | end 7 | 8 | def create 9 | @ban = @member.bans.build(ban_params) 10 | @ban.added_by = current_user 11 | 12 | if @ban.save 13 | MemberMailer.ban(@ban.member, @ban).deliver_now 14 | redirect_to [:admin, @member], notice: t('.success') 15 | else 16 | render 'new' 17 | end 18 | end 19 | 20 | private 21 | 22 | def ban_params 23 | params.require(:ban).permit(:note, :reason, :permanent, :expires_at, :explanation) 24 | end 25 | 26 | def set_member 27 | @member = Member.find(params[:member_id]) 28 | end 29 | end 30 | -------------------------------------------------------------------------------- /app/controllers/admin/chapters/feedback_controller.rb: -------------------------------------------------------------------------------- 1 | class Admin::Chapters::FeedbackController < Admin::ApplicationController 2 | before_action :set_chapter, only: [:index] 3 | after_action :verify_authorized 4 | 5 | def index 6 | authorize(@chapter) 7 | 8 | feedback = @chapter.feedbacks.includes(:tutorial) 9 | .includes(:coach) 10 | .order('feedbacks.created_at desc') 11 | @pagy, @feedback = pagy(feedback) 12 | 13 | render template: 'admin/feedback/index' 14 | end 15 | 16 | private 17 | 18 | def set_chapter 19 | @chapter = Chapter.find(params[:chapter_id]) 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /app/controllers/admin/contacts_controller.rb: -------------------------------------------------------------------------------- 1 | class Admin::ContactsController < Admin::ApplicationController 2 | def index 3 | authorize Contact 4 | @contacts = Contact.includes(:sponsor).all.order('sponsors.name') 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /app/controllers/admin/feedback_controller.rb: -------------------------------------------------------------------------------- 1 | class Admin::FeedbackController < SuperAdmin::ApplicationController 2 | def index 3 | feedback = Feedback.includes(:coach, :tutorial) 4 | .order('created_at desc') 5 | @pagy, @feedback = pagy(feedback) 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /app/controllers/admin/groups_controller.rb: -------------------------------------------------------------------------------- 1 | class Admin::GroupsController < Admin::ApplicationController 2 | after_action :verify_authorized 3 | 4 | def new 5 | @group = Group.new 6 | authorize @group 7 | end 8 | 9 | def create 10 | @group = Group.new(group_params) 11 | authorize @group 12 | 13 | if @group.save 14 | flash[:notice] = "Group #{@group.name} for chapter #{@group.chapter.name} has been successfully created" 15 | redirect_to [:admin, @group] 16 | else 17 | flash[:notice] = @group.errors.full_messages 18 | render 'new' 19 | end 20 | end 21 | 22 | def show 23 | @group = Group.find(params[:id]) 24 | authorize @group 25 | end 26 | 27 | private 28 | 29 | def group_params 30 | params.require(:group).permit(:name, :description, :chapter_id) 31 | end 32 | end 33 | -------------------------------------------------------------------------------- /app/controllers/admin/member_notes_controller.rb: -------------------------------------------------------------------------------- 1 | class Admin::MemberNotesController < Admin::ApplicationController 2 | def create 3 | @note = MemberNote.new(member_note_params) 4 | authorize @note 5 | 6 | @note.author = current_user 7 | flash[:error] = @note.errors.full_messages unless @note.save 8 | redirect_back fallback_location: root_path 9 | end 10 | 11 | def member_note_params 12 | params.require(:member_note).permit(:note, :member_id) 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /app/controllers/admin/portal_controller.rb: -------------------------------------------------------------------------------- 1 | class Admin::PortalController < Admin::ApplicationController 2 | def index 3 | authorize :admin_portal 4 | 5 | @chapters = Chapter.active.all.order(name: :asc) 6 | @workshops = Workshop.upcoming 7 | @groups = Group.joins(:chapter).merge(@chapters) 8 | @subscribers = Subscription.joins(:chapter).merge(@chapters) 9 | .ordered.limit(20).includes(:member, :group) 10 | end 11 | 12 | def guide; end 13 | end 14 | -------------------------------------------------------------------------------- /app/controllers/admin/testimonials_controller.rb: -------------------------------------------------------------------------------- 1 | class Admin::TestimonialsController < SuperAdmin::ApplicationController 2 | def index 3 | @testimonials = Testimonial.includes(:member).all 4 | 5 | authorize @testimonials 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /app/controllers/auth_sessions_controller.rb: -------------------------------------------------------------------------------- 1 | class AuthSessionsController < ApplicationController 2 | def create 3 | cookies[:member_type] = params[:member_type] 4 | redirect_to redirect_path 5 | end 6 | 7 | def destroy 8 | logout! 9 | redirect_to root_url 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /app/controllers/concerns/mailing_list_concerns.rb: -------------------------------------------------------------------------------- 1 | module MailingListConcerns 2 | extend ActiveSupport::Concern 3 | 4 | included do 5 | require 'services/mailing_list' 6 | 7 | include InstanceMethods 8 | end 9 | 10 | module InstanceMethods 11 | def subscribe_to_newsletter(member) 12 | member.update(opt_in_newsletter_at: Time.zone.now) 13 | MailingList.new(ENV['NEWSLETTER_ID']).subscribe(member.email, 14 | member.name, 15 | member.surname) 16 | end 17 | 18 | def unsubscribe_from_newsletter(member) 19 | member.update(opt_in_newsletter_at: nil) 20 | MailingList.new(ENV['NEWSLETTER_ID']).unsubscribe(member.email) 21 | end 22 | end 23 | end 24 | -------------------------------------------------------------------------------- /app/controllers/concerns/member_concerns.rb: -------------------------------------------------------------------------------- 1 | module MemberConcerns 2 | extend ActiveSupport::Concern 3 | 4 | included do 5 | include InstanceMethods 6 | end 7 | 8 | module InstanceMethods 9 | private 10 | 11 | def member_params 12 | params.require(:member).permit( 13 | :pronouns, :name, :surname, :email, :mobile, :twitter, :about_you, :skill_list, :newsletter 14 | ) 15 | end 16 | 17 | def suppress_notices 18 | @suppress_notices = true 19 | end 20 | 21 | def set_member 22 | @member = current_user 23 | end 24 | end 25 | end 26 | -------------------------------------------------------------------------------- /app/controllers/concerns/workshop_invitation_concerns.rb: -------------------------------------------------------------------------------- 1 | module WorkshopInvitationConcerns 2 | extend ActiveSupport::Concern 3 | 4 | included do 5 | before_action :set_invitation 6 | 7 | include InstanceMethods 8 | end 9 | 10 | module InstanceMethods 11 | private 12 | 13 | def invitation_params 14 | params[:workshop_invitation].present? ? params.require(:workshop_invitation).permit(:tutorial, :note) : {} 15 | end 16 | 17 | def back_with_message(message) 18 | redirect_back(fallback_location: invitation_path(@invitation), notice: message) 19 | end 20 | 21 | def set_invitation 22 | @invitation = WorkshopInvitation.find_by(token: token) 23 | end 24 | end 25 | end 26 | -------------------------------------------------------------------------------- /app/controllers/donations_controller.rb: -------------------------------------------------------------------------------- 1 | class DonationsController < ApplicationController 2 | def new 3 | redirect_to I18n.t('services.donations'), allow_other_host: true 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /app/controllers/mailing_lists_controller.rb: -------------------------------------------------------------------------------- 1 | class MailingListsController < ApplicationController 2 | include MailingListConcerns 3 | 4 | before_action :has_access? 5 | 6 | def create 7 | subscribe_to_newsletter(current_user) 8 | flash[:notice] = I18n.t('subscriptions.messages.mailing_list.subscribe') 9 | 10 | redirect_back fallback_location: root_path 11 | end 12 | 13 | def destroy 14 | unsubscribe_from_newsletter(current_user) 15 | flash[:notice] = I18n.t('subscriptions.messages.mailing_list.unsubscribe') 16 | 17 | redirect_back fallback_location: root_path 18 | end 19 | end 20 | -------------------------------------------------------------------------------- /app/controllers/meetings_controller.rb: -------------------------------------------------------------------------------- 1 | class MeetingsController < ApplicationController 2 | before_action :set_meeting 3 | 4 | def show 5 | @invitation = if params[:token].present? 6 | MeetingInvitation.find_by(token: params[:token], member: current_user) 7 | end 8 | @host_address = AddressPresenter.new(@meeting.venue.address) 9 | @attendees = @meeting.invitations.where(attending: true) 10 | end 11 | 12 | private 13 | 14 | def set_meeting 15 | @meeting = Meeting.find_by!(slug: params[:id]) 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /app/controllers/member/details_controller.rb: -------------------------------------------------------------------------------- 1 | class Member::DetailsController < ApplicationController 2 | include MemberConcerns 3 | include MailingListConcerns 4 | 5 | before_action :set_member 6 | before_action :suppress_notices 7 | before_action :is_logged_in?, only: %i[edit] 8 | 9 | def edit 10 | accept_terms 11 | 12 | flash[notice] = I18n.t('notifications.signing_up') 13 | @member.newsletter ||= true 14 | end 15 | 16 | def update 17 | return render :edit unless @member.update(member_params) 18 | 19 | member_params[:newsletter] ? subscribe_to_newsletter(@member) : unsubscribe_from_newsletter(@member) 20 | redirect_to step2_member_path 21 | end 22 | end 23 | -------------------------------------------------------------------------------- /app/controllers/pages_controller.rb: -------------------------------------------------------------------------------- 1 | class PagesController < ApplicationController 2 | include HighVoltage::StaticPage 3 | end 4 | -------------------------------------------------------------------------------- /app/controllers/payments_controller.rb: -------------------------------------------------------------------------------- 1 | class PaymentsController < ApplicationController 2 | before_action :is_logged_in? 3 | 4 | def new; end 5 | 6 | def create 7 | @amount = params[:amount] 8 | 9 | customer = Stripe::Customer.create( 10 | email: params[:data][:email], 11 | description: params[:name], 12 | source: params[:data][:id] 13 | ) 14 | 15 | charge_customer(customer, @amount) 16 | 17 | render layout: false 18 | end 19 | 20 | private 21 | 22 | def charge_customer(customer, amount) 23 | Stripe::Charge.create( 24 | amount: amount, 25 | description: 'Payment to codebar', 26 | currency: 'gbp', 27 | customer: customer.id 28 | ) 29 | end 30 | end 31 | -------------------------------------------------------------------------------- /app/controllers/sponsors_controller.rb: -------------------------------------------------------------------------------- 1 | class SponsorsController < ApplicationController 2 | def index 3 | @sponsor_levels = Sponsor.active.group_by(&:level) 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /app/controllers/super_admin/application_controller.rb: -------------------------------------------------------------------------------- 1 | class SuperAdmin::ApplicationController < ApplicationController 2 | include Pundit::Authorization 3 | 4 | before_action :authenticate_admin! 5 | end 6 | -------------------------------------------------------------------------------- /app/controllers/terms_and_conditions_controller.rb: -------------------------------------------------------------------------------- 1 | class TermsAndConditionsController < ApplicationController 2 | before_action :logged_in? 3 | skip_before_action :accept_terms 4 | 5 | def show 6 | @terms_and_conditions_form = TermsAndConditionsForm.new 7 | end 8 | 9 | def update 10 | @terms_and_conditions_form = TermsAndConditionsForm.new(terms_params) 11 | if @terms_and_conditions_form.valid? 12 | member = current_user 13 | member.accepted_toc_at = Time.zone.now 14 | member.save(validate: false) 15 | redirect_to previous_path 16 | else 17 | flash[notice] = I18n.t('terms_and_conditions.messages.notice') 18 | render :show 19 | end 20 | end 21 | 22 | private 23 | 24 | def terms_params 25 | params.require(:terms_and_conditions_form).permit(:terms) 26 | end 27 | end 28 | -------------------------------------------------------------------------------- /app/form_models/mailing_list_form.rb: -------------------------------------------------------------------------------- 1 | class MailingListForm 2 | include ActiveModel::Model 3 | 4 | attr_accessor :name 5 | end 6 | -------------------------------------------------------------------------------- /app/form_models/terms_and_conditions_form.rb: -------------------------------------------------------------------------------- 1 | class TermsAndConditionsForm 2 | include ActiveModel::Model 3 | 4 | attr_accessor :terms 5 | 6 | validates :terms, acceptance: true 7 | end 8 | -------------------------------------------------------------------------------- /app/helpers/README.md: -------------------------------------------------------------------------------- 1 | # Helpers vs presenters 2 | 3 | This codebases uses the presenter pattern to decorate records from the database. Have a look in app/presenters for examples. Helpers are discouraged but sometimes necessary if the code isn’t related to an individual record. 4 | -------------------------------------------------------------------------------- /app/helpers/email_header_helper.rb: -------------------------------------------------------------------------------- 1 | module EmailHeaderHelper 2 | private 3 | 4 | def mail_args(member, subject, from_email = 'meetings@codebar.io', cc = '', bcc = '') 5 | { from: "codebar.io <#{from_email}>", 6 | to: member.email, 7 | cc: cc, 8 | bcc: bcc, 9 | subject: subject } 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /app/helpers/email_helper.rb: -------------------------------------------------------------------------------- 1 | module EmailHelper 2 | private 3 | 4 | def full_url_for(path) 5 | "#{@host}#{path}" 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /app/jobs/application_job.rb: -------------------------------------------------------------------------------- 1 | class ApplicationJob < ActiveJob::Base 2 | end 3 | -------------------------------------------------------------------------------- /app/mailers/application_mailer.rb: -------------------------------------------------------------------------------- 1 | class ApplicationMailer < ActionMailer::Base 2 | default from: 'from@example.com' 3 | layout 'mailer' 4 | end 5 | -------------------------------------------------------------------------------- /app/mailers/contact_mailer.rb: -------------------------------------------------------------------------------- 1 | class ContactMailer < ApplicationMailer 2 | include EmailHeaderHelper 3 | 4 | helper ApplicationHelper 5 | helper EmailHelper 6 | 7 | def subscription_notification(contact) 8 | @contact = contact 9 | 10 | subject = "You have been added to codebar's sponsors mailing list" 11 | 12 | mail(mail_args(contact, subject, 'no-reply@codebar.io'), &:html) 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /app/mailers/feedback_request_mailer.rb: -------------------------------------------------------------------------------- 1 | class FeedbackRequestMailer < ApplicationMailer 2 | include EmailHeaderHelper 3 | 4 | helper ApplicationHelper 5 | 6 | def request_feedback(workshops, member, feedback_request) 7 | @workshop = workshops 8 | @member = member 9 | @feedback_request = feedback_request 10 | 11 | subject = "#{@workshop} Feedback for #{l(@workshop.date_and_time, format: :email_title)}" 12 | 13 | mail(mail_args(member, subject), &:html) 14 | end 15 | 16 | helper do 17 | def full_url_for(path) 18 | "#{@host}#{path}" 19 | end 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /app/models/address.rb: -------------------------------------------------------------------------------- 1 | class Address < ApplicationRecord 2 | belongs_to :sponsor 3 | end 4 | -------------------------------------------------------------------------------- /app/models/announcement.rb: -------------------------------------------------------------------------------- 1 | class Announcement < ApplicationRecord 2 | has_many :group_announcements 3 | has_many :groups, through: :group_announcements 4 | 5 | belongs_to :created_by, class_name: 'Member' 6 | 7 | scope :active, -> { where('expires_at > ?', Date.current) } 8 | 9 | attr_accessor :all_groups 10 | 11 | validates :message, presence: true 12 | end 13 | -------------------------------------------------------------------------------- /app/models/application_record.rb: -------------------------------------------------------------------------------- 1 | # See https://guides.rubyonrails.org/upgrading_ruby_on_rails.html#upgrading-from-rails-4-2-to-rails-5-0 2 | class ApplicationRecord < ActiveRecord::Base 3 | primary_abstract_class 4 | end 5 | -------------------------------------------------------------------------------- /app/models/attendance_warning.rb: -------------------------------------------------------------------------------- 1 | class AttendanceWarning < ApplicationRecord 2 | belongs_to :member 3 | belongs_to :issued_by, class_name: 'Member', foreign_key: 'sent_by_id', inverse_of: false 4 | 5 | scope :last_six_months, -> { where(created_at: 6.months.ago...Time.zone.now) } 6 | 7 | before_save :send_email 8 | 9 | private 10 | 11 | def send_email 12 | MemberMailer.attendance_warning(member, member.email).deliver_now 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /app/models/auth_service.rb: -------------------------------------------------------------------------------- 1 | class AuthService < ApplicationRecord 2 | belongs_to :member 3 | validates :uid, uniqueness: { constraint: :provider } 4 | end 5 | -------------------------------------------------------------------------------- /app/models/ban.rb: -------------------------------------------------------------------------------- 1 | class Ban < ApplicationRecord 2 | belongs_to :member 3 | belongs_to :added_by, class_name: 'Member' 4 | 5 | validates :expires_at, :reason, :note, :added_by, presence: true 6 | 7 | validate :valid_expiry_date? 8 | 9 | scope :active, -> { where('expires_at > ?', Time.zone.now) } 10 | scope :permanent, -> { where(permanent: true) } 11 | 12 | def active? 13 | expires_at.future? 14 | end 15 | 16 | private 17 | 18 | def valid_expiry_date? 19 | errors.add(:expires_at, 'must be in the future') unless expires_at&.future? 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /app/models/concerns/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codebar/planner/1a80f39ba971d16a89d9e1023d401ca6876f7534/app/models/concerns/.keep -------------------------------------------------------------------------------- /app/models/concerns/invitable.rb: -------------------------------------------------------------------------------- 1 | module Invitable 2 | extend ActiveSupport::Concern 3 | 4 | included do 5 | include InstanceMethods 6 | end 7 | 8 | module InstanceMethods 9 | def attendances 10 | invitations.accepted 11 | .includes(:member) 12 | .joins(:member).merge Member.not_banned 13 | end 14 | 15 | def attending_students 16 | attendances.where(role: 'Student').order('members.name, members.surname') 17 | end 18 | 19 | def attending_coaches 20 | attendances.where(role: 'Coach').order('members.name, members.surname') 21 | end 22 | end 23 | end 24 | -------------------------------------------------------------------------------- /app/models/concerns/permissions.rb: -------------------------------------------------------------------------------- 1 | module Permissions 2 | extend ActiveSupport::Concern 3 | 4 | included do 5 | rolify role_cname: 'Permission', role_table_name: :permission, role_join_table_name: :members_permissions 6 | 7 | include InstanceMethods 8 | end 9 | 10 | module InstanceMethods 11 | def organiser? 12 | organised_chapters.present? 13 | end 14 | 15 | def admin_or_organiser? 16 | has_role?(:admin) || organiser? 17 | end 18 | 19 | def monthlies_organiser? 20 | Meeting.with_role(:organiser, self).present? 21 | end 22 | 23 | def organised_chapters 24 | Chapter.with_role(:organiser, self) 25 | end 26 | end 27 | end 28 | -------------------------------------------------------------------------------- /app/models/eligibility_inquiry.rb: -------------------------------------------------------------------------------- 1 | class EligibilityInquiry < ApplicationRecord 2 | belongs_to :member 3 | belongs_to :issued_by, class_name: 'Member', foreign_key: 'sent_by_id', inverse_of: false 4 | 5 | before_save :send_email 6 | 7 | private 8 | 9 | def send_email 10 | MemberMailer.eligibility_check(member, member.email).deliver_now 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /app/models/feedback.rb: -------------------------------------------------------------------------------- 1 | class Feedback < ApplicationRecord 2 | belongs_to :tutorial 3 | belongs_to :coach, class_name: 'Member' 4 | belongs_to :workshop 5 | has_one :chapter, through: :workshop 6 | 7 | validates :rating, inclusion: { in: 1..5, message: "can't be blank" } 8 | validates :tutorial, presence: true 9 | 10 | def self.submit_feedback(params, token) 11 | return false unless feedback_request = FeedbackRequest.find_by(token: token) 12 | 13 | feedback = Feedback.new(params) 14 | feedback.workshop = feedback_request.workshop 15 | 16 | if feedback.valid? && !feedback_request.submited 17 | feedback_request.update(submited: true) 18 | feedback.save 19 | else 20 | false 21 | end 22 | end 23 | end 24 | -------------------------------------------------------------------------------- /app/models/feedback_request.rb: -------------------------------------------------------------------------------- 1 | class FeedbackRequest < ApplicationRecord 2 | belongs_to :member 3 | belongs_to :workshop 4 | 5 | validates :member_id, presence: true, uniqueness: { scope: [:workshop] } 6 | validates :workshop, presence: true 7 | validates :token, uniqueness: true, presence: true 8 | validates :submited, inclusion: { in: [true, false] } 9 | 10 | before_validation :set_token 11 | after_create :email 12 | 13 | private 14 | 15 | def set_token 16 | self.token = loop do 17 | random_token = SecureRandom.urlsafe_base64(nil, false) 18 | break random_token unless self.class.where(token: random_token).exists? 19 | end 20 | end 21 | 22 | def email 23 | FeedbackRequestMailer.request_feedback(workshop, member, self).deliver_now 24 | end 25 | end 26 | -------------------------------------------------------------------------------- /app/models/group.rb: -------------------------------------------------------------------------------- 1 | class Group < ApplicationRecord 2 | NAMES = %w[Coaches Students].freeze 3 | 4 | belongs_to :chapter 5 | has_many :subscriptions 6 | has_many :members, through: :subscriptions 7 | has_many :group_announcements 8 | has_many :announcements, through: :group_announcements 9 | 10 | scope :latest_members, -> { joins(:members).order('created_at') } 11 | scope :students, -> { where(name: 'Students') } 12 | scope :coaches, -> { where(name: 'Coaches') } 13 | 14 | validates :name, presence: true, inclusion: { in: NAMES, message: 'Invalid name for Group' } 15 | 16 | alias_attribute :city, :chapter 17 | 18 | default_scope -> { joins(:chapter).includes(:chapter) } 19 | 20 | def to_s 21 | "#{name} #{chapter.name}" 22 | end 23 | end 24 | -------------------------------------------------------------------------------- /app/models/group_announcement.rb: -------------------------------------------------------------------------------- 1 | class GroupAnnouncement < ApplicationRecord 2 | belongs_to :announcement 3 | belongs_to :group 4 | end 5 | -------------------------------------------------------------------------------- /app/models/invitation.rb: -------------------------------------------------------------------------------- 1 | class Invitation < ApplicationRecord 2 | include InvitationConcerns 3 | 4 | belongs_to :event 5 | belongs_to :member 6 | belongs_to :verified_by, class_name: 'Member' 7 | 8 | validates :event, :member, presence: true 9 | validates :member_id, uniqueness: { scope: %i[event_id role] } 10 | validates :role, inclusion: { in: %w[Student Coach] } 11 | 12 | scope :students, -> { where(role: 'Student') } 13 | scope :coaches, -> { where(role: 'Coach') } 14 | scope :verified, -> { where(verified: true).order(:updated_at) } 15 | 16 | def student_spaces? 17 | for_student? && event.student_spaces? 18 | end 19 | 20 | def coach_spaces? 21 | for_coach? && event.coach_spaces? 22 | end 23 | 24 | def to_param 25 | token 26 | end 27 | end 28 | -------------------------------------------------------------------------------- /app/models/meeting_invitation.rb: -------------------------------------------------------------------------------- 1 | class MeetingInvitation < ApplicationRecord 2 | include InvitationConcerns 3 | 4 | belongs_to :meeting 5 | belongs_to :member 6 | 7 | validates :meeting, :member, presence: true 8 | validates :member_id, uniqueness: { scope: [:meeting_id] } 9 | 10 | scope :accepted, -> { where(attending: true) } 11 | scope :attended, -> { where(attended: true) } 12 | 13 | alias event meeting 14 | end 15 | -------------------------------------------------------------------------------- /app/models/meeting_talk.rb: -------------------------------------------------------------------------------- 1 | class MeetingTalk < ApplicationRecord 2 | belongs_to :speaker, class_name: 'Member' 3 | belongs_to :meeting 4 | 5 | validates :title, :abstract, :speaker, :meeting, presence: true 6 | 7 | default_scope -> { order('title asc') } 8 | end 9 | -------------------------------------------------------------------------------- /app/models/member_note.rb: -------------------------------------------------------------------------------- 1 | class MemberNote < ApplicationRecord 2 | belongs_to :member 3 | belongs_to :author, class_name: 'Member' 4 | 5 | validates :member, :author, :note, presence: true 6 | end 7 | -------------------------------------------------------------------------------- /app/models/permission.rb: -------------------------------------------------------------------------------- 1 | class Permission < ApplicationRecord 2 | has_and_belongs_to_many :members, join_table: :members_permissions 3 | belongs_to :resource, polymorphic: true 4 | 5 | scopify 6 | end 7 | -------------------------------------------------------------------------------- /app/models/role.rb: -------------------------------------------------------------------------------- 1 | class Role < ApplicationRecord 2 | has_and_belongs_to_many :members 3 | 4 | scope :no_admins, -> { where.not(name: 'Admin') } 5 | end 6 | -------------------------------------------------------------------------------- /app/models/sponsors_search.rb: -------------------------------------------------------------------------------- 1 | class SponsorsSearch 2 | include ActiveModel::Model 3 | 4 | attr_accessor :name, :chapter 5 | 6 | def initialize(params = {}) 7 | @name = params.fetch(:name) 8 | @chapter = params.fetch(:chapter) 9 | end 10 | 11 | def call 12 | by_name 13 | by_chapter 14 | sponsors 15 | end 16 | 17 | private 18 | 19 | def sponsors 20 | # Get rid of unsafe SQL warning 21 | @sponsors ||= Sponsor.includes(:chapters).reorder(Arel.sql('lower(sponsors.name)')) 22 | end 23 | 24 | def by_name 25 | @sponsors = sponsors.by_name(name) if name.present? 26 | end 27 | 28 | def by_chapter 29 | if chapter.present? 30 | @sponsors = sponsors.joins(:workshops).where('workshops.chapter_id' => chapter).group('sponsors.id') 31 | end 32 | end 33 | end 34 | -------------------------------------------------------------------------------- /app/models/sponsorship.rb: -------------------------------------------------------------------------------- 1 | class Sponsorship < ApplicationRecord 2 | belongs_to :event 3 | belongs_to :sponsor 4 | end 5 | -------------------------------------------------------------------------------- /app/models/subscription.rb: -------------------------------------------------------------------------------- 1 | require 'services/mailing_list' 2 | 3 | class Subscription < ApplicationRecord 4 | belongs_to :group 5 | belongs_to :member 6 | has_one :chapter, through: :group 7 | 8 | validates :group, uniqueness: { scope: :member_id } 9 | scope :ordered, -> { order(created_at: :desc) } 10 | 11 | after_create :subscribe_to_mailing_list 12 | after_destroy :unsubscribe_from_mailing_list 13 | 14 | def student? 15 | group.name.casecmp('students').zero? 16 | end 17 | 18 | def coach? 19 | group.name.casecmp('coaches').zero? 20 | end 21 | 22 | private 23 | 24 | def subscribe_to_mailing_list 25 | MailingList.new(group.mailing_list_id).subscribe(member.email, member.name, member.surname) 26 | end 27 | 28 | def unsubscribe_from_mailing_list 29 | MailingList.new(group.mailing_list_id).unsubscribe(member.email) 30 | end 31 | end 32 | -------------------------------------------------------------------------------- /app/models/testimonial.rb: -------------------------------------------------------------------------------- 1 | class Testimonial < ApplicationRecord 2 | belongs_to :member 3 | end 4 | -------------------------------------------------------------------------------- /app/models/tutorial.rb: -------------------------------------------------------------------------------- 1 | class Tutorial < ApplicationRecord 2 | belongs_to :workshop 3 | 4 | validates :title, presence: true 5 | default_scope -> { order(:created_at) } 6 | 7 | def self.all_titles 8 | pluck(:title) 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /app/models/workshop_sponsor.rb: -------------------------------------------------------------------------------- 1 | class WorkshopSponsor < ApplicationRecord 2 | belongs_to :sponsor 3 | belongs_to :workshop 4 | 5 | validates :sponsor_id, uniqueness: { scope: :workshop_id, message: :already_sponsoring } 6 | 7 | scope :hosts, -> { where('workshop_sponsors.host = ?', true) } 8 | scope :for_workshop, ->(workshop_id) { where('workshop_sponsors.workshop_id = ?', workshop_id) } 9 | end 10 | -------------------------------------------------------------------------------- /app/policies/admin_portal_policy.rb: -------------------------------------------------------------------------------- 1 | class AdminPortalPolicy < ApplicationPolicy 2 | def index? 3 | user.has_role?(:admin) 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /app/policies/chapter_policy.rb: -------------------------------------------------------------------------------- 1 | class ChapterPolicy < ApplicationPolicy 2 | def index? 3 | show? 4 | end 5 | 6 | def create? 7 | is_admin_or_organiser? 8 | end 9 | 10 | def show? 11 | is_admin_or_organiser? 12 | end 13 | 14 | def edit? 15 | is_admin_or_organiser? 16 | end 17 | 18 | def update? 19 | is_admin_or_organiser? 20 | end 21 | 22 | def members? 23 | is_admin_or_organiser? 24 | end 25 | 26 | private 27 | 28 | def is_admin_or_organiser? 29 | user.is_admin? || user.has_role?(:organiser, record) || user.has_role?(:organiser) 30 | end 31 | end 32 | -------------------------------------------------------------------------------- /app/policies/contact_policy.rb: -------------------------------------------------------------------------------- 1 | class ContactPolicy < ApplicationPolicy 2 | def index? 3 | admin? 4 | end 5 | 6 | private 7 | 8 | def admin? 9 | return false unless user 10 | 11 | user.is_admin? 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /app/policies/event_policy.rb: -------------------------------------------------------------------------------- 1 | class EventPolicy < ApplicationPolicy 2 | def invite? 3 | is_admin_or_organiser? 4 | end 5 | 6 | def show? 7 | is_admin_or_organiser? 8 | end 9 | 10 | private 11 | 12 | def is_admin_or_organiser? 13 | return false unless user 14 | 15 | user.is_admin? || user.has_role?(:organiser, record) 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /app/policies/group_policy.rb: -------------------------------------------------------------------------------- 1 | class GroupPolicy < ApplicationPolicy 2 | def create? 3 | user.is_admin? 4 | end 5 | 6 | def show? 7 | is_admin_or_chapter_organiser? 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /app/policies/member_note_policy.rb: -------------------------------------------------------------------------------- 1 | class MemberNotePolicy < ApplicationPolicy 2 | def create? 3 | user && (user.has_role?(:admin) || user.roles.where(resource_type: 'Chapter').any?) 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /app/policies/organiser_policy.rb: -------------------------------------------------------------------------------- 1 | class OrganiserPolicy < ApplicationPolicy 2 | def index? 3 | admin? 4 | end 5 | 6 | def create? 7 | admin? 8 | end 9 | 10 | def destroy? 11 | admin? 12 | end 13 | 14 | private 15 | 16 | def admin? 17 | user.is_admin? 18 | end 19 | end 20 | -------------------------------------------------------------------------------- /app/policies/sponsor_policy.rb: -------------------------------------------------------------------------------- 1 | class SponsorPolicy < ApplicationPolicy 2 | def index? 3 | is_admin_or_chapter_organiser? 4 | end 5 | 6 | def create? 7 | is_admin_or_chapter_organiser? 8 | end 9 | 10 | def show? 11 | is_admin_or_chapter_organiser? 12 | end 13 | 14 | def edit? 15 | is_admin_or_chapter_organiser? 16 | end 17 | 18 | def update? 19 | is_admin_or_chapter_organiser? 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /app/policies/testimonial_policy.rb: -------------------------------------------------------------------------------- 1 | class TestimonialPolicy < ApplicationPolicy 2 | def index? 3 | user.has_role?(:admin) 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /app/policies/workshop_policy.rb: -------------------------------------------------------------------------------- 1 | class WorkshopPolicy < ApplicationPolicy 2 | def new? 3 | user.has_role?(:admin) || Chapter.find_roles(:organiser, user).any? 4 | end 5 | 6 | def create? 7 | user.has_role?(:admin) || Chapter.find_roles(:organiser, user).any? 8 | end 9 | 10 | def show? 11 | is_admin_or_chapter_organiser? 12 | end 13 | 14 | def invite? 15 | is_admin_or_chapter_organiser? 16 | end 17 | 18 | def update? 19 | is_admin_or_chapter_organiser? 20 | end 21 | 22 | def destroy? 23 | is_admin_or_chapter_organiser? 24 | end 25 | 26 | private 27 | 28 | def is_chapter_organiser? 29 | user.has_role?(:organiser, record) || 30 | user.has_role?(:organiser, record.chapter) || 31 | user.has_role?(:organiser, Chapter) 32 | end 33 | end 34 | -------------------------------------------------------------------------------- /app/presenters/base_presenter.rb: -------------------------------------------------------------------------------- 1 | class BasePresenter < SimpleDelegator 2 | private 3 | 4 | def model 5 | __getobj__ 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /app/presenters/chapter_presenter.rb: -------------------------------------------------------------------------------- 1 | class ChapterPresenter < BasePresenter 2 | def twitter_id 3 | model.twitter_id || Rails.application.config.twitter_id 4 | end 5 | 6 | def twitter_handle 7 | model.twitter || Rails.application.config.twitter 8 | end 9 | 10 | def upcoming_workshops 11 | model.workshops_upcoming 12 | end 13 | 14 | def organisers 15 | @organisers ||= model.permissions.find_by(name: 'organiser').members 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /app/presenters/contact_presenter.rb: -------------------------------------------------------------------------------- 1 | class ContactPresenter < BasePresenter 2 | def self.decorate_collection(collection) 3 | collection.map { |e| ContactPresenter.new(e) } 4 | end 5 | 6 | def full_name 7 | "#{name} #{surname}" 8 | end 9 | 10 | def mailing_list_subscription_class 11 | mailing_list_consent? ? 'fa-bell' : 'fa-bell-slash' 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /app/presenters/invitation_presenter.rb: -------------------------------------------------------------------------------- 1 | class InvitationPresenter < BasePresenter 2 | def self.decorate_collection(collection) 3 | collection.map { |e| InvitationPresenter.new(e) } 4 | end 5 | 6 | def member 7 | @member ||= MemberPresenter.new(model.member) 8 | end 9 | 10 | def attendance_status 11 | model.attending ? 'Attending' : 'RSVP' 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /app/presenters/meeting_presenter.rb: -------------------------------------------------------------------------------- 1 | class MeetingPresenter < EventPresenter 2 | delegate :venue, :description, to: :model 3 | 4 | def attendees_emails 5 | Member.joins(:meeting_invitations) 6 | .where('meeting_invitations.meeting_id = ? and meeting_invitations.attending = ?', model.id, true) 7 | .order_by_email 8 | .pluck(:email).join(', ') 9 | end 10 | 11 | def to_s 12 | model.name 13 | end 14 | 15 | def admin_path 16 | Rails.application.routes.url_helpers.admin_meeting_path(model) 17 | end 18 | 19 | def sponsors 20 | [] 21 | end 22 | 23 | def time 24 | I18n.l(model.date_and_time, format: :time_with_zone) 25 | end 26 | end 27 | -------------------------------------------------------------------------------- /app/presenters/sponsor_presenter.rb: -------------------------------------------------------------------------------- 1 | class SponsorPresenter < BasePresenter 2 | def self.decorate_collection(collection) 3 | collection.map { |e| SponsorPresenter.new(e) } 4 | end 5 | 6 | def address 7 | @address ||= model.address.present? ? AddressPresenter.new(model.address) : nil 8 | end 9 | 10 | def contacts 11 | @contacts ||= ContactPresenter.decorate_collection(model.contacts) 12 | end 13 | 14 | def sponsorships_count 15 | @sponsorships_count = workshops.count + events.count + meetings.count 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /app/presenters/virtual_workshop_presenter.rb: -------------------------------------------------------------------------------- 1 | class VirtualWorkshopPresenter < WorkshopPresenter 2 | def title 3 | I18n.t('workshops.virtual.title', chapter: chapter.name) 4 | end 5 | 6 | delegate :coach_spaces, :student_spaces, to: :model 7 | 8 | def student_spaces? 9 | student_spaces > attending_students.length 10 | end 11 | 12 | def coach_spaces? 13 | coach_spaces > attending_coaches.length 14 | end 15 | 16 | def spaces? 17 | virtual_workshop_spaces? 18 | end 19 | 20 | def send_attending_email(invitation, waitinglist = false) 21 | VirtualWorkshopInvitationMailer.attending(model, invitation.member, invitation, waitinglist).deliver_now 22 | end 23 | 24 | private 25 | 26 | def virtual_workshop_spaces? 27 | coach_spaces? || student_spaces? 28 | end 29 | end 30 | -------------------------------------------------------------------------------- /app/presenters/waiting_list_presenter.rb: -------------------------------------------------------------------------------- 1 | class WaitingListPresenter < BasePresenter 2 | def reminders 3 | @reminders ||= model.where(auto_rsvp: false) 4 | end 5 | 6 | def list 7 | model.where(auto_rsvp: true) 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /app/views/admin/announcements/edit.html.haml: -------------------------------------------------------------------------------- 1 | .container.py-4.py-lg-5 2 | .row.mb-4 3 | .col 4 | %h1 Edit announcement 5 | 6 | .row 7 | .col.col-md-10.col-lg-8 8 | = simple_form_for [:admin, @announcement] do |f| 9 | = f.association :groups, label_method: :to_s, label: 'Select groups' 10 | = f.input :message, input_html: { rows: 3 }, 11 | hint: raw(t('admin.shared.markdown_hint', link: link_to(t('admin.shared.markdown'), 'https://commonmark.org/help/'))) 12 | = f.input :expires_at, as: :string 13 | .text-right 14 | = f.button :button, :update, class: 'btn btn-primary' 15 | -------------------------------------------------------------------------------- /app/views/admin/announcements/new.html.haml: -------------------------------------------------------------------------------- 1 | .container.py-4.py-lg-5 2 | .row.mb-4 3 | .col 4 | %h1 New announcement 5 | 6 | .row 7 | .col.col-md-10.col-lg-8 8 | = simple_form_for [:admin, @announcement] do |f| 9 | = f.association :groups, label_method: :to_s, label: 'Select groups' 10 | = f.input :all_groups, as: :boolean, checked_value: true, unchecked_value: false, label: 'Send to all groups' 11 | = f.input :message, input_html: { rows: 3 }, 12 | hint: raw(t('admin.shared.markdown_hint', link: link_to(t('admin.shared.markdown'), 'https://commonmark.org/help/'))) 13 | = f.input :expires_at, as: :string 14 | .text-right 15 | = f.button :button, :create, class: 'btn btn-primary' 16 | -------------------------------------------------------------------------------- /app/views/admin/attendance_warnings/_attendance_warning.html.haml: -------------------------------------------------------------------------------- 1 | .row.d-flex.align-items-center.attendance-warning 2 | .col-2.col-md-1 3 | %span.fa-stack.text-warning 4 | %i.fas.fa-circle.fa-stack-2x 5 | %i.far.fa-clock.fa-stack-1x.fa-inverse 6 | .col-9.col-md-11.details 7 | %strong Sent attendance warning email by #{link_to(action.issued_by.full_name, admin_member_path(action.issued_by))} 8 | .date 9 | #{l(action.created_at, format: :website_format)} 10 | -------------------------------------------------------------------------------- /app/views/admin/bans/_ban.html.haml: -------------------------------------------------------------------------------- 1 | .row.d-flex.suspension 2 | .col-2.col-md-1 3 | %span.fa-stack.text-danger 4 | %i.fas.fa-user.fa-stack-1x 5 | %i.fas.fa-ban.fa-stack-2x 6 | .col-9.col-md-11.details 7 | %strong 8 | - if action.permanent? 9 | Suspended indefinitely 10 | - else 11 | Suspended until #{l(action.expires_at, format: :default_date)} 12 | by #{link_to(action.added_by.full_name, action.added_by)} 13 | %div 14 | %em= action.reason 15 | %p.mb-0 16 | = action.note 17 | - if action.explanation.present? 18 | .explanation 19 | %span.fa-stack.text-info 20 | %i.fas.fa-circle.fa-stack-2x 21 | %i.fas.fa-envelope-open.fa-stack-1x.fa-inverse 22 | %div= action.explanation 23 | .date 24 | = l(action.created_at, format: :website_format) 25 | -------------------------------------------------------------------------------- /app/views/admin/chapters/new.html.haml: -------------------------------------------------------------------------------- 1 | .container.py-4.py-lg-5 2 | .row.mb-4 3 | .col 4 | %h1 New Chapter 5 | 6 | .row 7 | .col.col-md-10.col-lg-8 8 | = simple_form_for [:admin, @chapter] do |f| 9 | = f.input :name, placeholder: 'e.g. Cambridge', required: true 10 | = f.input :email, placeholder: 'e.g. cambridge@codebar.io', required: true 11 | = f.input :city, required: true 12 | = f.input :time_zone, required: true 13 | .text-right 14 | = f.button :button, 'Create chapter', class: 'btn btn-primary' 15 | -------------------------------------------------------------------------------- /app/views/admin/eligibility_inquiries/_eligibility_inquiry.html.haml: -------------------------------------------------------------------------------- 1 | .row.d-flex.align-items-center.eligibility-inquiry 2 | .col-2.col-md-1 3 | %span.fa-stack.text-warning 4 | %i.fas.fa-circle.fa-stack-2x 5 | %i.fas.fa-paper-plane.fa-stack-1x.fa-inverse 6 | .col-9.col-md-11.details 7 | %strong Sent eligibility inquiry email by #{link_to(action.issued_by.full_name, admin_member_path(action.issued_by))} 8 | .date 9 | = l(action.created_at, format: :website_format) 10 | -------------------------------------------------------------------------------- /app/views/admin/events/_attendances.html.haml: -------------------------------------------------------------------------------- 1 | %ul.list-unstyled.ms-0 2 | - invitations.each do |invitation| 3 | %li 4 | .row 5 | .col-8 6 | = link_to admin_member_path(invitation.member) do 7 | = invitation.member.full_name 8 | - if invitation.member.newbie? 9 | %p.mb-0 10 | %em New attendee! 11 | %p.mt-2 12 | %small= invitation.note 13 | .col-4 14 | - if invitation.verified.blank? && @event.confirmation_required 15 | = link_to 'Verify', admin_event_invitation_verify_path(@event, invitation), class: 'btn btn-sm btn-success mb-2 w-100', method: :post 16 | = link_to 'Cancel attendance', admin_event_invitation_cancel_path(@event, invitation), class: 'btn btn-sm btn-danger w-100', method: :post 17 | %hr 18 | -------------------------------------------------------------------------------- /app/views/admin/events/edit.html.haml: -------------------------------------------------------------------------------- 1 | .container.py-4.py-lg-5 2 | .row.mb-4 3 | .col 4 | %h1 Edit Event 5 | 6 | .row 7 | .col.col-md-10.col-lg-8 8 | = render partial: 'form' 9 | -------------------------------------------------------------------------------- /app/views/admin/events/new.html.haml: -------------------------------------------------------------------------------- 1 | .container.py-4.py-lg-5 2 | .row.mb-4 3 | .col 4 | %h1 New Event 5 | 6 | .row 7 | .col.col-md-10.col-lg-8 8 | = render partial: 'form' 9 | -------------------------------------------------------------------------------- /app/views/admin/groups/new.html.haml: -------------------------------------------------------------------------------- 1 | .container.py-4.py-lg-5 2 | .row.mb-4 3 | .col 4 | %h1 New Group 5 | 6 | .row 7 | .col.col-lg-8 8 | = simple_form_for [:admin, @group] do |f| 9 | = f.input :name, label: 'Name', collection: Group::NAMES 10 | = f.input :description, input_html: { rows: 3 } 11 | = f.association :chapter, required: true 12 | .text-right 13 | = f.button :button, 'Create group', class: 'btn btn-primary' 14 | -------------------------------------------------------------------------------- /app/views/admin/groups/show.html.haml: -------------------------------------------------------------------------------- 1 | .container.py-4.py-lg-5 2 | .row.mb-4 3 | .col 4 | %h1 5 | = @group.name 6 | %small.text-muted #{@group.chapter.name} 7 | 8 | .row 9 | .col 10 | %h3.mb-3 Members (#{@group.members.count}) 11 | %table.table.table-striped.table-hover 12 | %tbody 13 | - @group.members.each do |member| 14 | %tr 15 | %td= image_tag(member.avatar(32), class: 'rounded-circle', title: member.full_name, alt: member.full_name) 16 | %td= link_to member.full_name, admin_member_path(member) 17 | %td= mail_to member.email, member.email 18 | %td= member.mobile 19 | -------------------------------------------------------------------------------- /app/views/admin/meetings/_meeting.html.haml: -------------------------------------------------------------------------------- 1 | = render partial: 'admin/events/event', locals: { event: meeting, invitation: invitation } 2 | -------------------------------------------------------------------------------- /app/views/admin/meetings/edit.html.haml: -------------------------------------------------------------------------------- 1 | .container.py-4.py-lg-5 2 | .row.mb-4 3 | .col 4 | %h1 Edit Monthly 5 | 6 | .row 7 | .col.col-md-10.col-lg-8 8 | = render partial: 'form' 9 | -------------------------------------------------------------------------------- /app/views/admin/meetings/new.html.haml: -------------------------------------------------------------------------------- 1 | .container.py-4.py-lg-5 2 | .row.mb-4 3 | .col 4 | %h1 New Monthly 5 | 6 | .row 7 | .col.col-md-10.col-lg-8 8 | = render partial: 'form' 9 | -------------------------------------------------------------------------------- /app/views/admin/member_notes/_member_note.html.haml: -------------------------------------------------------------------------------- 1 | .row.d-flex.align-items-start.note 2 | .col-2.col-md-1 3 | %span.fa-stack.text-primary 4 | %i.fas.fa-circle.fa-stack-2x 5 | %i.fas.fa-pencil-alt.fa-stack-1x.fa-inverse 6 | .col-9.col-md-11 7 | %strong Note added by #{link_to(action.author.full_name, admin_member_path(action.author))} 8 | %blockquote.blockquote.mb-0=action.note 9 | .date 10 | = l(action.created_at, format: :website_format) 11 | -------------------------------------------------------------------------------- /app/views/admin/members/_note.html.haml: -------------------------------------------------------------------------------- 1 | #note-modal.modal.fade{ 'aria-labelledby': 'modal-title', 'aria-hidden': 'true', role: 'dialog' } 2 | .modal-dialog 3 | .modal-content 4 | .modal-header 5 | %h5.modal-title#modal-title Add a note for #{@member.full_name} 6 | %button.btn-close{ type: 'button', 'data-bs-dismiss': 'modal', 'aria-label': 'Close' } 7 | .modal-body 8 | = simple_form_for [:admin, MemberNote.new], html: { class: 'form-inline' } do |f| 9 | = f.input :note, label: false, input_html: { rows: 3 }, placeholder: 'e.g. very enthusiastic student.' 10 | = f.hidden_field :member_id, value: @member.id 11 | .text-right 12 | = f.button :button, 'Save note', class: 'btn btn-primary mb-0' 13 | -------------------------------------------------------------------------------- /app/views/admin/members/index.html.haml: -------------------------------------------------------------------------------- 1 | .container.py-4.py-lg-5 2 | .row.mb-4 3 | .col 4 | %h1 Members Directory 5 | .row.mb-4 6 | .col-12.col-md-6 7 | = select_tag 'member_lookup_id', options_for_select(@members.collect{ |u| ["#{u.full_name} (#{u.email})", u.id] }), { class: 'chosen-select' } 8 | .row 9 | .col 10 | = link_to 'View Profile', '#', { class: 'btn btn-primary', id: 'view_profile' } 11 | -------------------------------------------------------------------------------- /app/views/admin/shared/_title.html.haml: -------------------------------------------------------------------------------- 1 | %section.title 2 | .row 3 | .large-12 4 | %h1 5 | %span 6 | = link_to "Admin", admin_root_path 7 | = "/ #{title}" 8 | - if date 9 | %span.date= date 10 | -------------------------------------------------------------------------------- /app/views/admin/sponsors/_contact_fields.html.haml: -------------------------------------------------------------------------------- 1 | .nested-fields.card.bg-light.border-secondary.mb-3 2 | .card-body 3 | .text-right 4 | = link_to_remove_association 'Delete', f 5 | = f.input :name 6 | = f.input :surname 7 | = f.input :email 8 | = f.input :mailing_list_consent, as: :boolean, hint_html: { class: 'd-block ms-1' } 9 | -------------------------------------------------------------------------------- /app/views/admin/sponsors/edit.html.haml: -------------------------------------------------------------------------------- 1 | .container.py-4.py-lg-5 2 | .row.mb-4 3 | .col 4 | %nav 5 | %ol.breadcrumb.m-0 6 | %li.breadcrumb-item= link_to 'Sponsors', admin_sponsors_path 7 | %li.breadcrumb-item= link_to @sponsor.name, admin_sponsor_path(@sponsor) 8 | %li.breadcrumb-item.active Edit 9 | 10 | .row.mb-4 11 | .col 12 | %h1 Edit Sponsor 13 | 14 | = render 'form' 15 | -------------------------------------------------------------------------------- /app/views/admin/sponsors/new.html.haml: -------------------------------------------------------------------------------- 1 | .container.py-4.py-lg-5 2 | .row.mb-4 3 | .col 4 | %h1 New Sponsor 5 | 6 | = render 'form' 7 | -------------------------------------------------------------------------------- /app/views/admin/subscriptions/_index.html.haml: -------------------------------------------------------------------------------- 1 | .d-md-flex.justify-content-between.mx-md-n2 2 | - subscribers.each_slice(10) do |subscriptions| 3 | .list-group.px-md-2 4 | - subscriptions.each do |subscription| 5 | = link_to admin_member_path(subscription.member), class: 'list-group-item list-group-item-action' do 6 | #{subscription.member.full_name} 7 | %br 8 | %small joined #{subscription.group.to_s} #{l(subscription.created_at, format: :log)} 9 | 10 | -------------------------------------------------------------------------------- /app/views/admin/testimonials/index.html.haml: -------------------------------------------------------------------------------- 1 | .container.py-4.py-lg-5 2 | .row.mb-4 3 | .col 4 | %h1 Testimonials 5 | 6 | .row 7 | .col 8 | %table.table.table-striped.table-hover 9 | %thead 10 | %tr 11 | %th 12 | Name 13 | %th 14 | Text 15 | %th 16 | Status 17 | %th 18 | Actions 19 | %tbody 20 | - @testimonials.each do |testimonial| 21 | %tr 22 | %td= testimonial.member.full_name 23 | %td= testimonial.text 24 | %td 25 | %td -------------------------------------------------------------------------------- /app/views/admin/workshops/_activity.html.haml: -------------------------------------------------------------------------------- 1 | %tr 2 | %th{ scope: "col" } 3 | = link_to invitation.member.name_and_surname, 4 | admin_member_path(invitation.member_id) 5 | %td 6 | - if invitation.not_attending? 7 | %span.text-muted No 8 | - else 9 | Yes 10 | %td 11 | - if invitation.last_overridden_by_id? 12 | = link_to invitation.overrider.full_name, 13 | admin_member_path(invitation.last_overridden_by_id) 14 | - else 15 | %span.text-muted No 16 | -------------------------------------------------------------------------------- /app/views/admin/workshops/_edit_form.html.haml: -------------------------------------------------------------------------------- 1 | = simple_form_for [:admin, @workshop], url: :admin_workshop, method: :put do |f| 2 | .row 3 | .col-12.col-md-6 4 | = render partial: 'shared_form', locals: { f: f } 5 | .col-12.col-md-6 6 | = render partial: 'virtual_workshop_fields', locals: { f: f } 7 | .col-12.col-md-6 8 | = f.input :organisers, collection: Member.all, value_method: :id, label_method: :full_name, selected: @workshop.organisers.map(&:id), input_html: { multiple: true } 9 | .col-12 10 | = f.input :invitable, hint_html: { class: 'd-block ms-1' } 11 | .row 12 | .col 13 | = f.button :button, 'Save', class: 'btn btn-primary' 14 | -------------------------------------------------------------------------------- /app/views/admin/workshops/_form.html.haml: -------------------------------------------------------------------------------- 1 | = simple_form_for [:admin, @workshop], url: :admin_workshops do |f| 2 | .row 3 | .col-12.col-md-6 4 | = render partial: 'shared_form', locals: { f: f } 5 | .col-12.col-md-6 6 | = render partial: 'virtual_workshop_fields', locals: { f: f } 7 | .col-12 8 | = f.input :invitable, hint_html: { class: 'd-block ms-1' } 9 | .row 10 | .col 11 | = f.button :button, 'Save', class: 'btn btn-primary' 12 | -------------------------------------------------------------------------------- /app/views/admin/workshops/_virtual_workshop_fields.html.haml: -------------------------------------------------------------------------------- 1 | .card.bg-light.border-info.mt-4.mt-md-0 2 | .card-body 3 | %p= t('admin.workshop.form.virtual_info') 4 | = f.input :virtual, as: :boolean 5 | = f.input :slack_channel 6 | = f.input :slack_channel_link 7 | = f.input :coach_spaces 8 | = f.input :student_spaces 9 | -------------------------------------------------------------------------------- /app/views/admin/workshops/_workshop.html.haml: -------------------------------------------------------------------------------- 1 | = render partial: 'admin/events/event', locals: { event: workshop, invitation: invitation } 2 | -------------------------------------------------------------------------------- /app/views/admin/workshops/edit.html.haml: -------------------------------------------------------------------------------- 1 | .container.py-4.py-lg-5 2 | .row.mb-4 3 | .col 4 | %h1 Edit Workshop 5 | 6 | = render partial: 'edit_form' 7 | -------------------------------------------------------------------------------- /app/views/admin/workshops/new.html.haml: -------------------------------------------------------------------------------- 1 | .container.py-4.py-lg-5 2 | .row.mb-4 3 | .col 4 | %h1 New Workshop 5 | 6 | = render partial: 'form' 7 | -------------------------------------------------------------------------------- /app/views/chapter/_subscriptions.html.haml: -------------------------------------------------------------------------------- 1 | - @chapter.groups.each do |group| 2 | - if belongs_to_group?(group) 3 | %span{ title: "Unsubscribe from #{@chapter.name} #{group.name}" } 4 | = link_to subscriptions_path(subscription: { group_id: group }), method: 'delete', class: 'btn btn-success' do 5 | = group.name 6 | %i.fas.fa-check 7 | - else 8 | %span{ title: "Subscribe to #{@chapter.name} #{group.name}" } 9 | = link_to subscriptions_path(subscription: { group_id: group }), method: 'post', class: 'btn btn-secondary' do 10 | = group.name 11 | %i.fas.fa-rss 12 | -------------------------------------------------------------------------------- /app/views/coach/_coach.html.haml: -------------------------------------------------------------------------------- 1 | .py-4.py-lg-5.bg-light 2 | .container 3 | .row 4 | - coaches.each do |coach| 5 | .col-sm-6.col-md-3.coach.mb-4 6 | .text-center.mb-4 7 | = link_to twitter_url_for(coach.twitter), class: 'border-0' do 8 | = image_tag(coach.avatar(50), class: 'rounded-circle', title: coach.full_name, alt: coach.full_name) 9 | 10 | = link_to twitter_url_for(coach.twitter) do 11 | = coach.full_name 12 | %p.small.mt-3= coach.about_you 13 | - if coach.skills.any? 14 | %p.small 15 | Skills: 16 | - coach.skills.each do |skill| 17 | = skill.name 18 | 19 | = render partial: 'shared/pagination', locals: { pagy: @pagy, model: 'coach' } -------------------------------------------------------------------------------- /app/views/contact_mailer/subscription_notification.html.haml: -------------------------------------------------------------------------------- 1 | Hi #{@contact.name}, 2 | 3 | %p 4 | You have been subscribed to codebar's sponsors mailing list. To opt-out follow the link below: 5 | %br 6 | =link_to 'Update subscription preferences', full_url_for(contact_preferences_url(token: @contact.token)), class: 'btn' 7 | -------------------------------------------------------------------------------- /app/views/contact_preferences/show.html.haml: -------------------------------------------------------------------------------- 1 | .container.py-4.py-lg-5 2 | .row.justify-content-md-center 3 | .col-md-10.col-lg-8 4 | %h1 Contact Preferences 5 | - if @contact.present? 6 | = simple_form_for @contact, url: :contact_preferences, method: :put do |f| 7 | = f.hidden_field :token, value: @contact.token 8 | = f.input :mailing_list_consent, label: 'Sponsors mailing list', hint_html: { class: 'd-block ms-1' } 9 | = f.button :button, 'Update', class: 'btn btn-primary' 10 | -------------------------------------------------------------------------------- /app/views/events/_event_sponsors.html.haml: -------------------------------------------------------------------------------- 1 | .row 2 | .col 3 | %h2.text-center 4 | = t('events.sponsors') 5 | %p.text-center 6 | %i= t('events.thx_to_sponsors') 7 | - if event.sponsors?(:gold) 8 | .row.mt-4 9 | .col 10 | %h3.text-center Gold 11 | = render partial: 'shared/sponsors', object: event.gold_sponsors 12 | - if event.sponsors?(:silver) 13 | .row.mt-4 14 | .col 15 | %h3.text-center Silver 16 | = render partial: 'shared/sponsors', object: event.silver_sponsors 17 | - if event.sponsors?(:bronze) 18 | .row.mt-4 19 | .col 20 | %h3.text-center Bronze 21 | = render partial: 'shared/sponsors', object: event.bronze_sponsors 22 | - if event.sponsors?(:standard) 23 | = render partial: 'shared/sponsors', object: event.sponsors -------------------------------------------------------------------------------- /app/views/events/_events.html.haml: -------------------------------------------------------------------------------- 1 | - grouped_events.each do |date, workshops| 2 | .row 3 | .col-12 4 | %h3.h5= date 5 | .row 6 | .col-md-8 7 | = render workshops 8 | -------------------------------------------------------------------------------- /app/views/events/index.html.haml: -------------------------------------------------------------------------------- 1 | - title t('events.title') 2 | 3 | .container{'data-test': 'upcoming-events'} 4 | .row 5 | .col 6 | - if @events.any? 7 | %h3.mb-4 Upcoming Events 8 | = render partial: 'events', locals: { grouped_events: @events } 9 | 10 | .container{'data-test': 'past-events'} 11 | .row 12 | .col 13 | - if @past_events.any? 14 | %h3.mb-4 Past Events 15 | = render partial: 'events', locals: { grouped_events: @past_events } 16 | -------------------------------------------------------------------------------- /app/views/invitation/_coach.html.haml: -------------------------------------------------------------------------------- 1 | %p 2 | = t('coaches.read_before') 3 | = succeed ',' do 4 | =link_to t('coaches.code_of_conduct'), "http://codebar.io/code-of-conduct" 5 | = t('coaches.policy') 6 | = succeed '.' do 7 | = link_to t('coaches.guide'), teaching_guide_path 8 | %p 9 | = t('coaches.unable_attend') 10 | 11 | %p 12 | - if @workshop.virtual? 13 | = t('workshop.virtual.invitation.shared_intro_3_html', email_link: mail_to(@workshop.chapter.email, @workshop.chapter.email)) 14 | - else 15 | %p= t('workshop.invitation.shared_intro_4_html', email_link: mail_to(@workshop.chapter.email, @workshop.chapter.email).html_safe) 16 | -------------------------------------------------------------------------------- /app/views/invitation/_student.html.haml: -------------------------------------------------------------------------------- 1 | %p= t('workshop.invitation.student_intro_1') 2 | %p= t('workshop.invitation.student_intro_2') 3 | - if @workshop.virtual? 4 | %p= t('workshop.virtual.invitation.shared_intro_3_html', email_link: mail_to(@workshop.chapter.email, @workshop.chapter.email)) 5 | - else 6 | %p= t('workshop.invitation.student_intro_3_html') 7 | %p= t('workshop.invitation.shared_intro_4_html', email_link: mail_to(@workshop.chapter.email, @workshop.chapter.email).html_safe) 8 | -------------------------------------------------------------------------------- /app/views/layouts/_messages.html.haml: -------------------------------------------------------------------------------- 1 | - flash.each do |name, msg| 2 | - unless (name.eql?('notice') && @suppress_notices) || (name.eql?('warning') && @suppress_warnings) 3 | - name = name.eql?('notice') ? 'info' : name 4 | - if msg.is_a?(String) 5 | .alert.alert-dismissible.fade.show.mb-0{ 'data-alert': '', class: "alert-#{name}", role: 'alert' } 6 | = content_tag :div, msg.html_safe 7 | %button.btn-close{ type: 'button', 'data-bs-dismiss': 'alert', 'aria-label': 'Close' } 8 | - elsif msg.is_a?(Array) 9 | - msg.each do |message| 10 | .alert.alert-dismissible.fade.show.mb-0{ 'data-alert': '', class: "alert-#{name}", role: 'alert' } 11 | = content_tag :span, message.html_safe 12 | %button.btn-close{ type: 'button', 'data-bs-dismiss': 'alert', 'aria-label': 'Close' } 13 | 14 | -------------------------------------------------------------------------------- /app/views/layouts/mailer.html.erb: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | 5 | 8 | 9 | 10 | 11 | <%= yield %> 12 | 13 | 14 | -------------------------------------------------------------------------------- /app/views/layouts/mailer.text.erb: -------------------------------------------------------------------------------- 1 | <%= yield %> 2 | -------------------------------------------------------------------------------- /app/views/meeting_invitation_mailer/_agenda.html.haml: -------------------------------------------------------------------------------- 1 | .content 2 | %table 3 | %tr 4 | %td 5 | %h4 Agenda 6 | %p= @meeting.description.html_safe 7 | -------------------------------------------------------------------------------- /app/views/meeting_invitation_mailer/_cancel_attendance.html.haml: -------------------------------------------------------------------------------- 1 | .content 2 | %table 3 | %tr 4 | %td 5 | %h4 6 | Can't make it anymore? 7 | %p 8 | = "Please #{link_to 'cancel your attendance', @cancellation_url} by following the instructions on the event page.".html_safe 9 | -------------------------------------------------------------------------------- /app/views/member_mailer/attendance_warning.html.haml: -------------------------------------------------------------------------------- 1 | %h1 Hi #{@member.name}, 2 | 3 | %p 4 | We noticed that you have missed more than 2 workshops that you have RSVP'd to. 5 | 6 | %p 7 | We have a three-strikes attendance policy for no-shows. This allows us to offer more opportunities to those who want to attend our heavily oversubscribed workshops. If you cannot make it to a workshop that you have RSVP'd to, please remember to update your attendance details through our website before 3:30PM, at the latest, on the day of the event. 8 | 9 | %p 10 | Please be advised that if you miss one more workshop, we will temporarily suspend your membership for one month and you will not be able to attend any of our workshops for that period of time. 11 | 12 | %p 13 | Thank you for your understanding. 14 | 15 | %p 16 | #{"-- "} 17 | %br 18 | The codebar organisational team 19 | -------------------------------------------------------------------------------- /app/views/members/_avatar_listing.html.haml: -------------------------------------------------------------------------------- 1 | - member.each do |member| 2 | .col-sm-4.col-md-3.mt-4 3 | = link_to twitter_url_for(member.twitter), class: 'border-0' do 4 | = image_tag(member.avatar(56), class: 'rounded-circle', title: member.full_name, alt: member.full_name) 5 | %p.mt-3= member.full_name 6 | - if show_info 7 | %p.mt-1= member.mobile 8 | -------------------------------------------------------------------------------- /app/views/members/_organisers_grid.html.haml: -------------------------------------------------------------------------------- 1 | - title = local_assigns[:title] ? local_assigns[:title] : t('events.organisers') 2 | 3 | #organisers.text-center 4 | .row 5 | .col 6 | %h2= title 7 | 8 | .row 9 | = render partial: 'members/avatar_listing', locals: { member: members, show_info: show_info } 10 | -------------------------------------------------------------------------------- /app/views/members/edit.html.haml: -------------------------------------------------------------------------------- 1 | .container.py-4.py-lg-5 2 | .row 3 | .col 4 | %h1 Update your details 5 | %p.lead.text-muted Please make sure your details are always up to date. 6 | 7 | .container.pb-4.pb-lg-5 8 | .row 9 | .col-12.col-lg-3.mb-4 10 | .bg-light.p-3 11 | .d-flex.d-lg-block.align-items-center.text-lg-center 12 | = image_tag(current_user.avatar(80), alt: current_user.full_name, class: 'rounded-circle mb-lg-2') 13 | %p.mb-0.ms-2.ms-lg-0 14 | You can change your avatar at 15 | = link_to('gravatar.com.', 'http://en.gravatar.com/') 16 | .col-12.col-lg-8.offset-lg-1.mb-4 17 | = render partial: 'members/new', locals: { submit_text: 'Save' } 18 | -------------------------------------------------------------------------------- /app/views/pages/breach-code-of-conduct.html.haml: -------------------------------------------------------------------------------- 1 | .container.py-4.py-lg-5 2 | .row.justify-content-md-center 3 | .col-md-10.col-lg-8 4 | :markdown 5 | # #{t('pages.breach.title')} 6 | 7 | .py-4.py-lg-5.bg-light 8 | .container 9 | .row.justify-content-md-center 10 | .col-md-10.col-lg-8 11 | :markdown 12 | #{t('pages.breach.opening_para')} 13 | 14 | #{t('pages.breach.second_para')} 15 | 16 | #{t('pages.breach.outcome_title')} 17 | 18 | - #{t('pages.breach.correction')} 19 | 20 | - #{t('pages.breach.warning')} 21 | 22 | - #{t('pages.breach.lifetime_ban')} 23 | 24 | #{t('pages.breach.closing_para')} 25 | -------------------------------------------------------------------------------- /app/views/pages/codebar-stories-podcast.html.haml: -------------------------------------------------------------------------------- 1 | .div.mb-5 2 | = image_tag 'codebar-stories-banner.png', alt: t('pages.codebar_stories_podcast.image_alt'), class: 'mw-100' 3 | 4 | .container.mb-5 5 | .row.justify-content-md-center 6 | .col-12.col-md-7.text-center 7 | %p.lead= t('pages.codebar_stories_podcast.opening') 8 | 9 | 10 | .container.mb-5 11 | .row.justify-content-md-center 12 | .col-12.col-md-8 13 | 14 | 15 | 16 | .container.mb-5 17 | .row.justify-content-md-center 18 | .col-12.col-md-7.text-center.border.border-3.border-primary 19 | %p.lead.pt-3= t('pages.codebar_stories_podcast.contact_us_html', email: 'podcast@codebar.io') 20 | -------------------------------------------------------------------------------- /app/views/public_activity/sponsor/_admin_contact_subscribe.html.haml: -------------------------------------------------------------------------------- 1 | - if activity.recipient.present? 2 | %li #{link_to(activity.owner.full_name, admin_member_path(activity.owner))} subscribed #{activity&.recipient.name} #{activity&.recipient.surname} with email #{activity.parameters[:note]} to the Sponsor newsletter 3 | -------------------------------------------------------------------------------- /app/views/public_activity/sponsor/_admin_contact_unsubscribe.html.haml: -------------------------------------------------------------------------------- 1 | - if activity.recipient.present? 2 | %li #{link_to(activity.owner.full_name, admin_member_path(activity.owner))} unsubscribed #{activity.recipient.name} #{activity.recipient.surname} with email #{activity.parameters[:note]} from the Sponsor newsletter 3 | -------------------------------------------------------------------------------- /app/views/public_activity/sponsor/_contact_subscribe.html.haml: -------------------------------------------------------------------------------- 1 | %li #{activity.owner.name} #{activity.owner.surname} with email #{activity.parameters[:note]} subscribed to the Sponsor newsletter 2 | -------------------------------------------------------------------------------- /app/views/public_activity/sponsor/_contact_unsubscribe.html.haml: -------------------------------------------------------------------------------- 1 | %li #{activity.owner.name} #{activity.owner.surname} with email #{activity.parameters[:note]} unsubscribed from the Sponsor newsletter 2 | -------------------------------------------------------------------------------- /app/views/shared/_announcements.html.haml: -------------------------------------------------------------------------------- 1 | .mb-4 2 | - @announcements.each do |announcement| 3 | .alert.alert-primary.announcement 4 | = dot_markdown(announcement.message) 5 | -------------------------------------------------------------------------------- /app/views/shared/_festival_banner.html.haml: -------------------------------------------------------------------------------- 1 | .container-fluid.py-4.festival-banner 2 | .row.justify-content-md-center 3 | .col-lg-8 4 | .row 5 | .col-md-4.mb-4.mb-md-0 6 | = link_to image_tag('festival/codebar-festival-logo-light.png', style: 'max-width: 218px;', alt: 'codebar Festival logo'), 'https://festival.codebar.io/', class: 'border-0' 7 | .col-md 8 | %p.text-white.mb-2 9 | %strong 4 - 9th March 2024 10 | %p.text-white.mb-0 Build a holistic career in tech with us at codebar Festival! Join us on the 4th, 5th, 6th, 7th, and 9th of March for 5 days of workshops, talks, panels and networking opportunities. #{link_to 'Checkout out the schedule and RSVP here', 'https://festival.codebar.io', class: 'link-light border-0 text-decoration-underline'}. 11 | -------------------------------------------------------------------------------- /app/views/shared/_pagination.html.haml: -------------------------------------------------------------------------------- 1 | .row.align-items-center.justify-content-between 2 | .col-auto 3 | %p.mb-3 4 | != pagy_info(pagy, item_name: model.pluralize(pagy.count)) 5 | .col-auto 6 | != pagy_bootstrap_nav(pagy) if pagy.pages > 1 -------------------------------------------------------------------------------- /app/views/shared/_sponsors.html.haml: -------------------------------------------------------------------------------- 1 | .row.d-flex.align-items-center.justify-content-center 2 | - sponsors.each do |sponsor| 3 | .col-4.col-md-3.col-lg-2.mt-4.d-flex.justify-content-center 4 | = link_to image_tag(sponsor.avatar.url, alt: sponsor.name, class: 'small-image mw-100'), sponsor.website, title: sponsor.name, class: 'border-0 mw-100' 5 | -------------------------------------------------------------------------------- /app/views/shared_mailers/_body_header.html.haml: -------------------------------------------------------------------------------- 1 | %table.head-wrap{ bgcolor: "#fdfdfd" } 2 | %tr 3 | %td 4 | %td.header.container 5 | .content 6 | %table{ bgcolor: "#fdfdfd" } 7 | %tr 8 | %td{ width: "40%" } 9 | // TODO: maybe get this from codebar.io 10 | = image_tag("https://raw.githubusercontent.com/codebar/assets/master/logo/png/website-logo.png", alt: "codebar logo") 11 | %td{ align: "right" } 12 | %h6.collapse= title 13 | %td 14 | -------------------------------------------------------------------------------- /app/views/shared_mailers/_footer.html.haml: -------------------------------------------------------------------------------- 1 | %table.footer-wrap 2 | %tr 3 | %td 4 | %td.container 5 | .content 6 | %table 7 | %tr 8 | %td{ align: "center" } 9 | %p 10 | %a{ href: full_url_for(unsubscribe_url(member_token(@member))) } 11 | %unsubscribe Unsubscribe 12 | %td 13 | -------------------------------------------------------------------------------- /app/views/shared_mailers/_header.html.haml: -------------------------------------------------------------------------------- 1 | !!! 2 | %html{ xmlns: "http://www.w3.org/1999/xhtml" } 3 | %head 4 | %meta{name: "viewport", content: "width=device-width" } 5 | 6 | %meta{ 'http-equiv' => "Content-Type", content: "text/html; charset=UTF-8" } 7 | %title=title 8 | 9 | %link{rel: "stylesheet", type: "text/css", href: "/assets/email.css"} 10 | -------------------------------------------------------------------------------- /app/views/shared_mailers/_venue.html.haml: -------------------------------------------------------------------------------- 1 | %tr 2 | %td 3 | %h4 Venue 4 | %tr 5 | %td{ width: '70%', style: 'vertical-align: top; padding-right: 20px;' } 6 | %p 7 | %strong #{host.name} 8 | %br 9 | #{address.to_html} 10 | - if host.address.directions.present? 11 | %p 12 | %strong Directions: 13 | %br 14 | #{host.address.directions} 15 | - if host.accessibility_info.present? 16 | %p 17 | %strong Accessibility information: 18 | %br 19 | #{host.accessibility_info} 20 | 21 | %td{ width: '30%', style: 'vertical-align: top;' } 22 | = image_tag(host.avatar.url, alt: host.name) 23 | -------------------------------------------------------------------------------- /app/views/terms_and_conditions/show.html.haml: -------------------------------------------------------------------------------- 1 | .container.py-4.py-lg-5 2 | .row.justify-content-md-center 3 | .col-md-10.col-lg-8 4 | %h1= t('terms_and_conditions.title') 5 | %p 6 | = t('terms_and_conditions.body') 7 | %br 8 | = link_to t('terms_and_conditions.link_text'), code_of_conduct_path, target: '_blank' 9 | 10 | = simple_form_for @terms_and_conditions_form, url: terms_and_conditions_path, method: :patch do |f| 11 | .row.justify-content-md-center 12 | .col-md-10.col-lg-8 13 | = f.input :terms, as: :boolean 14 | = f.button :button, t('terms_and_conditions.accept'), class: 'btn btn-primary mb-0' 15 | -------------------------------------------------------------------------------- /app/views/workshops/_workshop.html.haml: -------------------------------------------------------------------------------- 1 | = render partial: 'events/event', locals: { event: workshop } 2 | -------------------------------------------------------------------------------- /bin/bundle: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__) 3 | load Gem.bin_path('bundler', 'bundle') 4 | -------------------------------------------------------------------------------- /bin/dadmin: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -e 3 | 4 | if [ $# -gt 0 ] 5 | then 6 | docker compose exec web rails runner "Member.find_by(email: '$@').add_role(:admin)" 7 | else 8 | docker compose exec web rails runner "Member.last.add_role(:admin)" 9 | fi 10 | -------------------------------------------------------------------------------- /bin/ddown: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | 5 | docker compose down 6 | -------------------------------------------------------------------------------- /bin/delayed_job: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | require File.expand_path(File.join(File.dirname(__FILE__), '..', 'config', 'environment')) 4 | require 'delayed/command' 5 | Delayed::Command.new(ARGV).daemonize 6 | -------------------------------------------------------------------------------- /bin/dexec: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | 5 | docker compose exec web bash 6 | -------------------------------------------------------------------------------- /bin/drails: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | 5 | docker compose exec web rails $@ 6 | -------------------------------------------------------------------------------- /bin/drake: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | 5 | docker compose exec web rake $@ 6 | -------------------------------------------------------------------------------- /bin/drspec: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | 5 | docker compose exec web rspec $@ 6 | -------------------------------------------------------------------------------- /bin/dserver: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | 5 | docker compose exec web make serve 6 | -------------------------------------------------------------------------------- /bin/dstart: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | 5 | docker compose start 6 | -------------------------------------------------------------------------------- /bin/dstop: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | 5 | docker compose stop 6 | -------------------------------------------------------------------------------- /bin/dup: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | 5 | docker compose up --build --wait 6 | docker compose exec web bash -c "rake db:drop db:create db:migrate db:seed db:test:prepare" 7 | 8 | echo "Started." 9 | -------------------------------------------------------------------------------- /bin/rails: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | APP_PATH = File.expand_path('../config/application', __dir__) 3 | require_relative "../config/boot" 4 | require "rails/commands" 5 | -------------------------------------------------------------------------------- /bin/rake: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require_relative "../config/boot" 3 | require "rake" 4 | Rake.application.run 5 | -------------------------------------------------------------------------------- /bin/update: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require 'fileutils' 3 | include FileUtils 4 | 5 | # path to your application root. 6 | APP_ROOT = File.expand_path('..', __dir__) 7 | 8 | def system!(*args) 9 | system(*args) || abort("\n== Command #{args} failed ==") 10 | end 11 | 12 | chdir APP_ROOT do 13 | # This script is a way to update your development environment automatically. 14 | # Add necessary update steps to this file. 15 | 16 | puts '== Installing dependencies ==' 17 | system! 'gem install bundler --conservative' 18 | system('bundle check') || system!('bundle install') 19 | 20 | puts "\n== Updating database ==" 21 | system! 'bin/rails db:migrate' 22 | 23 | puts "\n== Removing old logs and tempfiles ==" 24 | system! 'bin/rails log:clear tmp:clear' 25 | 26 | puts "\n== Restarting application server ==" 27 | system! 'bin/rails restart' 28 | end 29 | -------------------------------------------------------------------------------- /config.ru: -------------------------------------------------------------------------------- 1 | # This file is used by Rack-based servers to start the application. 2 | 3 | require_relative 'config/environment' 4 | 5 | use Rack::Static, urls: ['/carrierwave'], root: 'tmp' 6 | run Rails.application 7 | Rails.application.load_server 8 | -------------------------------------------------------------------------------- /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 "logger" # Fix concurrent-ruby removing logger dependency which Rails itself does not have 5 | require "bootsnap/setup" # Speed up boot time by caching expensive operations. 6 | -------------------------------------------------------------------------------- /config/database.yml: -------------------------------------------------------------------------------- 1 | development: &default 2 | adapter: postgresql 3 | encoding: unicode 4 | database: planner_development 5 | pool: 5 6 | username: <%= ENV['DB_USER'] || '' %> 7 | password: <%= ENV['POSTGRES_PASSWORD'] || '' %> 8 | host: <%= (ENV['DB_HOST'] || 'localhost').to_json %> 9 | 10 | test: 11 | <<: *default 12 | database: planner_test 13 | pool: 5 14 | -------------------------------------------------------------------------------- /config/environment.rb: -------------------------------------------------------------------------------- 1 | # Load the Rails application. 2 | require_relative "application" 3 | 4 | # Initialize the Rails application. 5 | Rails.application.initialize! 6 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | 9 | # Precompile additional assets. 10 | # application.js, application.css, and all non-JS/CSS in the app/assets 11 | # folder are already added. 12 | # Rails.application.config.assets.precompile += %w( admin.js admin.css ) 13 | # TODO: consider moving as per upgrade guidance 14 | # https://github.com/rails/sprockets/blob/main/UPGRADING.md#manifestjs 15 | Rails.application.config.assets.precompile += %w(payments.js) 16 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /config/initializers/carrier_wave.rb: -------------------------------------------------------------------------------- 1 | CarrierWave.configure do |config| 2 | config.cache_storage = :file 3 | 4 | if Rails.env.development? 5 | config.storage = :file 6 | elsif Rails.env.production? 7 | config.cache_dir = "#{Rails.root}/tmp/uploads" 8 | config.root = Rails.root.join('tmp') 9 | config.sftp_host = ENV['UPLOADER_ASSET_HOST'] 10 | config.sftp_user = ENV['UPLOADER_USER'] 11 | config.sftp_folder = ENV['UPLOADER_FOLDER'] 12 | config.sftp_url = ENV['UPLOADER_URL'] 13 | config.sftp_options = { 14 | password: ENV['UPLOADER_PASSW'], 15 | port: 22 16 | } 17 | end 18 | end 19 | -------------------------------------------------------------------------------- /config/initializers/commonmarker.rb: -------------------------------------------------------------------------------- 1 | require 'commonmarker' 2 | -------------------------------------------------------------------------------- /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 = :marshal 6 | -------------------------------------------------------------------------------- /config/initializers/delayed_job.rb: -------------------------------------------------------------------------------- 1 | Delayed::Worker.destroy_failed_jobs = false 2 | Delayed::Worker.sleep_delay = 60 3 | Delayed::Worker.max_attempts = 3 4 | Delayed::Worker.max_run_time = 5.minutes 5 | Delayed::Worker.read_ahead = 10 6 | Delayed::Worker.default_queue_name = 'default' 7 | Delayed::Worker.delay_jobs = !Rails.env.test? 8 | Delayed::Worker.raise_signal_exceptions = :term 9 | Delayed::Worker.logger = Logger.new(File.join(Rails.root, 'log', 'delayed_job.log')) 10 | -------------------------------------------------------------------------------- /config/initializers/filter_parameter_logging.rb: -------------------------------------------------------------------------------- 1 | # Be sure to restart your server when you modify this file. 2 | 3 | # Configure parameters to be filtered from the log file. Use this to limit dissemination of 4 | # sensitive information. See the ActiveSupport::ParameterFilter documentation for supported 5 | # notations and behaviors. 6 | Rails.application.config.filter_parameters += [ 7 | :passw, :secret, :token, :_key, :crypt, :salt, :certificate, :otp, :ssn 8 | ] 9 | -------------------------------------------------------------------------------- /config/initializers/flodesk.rb: -------------------------------------------------------------------------------- 1 | require 'services/flodesk' 2 | 3 | key = Rails.env.test? ? 'test' : ENV['FLODESK_KEY'] 4 | Rails.logger.warn 'Missing FLODESK_KEY environment variable' unless key 5 | 6 | # We use Flodesk for newsletter sending, so we need both values 7 | Rails.logger.warn 'Missing NEWSLETTER_ID environment variable' unless ENV['NEWSLETTER_ID'] 8 | 9 | Flodesk::Client.api_key = key 10 | Flodesk::Client.complete_timeout = 15 11 | Flodesk::Client.open_timeout = 15 12 | -------------------------------------------------------------------------------- /config/initializers/haml_markdown.rb: -------------------------------------------------------------------------------- 1 | # Remove the haml_markdown initaliser. The internals changed so the monkey-patching to implement a custom render method 2 | # no longer works, but is also not necessary since the markdown filter uses CommonMarker anyway. 3 | 4 | # module Haml::Filters 5 | # remove_filter("Markdown") #remove the existing Markdown filter 6 | 7 | # module Markdown 8 | # include Haml::Filters::Base 9 | 10 | # def render(text) 11 | # CommonMarker.render_html(text, :DEFAULT).html_safe 12 | # end 13 | # end 14 | # end 15 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /config/initializers/locale.rb: -------------------------------------------------------------------------------- 1 | # The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded. 2 | # config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s] 3 | Rails.application.config.i18n.default_locale = :en 4 | Rails.application.config.i18n.fallbacks = true 5 | Rails.application.config.i18n.available_locales = [:en, :fr, :de] 6 | #config.i18n.enforce_available_locales = false 7 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /config/initializers/omniauth.rb: -------------------------------------------------------------------------------- 1 | Rails.application.config.middleware.use OmniAuth::Builder do 2 | if ENV['GITHUB_KEY'].blank? || ENV['GITHUB_SECRET'].blank? 3 | warn '*' * 80 4 | warn 'WARNING: Missing consumer key or secret. First, register an app with Github' 5 | warn 'Check README.md for instructions on how to set up Github Authentication.' 6 | warn '*' * 80 7 | if Rails.env.test? 8 | provider :github, 'fakekey', 'fakesecret', scope: 'user:email' 9 | end 10 | else 11 | provider :github, ENV['GITHUB_KEY'], ENV['GITHUB_SECRET'], scope: 'user:email' 12 | end 13 | end 14 | 15 | OmniAuth.config.allowed_request_methods = [:post, :get] 16 | OmniAuth.config.silence_get_warning = true 17 | -------------------------------------------------------------------------------- /config/initializers/permissions_policy.rb: -------------------------------------------------------------------------------- 1 | # Define an application-wide HTTP permissions policy. For further 2 | # information see https://developers.google.com/web/updates/2018/06/feature-policy 3 | # 4 | # Rails.application.config.permissions_policy do |f| 5 | # f.camera :none 6 | # f.gyroscope :none 7 | # f.microphone :none 8 | # f.usb :none 9 | # f.fullscreen :self 10 | # f.payment :self, "https://secure.example.com" 11 | # end 12 | -------------------------------------------------------------------------------- /config/initializers/premailer.rb: -------------------------------------------------------------------------------- 1 | Premailer::Rails.config.merge!(preserve_styles: true) 2 | -------------------------------------------------------------------------------- /config/initializers/rolify.rb: -------------------------------------------------------------------------------- 1 | 2 | # Wrapped to autoload safely at boot time 3 | Rails.application.reloader.to_prepare do 4 | Rolify.configure('Permission') do |config| 5 | # By default ORM adapter is ActiveRecord. uncomment to use mongoid 6 | # config.use_mongoid 7 | 8 | # Dynamic shortcuts for User class (user.is_admin? like methods). Default is: false 9 | # Enable this feature _after_ running rake db:migrate as it relies on the roles table 10 | config.use_dynamic_shortcuts 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /config/initializers/secret_token.rb: -------------------------------------------------------------------------------- 1 | key = ENV['PLANNER_SECRET'] 2 | key = 'sample-key' if Rails.env.development? || Rails.env.test? 3 | 4 | Rails.application.config.secret_key_base = key 5 | 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: '_planner_session', 4 | expire_after: 24.hours 5 | -------------------------------------------------------------------------------- /config/initializers/stripe.rb: -------------------------------------------------------------------------------- 1 | Rails.configuration.stripe = { 2 | publishable_key: ENV['STRIPE_PUBLISHABLE_KEY'], 3 | secret_key: ENV['STRIPE_SECRET_KEY'] 4 | } 5 | 6 | Stripe.api_key = Rails.configuration.stripe[:secret_key] 7 | -------------------------------------------------------------------------------- /config/initializers/twitter.rb: -------------------------------------------------------------------------------- 1 | Rails.application.config.twitter = ENV['HQ_TWITTER_HANDLE'] 2 | Rails.application.config.twitter_id = ENV['HQ_TWITTER_ID'] 3 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /config/locales/en.rb: -------------------------------------------------------------------------------- 1 | { 2 | en: { 3 | date: { 4 | formats: { 5 | humanised: lambda { |time, _| "%a, #{time.day.ordinalize} %B" }, 6 | } 7 | }, 8 | time: { 9 | formats: { 10 | humanised: lambda { |time, _| "%a, #{time.day.ordinalize} %B" }, 11 | humanised_with_time: lambda { |time, _| "%a, #{time.day.ordinalize} %B | %H:%M" }, 12 | humanised_with_year: lambda { |time, _| "%a, #{time.day.ordinalize} %B %Y | %H:%M" } 13 | } 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /config/locales/simple_form.fr.yml: -------------------------------------------------------------------------------- 1 | fr: 2 | simple_form: 3 | "yes": 'Oui' 4 | "no": 'Non' 5 | required: 6 | text: 'requis' 7 | mark: '*' 8 | # You can uncomment the line below if you need to overwrite the whole required html. 9 | # When using html, text and mark won't be used. 10 | # html: '*' 11 | error_notification: 12 | default_message: "Veuillez corriger les problèmes ci-dessous:" 13 | # Labels and hints examples 14 | # labels: 15 | # defaults: 16 | # password: 'Password' 17 | # user: 18 | # new: 19 | # email: 'E-mail to sign in.' 20 | # edit: 21 | # email: 'E-mail.' 22 | # hints: 23 | # defaults: 24 | # username: 'User name to sign in.' 25 | # password: 'No special characters, please.' 26 | -------------------------------------------------------------------------------- /config/newrelic.yml: -------------------------------------------------------------------------------- 1 | common: &default_settings 2 | license_key: <%= ENV['NEW_RELIC_LICENSE_KEY'] %> 3 | app_name: 'codebar.io' 4 | log_level: info 5 | 6 | development: 7 | <<: *default_settings 8 | app_name: 'codebar.io (Development)' 9 | log_level: debug 10 | 11 | test: 12 | <<: *default_settings 13 | monitor_mode: false 14 | 15 | staging: 16 | <<: *default_settings 17 | app_name: 'codebar.io (Staging)' 18 | 19 | production: 20 | <<: *default_settings 21 | -------------------------------------------------------------------------------- /crowdin.yml: -------------------------------------------------------------------------------- 1 | files: 2 | - source: /config/locales/en.yml 3 | translation: /config/locales/%osx_locale%.yml 4 | -------------------------------------------------------------------------------- /db/migrate/20131017221407_create_members.rb: -------------------------------------------------------------------------------- 1 | class CreateMembers < ActiveRecord::Migration[4.2] 2 | def change 3 | create_table :members do |t| 4 | t.string :name 5 | t.string :surname 6 | t.string :email 7 | t.string :twitter 8 | t.string :about_you 9 | 10 | t.timestamps 11 | end 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /db/migrate/20131020223957_create_sessions.rb: -------------------------------------------------------------------------------- 1 | class CreateSessions < ActiveRecord::Migration[4.2] 2 | def change 3 | create_table :sessions do |t| 4 | t.string :title 5 | t.text :description 6 | t.datetime :date_and_time 7 | 8 | t.timestamps 9 | end 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /db/migrate/20131020235644_create_invitations.rb: -------------------------------------------------------------------------------- 1 | class CreateInvitations < ActiveRecord::Migration[4.2] 2 | def change 3 | create_table :invitations do |t| 4 | t.references :sessions, index: true 5 | t.references :member, index: true 6 | t.boolean :attending 7 | t.boolean :attended 8 | t.text :note 9 | 10 | t.timestamps 11 | end 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /db/migrate/20131021011352_add_token_to_invitation.rb: -------------------------------------------------------------------------------- 1 | class AddTokenToInvitation < ActiveRecord::Migration[4.2] 2 | def change 3 | add_column :invitations, :token, :string 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20131021011859_add_index_to_invitation_token.rb: -------------------------------------------------------------------------------- 1 | class AddIndexToInvitationToken < ActiveRecord::Migration[4.2] 2 | def change 3 | add_index :invitations, :token, unique: true 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20131021040356_add_unsubscribed_to_member.rb: -------------------------------------------------------------------------------- 1 | class AddUnsubscribedToMember < ActiveRecord::Migration[4.2] 2 | def change 3 | add_column :members, :unsubscribed, :boolean 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20131021182241_add_seats_to_session.rb: -------------------------------------------------------------------------------- 1 | class AddSeatsToSession < ActiveRecord::Migration[4.2] 2 | def change 3 | add_column :sessions, :seats, :integer, default: 15 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20131024223507_create_roles.rb: -------------------------------------------------------------------------------- 1 | class CreateRoles < ActiveRecord::Migration[4.2] 2 | def change 3 | create_table :roles do |t| 4 | t.string :name 5 | t.string :description 6 | 7 | t.timestamps 8 | end 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /db/migrate/20131024224307_create_member_role.rb: -------------------------------------------------------------------------------- 1 | class CreateMemberRole < ActiveRecord::Migration[4.2] 2 | def change 3 | create_table :members_roles, id: false do |t| 4 | t.references :member 5 | t.references :role 6 | end 7 | add_index :members_roles, %i[member_id role_id] 8 | add_index :members_roles, :member_id 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /db/migrate/20131029210620_create_courses.rb: -------------------------------------------------------------------------------- 1 | class CreateCourses < ActiveRecord::Migration[4.2] 2 | def change 3 | create_table :courses do |t| 4 | t.string :title 5 | t.string :short_description 6 | t.text :description 7 | t.integer :tutor_id, index: true 8 | t.datetime :date_and_time 9 | t.integer :seats, default: 0 10 | t.string :slug 11 | t.string :url 12 | 13 | t.timestamps 14 | end 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /db/migrate/20131102132756_create_sponsors.rb: -------------------------------------------------------------------------------- 1 | class CreateSponsors < ActiveRecord::Migration[4.2] 2 | def change 3 | create_table :sponsors do |t| 4 | t.string :name 5 | t.text :description 6 | t.timestamps 7 | end 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /db/migrate/20131102141049_create_address.rb: -------------------------------------------------------------------------------- 1 | class CreateAddress < ActiveRecord::Migration[4.2] 2 | def change 3 | create_table :addresses do |t| 4 | t.string :flat 5 | t.string :street 6 | t.string :postal_code 7 | t.belongs_to :sponsor 8 | t.timestamps 9 | end 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /db/migrate/20131103174325_create_sponsor_sessions.rb: -------------------------------------------------------------------------------- 1 | class CreateSponsorSessions < ActiveRecord::Migration[4.2] 2 | def change 3 | create_table :sponsor_sessions do |t| 4 | t.belongs_to :sponsor, index: true 5 | t.belongs_to :sessions, index: true 6 | t.boolean :host, default: false 7 | t.timestamps 8 | end 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /db/migrate/20131103210723_rename_invitations_to_session_invitations.rb: -------------------------------------------------------------------------------- 1 | class RenameInvitationsToSessionInvitations < ActiveRecord::Migration[4.2] 2 | def change 3 | rename_table :invitations, :session_invitations 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20131103212835_create_course_invitations.rb: -------------------------------------------------------------------------------- 1 | class CreateCourseInvitations < ActiveRecord::Migration[4.2] 2 | def change 3 | create_table :course_invitations do |t| 4 | t.references :course, index: true 5 | t.references :member, index: true 6 | t.boolean :attending 7 | t.boolean :attended 8 | t.text :note 9 | t.string :token 10 | 11 | t.timestamps 12 | end 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /db/migrate/20131104030726_create_reminders.rb: -------------------------------------------------------------------------------- 1 | class CreateReminders < ActiveRecord::Migration[4.2] 2 | def change 3 | create_table :reminders do |t| 4 | t.string :reminder_type 5 | t.string :reminder_id 6 | t.datetime :date_and_time 7 | t.integer :count 8 | 9 | t.timestamps 10 | end 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /db/migrate/20131107182457_add_avatar_to_sponsor.rb: -------------------------------------------------------------------------------- 1 | class AddAvatarToSponsor < ActiveRecord::Migration[4.2] 2 | def change 3 | add_column :sponsors, :avatar, :string 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20131110220757_add_website_to_sponsor.rb: -------------------------------------------------------------------------------- 1 | class AddWebsiteToSponsor < ActiveRecord::Migration[4.2] 2 | def change 3 | add_column :sponsors, :website, :string 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20131111024701_add_role_to_session_invitations.rb: -------------------------------------------------------------------------------- 1 | class AddRoleToSessionInvitations < ActiveRecord::Migration[4.2] 2 | def change 3 | add_column :session_invitations, :role, :string 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20131112221451_remove_seats_from_sessions.rb: -------------------------------------------------------------------------------- 1 | class RemoveSeatsFromSessions < ActiveRecord::Migration[4.2] 2 | def change 3 | remove_column :sessions, :seats, :integer 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20131112221641_add_seats_to_sponsor.rb: -------------------------------------------------------------------------------- 1 | class AddSeatsToSponsor < ActiveRecord::Migration[4.2] 2 | def change 3 | add_column :sponsors, :seats, :integer, default: 15 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20131130211001_create_tutorials.rb: -------------------------------------------------------------------------------- 1 | class CreateTutorials < ActiveRecord::Migration[4.2] 2 | def change 3 | create_table :tutorials do |t| 4 | t.string :name 5 | t.text :description 6 | t.string :url 7 | t.references :sessions, index: true 8 | 9 | t.timestamps 10 | end 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /db/migrate/20131130211305_create_feedbacks.rb: -------------------------------------------------------------------------------- 1 | class CreateFeedbacks < ActiveRecord::Migration[4.2] 2 | def change 3 | create_table :feedbacks do |t| 4 | t.references :tutorial, index: true 5 | t.text :request 6 | t.references :coach, index: true 7 | t.text :suggestions 8 | 9 | t.timestamps 10 | end 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /db/migrate/20131201091346_rename_tutorials_table_name_column_to_title.rb: -------------------------------------------------------------------------------- 1 | class RenameTutorialsTableNameColumnToTitle < ActiveRecord::Migration[4.2] 2 | def change 3 | rename_column :tutorials, :name, :title 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20131208030221_create_meetings.rb: -------------------------------------------------------------------------------- 1 | class CreateMeetings < ActiveRecord::Migration[4.2] 2 | def change 3 | create_table :meetings do |t| 4 | t.datetime :date_and_time 5 | t.integer :duration, default: 120 6 | t.string :lanyrd_url 7 | t.integer :venue_id, index: true 8 | 9 | t.timestamps 10 | end 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /db/migrate/20131208030336_create_meeting_talks.rb: -------------------------------------------------------------------------------- 1 | class CreateMeetingTalks < ActiveRecord::Migration[4.2] 2 | def change 3 | create_table :meeting_talks do |t| 4 | t.references :meeting, index: true 5 | t.string :title 6 | t.string :description 7 | t.text :abstract 8 | t.integer :speaker_id, index: true 9 | 10 | t.timestamps 11 | end 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /db/migrate/20131208141447_create_auth_services.rb: -------------------------------------------------------------------------------- 1 | class CreateAuthServices < ActiveRecord::Migration[4.2] 2 | def change 3 | create_table :auth_services do |t| 4 | t.references :member, index: true 5 | t.string :provider 6 | t.string :uid 7 | 8 | t.timestamps 9 | end 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /db/migrate/20131208145950_add_can_log_in_to_users.rb: -------------------------------------------------------------------------------- 1 | class AddCanLogInToUsers < ActiveRecord::Migration[4.2] 2 | def change 3 | add_column :members, :can_log_in, :boolean, null: false, default: false 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20131221204400_add_token_to_feedbacks.rb: -------------------------------------------------------------------------------- 1 | class AddTokenToFeedbacks < ActiveRecord::Migration[4.2] 2 | def change 3 | add_column :feedbacks, :token, :string 4 | add_index :feedbacks, :token, unique: true 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /db/migrate/20131222160002_add_rating_to_feedbacks.rb: -------------------------------------------------------------------------------- 1 | class AddRatingToFeedbacks < ActiveRecord::Migration[4.2] 2 | def change 3 | add_column :feedbacks, :rating, :integer 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20140119093708_create_feedback_requests.rb: -------------------------------------------------------------------------------- 1 | class CreateFeedbackRequests < ActiveRecord::Migration[4.2] 2 | def change 3 | create_table :feedback_requests do |t| 4 | t.references :member, index: true 5 | t.references :sessions, index: true 6 | t.string :token 7 | t.boolean :submited 8 | 9 | t.timestamps 10 | end 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /db/migrate/20140202112853_remove_token_from_feedbacks.rb: -------------------------------------------------------------------------------- 1 | class RemoveTokenFromFeedbacks < ActiveRecord::Migration[4.2] 2 | def change 3 | remove_column :feedbacks, :token, :string 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20140329201235_add_phone_number_to_members.rb: -------------------------------------------------------------------------------- 1 | class AddPhoneNumberToMembers < ActiveRecord::Migration[4.2] 2 | def change 3 | add_column :members, :mobile, :string 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20140403004924_create_course_tutors.rb: -------------------------------------------------------------------------------- 1 | class CreateCourseTutors < ActiveRecord::Migration[4.2] 2 | def change 3 | create_table :course_tutors do |t| 4 | t.belongs_to :course, index: true 5 | t.belongs_to :tutor, index: true 6 | 7 | t.timestamps 8 | end 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /db/migrate/20140417151614_add_name_to_meeting.rb: -------------------------------------------------------------------------------- 1 | class AddNameToMeeting < ActiveRecord::Migration[4.2] 2 | def change 3 | add_column :meetings, :name, :string 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20140417152406_add_description_to_meeting.rb: -------------------------------------------------------------------------------- 1 | class AddDescriptionToMeeting < ActiveRecord::Migration[4.2] 2 | def change 3 | add_column :meetings, :description, :string 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20140417154809_add_slug_to_meeting.rb: -------------------------------------------------------------------------------- 1 | class AddSlugToMeeting < ActiveRecord::Migration[4.2] 2 | def change 3 | add_column :meetings, :slug, :string 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20140425155706_add_host_to_course.rb: -------------------------------------------------------------------------------- 1 | class AddHostToCourse < ActiveRecord::Migration[4.2] 2 | def change 3 | add_reference :courses, :sponsor, index: true 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20140425160722_add_ticket_url_to_course.rb: -------------------------------------------------------------------------------- 1 | class AddTicketUrlToCourse < ActiveRecord::Migration[4.2] 2 | def change 3 | add_column :courses, :ticket_url, :string 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20140501015844_add_verified_to_member.rb: -------------------------------------------------------------------------------- 1 | class AddVerifiedToMember < ActiveRecord::Migration[4.2] 2 | def change 3 | add_column :members, :verified, :boolean 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20140504143819_create_job.rb: -------------------------------------------------------------------------------- 1 | class CreateJob < ActiveRecord::Migration[4.2] 2 | def change 3 | create_table :jobs do |t| 4 | t.string :title 5 | t.text :description 6 | t.string :location 7 | t.datetime :expiry_date 8 | t.string :email 9 | t.string :link_to_job 10 | t.references :created_by, index: true 11 | t.boolean :approved, default: false 12 | t. boolean :submitted, default: false 13 | 14 | t.timestamps 15 | end 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /db/migrate/20140504171455_add_company_to_job.rb: -------------------------------------------------------------------------------- 1 | class AddCompanyToJob < ActiveRecord::Migration[4.2] 2 | def change 3 | add_column :jobs, :company, :string 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20140510232842_add_invitable_to_session.rb: -------------------------------------------------------------------------------- 1 | class AddInvitableToSession < ActiveRecord::Migration[4.2] 2 | def change 3 | add_column :sessions, :invitable, :boolean, default: true 4 | add_column :sessions, :sign_up_url, :string 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /db/migrate/20140510234035_add_city_to_address.rb: -------------------------------------------------------------------------------- 1 | class AddCityToAddress < ActiveRecord::Migration[4.2] 2 | def change 3 | add_column :addresses, :city, :string 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20140610130020_create_chapters.rb: -------------------------------------------------------------------------------- 1 | class CreateChapters < ActiveRecord::Migration[4.2] 2 | def change 3 | create_table :chapters do |t| 4 | t.string :name 5 | t.string :city 6 | 7 | t.timestamps 8 | end 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /db/migrate/20140610133755_create_groups.rb: -------------------------------------------------------------------------------- 1 | class CreateGroups < ActiveRecord::Migration[4.2] 2 | def change 3 | create_table :groups do |t| 4 | t.references :chapter, index: true 5 | t.string :name 6 | t.text :description 7 | 8 | t.timestamps 9 | end 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /db/migrate/20140610155915_create_subscriptions.rb: -------------------------------------------------------------------------------- 1 | class CreateSubscriptions < ActiveRecord::Migration[4.2] 2 | def change 3 | create_table :subscriptions do |t| 4 | t.references :group, index: true 5 | t.references :member, index: true 6 | 7 | t.timestamps 8 | end 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /db/migrate/20140610202421_add_chapter_to_session.rb: -------------------------------------------------------------------------------- 1 | class AddChapterToSession < ActiveRecord::Migration[4.2] 2 | def change 3 | add_reference :sessions, :chapter, index: true 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20140610212001_add_time_to_sessions.rb: -------------------------------------------------------------------------------- 1 | class AddTimeToSessions < ActiveRecord::Migration[4.2] 2 | def change 3 | add_column :sessions, :time, :datetime 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20140611191143_rolify_create_permissions.rb: -------------------------------------------------------------------------------- 1 | class RolifyCreatePermissions < ActiveRecord::Migration[4.2] 2 | def change 3 | create_table(:permissions) do |t| 4 | t.string :name 5 | t.references :resource, polymorphic: true 6 | 7 | t.timestamps 8 | end 9 | 10 | create_table(:members_permissions, id: false) do |t| 11 | t.references :member 12 | t.references :permission 13 | end 14 | 15 | add_index(:permissions, :name) 16 | add_index(:permissions, %i[name resource_type resource_id]) 17 | add_index(:members_permissions, %i[member_id permission_id]) 18 | end 19 | end 20 | -------------------------------------------------------------------------------- /db/migrate/20140615010338_add_chapter_to_course.rb: -------------------------------------------------------------------------------- 1 | class AddChapterToCourse < ActiveRecord::Migration[4.2] 2 | def change 3 | add_reference :courses, :chapter, index: true 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20140615030540_add_avatar_cache_to_sponsor.rb: -------------------------------------------------------------------------------- 1 | class AddAvatarCacheToSponsor < ActiveRecord::Migration[4.2] 2 | def change 3 | add_column :sponsors, :image_cache, :string 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20140621234319_add_email_to_chapter.rb: -------------------------------------------------------------------------------- 1 | class AddEmailToChapter < ActiveRecord::Migration[4.2] 2 | def change 3 | add_column :chapters, :email, :string 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20140708114919_add_number_of_coaches_to_sponsor.rb: -------------------------------------------------------------------------------- 1 | class AddNumberOfCoachesToSponsor < ActiveRecord::Migration[4.2] 2 | def change 3 | add_column :sponsors, :number_of_coaches, :integer, default: nil 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20140824234126_drop_reminders.rb: -------------------------------------------------------------------------------- 1 | class DropReminders < ActiveRecord::Migration[4.2] 2 | def change 3 | drop_table :reminders 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20140825005743_add_reminder_at_to_session_invitations.rb: -------------------------------------------------------------------------------- 1 | class AddReminderAtToSessionInvitations < ActiveRecord::Migration[4.2] 2 | def change 3 | add_column :session_invitations, :reminded_at, :datetime, default: nil 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20140828194906_create_waiting_lists.rb: -------------------------------------------------------------------------------- 1 | class CreateWaitingLists < ActiveRecord::Migration[4.2] 2 | def change 3 | create_table :waiting_lists do |t| 4 | t.references :invitation, index: true 5 | t.boolean :auto_rsvp, default: true 6 | 7 | t.timestamps 8 | end 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /db/migrate/20140908151822_add_twitter_handle_and_id_to_chapter.rb: -------------------------------------------------------------------------------- 1 | class AddTwitterHandleAndIdToChapter < ActiveRecord::Migration[4.2] 2 | def change 3 | add_column :chapters, :twitter, :string 4 | add_column :chapters, :twitter_id, :string 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /db/migrate/20140916134752_remove_verified_from_user.rb: -------------------------------------------------------------------------------- 1 | class RemoveVerifiedFromUser < ActiveRecord::Migration[4.2] 2 | def change 3 | remove_column :members, :verified 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20141003172945_create_testimonials.rb: -------------------------------------------------------------------------------- 1 | class CreateTestimonials < ActiveRecord::Migration[4.2] 2 | def change 3 | create_table :testimonials do |t| 4 | t.references :member, index: true 5 | t.string :text 6 | 7 | t.timestamps 8 | end 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /db/migrate/20141003195205_change_testimonial_string_to_text.rb: -------------------------------------------------------------------------------- 1 | class ChangeTestimonialStringToText < ActiveRecord::Migration[4.2] 2 | def change 3 | change_column :testimonials, :text, :text 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20141022052135_add_welcome_fields_to_member.rb: -------------------------------------------------------------------------------- 1 | class AddWelcomeFieldsToMember < ActiveRecord::Migration[4.2] 2 | def change 3 | add_column :members, :received_coach_welcome_email, :boolean, default: false 4 | add_column :members, :received_student_welcome_email, :boolean, default: false 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /db/migrate/20141203000909_create_events.rb: -------------------------------------------------------------------------------- 1 | class CreateEvents < ActiveRecord::Migration[4.2] 2 | def change 3 | create_table :events do |t| 4 | t.string :name 5 | t.text :description 6 | t.datetime :date_and_time 7 | t.datetime :ends_at 8 | t.references :venue, index: true 9 | 10 | t.timestamps 11 | end 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /db/migrate/20141203004824_create_sponsorships.rb: -------------------------------------------------------------------------------- 1 | class CreateSponsorships < ActiveRecord::Migration[4.2] 2 | def change 3 | create_table :sponsorships do |t| 4 | t.references :event, index: true 5 | t.references :sponsor, index: true 6 | 7 | t.timestamps 8 | end 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /db/migrate/20141203012421_add_slug_to_event.rb: -------------------------------------------------------------------------------- 1 | class AddSlugToEvent < ActiveRecord::Migration[4.2] 2 | def change 3 | add_column :events, :slug, :string 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20141203034740_add_schedule_to_event.rb: -------------------------------------------------------------------------------- 1 | class AddScheduleToEvent < ActiveRecord::Migration[4.2] 2 | def change 3 | add_column :events, :schedule, :text 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20141204011642_create_invitations_2.rb: -------------------------------------------------------------------------------- 1 | class CreateInvitations2 < ActiveRecord::Migration[4.2] 2 | def change 3 | create_table :invitations do |t| 4 | t.references :event, index: true 5 | t.boolean :attending 6 | t.references :member, index: true 7 | t.string :role 8 | t.text :note 9 | 10 | t.timestamps 11 | end 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /db/migrate/20141204164936_add_token_to_invitation_2.rb: -------------------------------------------------------------------------------- 1 | class AddTokenToInvitation2 < ActiveRecord::Migration[4.2] 2 | def change 3 | add_column :invitations, :token, :string 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20141204173228_add_student_and_coach_spaces_to_event.rb: -------------------------------------------------------------------------------- 1 | class AddStudentAndCoachSpacesToEvent < ActiveRecord::Migration[4.2] 2 | def change 3 | add_column :events, :coach_spaces, :integer 4 | add_column :events, :student_spaces, :integer 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /db/migrate/20141204181137_add_coach_and_student_questionnaire_to_event.rb: -------------------------------------------------------------------------------- 1 | class AddCoachAndStudentQuestionnaireToEvent < ActiveRecord::Migration[4.2] 2 | def change 3 | add_column :events, :coach_questionnaire, :string 4 | add_column :events, :student_questionnaire, :string 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /db/migrate/20141204181517_add_verified_and_verified_by_to_invitation.rb: -------------------------------------------------------------------------------- 1 | class AddVerifiedAndVerifiedByToInvitation < ActiveRecord::Migration[4.2] 2 | def change 3 | add_column :invitations, :verified, :boolean 4 | add_reference :invitations, :verified_by, index: true 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /db/migrate/20141204221303_add_coach_description_to_event.rb: -------------------------------------------------------------------------------- 1 | class AddCoachDescriptionToEvent < ActiveRecord::Migration[4.2] 2 | def change 3 | add_column :events, :coach_description, :text 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20141204232033_add_info_to_event.rb: -------------------------------------------------------------------------------- 1 | class AddInfoToEvent < ActiveRecord::Migration[4.2] 2 | def change 3 | add_column :events, :info, :string 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20150130001852_create_member_notes.rb: -------------------------------------------------------------------------------- 1 | class CreateMemberNotes < ActiveRecord::Migration[4.2] 2 | def change 3 | create_table :member_notes do |t| 4 | t.references :member, index: true 5 | t.references :author, index: true 6 | t.text :note 7 | 8 | t.timestamps 9 | end 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /db/migrate/20150211023345_add_rsvp_close_time_to_sessions.rb: -------------------------------------------------------------------------------- 1 | class AddRsvpCloseTimeToSessions < ActiveRecord::Migration[4.2] 2 | def change 3 | add_column :sessions, :rsvp_close_time, :datetime 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20150219223111_add_slug_to_chapter.rb: -------------------------------------------------------------------------------- 1 | class AddSlugToChapter < ActiveRecord::Migration[4.2] 2 | def change 3 | add_column :chapters, :slug, :string 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20150222110321_add_announce_only_to_event.rb: -------------------------------------------------------------------------------- 1 | class AddAnnounceOnlyToEvent < ActiveRecord::Migration[4.2] 2 | def change 3 | add_column :events, :announce_only, :boolean, defaults: false 4 | add_column :events, :url, :string, defaults: nil 5 | add_column :events, :email, :string, defaults: nil 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /db/migrate/20150224001247_add_mailing_list_id_to_group.rb: -------------------------------------------------------------------------------- 1 | class AddMailingListIdToGroup < ActiveRecord::Migration[4.2] 2 | def change 3 | add_column :groups, :mailing_list_id, :string 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20150328102113_add_invitable_to_event.rb: -------------------------------------------------------------------------------- 1 | class AddInvitableToEvent < ActiveRecord::Migration[4.2] 2 | def change 3 | add_column :events, :invitable, :boolean, default: false 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20150409140851_create_announcements.rb: -------------------------------------------------------------------------------- 1 | class CreateAnnouncements < ActiveRecord::Migration[4.2] 2 | def change 3 | create_table :announcements do |t| 4 | t.datetime :expires_at 5 | t.text :message 6 | t.references :created_by, index: true 7 | 8 | t.timestamps 9 | end 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /db/migrate/20150409145541_create_group_announcements.rb: -------------------------------------------------------------------------------- 1 | class CreateGroupAnnouncements < ActiveRecord::Migration[4.2] 2 | def change 3 | create_table :group_announcements do |t| 4 | t.references :announcement, index: true 5 | t.references :group, index: true 6 | 7 | t.timestamps 8 | end 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /db/migrate/20150418235316_create_bans.rb: -------------------------------------------------------------------------------- 1 | class CreateBans < ActiveRecord::Migration[4.2] 2 | def change 3 | create_table :bans do |t| 4 | t.references :member, index: true 5 | t.datetime :expires_at 6 | t.string :reason 7 | t.text :note 8 | t.references :added_by, index: true 9 | 10 | t.timestamps 11 | end 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /db/migrate/20150505133258_add_tito_url_to_event.rb: -------------------------------------------------------------------------------- 1 | class AddTitoUrlToEvent < ActiveRecord::Migration[4.2] 2 | def change 3 | add_column :events, :tito_url, :string 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20150505161414_create_chapters_events.rb: -------------------------------------------------------------------------------- 1 | class CreateChaptersEvents < ActiveRecord::Migration[4.2] 2 | def change 3 | create_table :chapters_events do |t| 4 | t.integer :chapter_id, index: true 5 | t.integer :event_id, index: true 6 | end 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /db/migrate/20150508211109_add_contacts_to_sponsors.rb: -------------------------------------------------------------------------------- 1 | class AddContactsToSponsors < ActiveRecord::Migration[4.2] 2 | def change 3 | add_column :sponsors, :email, :string 4 | add_column :sponsors, :contact_first_name, :string 5 | add_column :sponsors, :contact_surname, :string 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /db/migrate/20150509200835_create_contacts.rb: -------------------------------------------------------------------------------- 1 | class CreateContacts < ActiveRecord::Migration[4.2] 2 | def change 3 | create_table :contacts do |t| 4 | t.references :sponsor, index: true 5 | t.references :member, index: true 6 | 7 | t.timestamps 8 | end 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /db/migrate/20150629202748_create_eligibility_inquiries.rb: -------------------------------------------------------------------------------- 1 | class CreateEligibilityInquiries < ActiveRecord::Migration[4.2] 2 | def change 3 | create_table :eligibility_inquiries do |t| 4 | t.references :member, index: true 5 | t.references :sent_by, index: true 6 | 7 | t.timestamps 8 | end 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /db/migrate/20150714194446_create_attendance_warnings.rb: -------------------------------------------------------------------------------- 1 | class CreateAttendanceWarnings < ActiveRecord::Migration[4.2] 2 | def change 3 | create_table :attendance_warnings do |t| 4 | t.references :member, index: true 5 | t.references :sent_by, index: true 6 | 7 | t.timestamps 8 | end 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /db/migrate/20150725165534_create_member_contacts.rb: -------------------------------------------------------------------------------- 1 | class CreateMemberContacts < ActiveRecord::Migration[4.2] 2 | def change 3 | create_table :member_contacts do |t| 4 | t.integer :sponsor_id 5 | t.integer :member_id 6 | t.timestamps 7 | end 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /db/migrate/20150801134457_add_map_coords_to_address.rb: -------------------------------------------------------------------------------- 1 | class AddMapCoordsToAddress < ActiveRecord::Migration[4.2] 2 | def change 3 | add_column :addresses, :latitude, :string 4 | add_column :addresses, :longitude, :string 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /db/migrate/20150814042120_add_show_faq_to_events.rb: -------------------------------------------------------------------------------- 1 | class AddShowFaqToEvents < ActiveRecord::Migration[4.2] 2 | def change 3 | add_column :events, :show_faq, :boolean 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20150823215450_add_missing_unique_indices.acts_as_taggable_on_engine.rb: -------------------------------------------------------------------------------- 1 | # This migration comes from acts_as_taggable_on_engine (originally 2) 2 | class AddMissingUniqueIndices < ActiveRecord::Migration[4.2] 3 | def self.up 4 | add_index :tags, :name, unique: true 5 | 6 | remove_index :taggings, :tag_id 7 | remove_index :taggings, %i[taggable_id taggable_type context] 8 | add_index :taggings, 9 | %i[tag_id taggable_id taggable_type context tagger_id tagger_type], 10 | unique: true, name: 'taggings_idx' 11 | end 12 | 13 | def self.down 14 | remove_index :tags, :name 15 | 16 | remove_index :taggings, name: 'taggings_idx' 17 | add_index :taggings, :tag_id 18 | add_index :taggings, %i[taggable_id taggable_type context] 19 | end 20 | end 21 | -------------------------------------------------------------------------------- /db/migrate/20150823215451_add_taggings_counter_cache_to_tags.acts_as_taggable_on_engine.rb: -------------------------------------------------------------------------------- 1 | # This migration comes from acts_as_taggable_on_engine (originally 3) 2 | class AddTaggingsCounterCacheToTags < ActiveRecord::Migration[4.2] 3 | def self.up 4 | add_column :tags, :taggings_count, :integer, default: 0 5 | 6 | ActsAsTaggableOn::Tag.reset_column_information 7 | ActsAsTaggableOn::Tag.find_each do |tag| 8 | ActsAsTaggableOn::Tag.reset_counters(tag.id, :taggings) 9 | end 10 | end 11 | 12 | def self.down 13 | remove_column :tags, :taggings_count 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /db/migrate/20150823215452_add_missing_taggable_index.acts_as_taggable_on_engine.rb: -------------------------------------------------------------------------------- 1 | # This migration comes from acts_as_taggable_on_engine (originally 4) 2 | class AddMissingTaggableIndex < ActiveRecord::Migration[4.2] 3 | def self.up 4 | add_index :taggings, %i[taggable_id taggable_type context] 5 | end 6 | 7 | def self.down 8 | remove_index :taggings, %i[taggable_id taggable_type context] 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /db/migrate/20150823215453_change_collation_for_tag_names.acts_as_taggable_on_engine.rb: -------------------------------------------------------------------------------- 1 | # This migration comes from acts_as_taggable_on_engine (originally 5) 2 | # This migration is added to circumvent issue #623 and have special characters 3 | # work properly 4 | class ChangeCollationForTagNames < ActiveRecord::Migration[4.2] 5 | def up 6 | if ActsAsTaggableOn::Utils.using_mysql? 7 | execute('ALTER TABLE tags MODIFY name varchar(255) CHARACTER SET utf8 COLLATE utf8_bin;') 8 | end 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /db/migrate/20151110180108_add_togglable_fields_to_event.rb: -------------------------------------------------------------------------------- 1 | class AddTogglableFieldsToEvent < ActiveRecord::Migration[4.2] 2 | def change 3 | add_column :events, :display_students, :boolean 4 | add_column :events, :display_coaches, :boolean 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /db/migrate/20160123192121_add_approve_by_to_job.rb: -------------------------------------------------------------------------------- 1 | class AddApproveByToJob < ActiveRecord::Migration[4.2] 2 | def change 3 | add_column :jobs, :approved_by_id, :integer, index: true 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20160124024112_add_preferred_pronoun_to_member.rb: -------------------------------------------------------------------------------- 1 | class AddPreferredPronounToMember < ActiveRecord::Migration[4.2] 2 | def change 3 | add_column :members, :preferred_pronoun, :string 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20160124225727_add_active_to_chapter.rb: -------------------------------------------------------------------------------- 1 | class AddActiveToChapter < ActiveRecord::Migration[4.2] 2 | def change 3 | add_column :chapters, :active, :boolean, null: true, default: true 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20160201210920_change_meeting_fields.rb: -------------------------------------------------------------------------------- 1 | class ChangeMeetingFields < ActiveRecord::Migration[4.2] 2 | def change 3 | add_column :meetings, :invitable, :boolean 4 | add_column :meetings, :spaces, :integer 5 | add_column :meetings, :sponsor_id, :integer 6 | 7 | remove_column :meetings, :lanyrd_url 8 | remove_column :meetings, :duration 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /db/migrate/20160207151405_create_meeting_invitation.rb: -------------------------------------------------------------------------------- 1 | class CreateMeetingInvitation < ActiveRecord::Migration[4.2] 2 | def change 3 | create_table :meeting_invitations do |t| 4 | t.references :meeting, index: true 5 | t.boolean :attending 6 | t.references :member, index: true 7 | t.string :role 8 | t.text :note 9 | t.string :token 10 | 11 | t.timestamps 12 | end 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /db/migrate/20160211182925_change_meeting_description_to_text.rb: -------------------------------------------------------------------------------- 1 | class ChangeMeetingDescriptionToText < ActiveRecord::Migration[4.2] 2 | def change 3 | change_column :meetings, :description, :text 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20160228102639_change_preferred_pronoun_to_pronouns_in_member.rb: -------------------------------------------------------------------------------- 1 | class ChangePreferredPronounToPronounsInMember < ActiveRecord::Migration[4.2] 2 | def change 3 | rename_column :members, :preferred_pronoun, :pronouns 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20160306231907_rename_table_sessions_to_workshop.rb: -------------------------------------------------------------------------------- 1 | class RenameTableSessionsToWorkshop < ActiveRecord::Migration[4.2] 2 | def change 3 | rename_table :sessions, :workshops 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20160306234034_rename_session_ids_to_workshop_ids.rb: -------------------------------------------------------------------------------- 1 | class RenameSessionIdsToWorkshopIds < ActiveRecord::Migration[4.2] 2 | def change 3 | rename_column :feedback_requests, :sessions_id, :workshop_id 4 | rename_column :session_invitations, :sessions_id, :workshop_id 5 | rename_column :sponsor_sessions, :sessions_id, :workshop_id 6 | rename_column :tutorials, :sessions_id, :workshop_id 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /db/migrate/20160307015747_rename_sponsor_sessions_to_workshop_sponsors.rb: -------------------------------------------------------------------------------- 1 | class RenameSponsorSessionsToWorkshopSponsors < ActiveRecord::Migration[4.2] 2 | def change 3 | rename_table :sponsor_sessions, :workshop_sponsors 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20160307223728_rename_permissions_resource_type_value_to_workshop.rb: -------------------------------------------------------------------------------- 1 | class RenamePermissionsResourceTypeValueToWorkshop < ActiveRecord::Migration[4.2] 2 | def change 3 | session_permissions = Permission.where(resource_type: 'Sessions') 4 | 5 | session_permissions.each do |permission| 6 | permission.update_attribute(:resource_type, 'Workshop') 7 | end 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /db/migrate/20160320164227_add_attended_to_meeting_invitation.rb: -------------------------------------------------------------------------------- 1 | class AddAttendedToMeetingInvitation < ActiveRecord::Migration[4.2] 2 | def change 3 | add_column :meeting_invitations, :attended, :boolean, default: false 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20160326003113_add_more_data_to_bans.rb: -------------------------------------------------------------------------------- 1 | class AddMoreDataToBans < ActiveRecord::Migration[4.2] 2 | def change 3 | add_column :bans, :permanent, :boolean, default: false 4 | add_column :bans, :explanation, :text 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /db/migrate/20160424081653_create_chapters_meetings.rb: -------------------------------------------------------------------------------- 1 | class CreateChaptersMeetings < ActiveRecord::Migration[4.2] 2 | def change 3 | create_table :chapters_meetings do |t| 4 | t.belongs_to :chapter, index: true 5 | t.belongs_to :meeting, index: true 6 | end 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /db/migrate/20160424175400_add_invited_flag_to_meetings.rb: -------------------------------------------------------------------------------- 1 | class AddInvitedFlagToMeetings < ActiveRecord::Migration[4.2] 2 | def change 3 | add_column :meetings, :invites_sent, :boolean, default: false 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20160523171604_add_external_event_link_to_event.rb: -------------------------------------------------------------------------------- 1 | class AddExternalEventLinkToEvent < ActiveRecord::Migration[4.2] 2 | def change 3 | add_column :events, :external_url, :string 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20160523173346_add_more_fields_to_events.rb: -------------------------------------------------------------------------------- 1 | class AddMoreFieldsToEvents < ActiveRecord::Migration[4.2] 2 | def change 3 | add_column :events, :confirmation_required, :boolean, default: false 4 | add_column :events, :surveys_required, :boolean, default: false 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /db/migrate/20160526182452_add_rsvp_time_to_session_invitation.rb: -------------------------------------------------------------------------------- 1 | class AddRsvpTimeToSessionInvitation < ActiveRecord::Migration[4.2] 2 | def change 3 | add_column :session_invitations, :rsvp_time, :datetime 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20160614203328_add_target_group_to_event.rb: -------------------------------------------------------------------------------- 1 | class AddTargetGroupToEvent < ActiveRecord::Migration[4.2] 2 | def change 3 | add_column :events, :audience, :string 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20161028141043_add_rsvp_open_time_to_workshops.rb: -------------------------------------------------------------------------------- 1 | class AddRsvpOpenTimeToWorkshops < ActiveRecord::Migration[4.2] 2 | def change 3 | add_column :workshops, :rsvp_open_time, :datetime 4 | add_column :workshops, :rsvp_open_date, :datetime 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /db/migrate/20161228121833_add_workshop_id_to_feedback.rb: -------------------------------------------------------------------------------- 1 | class AddWorkshopIdToFeedback < ActiveRecord::Migration[4.2] 2 | def change 3 | add_column :feedbacks, :workshop_id, :integer 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20180108210921_remove_time_from_workshops.rb: -------------------------------------------------------------------------------- 1 | class RemoveTimeFromWorkshops < ActiveRecord::Migration[4.2] 2 | def change 3 | remove_column :workshops, :time, :datetime 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20180109024411_add_rsvp_opens_at_to_workshops.rb: -------------------------------------------------------------------------------- 1 | class AddRsvpOpensAtToWorkshops < ActiveRecord::Migration[4.2] 2 | def change 3 | rename_column :workshops, :rsvp_open_time, :rsvp_opens_at 4 | remove_column :workshops, :rsvp_open_date, :datetime 5 | rename_column :workshops, :rsvp_close_time, :rsvp_closes_at 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /db/migrate/20180109030511_add_accessibility_info_to_sponsors.rb: -------------------------------------------------------------------------------- 1 | class AddAccessibilityInfoToSponsors < ActiveRecord::Migration[4.2] 2 | def change 3 | add_column :sponsors, :accessibility_info, :text 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20180110212924_add_time_zone_to_chapters.rb: -------------------------------------------------------------------------------- 1 | class AddTimeZoneToChapters < ActiveRecord::Migration[4.2] 2 | def change 3 | add_column :chapters, :time_zone, :string, null: false, default: 'London' 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20180307221521_add_level_to_sponsors.rb: -------------------------------------------------------------------------------- 1 | class AddLevelToSponsors < ActiveRecord::Migration[4.2] 2 | def up 3 | # hidden: 0, 4 | # standard: 1, 5 | # bronze: 2, 6 | # silver: 3, 7 | # gold: 4, 8 | # community: 5, 9 | add_column :sponsors, :level, :integer, null: false, default: 1, index: true 10 | end 11 | 12 | def down 13 | remove_column :sponsors, :level 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /db/migrate/20180313165054_rename_table_session_invitations_to_workshop_invitations.rb: -------------------------------------------------------------------------------- 1 | class RenameTableSessionInvitationsToWorkshopInvitations < ActiveRecord::Migration[4.2] 2 | def change 3 | rename_table :session_invitations, :workshop_invitations 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20180430001328_add_unique_index_to_meeting_slug.rb: -------------------------------------------------------------------------------- 1 | class AddUniqueIndexToMeetingSlug < ActiveRecord::Migration[4.2] 2 | def change 3 | add_index :meetings, :slug, unique: true 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20180519231943_add_unique_index_to_event_slug.rb: -------------------------------------------------------------------------------- 1 | class AddUniqueIndexToEventSlug < ActiveRecord::Migration[4.2] 2 | def change 3 | add_index :events, :slug, unique: true 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20180608010545_add_directions_to_addresses.rb: -------------------------------------------------------------------------------- 1 | class AddDirectionsToAddresses < ActiveRecord::Migration[4.2] 2 | def change 3 | add_column :addresses, :directions, :text 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20181002213441_extend_job_model.rb: -------------------------------------------------------------------------------- 1 | class ExtendJobModel < ActiveRecord::Migration[4.2] 2 | def change 3 | add_column :jobs, :company_website, :string 4 | add_column :jobs, :company_address, :string 5 | add_column :jobs, :company_postcode, :string 6 | add_column :jobs, :published_on, :datetime 7 | add_column :jobs, :remote, :boolean 8 | add_column :jobs, :salary, :integer 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /db/migrate/20181012015419_create_friendly_id_slugs.rb: -------------------------------------------------------------------------------- 1 | class CreateFriendlyIdSlugs < ActiveRecord::Migration[4.2] 2 | def change 3 | create_table :friendly_id_slugs do |t| 4 | t.string :slug, :null => false 5 | t.integer :sluggable_id, :null => false 6 | t.string :sluggable_type, :limit => 50 7 | t.string :scope 8 | t.datetime :created_at 9 | end 10 | add_index :friendly_id_slugs, :sluggable_id 11 | add_index :friendly_id_slugs, [:slug, :sluggable_type], length: { slug: 140, sluggable_type: 50 } 12 | add_index :friendly_id_slugs, [:slug, :sluggable_type, :scope], length: { slug: 70, sluggable_type: 50, scope: 70 }, unique: true 13 | add_index :friendly_id_slugs, :sluggable_type 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /db/migrate/20181012015504_add_slug_to_job.rb: -------------------------------------------------------------------------------- 1 | class AddSlugToJob < ActiveRecord::Migration[4.2] 2 | def change 3 | add_column :jobs, :slug, :string 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20181013224547_add_status_to_job.rb: -------------------------------------------------------------------------------- 1 | class AddStatusToJob < ActiveRecord::Migration[4.2] 2 | def change 3 | add_column :jobs, :status, :integer, default: 0 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20181019002645_add_description_to_chapters.rb: -------------------------------------------------------------------------------- 1 | class AddDescriptionToChapters < ActiveRecord::Migration[4.2] 2 | def change 3 | add_column :chapters, :description, :text 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20181021014646_add_image_to_chapters.rb: -------------------------------------------------------------------------------- 1 | class AddImageToChapters < ActiveRecord::Migration[4.2] 2 | def change 3 | add_column :chapters, :image, :string 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20191018175052_add_ends_at_to_workshops.rb: -------------------------------------------------------------------------------- 1 | class AddEndsAtToWorkshops < ActiveRecord::Migration[4.2] 2 | def change 3 | add_column :workshops, :ends_at, :datetime 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20200120111440_add_accepted_toc_at_to_member.rb: -------------------------------------------------------------------------------- 1 | class AddAcceptedTocAtToMember < ActiveRecord::Migration[4.2] 2 | def change 3 | add_column :members, :accepted_toc_at, :datetime, default: nil 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20200124124311_add_opt_in_newsletter_at_to_member.rb: -------------------------------------------------------------------------------- 1 | class AddOptInNewsletterAtToMember < ActiveRecord::Migration[4.2] 2 | def change 3 | add_column :members, :opt_in_newsletter_at, :datetime, default: nil 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20200311233721_add_virtual_to_workshop.rb: -------------------------------------------------------------------------------- 1 | class AddVirtualToWorkshop < ActiveRecord::Migration[4.2] 2 | def change 3 | add_column :workshops, :virtual, :boolean, default: false 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20200312172212_add_student_and_coach_spaces_to_workshop.rb: -------------------------------------------------------------------------------- 1 | class AddStudentAndCoachSpacesToWorkshop < ActiveRecord::Migration[4.2] 2 | def change 3 | add_column :workshops, :student_spaces, :integer, default: 0 4 | add_column :workshops, :coach_spaces, :integer, default: 0 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /db/migrate/20200313211614_add_slack_channel_and_slack_channel_link_to_workshop.rb: -------------------------------------------------------------------------------- 1 | class AddSlackChannelAndSlackChannelLinkToWorkshop < ActiveRecord::Migration[4.2] 2 | def change 3 | add_column :workshops, :slack_channel, :string 4 | add_column :workshops, :slack_channel_link, :string 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /db/migrate/20200511151348_add_automated_rsvp_to_workshop_invitation.rb: -------------------------------------------------------------------------------- 1 | class AddAutomatedRsvpToWorkshopInvitation < ActiveRecord::Migration[4.2] 2 | def change 3 | add_column :workshop_invitations, :automated_rsvp, :boolean 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20200521151343_add_tutorial_to_workshop_invitation.rb: -------------------------------------------------------------------------------- 1 | class AddTutorialToWorkshopInvitation < ActiveRecord::Migration[4.2] 2 | def change 3 | add_column :workshop_invitations, :tutorial, :text 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20200522142646_add_email_index_to_member.rb: -------------------------------------------------------------------------------- 1 | class AddEmailIndexToMember < ActiveRecord::Migration[4.2] 2 | def change 3 | add_index :members, :email, unique: true 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20200721072708_update_contacts.rb: -------------------------------------------------------------------------------- 1 | class UpdateContacts < ActiveRecord::Migration[4.2] 2 | def change 3 | add_column :contacts, :name, :string 4 | add_column :contacts, :surname, :string 5 | add_column :contacts, :email, :string 6 | add_column :contacts, :mailing_list_consent, :boolean, default: false 7 | remove_column :contacts, :member_id, :integer 8 | 9 | add_index :contacts, [:email, :sponsor_id], unique: true 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /db/migrate/20200805104520_add_level_to_sponsorship.rb: -------------------------------------------------------------------------------- 1 | class AddLevelToSponsorship < ActiveRecord::Migration[4.2] 2 | def change 3 | add_column :sponsorships, :level, :string 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20200815141515_add_token_to_contact.rb: -------------------------------------------------------------------------------- 1 | class AddTokenToContact < ActiveRecord::Migration[4.2] 2 | def change 3 | add_column :contacts, :token, :string, null: false 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20201109043756_add_end_dt_to_meetings_courses.rb: -------------------------------------------------------------------------------- 1 | class AddEndDtToMeetingsCourses < ActiveRecord::Migration[4.2] 2 | def change 3 | add_column :meetings, :ends_at, :datetime 4 | add_column :courses, :ends_at, :datetime 5 | end 6 | end 7 | -------------------------------------------------------------------------------- /db/migrate/20201120012424_drop_member_contacts.rb: -------------------------------------------------------------------------------- 1 | class DropMemberContacts < ActiveRecord::Migration[4.2] 2 | def change 3 | drop_table :member_contacts 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20201120012812_remove_contact_details_from_sponsor.rb: -------------------------------------------------------------------------------- 1 | class RemoveContactDetailsFromSponsor < ActiveRecord::Migration[4.2] 2 | def change 3 | remove_column :sponsors, :contact_first_name 4 | remove_column :sponsors, :contact_surname 5 | remove_column :sponsors, :email 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /db/migrate/20220820180050_add_virtual_to_events.rb: -------------------------------------------------------------------------------- 1 | class AddVirtualToEvents < ActiveRecord::Migration[4.2] 2 | def change 3 | add_column :events, :virtual, :boolean, null: false, default: false 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20220820215847_add_time_zone_to_events.rb: -------------------------------------------------------------------------------- 1 | class AddTimeZoneToEvents < ActiveRecord::Migration[4.2] 2 | def change 3 | add_column :events, :time_zone, :string, null: false, default: 'London' 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /db/migrate/20230722001141_add_tenant_to_taggings.acts_as_taggable_on_engine.rb: -------------------------------------------------------------------------------- 1 | # This migration comes from acts_as_taggable_on_engine (originally 7) 2 | if ActiveRecord.gem_version >= Gem::Version.new('5.0') 3 | class AddTenantToTaggings < ActiveRecord::Migration[4.2]; end 4 | else 5 | class AddTenantToTaggings < ActiveRecord::Migration; end 6 | end 7 | AddTenantToTaggings.class_eval do 8 | def self.up 9 | add_column :taggings, :tenant, :string, limit: 128 10 | add_index :taggings, :tenant unless index_exists? :taggings, :tenant 11 | end 12 | 13 | def self.down 14 | remove_index :taggings, :tenant 15 | remove_column :taggings, :tenant 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /db/migrate/20230801074547_add_service_name_to_active_storage_blobs.active_storage.rb: -------------------------------------------------------------------------------- 1 | # This migration comes from active_storage (originally 20190112182829) 2 | class AddServiceNameToActiveStorageBlobs < ActiveRecord::Migration[6.0] 3 | def up 4 | return unless table_exists?(:active_storage_blobs) 5 | 6 | unless column_exists?(:active_storage_blobs, :service_name) 7 | add_column :active_storage_blobs, :service_name, :string 8 | 9 | if configured_service = ActiveStorage::Blob.service.name 10 | ActiveStorage::Blob.unscoped.update_all(service_name: configured_service) 11 | end 12 | 13 | change_column :active_storage_blobs, :service_name, :string, null: false 14 | end 15 | end 16 | 17 | def down 18 | return unless table_exists?(:active_storage_blobs) 19 | 20 | remove_column :active_storage_blobs, :service_name 21 | end 22 | end 23 | -------------------------------------------------------------------------------- /db/migrate/20230803225601_remove_not_null_on_active_storage_blobs_checksum.active_storage.rb: -------------------------------------------------------------------------------- 1 | # This migration comes from active_storage (originally 20211119233751) 2 | class RemoveNotNullOnActiveStorageBlobsChecksum < ActiveRecord::Migration[6.0] 3 | def change 4 | return unless table_exists?(:active_storage_blobs) 5 | 6 | change_column_null(:active_storage_blobs, :checksum, true) 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /db/migrate/20231230162506_add_last_overridden_by_id_to_workshop_invitations.rb: -------------------------------------------------------------------------------- 1 | class AddLastOverriddenByIdToWorkshopInvitations < ActiveRecord::Migration[7.0] 2 | def change 3 | add_column :workshop_invitations, :last_overridden_by_id, :integer, default: nil 4 | end 5 | end 6 | -------------------------------------------------------------------------------- /docker-compose.env: -------------------------------------------------------------------------------- 1 | DB_HOST=db 2 | DB_USER=postgres 3 | POSTGRES_PASSWORD=password 4 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | services: 2 | db: 3 | image: postgres 4 | volumes: 5 | - db_data:/var/lib/postgresql/data 6 | environment: 7 | POSTGRES_PASSWORD: password 8 | web: 9 | env_file: 10 | - docker-compose.env 11 | build: . 12 | command: tail -f /dev/null 13 | environment: 14 | DB_HOST: db 15 | volumes: 16 | - .:/planner 17 | - gem_cache:/usr/local/bundle/gems 18 | ports: 19 | - 3000:3000 20 | depends_on: 21 | - db 22 | 23 | volumes: 24 | db_data: 25 | gem_cache: 26 | -------------------------------------------------------------------------------- /lib/assets/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codebar/planner/1a80f39ba971d16a89d9e1023d401ca6876f7534/lib/assets/.keep -------------------------------------------------------------------------------- /lib/services/event_calendar.rb: -------------------------------------------------------------------------------- 1 | class EventCalendar 2 | attr_reader :event 3 | 4 | def initialize(event) 5 | @event = event 6 | setup_event 7 | end 8 | 9 | def calendar 10 | @calendar ||= Icalendar::Calendar.new 11 | end 12 | 13 | private 14 | 15 | def setup_event 16 | address = AddressPresenter.new(event.venue.address) if event.venue.present? 17 | calendar.event do |e| 18 | e.organizer = event.email.to_s 19 | e.dtstart = event.date_and_time 20 | e.dtend = event.ends_at 21 | e.summary = event.name 22 | e.location = address&.to_s 23 | e.ip_class = 'PRIVATE' 24 | end 25 | end 26 | end 27 | -------------------------------------------------------------------------------- /lib/services/ticket.rb: -------------------------------------------------------------------------------- 1 | class Ticket 2 | def initialize(request, params) 3 | authorise(request) 4 | @params = params 5 | end 6 | 7 | def email 8 | @email ||= params[:email] 9 | end 10 | 11 | private 12 | 13 | attr_reader :params 14 | 15 | def authorise(request) 16 | # TODO 17 | # verify referer 18 | end 19 | end 20 | -------------------------------------------------------------------------------- /lib/tasks/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codebar/planner/1a80f39ba971d16a89d9e1023d401ca6876f7534/lib/tasks/.keep -------------------------------------------------------------------------------- /lib/tasks/feedback.rake: -------------------------------------------------------------------------------- 1 | namespace :feedback do 2 | desc 'Request feedback from students that attended our latest workshop' 3 | task request: :environment do 4 | workshops = Workshop.completed_since_yesterday 5 | Rails.logger.info 'Sending Feedback request emails' if workshops.any? 6 | workshops.each do |workshop| 7 | WorkshopInvitation.accepted.where(workshop: workshop, role: 'Student').map do |invitation| 8 | FeedbackRequest.create(member: invitation.member, workshop: workshop, submited: false) 9 | end 10 | Rails.logger.info "Feedback requests sent for #{workshop.chapter.name}'s #{workshop}: \ 11 | #{FeedbackRequest.where(workshop: workshop).count}" 12 | end 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /lib/tasks/mailing_list.rake: -------------------------------------------------------------------------------- 1 | namespace :mailing_list do 2 | require 'services/mailing_list' 3 | 4 | desc 'Subscribe all active members to newsletter mailing list' 5 | task subscribe_active_members: :environment do 6 | newsletter_id = ENV['NEWSLETTER_ID'] || Rails.logger.info('NEWSLETTER_ID not set. Aborting task') && abort 7 | 8 | members = Member.includes(:subscriptions).where.not('subscriptions.member_id' => nil).uniq 9 | newsletter = MailingList.new(newsletter_id) 10 | 11 | members.each do |member| 12 | member.update(opt_in_newsletter_at: Time.zone.now) 13 | newsletter.subscribe(member.email, member.name, member.surname) 14 | end 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /lib/tasks/rubocop.rake: -------------------------------------------------------------------------------- 1 | if Gem.loaded_specs.key?('rubocop') 2 | require 'rubocop/rake_task' 3 | 4 | desc 'Run the rubocop static code analyzer' 5 | task rubocop: :environment do 6 | unless system 'rubocop' 7 | exit 1 8 | end 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /lib/tasks/seed_tags.rake: -------------------------------------------------------------------------------- 1 | namespace :skills do 2 | desc 'Create initial list of commonly used skills' 3 | 4 | task seed_tag_table: :environment do 5 | list = %w[html css javascript jQuery rails ruby php python c++ wordpress] 6 | 7 | list.each do |tag| 8 | ActsAsTaggableOn::Tag.new(name: tag).save 9 | end 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /lib/tasks/workshop.rake: -------------------------------------------------------------------------------- 1 | namespace :workshop do 2 | desc 'Send waiting list emails' 3 | 4 | task reminders: :environment do 5 | workshops = Workshop.upcoming 6 | 7 | workshops.each do |workshop| 8 | waiting_list = WaitingList.by_workshop(workshop) 9 | if waiting_list.exists? 10 | InvitationManager.new.send_waiting_list_emails(workshop) 11 | end 12 | end 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /lib/templates/erb/scaffold/_form.html.erb: -------------------------------------------------------------------------------- 1 | <%# frozen_string_literal: true %> 2 | <%%= simple_form_for(@<%= singular_table_name %>) do |f| %> 3 | <%%= f.error_notification %> 4 | <%%= f.error_notification message: f.object.errors[:base].to_sentence if f.object.errors[:base].present? %> 5 | 6 |