├── log └── .keep ├── swagger.json ├── VERSION ├── app ├── mailers │ └── .keep ├── models │ ├── .keep │ ├── concerns │ │ └── .keep │ ├── application_record.rb │ ├── telegram │ │ ├── channel.rb │ │ └── botan.rb │ ├── telegram.rb │ ├── event_participation.rb │ ├── ability.rb │ ├── authentication.rb │ └── calendar.rb ├── controllers │ ├── concerns │ │ └── .keep │ ├── my.rb │ ├── sitemaps_controller.rb │ ├── letsencrypt_controller.rb │ ├── pages_controller.rb │ ├── turbo │ │ └── events_controller.rb │ ├── errors_controller.rb │ ├── users_controller.rb │ ├── api │ │ ├── v1 │ │ │ ├── users_controller.rb │ │ │ ├── api_controller.rb │ │ │ └── events_controller.rb │ │ └── v2 │ │ │ ├── tags_controller.rb │ │ │ ├── api_controller.rb │ │ │ └── events_controller.rb │ ├── my │ │ ├── authentications_controller.rb │ │ └── users_controller.rb │ ├── telegram_hooks_controller.rb │ ├── event_participations_controller.rb │ ├── omniauth_callbacks_controller.rb │ ├── mailchimp_hooks_controller.rb │ └── application_controller.rb ├── views │ ├── events │ │ ├── edit.html.slim │ │ ├── new.html.slim │ │ ├── _admin_info.html.slim │ │ ├── _participants_block.html.slim │ │ ├── _event-item.rss.slim │ │ ├── _participate_block.html.slim │ │ ├── index.rss.builder │ │ └── _form.html.slim │ ├── authentications │ │ ├── _authentication.html.slim │ │ └── _unlinked.html.slim │ ├── pages │ │ ├── thankyou.html.slim │ │ ├── communities.html.slim │ │ └── manifesto.ru.html.slim │ ├── my │ │ ├── authentications │ │ │ └── _authentication.html.slim │ │ └── users │ │ │ ├── edit.html.slim │ │ │ └── show.html.slim │ ├── startups │ │ ├── edit.html.slim │ │ ├── new.html.slim │ │ ├── index.html.slim │ │ ├── show.html.slim │ │ ├── _form.html.slim │ │ └── _startup.html.slim │ ├── users │ │ ├── _user.html.slim │ │ ├── index.html.slim │ │ ├── show.html.slim │ │ └── _user-events.html.slim │ ├── shared │ │ ├── _oauth_login_block.html.slim │ │ └── _small_screens_footer.html.slim │ ├── devise │ │ ├── mailer │ │ │ ├── unlock_instructions.html.slim │ │ │ ├── reset_password_instructions.html.slim │ │ │ └── confirmation_instructions.html.slim │ │ ├── passwords │ │ │ ├── new.html.slim │ │ │ └── edit.html.slim │ │ ├── unlocks │ │ │ └── new.html.slim │ │ ├── registrations │ │ │ ├── new.html.slim │ │ │ └── edit.html.slim │ │ ├── confirmations │ │ │ └── new.html.slim │ │ ├── sessions │ │ │ └── new.html.slim │ │ └── shared │ │ │ └── _links.slim │ ├── turbo │ │ └── events │ │ │ ├── _event.rss.builder │ │ │ └── index.rss.builder │ ├── errors │ │ └── error_404.html.slim │ └── sitemaps │ │ └── index.xml.slim ├── assets │ ├── config │ │ └── manifest.js │ ├── fonts │ │ ├── HelveticaNeue.otf │ │ ├── HelveticaNeue-Bold.otf │ │ ├── HelveticaNeue-Light.otf │ │ ├── HelveticaNeue-Thin.otf │ │ ├── HelveticaNeue-Italic.otf │ │ ├── HelveticaNeue-Medium.otf │ │ ├── HelveticaNeue-BoldItalic.otf │ │ ├── HelveticaNeue-ThinItalic.otf │ │ ├── HelveticaNeue-UltraLight.otf │ │ ├── HelveticaNeue-CondensedBold.otf │ │ ├── HelveticaNeue-LightItalic.otf │ │ ├── HelveticaNeue-MediumItalic.otf │ │ ├── HelveticaNeue-CondensedBlack.otf │ │ └── HelveticaNeue-UltraLightItalic.otf │ ├── images │ │ ├── it52_favicon.ico │ │ ├── it52-logo-16x16.png │ │ ├── it52-logo-32x32.png │ │ ├── it52-logo-96x96.png │ │ ├── it52_logo_fb@2x.png │ │ ├── google-play-badge.png │ │ ├── it52-logo-144x144.png │ │ ├── it52-logo-180x180.png │ │ ├── it52-logo-192x192.png │ │ ├── events_fallback │ │ │ ├── default.png │ │ │ ├── fb_1200_default.png │ │ │ └── square_500_default.png │ │ └── avatars_fallback │ │ │ ├── default.png │ │ │ ├── square_150_default.png │ │ │ ├── square_25_default.png │ │ │ └── square_50_default.png │ └── stylesheets │ │ ├── user_profiles.sass │ │ ├── app.sass │ │ └── application.css ├── serializers │ ├── startup_serializer.rb │ ├── v2 │ │ ├── tag_serializer.rb │ │ ├── user_serializer.rb │ │ └── event_serializer.rb │ ├── event_brief_serializer.rb │ ├── authentication_serializer.rb │ └── event_serializer.rb ├── helpers │ ├── events_helper.rb │ └── application_helper.rb ├── services │ ├── extract_event_address_service.rb │ ├── render_ar_collection_to_csv.rb │ └── update_user_from_omniauth.rb ├── uploaders │ ├── event_title_image_uploader.rb │ ├── startup_logo_uploader.rb │ ├── user_avatar_uploader.rb │ └── concerns │ │ └── uploader_concern.rb ├── decorators │ ├── user_decorator.rb │ └── authentication_decorator.rb └── javascript │ └── packs │ ├── application.ts │ └── editor.ts ├── lib ├── assets │ └── .keep ├── rails │ └── sub_test_task.rb ├── tasks │ └── events.rake ├── templates │ └── slim │ │ └── scaffold │ │ └── _form.html.slim ├── da_data │ └── configuration.rb └── da_data.rb ├── public ├── ads.txt ├── app-ads.txt ├── favicon.ico ├── logo-it52-96x96.png ├── yandex_637a660a79fbb6d1.html ├── robots.txt ├── 404.html └── 500.html ├── .ruby-gemset ├── .ruby-version ├── .browserslistrc ├── .gemrc ├── .rspec ├── codecov.yml ├── spec ├── fixtures │ └── logo.png ├── support │ ├── webmock.rb │ ├── factory_bot.rb │ ├── codecov.rb │ ├── helpers │ │ └── response.rb │ └── database_cleaner.rb ├── controllers │ ├── sitemaps_controller_spec.rb │ ├── turbo │ │ └── events_controller_spec.rb │ └── mailchimp_hooks_controller_spec.rb ├── factories │ ├── startups.rb │ ├── event.rb │ ├── addresses.rb │ └── user.rb ├── lib │ └── da_data │ │ └── request_spec.rb └── models │ └── event_spec.rb ├── config ├── webpack │ ├── environment.js │ ├── test.js │ ├── production.js │ └── development.js ├── initializers │ ├── high_voltage.rb │ ├── draper.rb │ ├── da_data.rb │ ├── session_store.rb │ ├── mime_types.rb │ ├── string_to_url_extender.rb │ ├── pluralization.rb │ ├── filter_parameter_logging.rb │ ├── cookies_serializer.rb │ ├── application_controller_renderer.rb │ ├── taggable.rb │ ├── sidekiq.rb │ ├── silencer.rb │ ├── apipie.rb │ ├── kaminari_config.rb │ ├── backtrace_silencers.rb │ ├── runtimeerror_notifier.rb │ ├── wrap_parameters.rb │ ├── inflections.rb │ ├── string_unicode_path.rb │ ├── assets.rb │ ├── carrier_wave.rb │ └── meta_tags.rb ├── environments │ └── staging.rb ├── REFACTOR.md ├── spring.rb ├── environment.rb ├── cable.yml ├── boot.rb ├── locales │ ├── kaminari-ru.yml │ ├── plurals.rb │ ├── simple_form.en.yml │ ├── telegram.ru.yml │ └── en.yml ├── puma.rb ├── sidekiq.yml ├── unicorn │ └── production.rb ├── database.yml ├── application.yml ├── storage.yml └── deploy.rb ├── .env ├── config.ru ├── bin ├── rails ├── yarn ├── sync_db ├── webpack ├── webpack-dev-server ├── rake ├── rackup ├── ri ├── pry ├── puma ├── rdoc ├── sdoc ├── thor ├── tilt ├── oauth ├── byebug ├── figaro ├── ldiff ├── listen ├── pumactl ├── rspec ├── slimrb ├── spring ├── coderay ├── foreman ├── launchy ├── rubocop ├── sidekiq ├── annotate ├── htmldiff ├── newrelic ├── nokogiri ├── nrdebug ├── redcarpet ├── ruby-parse ├── safe_yaml ├── sdoc-merge ├── sprockets ├── restclient ├── sidekiqctl ├── mongrel_rpm ├── ruby-rewrite ├── newrelic_cmd ├── update ├── rollbar-rails-runner ├── cc-tddium-post-worker ├── codeclimate-test-reporter └── setup ├── db ├── migrate │ ├── 20140520095824_add_bio_to_users.rb │ ├── 20140602183636_add_place_to_events.rb │ ├── 20140902183616_add_website_to_user.rb │ ├── 20140507084053_add_role_to_users.rb │ ├── 20181010093500_add_employment_to_users.rb │ ├── 20190301095130_add_kind_to_events.rb │ ├── 20140521054705_add_title_image_to_events.rb │ ├── 20140521062142_add_avatar_image_to_users.rb │ ├── 20141127113116_add_subscription_to_users.rb │ ├── 20181011094902_add_foreign_link_to_event.rb │ ├── 20140522134058_add_link_to_authentications.rb │ ├── 20150516133610_add_point_to_events.rb │ ├── 20140430090944_add_name_to_users.rb │ ├── 20140507093336_add_published_to_events.rb │ ├── 20141111093102_drop_index_users_on_email.rb │ ├── 20181119192414_add_pageviews_to_events.rb │ ├── 20140507093209_add_organizer_referenses_to_events.rb │ ├── 20140902181203_add_slug_to_users.rb │ ├── 20141126154826_add_slug_to_events.rb │ ├── 20140430100247_create_events.rb │ ├── 20190612020440_add_address_id_to_event.rb │ ├── 20140520095617_add_first_name_and_last_name_to_users.rb │ ├── 20140508095102_add_description_and_started_at_to_events.rb │ ├── 20140901165216_add_token_to_authentications.rb │ ├── 20140902165236_rename_users_name_to_nickname.rb │ ├── 20140521082751_nullable_sorcery_core.rb │ ├── 20140430090220_sorcery_external.rb │ ├── 20140508105348_create_event_participations.rb │ ├── 20140430090218_sorcery_remember_me.rb │ ├── 20190605125210_create_donations.rb │ ├── 20141125211802_add_published_at_to_events.rb │ ├── 20140430090217_sorcery_core.rb │ ├── 20140430090219_sorcery_reset_password.rb │ ├── 20140430090221_sorcery_activity_logging.rb │ ├── 20190624125250_create_startups.rb │ ├── 20190301180743_add_missing_taggable_index.acts_as_taggable_on_engine.rb │ ├── 20190612020134_create_addresses.rb │ ├── 20140902180100_create_friendly_id_slugs.rb │ ├── 20190301180744_change_collation_for_tag_names.acts_as_taggable_on_engine.rb │ ├── 20190301180742_add_taggings_counter_cache_to_tags.acts_as_taggable_on_engine.rb │ ├── 20190301180741_add_missing_unique_indices.acts_as_taggable_on_engine.rb │ ├── 20190301180740_acts_as_taggable_on_migration.acts_as_taggable_on_engine.rb │ └── 20190301180745_add_missing_indexes_on_taggings.acts_as_taggable_on_engine.rb └── seeds.rb ├── start_server.sh ├── postcss.config.js ├── Rakefile ├── .eslintrc.json ├── deploy └── systemd │ ├── metabase.service │ └── it52.service ├── .github ├── workflows │ ├── deploy.yml │ ├── docker-build-and-push-develpoment.yml │ └── docker-build-and-push-production.yml └── FUNDING.yml ├── .dockerignore ├── tsconfig.json ├── .old-travis.yml ├── Makefile ├── LICENSE.md ├── .rubocop.yml ├── docker └── docker-compose.production.yml ├── Capfile └── .gitignore /log/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /swagger.json: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /VERSION: -------------------------------------------------------------------------------- 1 | 0.2.3 2 | -------------------------------------------------------------------------------- /app/mailers/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/models/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /lib/assets/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/ads.txt: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/app-ads.txt: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.ruby-gemset: -------------------------------------------------------------------------------- 1 | it52 2 | -------------------------------------------------------------------------------- /.ruby-version: -------------------------------------------------------------------------------- 1 | 3.2.2 2 | -------------------------------------------------------------------------------- /.browserslistrc: -------------------------------------------------------------------------------- 1 | defaults 2 | -------------------------------------------------------------------------------- /app/models/concerns/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gemrc: -------------------------------------------------------------------------------- 1 | install: --no-document 2 | -------------------------------------------------------------------------------- /app/controllers/concerns/.keep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.rspec: -------------------------------------------------------------------------------- 1 | --color 2 | --require rails_helper 3 | --profile 5 4 | -------------------------------------------------------------------------------- /codecov.yml: -------------------------------------------------------------------------------- 1 | ignore: 2 | - "yarn.lock" 3 | - "Gemfile.lock" 4 | -------------------------------------------------------------------------------- /app/controllers/my.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module My 4 | end 5 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NNRUG/it52-rails/HEAD/public/favicon.ico -------------------------------------------------------------------------------- /app/views/events/edit.html.slim: -------------------------------------------------------------------------------- 1 | .page-header 2 | h1 = t '.title' 3 | 4 | = render 'form' -------------------------------------------------------------------------------- /app/views/events/new.html.slim: -------------------------------------------------------------------------------- 1 | .page-header 2 | h1 = t '.title' 3 | 4 | = render 'form' -------------------------------------------------------------------------------- /app/views/authentications/_authentication.html.slim: -------------------------------------------------------------------------------- 1 | li = link_to authentication.link_to_social 2 | -------------------------------------------------------------------------------- /app/views/pages/thankyou.html.slim: -------------------------------------------------------------------------------- 1 | h1 Спасибо 2 | p Ваши пожертвования пойдут на доброе дело. 3 | -------------------------------------------------------------------------------- /spec/fixtures/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NNRUG/it52-rails/HEAD/spec/fixtures/logo.png -------------------------------------------------------------------------------- /public/logo-it52-96x96.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NNRUG/it52-rails/HEAD/public/logo-it52-96x96.png -------------------------------------------------------------------------------- /app/assets/config/manifest.js: -------------------------------------------------------------------------------- 1 | //= link application.css 2 | //= link_tree ../fonts 3 | //= link_tree ../images 4 | -------------------------------------------------------------------------------- /app/assets/fonts/HelveticaNeue.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NNRUG/it52-rails/HEAD/app/assets/fonts/HelveticaNeue.otf -------------------------------------------------------------------------------- /app/assets/images/it52_favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NNRUG/it52-rails/HEAD/app/assets/images/it52_favicon.ico -------------------------------------------------------------------------------- /config/webpack/environment.js: -------------------------------------------------------------------------------- 1 | const { environment } = require('@rails/webpacker') 2 | 3 | module.exports = environment 4 | -------------------------------------------------------------------------------- /app/assets/images/it52-logo-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NNRUG/it52-rails/HEAD/app/assets/images/it52-logo-16x16.png -------------------------------------------------------------------------------- /app/assets/images/it52-logo-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NNRUG/it52-rails/HEAD/app/assets/images/it52-logo-32x32.png -------------------------------------------------------------------------------- /app/assets/images/it52-logo-96x96.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NNRUG/it52-rails/HEAD/app/assets/images/it52-logo-96x96.png -------------------------------------------------------------------------------- /app/assets/images/it52_logo_fb@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NNRUG/it52-rails/HEAD/app/assets/images/it52_logo_fb@2x.png -------------------------------------------------------------------------------- /app/assets/fonts/HelveticaNeue-Bold.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NNRUG/it52-rails/HEAD/app/assets/fonts/HelveticaNeue-Bold.otf -------------------------------------------------------------------------------- /app/assets/fonts/HelveticaNeue-Light.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NNRUG/it52-rails/HEAD/app/assets/fonts/HelveticaNeue-Light.otf -------------------------------------------------------------------------------- /app/assets/fonts/HelveticaNeue-Thin.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NNRUG/it52-rails/HEAD/app/assets/fonts/HelveticaNeue-Thin.otf -------------------------------------------------------------------------------- /app/assets/images/google-play-badge.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NNRUG/it52-rails/HEAD/app/assets/images/google-play-badge.png -------------------------------------------------------------------------------- /app/assets/images/it52-logo-144x144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NNRUG/it52-rails/HEAD/app/assets/images/it52-logo-144x144.png -------------------------------------------------------------------------------- /app/assets/images/it52-logo-180x180.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NNRUG/it52-rails/HEAD/app/assets/images/it52-logo-180x180.png -------------------------------------------------------------------------------- /app/assets/images/it52-logo-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NNRUG/it52-rails/HEAD/app/assets/images/it52-logo-192x192.png -------------------------------------------------------------------------------- /app/assets/fonts/HelveticaNeue-Italic.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NNRUG/it52-rails/HEAD/app/assets/fonts/HelveticaNeue-Italic.otf -------------------------------------------------------------------------------- /app/assets/fonts/HelveticaNeue-Medium.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NNRUG/it52-rails/HEAD/app/assets/fonts/HelveticaNeue-Medium.otf -------------------------------------------------------------------------------- /app/assets/fonts/HelveticaNeue-BoldItalic.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NNRUG/it52-rails/HEAD/app/assets/fonts/HelveticaNeue-BoldItalic.otf -------------------------------------------------------------------------------- /app/assets/fonts/HelveticaNeue-ThinItalic.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NNRUG/it52-rails/HEAD/app/assets/fonts/HelveticaNeue-ThinItalic.otf -------------------------------------------------------------------------------- /app/assets/fonts/HelveticaNeue-UltraLight.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NNRUG/it52-rails/HEAD/app/assets/fonts/HelveticaNeue-UltraLight.otf -------------------------------------------------------------------------------- /app/assets/images/events_fallback/default.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NNRUG/it52-rails/HEAD/app/assets/images/events_fallback/default.png -------------------------------------------------------------------------------- /app/assets/fonts/HelveticaNeue-CondensedBold.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NNRUG/it52-rails/HEAD/app/assets/fonts/HelveticaNeue-CondensedBold.otf -------------------------------------------------------------------------------- /app/assets/fonts/HelveticaNeue-LightItalic.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NNRUG/it52-rails/HEAD/app/assets/fonts/HelveticaNeue-LightItalic.otf -------------------------------------------------------------------------------- /app/assets/fonts/HelveticaNeue-MediumItalic.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NNRUG/it52-rails/HEAD/app/assets/fonts/HelveticaNeue-MediumItalic.otf -------------------------------------------------------------------------------- /app/assets/images/avatars_fallback/default.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NNRUG/it52-rails/HEAD/app/assets/images/avatars_fallback/default.png -------------------------------------------------------------------------------- /config/initializers/high_voltage.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | HighVoltage.configure do |config| 4 | config.routes = false 5 | end 6 | -------------------------------------------------------------------------------- /app/assets/fonts/HelveticaNeue-CondensedBlack.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NNRUG/it52-rails/HEAD/app/assets/fonts/HelveticaNeue-CondensedBlack.otf -------------------------------------------------------------------------------- /spec/support/webmock.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'webmock/rspec' 4 | 5 | WebMock.disable_net_connect!(allow_localhost: true) 6 | -------------------------------------------------------------------------------- /app/assets/fonts/HelveticaNeue-UltraLightItalic.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NNRUG/it52-rails/HEAD/app/assets/fonts/HelveticaNeue-UltraLightItalic.otf -------------------------------------------------------------------------------- /app/assets/images/events_fallback/fb_1200_default.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NNRUG/it52-rails/HEAD/app/assets/images/events_fallback/fb_1200_default.png -------------------------------------------------------------------------------- /spec/support/factory_bot.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | RSpec.configure do |config| 4 | config.include FactoryBot::Syntax::Methods 5 | end 6 | -------------------------------------------------------------------------------- /app/assets/images/avatars_fallback/square_150_default.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NNRUG/it52-rails/HEAD/app/assets/images/avatars_fallback/square_150_default.png -------------------------------------------------------------------------------- /app/assets/images/avatars_fallback/square_25_default.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NNRUG/it52-rails/HEAD/app/assets/images/avatars_fallback/square_25_default.png -------------------------------------------------------------------------------- /app/assets/images/avatars_fallback/square_50_default.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NNRUG/it52-rails/HEAD/app/assets/images/avatars_fallback/square_50_default.png -------------------------------------------------------------------------------- /app/assets/images/events_fallback/square_500_default.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NNRUG/it52-rails/HEAD/app/assets/images/events_fallback/square_500_default.png -------------------------------------------------------------------------------- /config/environments/staging.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Based on production defaults 4 | require Rails.root.join('config/environments/production') 5 | -------------------------------------------------------------------------------- /config/initializers/draper.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | Draper::CollectionDecorator.delegate :current_page, :total_pages, :limit_value, :total_count 4 | -------------------------------------------------------------------------------- /.env: -------------------------------------------------------------------------------- 1 | COMPOSE_PROJECT_NAME=it52 2 | VCS_REF=$(git rev-parse --short HEAD) 3 | BUILD_DATE=$(date -u +"%Y-%m-%dT%H:%M:%SZ") 4 | VERSION=latest 5 | REDIS_URL=redis://redis:6379 6 | 7 | -------------------------------------------------------------------------------- /config/REFACTOR.md: -------------------------------------------------------------------------------- 1 | # Refactor it52.info 2 | 3 | ## Features 4 | 5 | 1. Календарь 6 | 2. Карта 7 | 3. Админка для устроителей 8 | 1. Список участников 9 | 2. Анкетирование 10 | -------------------------------------------------------------------------------- /config/spring.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | %w[ 4 | .ruby-version 5 | .rbenv-vars 6 | tmp/restart.txt 7 | tmp/caching-dev.txt 8 | ].each { |path| Spring.watch(path) } 9 | -------------------------------------------------------------------------------- /lib/rails/sub_test_task.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Draper workaround for Rails 5 4 | require 'rake/testtask' 5 | 6 | class Rails::SubTestTask < Rake::TestTask 7 | end -------------------------------------------------------------------------------- /config.ru: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # This file is used by Rack-based servers to start the application. 4 | 5 | require_relative 'config/environment' 6 | 7 | run Rails.application 8 | -------------------------------------------------------------------------------- /config/webpack/test.js: -------------------------------------------------------------------------------- 1 | process.env.NODE_ENV = process.env.NODE_ENV || 'development' 2 | 3 | const environment = require('./environment') 4 | 5 | module.exports = environment.toWebpackConfig() 6 | -------------------------------------------------------------------------------- /config/initializers/da_data.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | DaData.configure do |config| 4 | config.default_params = { locations_boost: [{ kladr_id: 5_200_000_100_000 }] }.freeze 5 | end 6 | -------------------------------------------------------------------------------- /config/webpack/production.js: -------------------------------------------------------------------------------- 1 | process.env.NODE_ENV = process.env.NODE_ENV || 'production' 2 | 3 | const environment = require('./environment') 4 | 5 | module.exports = environment.toWebpackConfig() 6 | -------------------------------------------------------------------------------- /app/serializers/startup_serializer.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class StartupSerializer < ActiveModel::Serializer 4 | attributes :id, :name, :url, :logo, :description, :contacts 5 | end 6 | -------------------------------------------------------------------------------- /bin/rails: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | APP_PATH = File.expand_path('../config/application', __dir__) 5 | require_relative '../config/boot' 6 | require 'rails/commands' 7 | -------------------------------------------------------------------------------- /config/environment.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Load the Rails application. 4 | require_relative 'application' 5 | 6 | # Initialize the Rails application. 7 | Rails.application.initialize! 8 | -------------------------------------------------------------------------------- /app/views/my/authentications/_authentication.html.slim: -------------------------------------------------------------------------------- 1 | - icon = t("social.#{authentication.provider}.icon") 2 | 3 | li: .btn-group 4 | = authentication.link_to_social 5 | = authentication.link_to_destroy 6 | -------------------------------------------------------------------------------- /db/migrate/20140520095824_add_bio_to_users.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class AddBioToUsers < ActiveRecord::Migration[4.2] 4 | def change 5 | add_column :users, :bio, :text 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /app/views/startups/edit.html.slim: -------------------------------------------------------------------------------- 1 | - content_for(:topbar_actions) do 2 | a.material-icons.mdc-top-app-bar__action-item href=startups_path title='Все стартапы' list 3 | 4 | h1 = @startup.title 5 | 6 | == render 'form' 7 | -------------------------------------------------------------------------------- /public/yandex_637a660a79fbb6d1.html: -------------------------------------------------------------------------------- 1 | 2 |
3 | 4 | 5 | Verification: 637a660a79fbb6d1 6 | 7 | -------------------------------------------------------------------------------- /app/models/application_record.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class ApplicationRecord < ActiveRecord::Base 4 | self.abstract_class = true 5 | 6 | delegate :url_helpers, to: 'Rails.application.routes' 7 | end 8 | -------------------------------------------------------------------------------- /db/migrate/20140602183636_add_place_to_events.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class AddPlaceToEvents < ActiveRecord::Migration[4.2] 4 | def change 5 | add_column :events, :place, :string 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /db/migrate/20140902183616_add_website_to_user.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class AddWebsiteToUser < ActiveRecord::Migration[4.2] 4 | def change 5 | add_column :users, :website, :string 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /config/initializers/session_store.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Be sure to restart your server when you modify this file. 4 | 5 | Rails.application.config.session_store :cookie_store, key: '_it52_rails_session' 6 | -------------------------------------------------------------------------------- /db/migrate/20140507084053_add_role_to_users.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class AddRoleToUsers < ActiveRecord::Migration[4.2] 4 | def change 5 | add_column :users, :role, :integer, index: true 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /start_server.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | docker-compose -f docker/docker-compose.yml down 4 | [ -e tmp/pids/server.pid ] && rm tmp/pids/server.pid 5 | rm -fr public/packs/* 6 | docker-compose -f docker/docker-compose.yml up 7 | -------------------------------------------------------------------------------- /app/views/startups/new.html.slim: -------------------------------------------------------------------------------- 1 | - content_for(:topbar_actions) do 2 | a.material-icons.mdc-top-app-bar__action-item href=startups_path title='Все стартапы' list 3 | 4 | h1 = t('meta.startups.new.title') 5 | 6 | == render 'form' 7 | -------------------------------------------------------------------------------- /db/migrate/20181010093500_add_employment_to_users.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class AddEmploymentToUsers < ActiveRecord::Migration[5.2] 4 | def change 5 | add_column :users, :employment, :string 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /db/migrate/20190301095130_add_kind_to_events.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class AddKindToEvents < ActiveRecord::Migration[5.2] 4 | def change 5 | add_column :events, :kind, :integer, default: 0 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /db/migrate/20140521054705_add_title_image_to_events.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class AddTitleImageToEvents < ActiveRecord::Migration[4.2] 4 | def change 5 | add_column :events, :title_image, :string 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /db/migrate/20140521062142_add_avatar_image_to_users.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class AddAvatarImageToUsers < ActiveRecord::Migration[4.2] 4 | def change 5 | add_column :users, :avatar_image, :string 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /db/migrate/20141127113116_add_subscription_to_users.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class AddSubscriptionToUsers < ActiveRecord::Migration[4.2] 4 | def change 5 | add_column :users, :subscription, :boolean 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /db/migrate/20181011094902_add_foreign_link_to_event.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class AddForeignLinkToEvent < ActiveRecord::Migration[5.2] 4 | def change 5 | add_column :events, :foreign_link, :string 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /config/initializers/mime_types.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Be sure to restart your server when you modify this file. 4 | 5 | # Add new mime types for use in respond_to blocks: 6 | # Mime::Type.register "text/richtext", :rtf 7 | -------------------------------------------------------------------------------- /db/migrate/20140522134058_add_link_to_authentications.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class AddLinkToAuthentications < ActiveRecord::Migration[4.2] 4 | def change 5 | add_column :authentications, :link, :string 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /db/migrate/20150516133610_add_point_to_events.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class AddPointToEvents < ActiveRecord::Migration[4.2] 4 | def change 5 | add_column :events, :location, :point, geographic: true 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /lib/tasks/events.rake: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | namespace :events do 4 | desc 'Update events pageviews from Google Analytics' 5 | task update_pageviews: :environment do 6 | UpdateEventPageviews.perform 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /db/migrate/20140430090944_add_name_to_users.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class AddNameToUsers < ActiveRecord::Migration[4.2] 4 | def change 5 | add_column :users, :name, :string 6 | add_index :users, :name 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /db/migrate/20140507093336_add_published_to_events.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class AddPublishedToEvents < ActiveRecord::Migration[4.2] 4 | def change 5 | add_column :events, :published, :boolean, default: false 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /db/migrate/20141111093102_drop_index_users_on_email.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class DropIndexUsersOnEmail < ActiveRecord::Migration[4.2] 4 | def change 5 | remove_index :users, name: 'index_users_on_email' 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /db/migrate/20181119192414_add_pageviews_to_events.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class AddPageviewsToEvents < ActiveRecord::Migration[5.2] 4 | def change 5 | add_column :events, :pageviews, :integer, default: 0 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /spec/support/codecov.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | if ENV['CI'] == 'true' 4 | require 'simplecov' 5 | SimpleCov.start 'rails' 6 | 7 | require 'codecov' 8 | SimpleCov.formatter = SimpleCov::Formatter::Codecov 9 | end 10 | -------------------------------------------------------------------------------- /app/helpers/events_helper.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module EventsHelper 4 | def admin_event_icon_class(event) 5 | if event.published? 6 | 'fa-eye' 7 | else 8 | 'fa-eye-slash' 9 | end 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /config/initializers/string_to_url_extender.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class String 4 | def to_url 5 | parsed = Addressable::URI.heuristic_parse(self).to_s 6 | parsed if parsed&.match?(URI.regexp(%w[http https])) 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /config/cable.yml: -------------------------------------------------------------------------------- 1 | development: 2 | adapter: async 3 | 4 | test: 5 | adapter: async 6 | 7 | production: 8 | adapter: redis 9 | url: <%= ENV.fetch("REDIS_URL") { "redis://localhost:6379/1" } %> 10 | channel_prefix: it52_rails_production 11 | -------------------------------------------------------------------------------- /app/views/events/_admin_info.html.slim: -------------------------------------------------------------------------------- 1 | .admin-info 2 | i.fas [class="#{admin_event_icon_class(event)}" 3 | data-title="#{Event.human_attribute_name :published}: #{t(event.published.to_s)}" 4 | data-toggle="tooltip" data-placement="bottom"] 5 | 6 | -------------------------------------------------------------------------------- /db/migrate/20140507093209_add_organizer_referenses_to_events.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class AddOrganizerReferensesToEvents < ActiveRecord::Migration[4.2] 4 | def change 5 | add_reference :events, :organizer, index: true 6 | end 7 | end 8 | -------------------------------------------------------------------------------- /db/migrate/20140902181203_add_slug_to_users.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class AddSlugToUsers < ActiveRecord::Migration[4.2] 4 | def change 5 | add_column :users, :slug, :string 6 | add_index :users, :slug, unique: true 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /db/migrate/20141126154826_add_slug_to_events.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class AddSlugToEvents < ActiveRecord::Migration[4.2] 4 | def change 5 | add_column :events, :slug, :string 6 | add_index :events, :slug, unique: true 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /app/views/users/_user.html.slim: -------------------------------------------------------------------------------- 1 | .col-xs-12.col-sm-2 2 | .user-profile-preview = link_to user do 3 | .row 4 | .col-xs-2.col-sm-12 5 | .avatar = image_tag user.avatar_image.square_150.url 6 | .col-xs-10.col-sm-12 7 | = user.full_name 8 | -------------------------------------------------------------------------------- /spec/support/helpers/response.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Helpers 4 | module Response 5 | def response_body 6 | JSON.parse(response.body) 7 | rescue JSON::ParserError 8 | response.body 9 | end 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /app/serializers/v2/tag_serializer.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module V2 4 | class TagSerializer 5 | include FastJsonapi::ObjectSerializer 6 | 7 | set_key_transform :camel_lower 8 | 9 | attributes :name, :taggings_count 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /config/webpack/development.js: -------------------------------------------------------------------------------- 1 | process.env.NODE_ENV = process.env.NODE_ENV || 'development' 2 | 3 | const environment = require('./environment') 4 | const config = environment.toWebpackConfig(); 5 | config.output.filename = "js/[name]-[hash].js" 6 | 7 | module.exports = config 8 | -------------------------------------------------------------------------------- /app/views/startups/index.html.slim: -------------------------------------------------------------------------------- 1 | - content_for(:topbar_actions) do 2 | a.material-icons.mdc-top-app-bar__action-item href=new_startup_path title=t('meta.startups.new.title') add 3 | 4 | h1 Стартапы в Нижнем Новгороде 5 | br 6 | .grid 7 | .grid__inner 8 | = render @startups 9 | -------------------------------------------------------------------------------- /config/initializers/pluralization.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # rubocop:disable Lint/SendWithMixinArgument 4 | require 'i18n/backend/pluralization' 5 | I18n::Backend::Simple.send(:include, I18n::Backend::Pluralization) 6 | # rubocop:enable Lint/SendWithMixinArgument 7 | -------------------------------------------------------------------------------- /app/models/telegram/channel.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Telegram 4 | class Channel 5 | def self.groups 6 | @groups ||= YAML.load_file(Rails.root.join('config', 'telegram_channels.yml')).deep_symbolize_keys[:groups] 7 | end 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /db/migrate/20140430100247_create_events.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class CreateEvents < ActiveRecord::Migration[4.2] 4 | def change 5 | create_table :events do |t| 6 | t.string :title, null: false 7 | t.timestamps 8 | end 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /app/views/authentications/_unlinked.html.slim: -------------------------------------------------------------------------------- 1 | - icon = t("social.#{provider}.icon") 2 | 3 | li = link_to omniauth_authorize_path(:user, provider), class: %(btn btn-#{icon} btn-social), :"data-turbolinks" => false do 4 | i.fab> class="fa-#{icon}" 5 | span< = t("social.#{provider}.name") 6 | -------------------------------------------------------------------------------- /app/views/users/index.html.slim: -------------------------------------------------------------------------------- 1 | = cache @users do 2 | .page-header 3 | h1 4 | = t('.title') 5 | small< = t('.counter', count: User.count) 6 | 7 | - @users.each_slice(6) do |row_slice| 8 | .row = render row_slice 9 | 10 | .text-center 11 | == paginate @users 12 | -------------------------------------------------------------------------------- /config/initializers/filter_parameter_logging.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Be sure to restart your server when you modify this file. 4 | 5 | # Configure sensitive parameters which will be filtered from the log file. 6 | Rails.application.config.filter_parameters += %i[password token] 7 | -------------------------------------------------------------------------------- /db/migrate/20190612020440_add_address_id_to_event.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class AddAddressIdToEvent < ActiveRecord::Migration[5.2] 4 | def change 5 | add_reference :events, :address, foreign_key: true 6 | add_column :events, :address_comment, :string 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: [ 3 | require('postcss-import'), 4 | require('postcss-flexbugs-fixes'), 5 | require('postcss-preset-env')({ 6 | autoprefixer: { 7 | flexbox: 'no-2009' 8 | }, 9 | stage: 3 10 | }) 11 | ] 12 | } 13 | -------------------------------------------------------------------------------- /app/controllers/sitemaps_controller.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class SitemapsController < ApplicationController 4 | respond_to :xml 5 | 6 | def index 7 | @events = Event.published 8 | @startups = Startup.all 9 | @pages = HighVoltage.page_ids 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /db/migrate/20140520095617_add_first_name_and_last_name_to_users.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class AddFirstNameAndLastNameToUsers < ActiveRecord::Migration[4.2] 4 | def change 5 | add_column :users, :first_name, :string 6 | add_column :users, :last_name, :string 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /app/controllers/letsencrypt_controller.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class LetsencryptController < ApplicationController 4 | # skip_before_action :verify_authenticity_token 5 | 6 | def approve 7 | render text: ENV.fetch('letsencrypt_token') { 'letsencrypt_token' } 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /db/migrate/20140508095102_add_description_and_started_at_to_events.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class AddDescriptionAndStartedAtToEvents < ActiveRecord::Migration[4.2] 4 | def change 5 | add_column :events, :description, :text 6 | add_column :events, :started_at, :datetime 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /db/migrate/20140901165216_add_token_to_authentications.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class AddTokenToAuthentications < ActiveRecord::Migration[4.2] 4 | def change 5 | add_column :authentications, :token, :string 6 | add_column :authentications, :token_expires, :datetime 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /app/views/pages/communities.html.slim: -------------------------------------------------------------------------------- 1 | h1 IT-сообщества Нижнего Новгорода 2 | 3 | - Telegram::Channel.groups.values.each do |group| 4 | h3 = group[:name] 5 | ul.chevron-bullets 6 | - group[:channels].each_pair do |id, description| 7 | li #{link_to "@#{id}", "tg://resolve/?domain=#{id}"} — #{description} 8 | -------------------------------------------------------------------------------- /app/views/shared/_oauth_login_block.html.slim: -------------------------------------------------------------------------------- 1 | h2 = t('.social_providers') 2 | - t(:social).each_key do |provider| 3 | = link_to auth_at_provider_path(provider: provider), class: "btn btn-default btn-lg btn-#{provider}" do 4 | i.fas.fa-fw> class="fa-#{provider}" 5 | = t(:name, scope: "social.#{provider}") 6 | -------------------------------------------------------------------------------- /app/views/devise/mailer/unlock_instructions.html.slim: -------------------------------------------------------------------------------- 1 | p = "Привет, #{@resource.email}!" 2 | p Ваш аккаунт был заблокирован из-за нескольких попыток неправильного вводе пароля. 3 | p Пройдите по ссылке ниже, чтобы снять блокировку: 4 | p = link_to 'Разблокировать мой аккаунт', unlock_url(@resource, unlock_token: @token) 5 | -------------------------------------------------------------------------------- /db/migrate/20140902165236_rename_users_name_to_nickname.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class RenameUsersNameToNickname < ActiveRecord::Migration[4.2] 4 | def change 5 | rename_column :users, :name, :nickname 6 | change_column :users, :nickname, :string, uniq: true, index: true, default: '' 7 | end 8 | end 9 | -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | # See http://www.robotstxt.org/robotstxt.html for documentation on how to use the robots.txt file 2 | # 3 | # To ban all spiders from the entire site uncomment the next two lines: 4 | User-agent: * 5 | Allow: / 6 | Host: https://www.it52.info 7 | Crawl-delay: 2 8 | Sitemap: https://www.it52.info/sitemap.xml 9 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Add your own tasks in files placed in lib/tasks ending in .rake, 4 | # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake. 5 | 6 | require_relative 'config/application' 7 | require 'rake/testtask' 8 | 9 | Rails.application.load_tasks 10 | -------------------------------------------------------------------------------- /config/initializers/cookies_serializer.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Be sure to restart your server when you modify this file. 4 | 5 | # Specify a serializer for the signed and encrypted cookie jars. 6 | # Valid options are :json, :marshal, and :hybrid. 7 | Rails.application.config.action_dispatch.cookies_serializer = :json 8 | -------------------------------------------------------------------------------- /config/initializers/application_controller_renderer.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Be sure to restart your server when you modify this file. 4 | 5 | # ActiveSupport::Reloader.to_prepare do 6 | # ApplicationController.renderer.defaults.merge!( 7 | # http_host: 'example.org', 8 | # https: false 9 | # ) 10 | # end 11 | -------------------------------------------------------------------------------- /config/initializers/taggable.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class TagsParser < ActsAsTaggableOn::GenericParser 4 | def parse 5 | ActsAsTaggableOn::TagList.new.tap do |tag_list| 6 | tag_list.add @tag_list.split(%r{\,|\s|\||/|\;}) 7 | end 8 | end 9 | end 10 | 11 | ActsAsTaggableOn.default_parser = TagsParser 12 | -------------------------------------------------------------------------------- /db/migrate/20140521082751_nullable_sorcery_core.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class NullableSorceryCore < ActiveRecord::Migration[4.2] 4 | def change 5 | change_column_null(:users, :email, true) 6 | change_column_null(:users, :crypted_password, true) 7 | change_column_null(:users, :salt, true) 8 | end 9 | end 10 | -------------------------------------------------------------------------------- /bin/yarn: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # frozen_string_literal: true 3 | 4 | APP_ROOT = File.expand_path('..', __dir__) 5 | Dir.chdir(APP_ROOT) do 6 | exec 'yarnpkg', *ARGV 7 | rescue Errno::ENOENT 8 | warn 'Yarn executable was not detected in the system.' 9 | warn 'Download Yarn at https://yarnpkg.com/en/docs/install' 10 | exit 1 11 | end 12 | -------------------------------------------------------------------------------- /lib/templates/slim/scaffold/_form.html.slim: -------------------------------------------------------------------------------- 1 | = simple_form_for(@<%= singular_table_name %>) do |f| 2 | = f.error_notification 3 | 4 | .form-inputs 5 | <%- attributes.each do |attribute| -%> 6 | = f.<%= attribute.reference? ? :association : :input %> :<%= attribute.name %> 7 | <%- end -%> 8 | 9 | .form-actions 10 | = f.button :submit 11 | -------------------------------------------------------------------------------- /bin/sync_db: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | heroku pg:backups:capture -a it52 3 | heroku pg:backups:download -a it52 4 | docker cp ./latest.dump $(docker-compose ps -q db):/tmp/latest.dump 5 | docker-compose exec db pg_restore --verbose --clean --no-acl --no-owner -U postgres -d it52_rails_dev /tmp/latest.dump 6 | docker-compose exec db rm /tmp/latest.dump 7 | rm ./latest.dump 8 | -------------------------------------------------------------------------------- /db/migrate/20140430090220_sorcery_external.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class SorceryExternal < ActiveRecord::Migration[4.2] 4 | def change 5 | create_table :authentications do |t| 6 | t.integer :user_id, null: false 7 | t.string :provider, :uid, null: false 8 | 9 | t.timestamps 10 | end 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /config/initializers/sidekiq.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | REDIS_OPTIONS = { url: ENV.fetch('REDIS_URL') { 'redis://redis:6379' }, 4 | db: 1 }.freeze 5 | 6 | Sidekiq.configure_server do |config| 7 | config.redis = REDIS_OPTIONS.dup 8 | end 9 | 10 | Sidekiq.configure_client do |config| 11 | config.redis = REDIS_OPTIONS.dup 12 | end 13 | -------------------------------------------------------------------------------- /config/initializers/silencer.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | if Rails.env.development? 4 | require 'silencer/logger' 5 | 6 | Rails.application.configure do 7 | config.middleware.swap( 8 | Rails::Rack::Logger, 9 | Silencer::Logger, 10 | config.log_tags, 11 | get: [%r{^/images/aws_host/uploads/}] 12 | ) 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { "browser": true }, 3 | "extends": ["airbnb"], 4 | "plugins": ["@typescript-eslint"], 5 | "parser": "@typescript-eslint/parser", 6 | "parserOptions": { "project": ["./tsconfig.json"] }, 7 | "rules": { 8 | "import/no-unresolved": 0, 9 | "react/jsx-filename-extension": [1, { "extensions": [".jsx", ".tsx"] }] 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /db/migrate/20140508105348_create_event_participations.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class CreateEventParticipations < ActiveRecord::Migration[4.2] 4 | def change 5 | create_table :event_participations do |t| 6 | t.references :user, index: true 7 | t.references :event, index: true 8 | 9 | t.timestamps 10 | end 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /config/initializers/apipie.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Apipie.configure do |config| 4 | # config.app_name = "IT52" 5 | # config.api_base_url = "/api" 6 | # config.doc_base_url = "/apidoc" 7 | # # where is your API defined? 8 | # config.api_controllers_matcher = "#{Rails.root}/app/controllers/api/**/*.rb" 9 | # end 10 | -------------------------------------------------------------------------------- /db/migrate/20140430090218_sorcery_remember_me.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class SorceryRememberMe < ActiveRecord::Migration[4.2] 4 | def change 5 | add_column :users, :remember_me_token, :string, default: nil 6 | add_column :users, :remember_me_token_expires_at, :datetime, default: nil 7 | 8 | add_index :users, :remember_me_token 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /app/views/devise/passwords/new.html.slim: -------------------------------------------------------------------------------- 1 | .page-header: h1 = t('.title') 2 | 3 | .row: .col-xs-12.col-sm-6.col-md-6.col-lg-5 4 | = simple_form_for(resource, as: resource_name, url: password_path(resource_name), html: { method: :post }) do |f| 5 | = f.input :email, autofocus: true 6 | = f.button :submit, t('.send'), class: 'btn-success' 7 | hr 8 | = render "devise/shared/links" 9 | -------------------------------------------------------------------------------- /app/controllers/pages_controller.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class PagesController < ApplicationController 4 | include HighVoltage::StaticPage 5 | 6 | before_action :set_telegram_domain, if: -> { params[:id] == 'communities' } 7 | 8 | private 9 | 10 | def set_telegram_domain 11 | @telegram_domain = ENV.fetch('telegram_domain') { 't.me' } 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /db/migrate/20190605125210_create_donations.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class CreateDonations < ActiveRecord::Migration[5.2] 4 | def change 5 | create_table :donations do |t| 6 | t.float :amount, null: false 7 | t.integer :kind, null: false 8 | t.float :amount_in_rub, null: false 9 | 10 | t.timestamps 11 | end 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /lib/da_data/configuration.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module DaData 4 | class Configuration 5 | attr_accessor :auth_token, :auth_secret, :default_params 6 | 7 | def initialize 8 | @auth_token = ENV.fetch('DADATA_AUTH_TOKEN') { nil } 9 | @auth_secret = ENV.fetch('DADATA_AUTH_SECRET') { nil } 10 | @default_params = {} 11 | end 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /app/assets/stylesheets/user_profiles.sass: -------------------------------------------------------------------------------- 1 | .user-profile-preview 2 | @media (min-width: $screen-sm) 3 | text-align: center 4 | @media (min-width: $screen-md) 5 | margin-bottom: $line-height-computed 6 | a 7 | color: $text-color 8 | display: block 9 | .avatar 10 | margin-bottom: 1em 11 | 12 | .user-profile-page, 13 | .edit_user 14 | .avatar 15 | max-width: 150px 16 | -------------------------------------------------------------------------------- /app/views/turbo/events/_event.rss.builder: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | html = render partial: 'events/event-item', locals: { event: event } 4 | 5 | xml.item(turbo: 'true') do |item| 6 | item.link event_url(event) 7 | item.pubDate event.published_at.rfc2822 8 | item.author event.organizer.to_s 9 | item.turbo(:content) do |content| 10 | content.cdata! html 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /app/services/extract_event_address_service.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class ExtractEventAddressService 4 | def initialize(event) 5 | @event = event 6 | end 7 | 8 | def call 9 | suggestions = DaData::Request.suggest_address(@event.place) 10 | fias_id = suggestions['suggestions'][0]['data']['fias_id'] 11 | data = DaData::Request.find_by(id: fias_id) 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /app/controllers/turbo/events_controller.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Turbo 4 | class EventsController < ApplicationController 5 | respond_to :rss 6 | 7 | def index 8 | @events = Event.includes(:event_participations, :participants, :organizer) 9 | .order(published_at: :asc) 10 | .published.decorate 11 | end 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /app/models/telegram.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Telegram 4 | API_KEY = ENV.fetch('telegram_bot_token') { 'telegram_bot_token' } 5 | CHAT_ID = ENV.fetch('telegram_chat_id') { 'telegram_chat_id' } 6 | BASE_URI = 'https://api.telegram.org' 7 | 8 | class ParseError < StandardError; end 9 | class LongMessageError < StandardError; end 10 | class Error < StandardError; end 11 | end 12 | -------------------------------------------------------------------------------- /app/views/events/_participants_block.html.slim: -------------------------------------------------------------------------------- 1 | - if event.participants.any? 2 | ul.list-unstyled 3 | - event.participants.sample(24).each do |p| 4 | li.participant 5 | = link_to p, data: { toggle: 'tooltip', placement: 'bottom', title: p.full_name }, class: 'participant-link' do 6 | .avatar = image_tag p.avatar_image.square_50.url, alt: p.to_s 7 | - else 8 | p.lead = t('.no_participants') 9 | -------------------------------------------------------------------------------- /config/initializers/kaminari_config.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | Kaminari.configure do |config| 4 | config.default_per_page = 30 5 | # config.max_per_page = nil 6 | # config.window = 4 7 | # config.outer_window = 0 8 | # config.left = 0 9 | # config.right = 0 10 | # config.page_method_name = :page 11 | # config.param_name = :page 12 | # config.params_on_first_page = false 13 | end 14 | -------------------------------------------------------------------------------- /deploy/systemd/metabase.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=it52 metabase service 3 | Requires=docker.service 4 | After=docker.service 5 | 6 | [Service] 7 | Restart=always 8 | WorkingDirectory=/opt/it52 9 | 10 | ExecStart=/usr/bin/docker run -p 3010:3000 --env-file /opt/it52/docker/.env.metabase --name metabase metabase/metabase 11 | ExecStop=/usr/bin/docker rm metabase 12 | 13 | [Install] 14 | WantedBy=multi-user.target 15 | -------------------------------------------------------------------------------- /db/migrate/20141125211802_add_published_at_to_events.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class AddPublishedAtToEvents < ActiveRecord::Migration[4.2] 4 | def change 5 | add_column :events, :published_at, :datetime 6 | 7 | Event.published.each do |event| 8 | publish_time = event.past? ? event.created_at : Time.zone.now 9 | event.update(published_at: publish_time) 10 | end 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /db/migrate/20140430090217_sorcery_core.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class SorceryCore < ActiveRecord::Migration[4.2] 4 | def change 5 | create_table :users do |t| 6 | t.string :email, null: false 7 | t.string :crypted_password, null: false 8 | t.string :salt, null: false 9 | 10 | t.timestamps 11 | end 12 | 13 | add_index :users, :email, unique: true 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /lib/da_data.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'da_data/configuration' 4 | require 'da_data/request' 5 | 6 | module DaData 7 | class << self 8 | attr_accessor :configuration 9 | end 10 | 11 | def self.configuration 12 | @configuration ||= Configuration.new 13 | end 14 | 15 | def self.reset 16 | @configuration = Configuration.new 17 | end 18 | 19 | def self.configure 20 | yield(configuration) 21 | end 22 | end 23 | -------------------------------------------------------------------------------- /spec/support/database_cleaner.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'database_cleaner' 4 | 5 | DatabaseCleaner.allow_remote_database_url = true 6 | DatabaseCleaner.strategy = :transaction 7 | 8 | RSpec.configure do |config| 9 | config.before(:suite) do 10 | DatabaseCleaner.clean_with(:truncation) 11 | end 12 | 13 | config.around do |example| 14 | DatabaseCleaner.cleaning do 15 | example.run 16 | end 17 | end 18 | end 19 | -------------------------------------------------------------------------------- /app/serializers/event_brief_serializer.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class EventBriefSerializer < ActiveModel::Serializer 4 | cache key: 'event', expires_in: 3.hours 5 | 6 | attributes :id, :title, :description, :image_url, :place, :started_at, :started_at_js, :location, :tag_list 7 | 8 | def image_url 9 | object.title_image.square_500.url 10 | end 11 | 12 | def started_at_js 13 | object.started_at.to_f * 1000 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /db/migrate/20140430090219_sorcery_reset_password.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class SorceryResetPassword < ActiveRecord::Migration[4.2] 4 | def change 5 | add_column :users, :reset_password_token, :string, default: nil 6 | add_column :users, :reset_password_token_expires_at, :datetime, default: nil 7 | add_column :users, :reset_password_email_sent_at, :datetime, default: nil 8 | 9 | add_index :users, :reset_password_token 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /spec/controllers/sitemaps_controller_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | describe SitemapsController do 4 | render_views 5 | 6 | describe 'GET index' do 7 | before do 8 | FactoryBot.create(:event, :published) 9 | get :index, format: :xml 10 | end 11 | 12 | it { expect(response).to have_http_status(:ok) } 13 | it { expect(response).to be_ok } 14 | it { expect(response.content_type).to eq 'application/xml' } 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /.github/workflows/deploy.yml: -------------------------------------------------------------------------------- 1 | name: Deploy container to production 2 | on: workflow_dispatch 3 | jobs: 4 | deploy: 5 | name: deploy 6 | runs-on: ubuntu-latest 7 | steps: 8 | - name: Update and restart docker container 9 | uses: appleboy/ssh-action@master 10 | with: 11 | host: ${{ secrets.DEPLOY_HOST }} 12 | username: ${{ secrets.DEPLOY_USERNAME }} 13 | key: ${{ secrets.DEPLOY_KEY }} 14 | script: sudo /opt/it52/update_docker 15 | -------------------------------------------------------------------------------- /app/helpers/application_helper.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module ApplicationHelper 4 | def render_editor? 5 | controller.controller_name == 'events' && !%w[index show].include?(controller.action_name) 6 | end 7 | 8 | def logo_class 9 | return 'user' if current_user&.member? 10 | return 'root' if current_user&.admin? 11 | 12 | '' 13 | end 14 | 15 | def meta_t(key) 16 | I18n.t("meta.#{controller_name}.#{action_name}.#{key}") 17 | end 18 | end 19 | -------------------------------------------------------------------------------- /app/views/devise/unlocks/new.html.slim: -------------------------------------------------------------------------------- 1 | .page-header: h1 = t('.title') 2 | 3 | .row: .col-xs-12.col-sm-6.col-md-6.col-lg-5 4 | 5 | = simple_form_for(resource, as: resource_name, url: unlock_path(resource_name), html: { method: :post }) do |f| 6 | = f.error_notification 7 | = f.full_error :unlock_token 8 | = f.input :email, required: true, autofocus: true 9 | 10 | = f.button :submit, "Resend unlock instructions" 11 | 12 | hr 13 | 14 | = render "devise/shared/links" 15 | -------------------------------------------------------------------------------- /app/models/event_participation.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # == Schema Information 4 | # 5 | # Table name: event_participations 6 | # 7 | # id :integer not null, primary key 8 | # user_id :integer 9 | # event_id :integer 10 | # created_at :datetime 11 | # updated_at :datetime 12 | # 13 | 14 | class EventParticipation < ApplicationRecord 15 | belongs_to :user 16 | belongs_to :event 17 | 18 | validates :user_id, uniqueness: { scope: :event_id } 19 | end 20 | -------------------------------------------------------------------------------- /bin/webpack: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | ENV["RAILS_ENV"] ||= ENV["RACK_ENV"] || "development" 4 | ENV["NODE_ENV"] ||= "development" 5 | 6 | require "pathname" 7 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", 8 | Pathname.new(__FILE__).realpath) 9 | 10 | require "bundler/setup" 11 | 12 | require "webpacker" 13 | require "webpacker/webpack_runner" 14 | 15 | APP_ROOT = File.expand_path("..", __dir__) 16 | Dir.chdir(APP_ROOT) do 17 | Webpacker::WebpackRunner.run(ARGV) 18 | end 19 | -------------------------------------------------------------------------------- /app/controllers/errors_controller.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class ErrorsController < ApplicationController 4 | layout false 5 | 6 | def error_404; end 7 | 8 | def image 9 | redirect_to build_attachment_path, status: :permanent_redirect 10 | end 11 | 12 | private 13 | 14 | def build_attachment_path 15 | production_prefix = 'https://assets.it52.info' 16 | [production_prefix, request.path.gsub('uploads/development', 'uploads/production')].join 17 | end 18 | end 19 | -------------------------------------------------------------------------------- /app/views/events/_event-item.rss.slim: -------------------------------------------------------------------------------- 1 | header 2 | h1 = event.title 3 | figure = image_tag event.title_image.square_500.url 4 | h2 = [l(event.started_at, format: :date_time_full), event.place].join(' | ') 5 | 6 | = event.rendered_description 7 | 8 | button formaction=event_url(event) data={'background-color' => '#333333', color: '#FEFEFE', turbo: 'false', primary: 'true'} Зарегистрироваться 9 | 10 | div data={ block: 'share', network: 'telegram, vkontakte, twitter, facebook, google'} 11 | 12 | 13 | -------------------------------------------------------------------------------- /config/boot.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__) 4 | 5 | require 'bundler/setup' # Set up gems listed in the Gemfile. 6 | 7 | begin 8 | require 'bootsnap/setup' # Speed up boot time by caching expensive operations. 9 | rescue LoadError 10 | # bootsnap is an optional dependency, so if we don't have it it's fine 11 | # Do not load in production because file system (where cache would be written) is read-only 12 | nil 13 | end 14 | -------------------------------------------------------------------------------- /config/initializers/backtrace_silencers.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Be sure to restart your server when you modify this file. 4 | 5 | # You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces. 6 | # Rails.backtrace_cleaner.add_silencer { |line| line =~ /my_noisy_library/ } 7 | 8 | # You can also remove all the silencers if you're trying to debug a problem that might stem from framework code. 9 | # Rails.backtrace_cleaner.remove_silencers! 10 | -------------------------------------------------------------------------------- /app/controllers/users_controller.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class UsersController < ApplicationController 4 | respond_to :html 5 | 6 | def index 7 | @users = User.order(:slug).page(params[:page]) 8 | end 9 | 10 | def show 11 | @user = User.friendly.find(params[:id]).decorate 12 | @owned_events = @user.owner_of_events.visible_by_user(current_user) 13 | @attended_events = @user.member_in_events.visible_by_user(current_user) 14 | respond_with @user 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /app/views/devise/registrations/new.html.slim: -------------------------------------------------------------------------------- 1 | .page-header: h1 = t('.title') 2 | 3 | .row: .col-xs-12.col-sm-6.col-md-6.col-lg-5 4 | = simple_form_for resource, as: resource_name, url: registration_path(resource_name) do |f| 5 | = f.input :email, autofocus: true, required: true 6 | = f.input :password, required: true 7 | = f.input :password_confirmation, required: true 8 | 9 | = f.button :submit, t('.sign_up'), class: 'btn-success' 10 | 11 | hr 12 | 13 | = render "devise/shared/links" 14 | -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | .byebug_history 2 | .bundle/ 3 | .dockerignore 4 | .env* 5 | .git 6 | .github/* 7 | .gitignore 8 | .idea 9 | .vagrant/* 10 | coverage/* 11 | config/master.key 12 | docker/Dockerfile* 13 | docker/docker-compose.* 14 | log/* 15 | node_modules/* 16 | Procfile* 17 | public/assets/* 18 | public/packs/* 19 | public/packs-test/* 20 | public/system/* 21 | public/sitemap* 22 | public/uploads/* 23 | storage/* 24 | tmp/* 25 | vendor/* 26 | yarn-error.log 27 | 28 | *.sublime-project 29 | *.sublime-workspace 30 | -------------------------------------------------------------------------------- /app/uploaders/event_title_image_uploader.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class EventTitleImageUploader < CarrierWave::Uploader::Base 4 | include UploaderConcern 5 | 6 | def default_url 7 | ActionController::Base.helpers.asset_path('events_fallback/' + [version_name, 'default.png'].compact.join('_')) 8 | end 9 | 10 | version :square_500 do 11 | process resize_to_fit: [500, 500] 12 | end 13 | 14 | version :fb_1200 do 15 | process resize_to_fill: [1200, 630] 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /app/views/devise/confirmations/new.html.slim: -------------------------------------------------------------------------------- 1 | .page-header: h1 = t('.title') 2 | 3 | .row: .col-xs-12.col-sm-6.col-md-6.col-lg-5 4 | = simple_form_for resource, as: resource_name, url: confirmation_path(resource_name), html: { method: :post } do |f| 5 | - if f.error(:confirmation_token).present? 6 | .alert.alert-danger: p = f.error(:confirmation_token) 7 | = f.input :email, autofocus: true 8 | = f.button :submit, t('.send'), class: 'btn-success' 9 | hr 10 | = render "devise/shared/links" 11 | -------------------------------------------------------------------------------- /bin/webpack-dev-server: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | ENV["RAILS_ENV"] ||= ENV["RACK_ENV"] || "development" 4 | ENV["NODE_ENV"] ||= "development" 5 | 6 | require "pathname" 7 | ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", 8 | Pathname.new(__FILE__).realpath) 9 | 10 | require "bundler/setup" 11 | 12 | require "webpacker" 13 | require "webpacker/dev_server_runner" 14 | 15 | APP_ROOT = File.expand_path("..", __dir__) 16 | Dir.chdir(APP_ROOT) do 17 | Webpacker::DevServerRunner.run(ARGV) 18 | end 19 | -------------------------------------------------------------------------------- /config/initializers/runtimeerror_notifier.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # if defined?(RuntimeerrorNotifier) 4 | # # Get your secret email address from RuntimeError.net and 5 | # # 1. Set it as environment variable RUNTIMEERROR_EMAIL (preferred method) 6 | # # 2. OR, change the value (legacy method) 7 | # RuntimeerrorNotifier.for ENV['RUNTIMEERROR_EMAIL'] 8 | 9 | # RuntimeerrorNotifier::Notifier::IGNORED_EXCEPTIONS.push(*%w[ 10 | # ActionController::RoutingError 11 | # ]) 12 | # end 13 | -------------------------------------------------------------------------------- /deploy/systemd/it52.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=it52 service with docker-compose 3 | Requires=docker.service 4 | After=docker.service 5 | 6 | [Service] 7 | Restart=always 8 | WorkingDirectory=/opt/it52 9 | 10 | Environment="COMPOSE_PROJECT_NAME=it52" 11 | 12 | ExecStart=/usr/local/bin/docker-compose -f docker/docker-compose.production.yml up rails sidekiq 13 | ExecStop=/usr/local/bin/docker-compose -f docker/docker-compose.production.yml down rails sidekiq 14 | 15 | [Install] 16 | WantedBy=multi-user.target 17 | -------------------------------------------------------------------------------- /app/views/devise/passwords/edit.html.slim: -------------------------------------------------------------------------------- 1 | .page-header: h1 = t('.title') 2 | 3 | .row: .col-xs-12.col-sm-6.col-md-6.col-lg-5 4 | = simple_form_for(resource, as: resource_name, url: password_path(resource_name), html: { method: :put }) do |f| 5 | = f.input :reset_password_token, as: :hidden 6 | = f.full_error :reset_password_token 7 | = f.input :password, autofocus: true 8 | = f.input :password_confirmation 9 | 10 | = f.button :submit, t('.submit') 11 | hr 12 | = render "devise/shared/links" 13 | -------------------------------------------------------------------------------- /db/migrate/20140430090221_sorcery_activity_logging.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class SorceryActivityLogging < ActiveRecord::Migration[4.2] 4 | def change 5 | add_column :users, :last_login_at, :datetime, default: nil 6 | add_column :users, :last_logout_at, :datetime, default: nil 7 | add_column :users, :last_activity_at, :datetime, default: nil 8 | add_column :users, :last_login_from_ip_address, :string, default: nil 9 | 10 | add_index :users, %i[last_logout_at last_activity_at] 11 | end 12 | end 13 | -------------------------------------------------------------------------------- /app/views/devise/mailer/reset_password_instructions.html.slim: -------------------------------------------------------------------------------- 1 | p 2 | - if @resource.to_s.present? 3 | = t('devise.emails.reset_password.greetings.named', name: @resource.to_s||@resource.email) 4 | - else 5 | = t('devise.emails.reset_password.greetings.anon') 6 | 7 | p == t('devise.emails.reset_password.body')[0] 8 | p = link_to t('devise.emails.reset_password.reset_link'), edit_password_url(@resource, reset_password_token: @token) 9 | p = t('devise.emails.reset_password.body')[1] 10 | 11 | '-- 12 | br 13 | == t('devise.emails.signature') 14 | -------------------------------------------------------------------------------- /app/assets/stylesheets/app.sass: -------------------------------------------------------------------------------- 1 | @use "sass:math" 2 | 3 | // Sass 4 | @import "font-awesome-sprockets" 5 | @import "font-awesome" 6 | 7 | @import "theme/variables" 8 | @import "theme/type" 9 | 10 | @import "theme/bootstrap_and_overrides" 11 | 12 | @import "theme/common_styles" 13 | @import "theme/typography" 14 | 15 | @import "events" 16 | @import "user_profiles" 17 | 18 | // CSS 19 | @import "simplemde/dist/simplemde.min" 20 | @import "flatpickr/dist/flatpickr" 21 | @import "flatpickr/dist/themes/airbnb" 22 | 23 | // Material 24 | @import "material" 25 | -------------------------------------------------------------------------------- /app/services/render_ar_collection_to_csv.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'csv' 4 | 5 | class RenderArCollectionToCsv 6 | def self.perform(collection, column_names = nil, options = {}) 7 | column_names ||= collection.table_name.singularize.capitalize.constantize.column_names 8 | 9 | CSV.generate(**options) do |csv| 10 | csv << column_names 11 | collection.each do |collection_item| 12 | csv << column_names.map { |method_name| collection_item.send(method_name) } 13 | end 14 | end 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /app/views/devise/mailer/confirmation_instructions.html.slim: -------------------------------------------------------------------------------- 1 | h4 Добро пожаловать! 2 | p 3 | = "Вы собираетесь зарегистрироваться (или изменить email) на сайте #{ENV.fetch('mailing_host') {'mailing_host'}} с адресом" 4 | strong< = @resource.email 5 | p Пожалуйста, подтвердите свой email, кликнув на ссылку ниже. 6 | p == link_to 'Да, это моя почта', confirmation_url(@resource, confirmation_token: @token) 7 | p Если вы не регистрировались на указанном сайте, просто проигнорируйте это сообщение. 8 | 9 | == "--" 10 | br/ 11 | == t('devise.emails.signature') 12 | -------------------------------------------------------------------------------- /app/uploaders/startup_logo_uploader.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class StartupLogoUploader < CarrierWave::Uploader::Base 4 | include UploaderConcern 5 | 6 | def default_url 7 | ActionController::Base.helpers.asset_path('avatars_fallback/' + [version_name, 'default.png'].compact.join('_')) 8 | end 9 | 10 | version :big do 11 | process resize_to_fit: [512, 512] 12 | end 13 | 14 | version :medium do 15 | process resize_to_fit: [256, 256] 16 | end 17 | 18 | version :small do 19 | process resize_to_fit: [32, 32] 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /db/migrate/20190624125250_create_startups.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class CreateStartups < ActiveRecord::Migration[5.2] 4 | def change 5 | create_table :startups do |t| 6 | t.string :title, null: false, index: true 7 | t.string :url 8 | t.string :slug, index: true 9 | t.string :logo 10 | t.string :intro 11 | t.text :description, null: false 12 | t.jsonb :contacts, default: { name: '', email: '' } 13 | t.references :author, null: false, index: true 14 | 15 | t.timestamps 16 | end 17 | end 18 | end 19 | -------------------------------------------------------------------------------- /spec/controllers/turbo/events_controller_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | describe Turbo::EventsController do 4 | render_views 5 | 6 | describe 'GET index' do 7 | before do 8 | create(:event, :published) 9 | create(:event) 10 | get :index, format: :rss 11 | end 12 | 13 | it 'returns valid response' do 14 | expect(response).to have_http_status(:ok) 15 | expect(response.content_type).to eq 'application/rss+xml' 16 | expect(Nokogiri::XML(response.body).css('channel item').count).to eq 1 17 | end 18 | end 19 | end 20 | -------------------------------------------------------------------------------- /app/uploaders/user_avatar_uploader.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class UserAvatarUploader < CarrierWave::Uploader::Base 4 | include UploaderConcern 5 | 6 | def default_url 7 | ActionController::Base.helpers.asset_path('avatars_fallback/' + [version_name, 'default.png'].compact.join('_')) 8 | end 9 | 10 | version :square_25 do 11 | process resize_to_fill: [25, 25] 12 | end 13 | 14 | version :square_50 do 15 | process resize_to_fill: [50, 50] 16 | end 17 | 18 | version :square_150 do 19 | process resize_to_fill: [150, 150] 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /spec/factories/startups.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | FactoryBot.define do 4 | factory :startup do 5 | title { FFaker::Company.name } 6 | url { FFaker::Internet.http_url } 7 | logo { Rack::Test::UploadedFile.new(Rails.root.join('spec/fixtures/logo.png'), 'image/png') } 8 | intro { FFaker::Company.catch_phrase } 9 | description { FFaker::LoremRU.paragraphs(5).join("\n\n") } 10 | contacts { { contacts: [{ name: FFaker::Name.name, email: FFaker::Internet.email }] } } 11 | author { create(:user) } 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "declaration": false, 4 | "emitDecoratorMetadata": true, 5 | "experimentalDecorators": true, 6 | "lib": ["es6", "dom"], 7 | "module": "es6", 8 | "moduleResolution": "node", 9 | "baseUrl": ".", 10 | "paths": { 11 | "*": ["node_modules/*", "app/javascript/*"] 12 | }, 13 | "sourceMap": true, 14 | "target": "es5", 15 | "noEmit": true 16 | }, 17 | "exclude": [ 18 | "**/*.spec.ts", 19 | "node_modules", 20 | "vendor", 21 | "public" 22 | ], 23 | "compileOnSave": false 24 | } 25 | -------------------------------------------------------------------------------- /app/serializers/v2/user_serializer.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module V2 4 | class UserSerializer 5 | include FastJsonapi::ObjectSerializer 6 | 7 | cache_options enabled: true, cache_length: 1.day 8 | set_key_transform :camel_lower 9 | 10 | attributes :created_at, :updated_at, :nickname, :role, :first_name, :last_name, :bio, :avatar_image, :slug, :website, :subscription, :employment 11 | 12 | link :url do |object| 13 | Rails.application.routes.url_helpers.user_url(object, host: ENV.fetch('mailing_host') { 'it52.info' }) 14 | end 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /config/initializers/wrap_parameters.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Be sure to restart your server when you modify this file. 4 | 5 | # This file contains settings for ActionController::ParamsWrapper which 6 | # is enabled by default. 7 | 8 | # Enable parameter wrapping for JSON. You can disable this by setting :format to an empty array. 9 | ActiveSupport.on_load(:action_controller) do 10 | wrap_parameters format: [:json] 11 | end 12 | 13 | # To enable root element in JSON for ActiveRecord objects. 14 | # ActiveSupport.on_load(:active_record) do 15 | # self.include_root_in_json = true 16 | # end 17 | -------------------------------------------------------------------------------- /app/controllers/api/v1/users_controller.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Api 4 | module V1 5 | class UsersController < ApiController 6 | # resource_description do 7 | # short 'Участники' 8 | # formats ['json'] 9 | # param :id, /\d+/, desc: "User ID", required: true 10 | # api_version "v1" 11 | # api_base_url 'api/v1/users' 12 | # end 13 | 14 | # api :GET, '/:id', 'Получить данные пользователя' 15 | def show 16 | @response_object = User.find(params[:id]) 17 | render render_options 18 | end 19 | end 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /bin/rake: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # 3 | # This file was generated by RubyGems. 4 | # 5 | # The application 'rake' is installed as part of a gem, and 6 | # this file is here to facilitate running it. 7 | # 8 | 9 | require 'rubygems' 10 | 11 | version = ">= 0.a" 12 | 13 | str = ARGV.first 14 | if str 15 | str = str.b[/\A_(.*)_\z/, 1] 16 | if str and Gem::Version.correct?(str) 17 | version = str 18 | ARGV.shift 19 | end 20 | end 21 | 22 | if Gem.respond_to?(:activate_bin_path) 23 | load Gem.activate_bin_path('rake', 'rake', version) 24 | else 25 | gem "rake", version 26 | load Gem.bin_path("rake", "rake", version) 27 | end 28 | -------------------------------------------------------------------------------- /bin/rackup: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # 3 | # This file was generated by RubyGems. 4 | # 5 | # The application 'rack' is installed as part of a gem, and 6 | # this file is here to facilitate running it. 7 | # 8 | 9 | require 'rubygems' 10 | 11 | version = ">= 0.a" 12 | 13 | str = ARGV.first 14 | if str 15 | str = str.b[/\A_(.*)_\z/, 1] 16 | if str and Gem::Version.correct?(str) 17 | version = str 18 | ARGV.shift 19 | end 20 | end 21 | 22 | if Gem.respond_to?(:activate_bin_path) 23 | load Gem.activate_bin_path('rack', 'rackup', version) 24 | else 25 | gem "rack", version 26 | load Gem.bin_path("rack", "rackup", version) 27 | end 28 | -------------------------------------------------------------------------------- /spec/lib/da_data/request_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | describe DaData::Request do 4 | subject { described_class.new(:suggest_address) } 5 | 6 | before { allow(subject.client).to receive(:post).and_return('{"a": 1}') } 7 | 8 | describe '.new' do 9 | it { expect(subject.content_type).to eq 'application/json' } 10 | 11 | it { 12 | expect(subject.client.default_options.headers.to_h) 13 | .to include('Content-Type' => 'application/json', 'Accept' => 'application/json') 14 | } 15 | end 16 | 17 | describe '#query' do 18 | it { expect(subject.query('')).to eq('a' => 1) } 19 | end 20 | end 21 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: [kugaevsky, r3nya, ujifyxbr, noroot] 4 | patreon: it52 5 | open_collective: # Replace with a single Open Collective username 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://www.it52.info/donate 13 | -------------------------------------------------------------------------------- /config/locales/kaminari-ru.yml: -------------------------------------------------------------------------------- 1 | ru: 2 | views: 3 | pagination: 4 | first: "« Первая" 5 | last: "Последняя »" 6 | previous: "‹ Пред." 7 | next: "Следующая ›" 8 | truncate: "…" 9 | helpers: 10 | page_entries_info: 11 | one_page: 12 | display_entries: 13 | zero: "%{entry_name.capitalize} не найдено" 14 | one: "Отображение 1 %{entry_name}" 15 | other: "Отображение все %{count} %{entry_name}" 16 | more_pages: 17 | display_entries: "Отображение %{entry_name} %{first} - %{last} из %{total} всего" 18 | -------------------------------------------------------------------------------- /db/migrate/20190301180743_add_missing_taggable_index.acts_as_taggable_on_engine.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # This migration comes from acts_as_taggable_on_engine (originally 4) 4 | if ActiveRecord.gem_version >= Gem::Version.new('5.0') 5 | class AddMissingTaggableIndex < ActiveRecord::Migration[4.2]; end 6 | else 7 | class AddMissingTaggableIndex < ActiveRecord::Migration; end 8 | end 9 | AddMissingTaggableIndex.class_eval do 10 | def self.up 11 | add_index :taggings, %i[taggable_id taggable_type context] 12 | end 13 | 14 | def self.down 15 | remove_index :taggings, %i[taggable_id taggable_type context] 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /spec/factories/event.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | FactoryBot.define do 4 | factory :event do 5 | title { FFaker::Lorem.words(4).join(' ') } 6 | description { FFaker::Lorem.paragraphs(3).join("\n\n") } 7 | place { FFaker::Address.street_address } 8 | started_at { 1.month.from_now } 9 | tag_list { FFaker::Lorem.words(2) } 10 | organizer { create(:user) } 11 | 12 | trait :with_markdown do 13 | description { %(I'm **description** with _markdown_.) } 14 | end 15 | 16 | trait :published do 17 | published_at { Time.current } 18 | published { true } 19 | end 20 | end 21 | end 22 | -------------------------------------------------------------------------------- /app/views/errors/error_404.html.slim: -------------------------------------------------------------------------------- 1 | doctype html 2 | html 3 | head 4 | title Страницы, которую вы запрашиваете не существует (404) 5 | meta[name="viewport" content="width=device-width,initial-scale=1"] 6 | style 7 | | body { background-color: #FFF; text-align: center; font-family: arial, sans-serif; margin: 0; } .logo { margin-top: 100px; } .message { width: 95%; max-width: 33em; margin: 7em auto 0; } 8 | body 9 | .logo = image_tag 'it52_logo_white_clean.svg', alt: 'it52' 10 | .message 11 | h1 Ой! 12 | h3 Такой страницы у нас нет. 13 | p 14 | = link_to 'Вернуться на главную страницу', root_path 15 | |. 16 | -------------------------------------------------------------------------------- /db/migrate/20190612020134_create_addresses.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class CreateAddresses < ActiveRecord::Migration[5.2] 4 | def change 5 | create_table :addresses do |t| 6 | t.string :unrestricted_value, null: false 7 | t.string :city, null: false 8 | t.string :street, null: false 9 | t.string :house, null: false 10 | t.string :kladr_id, null: false 11 | t.string :fias_id, null: false 12 | t.float :lat, null: false 13 | t.float :long, null: false 14 | 15 | t.timestamps 16 | end 17 | end 18 | end 19 | -------------------------------------------------------------------------------- /spec/factories/addresses.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # == Schema Information 4 | # 5 | # Table name: addresses 6 | # 7 | # id :bigint not null, primary key 8 | # city :string not null 9 | # street :string not null 10 | # house :string not null 11 | # kladr_id :string not null 12 | # fias_id :string not null 13 | # lat :float not null 14 | # long :float not null 15 | # created_at :datetime not null 16 | # updated_at :datetime not null 17 | # 18 | 19 | FactoryBot.define do 20 | factory :address do 21 | end 22 | end 23 | -------------------------------------------------------------------------------- /app/serializers/authentication_serializer.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # == Schema Information 4 | # 5 | # Table name: authentications 6 | # 7 | # id :integer not null, primary key 8 | # user_id :integer not null 9 | # provider :string(255) not null 10 | # uid :string(255) not null 11 | # created_at :datetime 12 | # updated_at :datetime 13 | # link :string(255) 14 | # token :string(255) 15 | # token_expires :datetime 16 | # 17 | 18 | class AuthenticationSerializer < ActiveModel::Serializer 19 | cache key: 'authentication', expires_in: 3.hours 20 | attributes :id, :provider, :link 21 | end 22 | -------------------------------------------------------------------------------- /config/puma.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | workers Integer(ENV.fetch('WEB_CONCURRENCY') { 1 }) 4 | threads_count = Integer(ENV.fetch('RAILS_MAX_THREADS') { 4 }) 5 | threads 2, threads_count 6 | 7 | preload_app! 8 | 9 | rackup DefaultRackup if defined?(DefaultRackup) 10 | 11 | port Integer(ENV.fetch('PORT') { 3000 }) 12 | environment ENV.fetch('RACK_ENV') { 'development' } 13 | 14 | # stdout_redirect '/dev/stdout', '/dev/stderr', true 15 | 16 | on_worker_boot do 17 | # Worker specific setup for Rails 4.1+ 18 | # See: https://devcenter.heroku.com/articles/deploying-rails-applications-with-the-puma-web-server#on-worker-boot 19 | ActiveRecord::Base.establish_connection 20 | end 21 | -------------------------------------------------------------------------------- /db/migrate/20140902180100_create_friendly_id_slugs.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class CreateFriendlyIdSlugs < ActiveRecord::Migration[4.2] 4 | def change 5 | create_table :friendly_id_slugs do |t| 6 | t.string :slug, null: false 7 | t.integer :sluggable_id, null: false 8 | t.string :sluggable_type, limit: 50 9 | t.string :scope 10 | t.datetime :created_at 11 | end 12 | add_index :friendly_id_slugs, :sluggable_id 13 | add_index :friendly_id_slugs, %i[slug sluggable_type] 14 | add_index :friendly_id_slugs, %i[slug sluggable_type scope], unique: true 15 | add_index :friendly_id_slugs, :sluggable_type 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /app/views/shared/_small_screens_footer.html.slim: -------------------------------------------------------------------------------- 1 | .row: .visible-xs.visible-sm.col-sm-12 2 | hr 3 | h2 = t(:app_name) 4 | h3 = t('.social_links') 5 | ul#social-links.nav.nav-pills 6 | li = link_to 'https://twitter.com/it_rostov', target: '_blank' do 7 | i.fas.fa-fw.fa-twitter' 8 | span.gray 9 | ' / 10 | ' it_rostov 11 | li = link_to 'https://vk.com/it_61', target: '_blank' do 12 | i.fas.fa-fw.fa-vk' 13 | span.gray 14 | ' / 15 | ' it_61 16 | li = link_to 'https://www.facebook.com/it61.info', target: '_blank' do 17 | i.fas.fa-fw.fa-facebook' 18 | span.gray 19 | ' / 20 | ' it61.info 21 | hr 22 | h4 = t('.hashtag') 23 | -------------------------------------------------------------------------------- /app/views/startups/show.html.slim: -------------------------------------------------------------------------------- 1 | - content_for(:topbar_actions) do 2 | a.material-icons.mdc-top-app-bar__action-item href=startups_path title='Все стартапы' list 3 | - if can? :edit, @startup 4 | a.material-icons.mdc-top-app-bar__action-item href=edit_startup_path(@startup) title='Изменить' edit 5 | 6 | h1 = @startup.title 7 | h3 = @startup.intro 8 | 9 | .grid 10 | .grid__inner 11 | .grid__cell--startup-meta 12 | = image_tag @startup.logo.big.url, alt: @startup, class: 'startup-image' 13 | p.startup-url = link_to @startup.url, @startup.url 14 | p.startup-contacts = @startup.contacts.values.join(': ') 15 | .grid__cell--startup-description = @startup.rendered_description 16 | -------------------------------------------------------------------------------- /.old-travis.yml: -------------------------------------------------------------------------------- 1 | language: generic 2 | 3 | services: 4 | - docker 5 | 6 | before_install: 7 | - docker pull it52/rails:latest 8 | 9 | install: 10 | - make build 11 | 12 | before_script: 13 | - docker-compose -f docker/docker-compose.yml run rails sh -c "bin/rails db:create && bin/rails db:schema:load" 14 | 15 | script: 16 | - make test 17 | 18 | before_cache: 19 | - sudo rm -fr coverage public/uploads/* tmp/cache tmp/uploads 20 | 21 | before_deploy: 22 | - echo "$DOCKER_PASSWORD" | docker login -u "$DOCKER_USERNAME" --password-stdin 23 | - docker push it52/rails:latest 24 | 25 | deploy: 26 | provider: script 27 | script: bash -c "make build_and_publish_prod" 28 | on: 29 | branch: it52 30 | -------------------------------------------------------------------------------- /app/controllers/api/v2/tags_controller.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Api 4 | module V2 5 | class TagsController < ApiController 6 | TAGS_PAGE_SIZE = 50 7 | 8 | def index 9 | @tags = ActsAsTaggableOn::Tag.order(taggings_count: :desc) 10 | if params[:q].present? 11 | @tags = @tags.where('name ILIKE ?', "#{params[:q].to_s.downcase}%") 12 | end 13 | options = { is_collection: true, 14 | params: { action: action_name }, 15 | meta: { totalCount: @tags.count } } 16 | render json: ::V2::TagSerializer.new(@tags.limit(TAGS_PAGE_SIZE), options).serializable_hash 17 | end 18 | end 19 | end 20 | end 21 | -------------------------------------------------------------------------------- /app/views/users/show.html.slim: -------------------------------------------------------------------------------- 1 | .row 2 | .col-sm-3: .avatar.image-container = image_tag @user.avatar_image.square_150.url 3 | 4 | .col-sm-9 5 | .page-header 6 | h1 7 | = @user 8 | small< = @user.nickname 9 | = @user.link_to_website 10 | 11 | - unless @user.employment.blank? 12 | h4 #{ t('activerecord.attributes.user.employment') }: #{ @user.employment } 13 | 14 | - if @user.bio? 15 | = @user.bio 16 | hr 17 | 18 | - if @user.authentications.present? 19 | section 20 | h5.subheader = t('.linked_accounts') 21 | ul.list-inline = render @user.authentications 22 | hr 23 | 24 | = render partial: 'users/user-events', locals: { user: @user } 25 | -------------------------------------------------------------------------------- /app/assets/stylesheets/application.css: -------------------------------------------------------------------------------- 1 | /* 2 | * This is a manifest file that'll be compiled into application.css, which will include all the files 3 | * listed below. 4 | * 5 | * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets, 6 | * or vendor/assets/stylesheets of plugins, if any, can be referenced here using a relative path. 7 | * 8 | * You're free to add application-wide styles to this file and they'll appear at the bottom of the 9 | * compiled file so the styles you add here take precedence over styles defined in any styles 10 | * defined in the other CSS/SCSS files in this directory. It is generally better to create a new 11 | * file per style scope. 12 | * 13 | *= require app 14 | */ 15 | -------------------------------------------------------------------------------- /db/migrate/20190301180744_change_collation_for_tag_names.acts_as_taggable_on_engine.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # This migration comes from acts_as_taggable_on_engine (originally 5) 4 | # This migration is added to circumvent issue #623 and have special characters 5 | # work properly 6 | if ActiveRecord.gem_version >= Gem::Version.new('5.0') 7 | class ChangeCollationForTagNames < ActiveRecord::Migration[4.2]; end 8 | else 9 | class ChangeCollationForTagNames < ActiveRecord::Migration; end 10 | end 11 | ChangeCollationForTagNames.class_eval do 12 | def up 13 | if ActsAsTaggableOn::Utils.using_mysql? 14 | execute('ALTER TABLE tags MODIFY name varchar(255) CHARACTER SET utf8 COLLATE utf8_bin;') 15 | end 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /app/controllers/api/v2/api_controller.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Api 4 | module V2 5 | class ApiController < ActionController::API 6 | before_action :set_allow_cors_headers 7 | 8 | rescue_from ActiveRecord::RecordNotFound, with: :record_not_found 9 | 10 | protected 11 | 12 | def set_allow_cors_headers 13 | headers['Access-Control-Allow-Origin'] = '*' 14 | headers['Access-Control-Allow-Methods'] = 'GET' 15 | headers['Access-Control-Request-Method'] = 'OPTIONS' 16 | headers['Access-Control-Allow-Headers'] = 'Content-Type' 17 | end 18 | 19 | private 20 | 21 | def record_not_found 22 | head 404 23 | end 24 | end 25 | end 26 | end 27 | -------------------------------------------------------------------------------- /app/controllers/my/authentications_controller.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module My 4 | class AuthenticationsController < ApplicationController 5 | before_action :set_user_and_auth 6 | 7 | def destroy 8 | if @user.authentications.size == 1 && @user.email.blank? 9 | flash[:danger] = t('authentications.not_destroyed') 10 | else 11 | @authentication.destroy 12 | flash[:success] = t('authentications.destroyed', provider: @authentication.provider.capitalize) 13 | end 14 | redirect_to my_profile_path 15 | end 16 | 17 | private 18 | 19 | def set_user_and_auth 20 | @user = current_user 21 | @authentication = @user.authentications.find(params[:id]) 22 | end 23 | end 24 | end 25 | -------------------------------------------------------------------------------- /spec/factories/user.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | pass = Devise.friendly_token 4 | 5 | FactoryBot.define do 6 | factory :user do 7 | email { FFaker::Internet.email } 8 | first_name { FFaker::Name.first_name } 9 | last_name { FFaker::Name.last_name } 10 | password { pass } 11 | password_confirmation { pass } 12 | remember_me { false } 13 | confirmed_at { Time.zone.now } 14 | 15 | factory :admin do 16 | role { :admin } 17 | end 18 | 19 | factory :unconfirmed_user do 20 | confirmed_at { nil } 21 | end 22 | 23 | trait :subscribed do 24 | subscription { true } 25 | end 26 | 27 | trait :unsubscribed do 28 | subscription { false } 29 | end 30 | end 31 | end 32 | -------------------------------------------------------------------------------- /config/initializers/inflections.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Be sure to restart your server when you modify this file. 4 | 5 | # Add new inflection rules using the following format. Inflections 6 | # are locale specific, and you may define rules for as many different 7 | # locales as you wish. All of these examples are active by default: 8 | # ActiveSupport::Inflector.inflections(:en) do |inflect| 9 | # inflect.plural /^(ox)$/i, '\1en' 10 | # inflect.singular /^(ox)en/i, '\1' 11 | # inflect.irregular 'person', 'people' 12 | # inflect.uncountable %w( fish sheep ) 13 | # end 14 | 15 | # These inflection rules are supported but not enabled by default: 16 | # ActiveSupport::Inflector.inflections(:en) do |inflect| 17 | # inflect.acronym 'RESTful' 18 | # end 19 | -------------------------------------------------------------------------------- /config/initializers/string_unicode_path.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class String 4 | def downcase 5 | if !frozen? 6 | Unicode.downcase(force_encoding('utf-8')) 7 | else 8 | Unicode.downcase(self) 9 | end 10 | end 11 | 12 | def downcase! 13 | replace(downcase) 14 | end 15 | 16 | def upcase 17 | if !frozen? 18 | Unicode.upcase(force_encoding('utf-8')) 19 | else 20 | Unicode.upcase(self) 21 | end 22 | end 23 | 24 | def upcase! 25 | replace upcase 26 | end 27 | 28 | def capitalize 29 | if !frozen? 30 | Unicode.capitalize(force_encoding('utf-8')) 31 | else 32 | Unicode.capitalize(self) 33 | end 34 | end 35 | 36 | def capitalize! 37 | replace capitalize 38 | end 39 | end 40 | -------------------------------------------------------------------------------- /config/locales/plurals.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | { ru: 4 | { i18n: 5 | { plural: 6 | { keys: %i[zero one few many], 7 | rule: lambda { |n| 8 | if n == 0 9 | :zero 10 | elsif 11 | ((n % 10) == 1) && ((n % 100 != 11)) 12 | # 1, 21, 31, 41, 51, 61... 13 | :one 14 | elsif 15 | [2, 3, 4].include?(n % 10) \ 16 | && ![12, 13, 14].include?(n % 100) 17 | # 2-4, 22-24, 32-34... 18 | :few 19 | elsif (n % 10) == 0 || \ 20 | ![5, 6, 7, 8, 9].include?(n % 10) || \ 21 | ![11, 12, 13, 14].include?(n % 100) 22 | # 0, 5-20, 25-30, 35-40... 23 | :many 24 | end 25 | } } } } } 26 | -------------------------------------------------------------------------------- /config/locales/simple_form.en.yml: -------------------------------------------------------------------------------- 1 | en: 2 | simple_form: 3 | "yes": 'Yes' 4 | "no": 'No' 5 | required: 6 | # text: 'required' 7 | # mark: '*' 8 | # You can uncomment the line below if you need to overwrite the whole required html. 9 | # When using html, text and mark won't be used. 10 | html: '' 11 | error_notification: 12 | default_message: "Please review the problems below:" 13 | # 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 | 27 | -------------------------------------------------------------------------------- /config/sidekiq.yml: -------------------------------------------------------------------------------- 1 | --- 2 | :concurrency: 5 3 | staging: 4 | :concurrency: 10 5 | production: 6 | :concurrency: 2 7 | :queues: 8 | - critical 9 | - mailers 10 | - it52_active_job_development_mailers 11 | - it52_active_job_production_mailers 12 | - default 13 | - low 14 | - it52.<%= ENV.fetch('RAILS_ENV') { 'develpoment' } %>.critical 15 | - it52.<%= ENV.fetch('RAILS_ENV') { 'develpoment' } %>.mailers 16 | - it52.<%= ENV.fetch('RAILS_ENV') { 'develpoment' } %>.default 17 | - it52.<%= ENV.fetch('RAILS_ENV') { 'develpoment' } %>.low 18 | - it52.<%= ENV.fetch('RAILS_ENV') { 'develpoment' } %>_critical 19 | - it52.<%= ENV.fetch('RAILS_ENV') { 'develpoment' } %>_mailers 20 | - it52.<%= ENV.fetch('RAILS_ENV') { 'develpoment' } %>_default 21 | - it52.<%= ENV.fetch('RAILS_ENV') { 'develpoment' } %>_low 22 | -------------------------------------------------------------------------------- /app/views/devise/registrations/edit.html.slim: -------------------------------------------------------------------------------- 1 | .page-header: h1 = t('.title') 2 | 3 | .row: .col-xs-12.col-sm-6.col-md-6.col-lg-6 4 | = simple_form_for(resource, as: resource_name, url: registration_path(resource_name), html: { method: :put }) do |f| 5 | - if current_user.email.present? 6 | = f.input :email, required: true, autofocus: true, disabled: true 7 | - else 8 | = f.input :email, required: true, autofocus: true 9 | - if devise_mapping.confirmable? && resource.pending_reconfirmation? 10 | .alert.alert-warning: p 11 | 'Ждём подтверждения адреса 12 | strong = resource.unconfirmed_email 13 | '. 14 | = f.input :password, autocomplete: "off" 15 | = f.input :password_confirmation 16 | = f.input :current_password 17 | = f.button :submit, t('.submit'), class: "btn-primary" 18 | -------------------------------------------------------------------------------- /db/migrate/20190301180742_add_taggings_counter_cache_to_tags.acts_as_taggable_on_engine.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # This migration comes from acts_as_taggable_on_engine (originally 3) 4 | if ActiveRecord.gem_version >= Gem::Version.new('5.0') 5 | class AddTaggingsCounterCacheToTags < ActiveRecord::Migration[4.2]; end 6 | else 7 | class AddTaggingsCounterCacheToTags < ActiveRecord::Migration; end 8 | end 9 | AddTaggingsCounterCacheToTags.class_eval do 10 | def self.up 11 | add_column :tags, :taggings_count, :integer, default: 0 12 | 13 | ActsAsTaggableOn::Tag.reset_column_information 14 | ActsAsTaggableOn::Tag.find_each do |tag| 15 | ActsAsTaggableOn::Tag.reset_counters(tag.id, :taggings) 16 | end 17 | end 18 | 19 | def self.down 20 | remove_column :tags, :taggings_count 21 | end 22 | end 23 | -------------------------------------------------------------------------------- /config/initializers/assets.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Be sure to restart your server when you modify this file. 4 | 5 | # Version of your assets, change this if you want to expire all your assets. 6 | Rails.application.config.assets.version = '1.0' 7 | 8 | # Add additional assets to the asset load path. 9 | 10 | Rails.application.config.assets.digest = true 11 | 12 | Rails.application.config.assets.compress = true 13 | 14 | # Rails.application.config.assets.paths << Emoji.images_path 15 | # Add Yarn node_modules folder to the asset load path. 16 | Rails.application.config.assets.paths << Rails.root.join('node_modules') 17 | 18 | # Precompile additional assets. 19 | # application.js, application.css, and all non-JS/CSS in the app/assets 20 | # folder are already added. 21 | # Rails.application.config.assets.precompile += %w( admin.js admin.css ) 22 | -------------------------------------------------------------------------------- /config/locales/telegram.ru.yml: -------------------------------------------------------------------------------- 1 | ru: 2 | telegram: 3 | unknown_command: 'Мы таким командам не обучены. Вот только эти знаем: %{list}.' 4 | not_found: 'Мы не нашли событий, соответствующих вашему запросу.' 5 | help: > 6 | Бот позволяет получить информацию о событиях с сайта https://www.it52.info. 7 | Команды: 8 | - /get N – Получить полную справку о событии. N – номер мероприятия (цифра перед названием). По умолчанию выводит информацию о последнем зарегистрированном событии. 9 | - /previous N – Получить краткий список прошедших мероприятий. N может быть от 1 до 5. По умолчанию покажет последнее прошедшее. 10 | - /next N – Получить краткий список предстоящих мероприятий. N может быть от 1 до 5. По умолчанию покажет следующее. 11 | - /help – Помощь по командам 12 | 13 | Канал с анонсами событий @it52info. 14 | -------------------------------------------------------------------------------- /public/404.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |