From 149dd526cd25c8c591138dac698e28041ae0320a Mon Sep 17 00:00:00 2001 From: Jeremy Date: Thu, 24 Dec 2020 13:23:16 -0500 Subject: [PATCH 1/7] feat: aws upload --- Gemfile | 2 ++ Gemfile.lock | 18 ++++++++++++++++ app/commands/upload_to_s3.rb | 21 +++++++++++++++++++ app/models/greenlight_status.rb | 1 + config/initializers/amazon_s3.rb | 5 +++++ lib/reports/school.rb | 35 ++++++++++++++++++++++++++++++++ 6 files changed, 82 insertions(+) create mode 100644 app/commands/upload_to_s3.rb create mode 100644 config/initializers/amazon_s3.rb create mode 100644 lib/reports/school.rb diff --git a/Gemfile b/Gemfile index 843f5e3..195f00e 100644 --- a/Gemfile +++ b/Gemfile @@ -95,6 +95,8 @@ gem 'skylight' gem 'table_print', require: false # Email validations gem 'valid_email2' +# AWS S3 +gem 'aws-sdk-s3' group :development, :test do # Annotate Rails classes with schema and routes info diff --git a/Gemfile.lock b/Gemfile.lock index b8e1da7..b77ffd2 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -71,6 +71,22 @@ GEM activerecord (>= 3.2, < 7.0) rake (>= 10.4, < 14.0) ast (2.4.1) + aws-eventstream (1.1.0) + aws-partitions (1.412.0) + aws-sdk-core (3.110.0) + aws-eventstream (~> 1, >= 1.0.2) + aws-partitions (~> 1, >= 1.239.0) + aws-sigv4 (~> 1.1) + jmespath (~> 1.0) + aws-sdk-kms (1.40.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sigv4 (~> 1.1) + aws-sdk-s3 (1.87.0) + aws-sdk-core (~> 3, >= 3.109.0) + aws-sdk-kms (~> 1) + aws-sigv4 (~> 1.1) + aws-sigv4 (1.2.2) + aws-eventstream (~> 1, >= 1.0.2) backport (1.1.2) bcrypt (3.1.16) benchmark (0.1.0) @@ -132,6 +148,7 @@ GEM concurrent-ruby (~> 1.0) interception (0.5) jaro_winkler (1.5.4) + jmespath (1.4.0) json-schema (2.8.1) addressable (>= 2.4) jwt (2.2.2) @@ -364,6 +381,7 @@ PLATFORMS DEPENDENCIES active_attr annotate + aws-sdk-s3 bcrypt (~> 3.1.7) better_errors binding_of_caller diff --git a/app/commands/upload_to_s3.rb b/app/commands/upload_to_s3.rb new file mode 100644 index 0000000..7c5723a --- /dev/null +++ b/app/commands/upload_to_s3.rb @@ -0,0 +1,21 @@ +# frozen_literal_string: true +class UploadToS3 < ApplicationCommand + attribute :csv + + def work + obj = AMAZON_S3_CLIENT.bucket(s3_bucket).object("#{Time.now}/report.csv") + obj.put(body: csv, acl: 'public-read', content_disposition: 'attachment') + + return obj.public_url + rescue => e + puts e.inspect + end + + def s3_bucket + if Rails.env == 'development' + 'glit-dev' + else + 'glit-prod' + end + end +end diff --git a/app/models/greenlight_status.rb b/app/models/greenlight_status.rb index 76a5928..fba9b21 100644 --- a/app/models/greenlight_status.rb +++ b/app/models/greenlight_status.rb @@ -48,6 +48,7 @@ class GreenlightStatus < ApplicationRecord scope :recently_created, -> { where(created_at: 20.days.ago.beginning_of_day..Time.zone.now.end_of_day) } scope :not_expired, -> { where('expiration_date <= ?', Time.current.to_date) } + scope :chronical, -> { order(submission_date: :asc) } has_many :medical_events before_validation :assign_associated_users_to_medical_events diff --git a/config/initializers/amazon_s3.rb b/config/initializers/amazon_s3.rb new file mode 100644 index 0000000..cb1b6d5 --- /dev/null +++ b/config/initializers/amazon_s3.rb @@ -0,0 +1,5 @@ +AMAZON_S3_CLIENT = Aws::S3::Resource.new( + region: 'us-east-1', + access_key_id: ENV['AWS_ACCESS_KEY_ID'], + secret_access_key: ENV['AWS_SECRET_ACCESS_KEY'], +) diff --git a/lib/reports/school.rb b/lib/reports/school.rb new file mode 100644 index 0000000..b5c6a3d --- /dev/null +++ b/lib/reports/school.rb @@ -0,0 +1,35 @@ +# frozen_literal_string: true +require 'csv' + +module Reports + class School + COLUMNS = "First Name, Last Name, Parent First Name, Parent Last Name, \ + Parent Email, Parent Phone, Submissions, Date Registered, \ + Last Date Yellow, Last Date Red, Last Test Date, \ + Last Test Result".split(', ').map(&:strip).freeze + + def initialize(school) + @school = school + end + + def csv + CSV.generate(headers: true) do |csv| + csv << COLUMNS + + @school.users.each do |user| + parent = user.parents.first + + csv << [ + user.first_name, + user.last_name, + parent&.first_name, + parent&.last_name, + parent&.email, + parent&.mobile_number, + user.greenlight_statuses.chronical.map(&:status).join(' '), + ] + end + end + end + end +end From d317995ea13d4d63c8fddd167606e1849be1babb Mon Sep 17 00:00:00 2001 From: Jeremy Date: Wed, 6 Jan 2021 04:59:55 -0500 Subject: [PATCH 2/7] feat: report worker for gen,upload, and mail --- app/commands/upload_to_s3.rb | 24 +++++++++++++--- app/workers/school_report_worker.rb | 44 +++++++++++++++++++++++++++++ config/initializers/amazon_s3.rb | 5 ---- config/locales/en.yml | 7 +++++ 4 files changed, 71 insertions(+), 9 deletions(-) create mode 100644 app/workers/school_report_worker.rb delete mode 100644 config/initializers/amazon_s3.rb diff --git a/app/commands/upload_to_s3.rb b/app/commands/upload_to_s3.rb index 7c5723a..c50bb12 100644 --- a/app/commands/upload_to_s3.rb +++ b/app/commands/upload_to_s3.rb @@ -1,16 +1,32 @@ # frozen_literal_string: true class UploadToS3 < ApplicationCommand - attribute :csv + attribute :content + attribute :path + attribute :filename + attribute :expires_in, default: 3600 + + validates :content, presence: true + validates :path, presence: true + validates :filename, presence: true def work - obj = AMAZON_S3_CLIENT.bucket(s3_bucket).object("#{Time.now}/report.csv") - obj.put(body: csv, acl: 'public-read', content_disposition: 'attachment') + s3 = Aws::S3::Resource.new( + region: 'us-east-1', + access_key_id: ENV['AWS_ACCESS_KEY_ID'], + secret_access_key: ENV['AWS_SECRET_ACCESS_KEY'], + ) + + bucket = s3.bucket(s3_bucket) + obj = bucket.object(self.path) + obj.put(body: self.content, content_disposition: "attachment; filename=#{self.filename}") - return obj.public_url + obj.presigned_url(:get, expires_in: self.expires_in) rescue => e puts e.inspect end + private + def s3_bucket if Rails.env == 'development' 'glit-dev' diff --git a/app/workers/school_report_worker.rb b/app/workers/school_report_worker.rb new file mode 100644 index 0000000..1b65144 --- /dev/null +++ b/app/workers/school_report_worker.rb @@ -0,0 +1,44 @@ +# frozen_string_literal: true + +class SchoolReportWorker < ApplicationWorker + def perform(user_id, location_id) + user = User.find(user_id) + location = Location.find(location_id) + + school_report = Reports::School.new(location) + s3_upload = UploadToS3.new( + content: school_report.csv, + path: "reports/#{location.permalink}/#{Time.now.strftime('%Y-%m-%d_%H_%M')}.csv", + filename: "report(#{location.permalink}).csv", + ) + s3_upload.run + + if s3_upload.succeeded? + download_url = s3_upload.result + + SendGridEmail.new( + to: user.name_with_email, + subject: I18n.t('emails.school_report.subject'), + html: eval(html_template), + ).run + end + end + + private + + def html_template + Erubi::Engine.new(<<~HTML).src +

<%= I18n.t('emails.school_report.title') %>

+ +

+ <%= I18n.t('emails.school_report.body', school: location.name) %> +

+ +

+ + <%= I18n.t('emails.school_report.action') %> + +

+ HTML + end +end diff --git a/config/initializers/amazon_s3.rb b/config/initializers/amazon_s3.rb deleted file mode 100644 index cb1b6d5..0000000 --- a/config/initializers/amazon_s3.rb +++ /dev/null @@ -1,5 +0,0 @@ -AMAZON_S3_CLIENT = Aws::S3::Resource.new( - region: 'us-east-1', - access_key_id: ENV['AWS_ACCESS_KEY_ID'], - secret_access_key: ENV['AWS_SECRET_ACCESS_KEY'], -) diff --git a/config/locales/en.yml b/config/locales/en.yml index db7c774..c0f0b43 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -23,6 +23,13 @@ en: You requested to reset your password and here's the link! Note that this link expires in 1 hour and can only be used once. action: Click Here to Reset Password + school_report: + subject: ✨ Greenlight School Report + title: Download the School Report + body: | + "You requested a report for %{school} and here's the download link!" + Note that this link expires in 1 hour and can only be used once. + action: Click Here to Download Report texts: magic_sign_in: "Greenlight Magic Sign In: %{link}" reminder: "Greenlight reminding you to send out your symptom surveys!" From e0d90e6bd01c0660a6afa9246fa8e4a087b9de6c Mon Sep 17 00:00:00 2001 From: Jeremy Date: Thu, 7 Jan 2021 07:30:16 -0500 Subject: [PATCH 3/7] patch: report content --- ...port_worker.rb => people_report_worker.rb} | 20 ++--- config/locales/en.yml | 8 +- lib/reports/people.rb | 80 +++++++++++++++++++ lib/reports/school.rb | 35 -------- 4 files changed, 94 insertions(+), 49 deletions(-) rename app/workers/{school_report_worker.rb => people_report_worker.rb} (56%) create mode 100644 lib/reports/people.rb delete mode 100644 lib/reports/school.rb diff --git a/app/workers/school_report_worker.rb b/app/workers/people_report_worker.rb similarity index 56% rename from app/workers/school_report_worker.rb rename to app/workers/people_report_worker.rb index 1b65144..e44b092 100644 --- a/app/workers/school_report_worker.rb +++ b/app/workers/people_report_worker.rb @@ -1,13 +1,13 @@ # frozen_string_literal: true -class SchoolReportWorker < ApplicationWorker - def perform(user_id, location_id) - user = User.find(user_id) +class PeopleReportWorker < ApplicationWorker + def perform(admin_id, location_id) + admin = User.find(admin_id) location = Location.find(location_id) - school_report = Reports::School.new(location) + people_report = Reports::People.new(location) s3_upload = UploadToS3.new( - content: school_report.csv, + content: people_report.csv, path: "reports/#{location.permalink}/#{Time.now.strftime('%Y-%m-%d_%H_%M')}.csv", filename: "report(#{location.permalink}).csv", ) @@ -17,8 +17,8 @@ def perform(user_id, location_id) download_url = s3_upload.result SendGridEmail.new( - to: user.name_with_email, - subject: I18n.t('emails.school_report.subject'), + to: admin.name_with_email, + subject: I18n.t('emails.people_report.subject'), html: eval(html_template), ).run end @@ -28,15 +28,15 @@ def perform(user_id, location_id) def html_template Erubi::Engine.new(<<~HTML).src -

<%= I18n.t('emails.school_report.title') %>

+

<%= I18n.t('emails.people_report.title') %>

- <%= I18n.t('emails.school_report.body', school: location.name) %> + <%= I18n.t('emails.people_report.body', location: location.name) %>

- <%= I18n.t('emails.school_report.action') %> + <%= I18n.t('emails.people_report.action') %>

HTML diff --git a/config/locales/en.yml b/config/locales/en.yml index c0f0b43..6b1c5f5 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -23,11 +23,11 @@ en: You requested to reset your password and here's the link! Note that this link expires in 1 hour and can only be used once. action: Click Here to Reset Password - school_report: - subject: ✨ Greenlight School Report - title: Download the School Report + people_report: + subject: ✨ Greenlight Report + title: Download the Report body: | - "You requested a report for %{school} and here's the download link!" + "You requested a report for %{location} and here's the download link!" Note that this link expires in 1 hour and can only be used once. action: Click Here to Download Report texts: diff --git a/lib/reports/people.rb b/lib/reports/people.rb new file mode 100644 index 0000000..0f492ef --- /dev/null +++ b/lib/reports/people.rb @@ -0,0 +1,80 @@ +# frozen_literal_string: true +require 'csv' + +module Reports + class People + SCHOOL_COLUMNS = "First Name, Last Name, Parent First Name, Parent Last Name, \ + Parent Email, Parent Phone, Submissions, Date Registered, \ + Last Date Yellow, Last Date Red, Last Test Date, \ + Last Test Result".split(', ').map(&:strip).freeze + OTHER_COLUMNS = "First Name, Last Name, Submissions, Date Registered, \ + Last Date Yellow, Last Date Red, Last Test Date, \ + Last Test Result".split(', ').map(&:strip).freeze + + def initialize(location) + @location = location + @users = @location.users.includes(:parents) + @is_school = @location.category == 'school' + end + + def csv + CSV.generate(headers: true) do |csv| + csv << (@is_school ? SCHOOL_COLUMNS : OTHER_COLUMNS) + + @users.each do |user| + csv << csv_row(user) + end + end + end + + private + + def csv_row(user) + parent = user.parents.first + submission_stats = submission_stats(user) + + user_row = [ user.first_name, user.last_name ] + + if @is_school + user_row << parent&.first_name + user_row << parent&.last_name + user_row << parent&.email + user_row << parent&.mobile_number + end + + user_row << submission_stats[:submissions].join(' ') + user_row << user.created_at.strftime('%Y-%m-%d') + user_row << submission_stats[:last_yellow_date] + user_row << submission_stats[:last_red_date] + user_row << submission_stats[:last_test_date] + user_row << submission_stats[:last_test_result] + end + + def submission_stats(user) + statuses_chronical = user.greenlight_statuses.chronical + + submissions = [] + last_yellow_date = nil + last_red_date = nil + last_greenlight_status = statuses_chronical.last + + statuses_chronical.each do |greenlight_status| + submissions << greenlight_status.status + + if greenlight_status.status == 'pending' + last_yellow_date = greenlight_status.submission_date + elsif greenlight_status.status == 'recovery' + last_red_date = greenlight_status.submission_date + end + end + + { + submissions: submissions, + last_yellow_date: last_yellow_date, + last_red_date: last_red_date, + last_test_date: last_greenlight_status&.submission_date, + last_test_result: last_greenlight_status&.status, + } + end + end +end diff --git a/lib/reports/school.rb b/lib/reports/school.rb deleted file mode 100644 index b5c6a3d..0000000 --- a/lib/reports/school.rb +++ /dev/null @@ -1,35 +0,0 @@ -# frozen_literal_string: true -require 'csv' - -module Reports - class School - COLUMNS = "First Name, Last Name, Parent First Name, Parent Last Name, \ - Parent Email, Parent Phone, Submissions, Date Registered, \ - Last Date Yellow, Last Date Red, Last Test Date, \ - Last Test Result".split(', ').map(&:strip).freeze - - def initialize(school) - @school = school - end - - def csv - CSV.generate(headers: true) do |csv| - csv << COLUMNS - - @school.users.each do |user| - parent = user.parents.first - - csv << [ - user.first_name, - user.last_name, - parent&.first_name, - parent&.last_name, - parent&.email, - parent&.mobile_number, - user.greenlight_statuses.chronical.map(&:status).join(' '), - ] - end - end - end - end -end From dc8033f1817ad9c226795cb2ce8928ec0f02fe0e Mon Sep 17 00:00:00 2001 From: Jeremy Date: Thu, 7 Jan 2021 08:11:18 -0500 Subject: [PATCH 4/7] feat: request report UI --- app/controllers/locations_controller.rb | 9 ++++++++ app/workers/people_report_worker.rb | 2 +- client/src/api/index.ts | 4 ++++ client/src/i18n/locales/en.json | 5 ++++- .../pages/user-locations/UserLocationPage.tsx | 21 ++++++++++++++++++- 5 files changed, 38 insertions(+), 3 deletions(-) diff --git a/app/controllers/locations_controller.rb b/app/controllers/locations_controller.rb index 4051f1d..9e57788 100644 --- a/app/controllers/locations_controller.rb +++ b/app/controllers/locations_controller.rb @@ -137,5 +137,14 @@ module LocationsController render json: Reports::Location.new(location).to_h end + + post '/v1/locations/:location_id/people-report' do + location_id = params[:location_id] + location = Location.find_by_id_or_permalink(location_id) + ensure_or_forbidden! { location && current_user.admin_at?(location) } + + PeopleReportWorker.perform_async(location.id, current_user.id) + success_response + end end end diff --git a/app/workers/people_report_worker.rb b/app/workers/people_report_worker.rb index e44b092..6a1485b 100644 --- a/app/workers/people_report_worker.rb +++ b/app/workers/people_report_worker.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true class PeopleReportWorker < ApplicationWorker - def perform(admin_id, location_id) + def perform(location_id, admin_id) admin = User.find(admin_id) location = Location.find(location_id) diff --git a/client/src/api/index.ts b/client/src/api/index.ts index a96accd..de59be4 100644 --- a/client/src/api/index.ts +++ b/client/src/api/index.ts @@ -124,6 +124,10 @@ export async function updateLocationAccount(locationAccount: LocationAccount, up return entity } +export async function requestPeopleReport(location: Location) { + await v1.post(`/locations/${location.id}/people-report`) +} + // // Users // diff --git a/client/src/i18n/locales/en.json b/client/src/i18n/locales/en.json index 3b5074e..b8124c3 100644 --- a/client/src/i18n/locales/en.json +++ b/client/src/i18n/locales/en.json @@ -146,6 +146,9 @@ "LoadingPage.message": "Stuck here for too long? Try refreshing the page. If you still need help please email us at <0/>.", "LoadingPage.title": "Loading...", "Location.register": "Register", + "Location.request_report": "Request Report", + "Location.requesting_report": "Requesting Report...", + "Location.request_report_success": "The generated report will be sent to your email.", "LocationDetailsForm.business_name": "{0} Name", "LocationDetailsForm.number_of_users": "How many people will use Greenlight?", "LocationDetailsForm.registration": "Users will be able to register for your {0} by visiting: glit.me/go/{1}", @@ -407,4 +410,4 @@ "{0, plural, one {# child} other {# children}}": "{0, plural, one {# child} other {# children}}", "{0, plural, one {# location} other {# locations}}": "{0, plural, one {# location} other {# locations}}", "{0, plural, one {child} other {children}}": "{0, plural, one {child} other {children}}" -} \ No newline at end of file +} diff --git a/client/src/pages/user-locations/UserLocationPage.tsx b/client/src/pages/user-locations/UserLocationPage.tsx index cc902d3..fc9d6be 100644 --- a/client/src/pages/user-locations/UserLocationPage.tsx +++ b/client/src/pages/user-locations/UserLocationPage.tsx @@ -11,7 +11,7 @@ import { assertNotNull, assertNotUndefined, formatPhone } from 'src/helpers/util import { Location, User } from 'src/models' import { - getLocation, getUser, store, updateLocationAccount, + getLocation, getUser, store, updateLocationAccount, requestPeopleReport, } from 'src/api' import SubmitHandler from 'src/helpers/SubmitHandler' import { LocationAccount, PermissionLevels } from 'src/models/LocationAccount' @@ -61,6 +61,15 @@ export default function UserLocationPage(props: F7Props) { const l = state.location const handler = new SubmitHandler(f7) + const reportHandler = new SubmitHandler(f7, { + onSubmit: async () => { + await requestPeopleReport(l) + }, + errorTitle: t({ id: 'Common.failed', message: 'Action Failed' }), + submittingMessage: t({ id: 'Location.requesting_report', message: 'Requesting Report...' }), + successMessage: t({ id: 'Location.request_report_success', message: 'The generated report will be sent to your email.' }), + }) + return ( @@ -111,6 +120,16 @@ export default function UserLocationPage(props: F7Props) { )} + {la.isAdmin() + && ( +

+ +

+ )}
From 380c8ae976f69a8d15ca0c3e1b8d1821388f850d Mon Sep 17 00:00:00 2001 From: Jeremy Date: Fri, 8 Jan 2021 00:04:21 -0500 Subject: [PATCH 5/7] spec: people report endpoint and worker --- .../location_account_fabricator.rb | 6 +-- spec/requests/locations_spec.rb | 41 +++++++++++++++++++ spec/workers/people_report_worker_spec.rb | 36 ++++++++++++++++ 3 files changed, 80 insertions(+), 3 deletions(-) create mode 100644 spec/requests/locations_spec.rb create mode 100644 spec/workers/people_report_worker_spec.rb diff --git a/spec/fabricators/location_account_fabricator.rb b/spec/fabricators/location_account_fabricator.rb index 5188c13..4dd3afc 100644 --- a/spec/fabricators/location_account_fabricator.rb +++ b/spec/fabricators/location_account_fabricator.rb @@ -2,9 +2,9 @@ Fabricator(:location_account) do user nil location nil - extenal_id "MyText" - role "MyText" - permission_level "MyText" + external_id { Faker::Alphanumeric.unique.alpha(number: 10) } + role "unknown" + permission_level "none" title "MyText" attendance_status "MyText" approved_by_user_at "2020-09-14 17:49:37" diff --git a/spec/requests/locations_spec.rb b/spec/requests/locations_spec.rb new file mode 100644 index 0000000..ff6bf99 --- /dev/null +++ b/spec/requests/locations_spec.rb @@ -0,0 +1,41 @@ +# frozen_literal_string: true +require 'rails_helper' + +RSpec.describe '/v1/locations', type: :request do + let(:location) { Fabricate(:location) } + let(:admin) { Fabricate(:user) } + + before do + # skip actual uploading to S3 bucket, stub the operation + allow_any_instance_of(UploadToS3) + .to receive(:work).and_return(Faker::Internet.url) + end + + describe 'POST :location_id/people-report' do + subject { post_json("/v1/locations/#{location.id}/people-report", user: admin) } + + it "returns 403 if a user isn't the admin of the location" do + subject + + expect(response.status).to eq(403) + end + + context 'when requested by the location admin' do + before do + Fabricate( + :location_account, + user: admin, + location: location, + permission_level: 'admin', + ) + end + + it "generates report and sends download link" do + subject + + expect_success_response + expect_work(PeopleReportWorker) + end + end + end +end diff --git a/spec/workers/people_report_worker_spec.rb b/spec/workers/people_report_worker_spec.rb new file mode 100644 index 0000000..48d7baf --- /dev/null +++ b/spec/workers/people_report_worker_spec.rb @@ -0,0 +1,36 @@ +# frozen_string_literal: true +require 'rails_helper' + +RSpec.describe PeopleReportWorker do + let(:dummy_download_link) { Faker::Internet.url } + + before do + allow_any_instance_of(UploadToS3) + .to receive(:work).and_return(dummy_download_link) + end + + describe '#perform' do + let(:location) { Fabricate(:location) } + let(:admin) { Fabricate(:user) } + + before do + Fabricate( + :location_account, + user: admin, + location: location, + permission_level: 'admin', + ) + end + + it 'sends an email with the report download link' do + PeopleReportWorker.new.perform(location.id, admin.id) + + sent_mails = Mail::TestMailer.deliveries + expect(sent_mails.size).to eq(1) + + sent_mail = sent_mails.first + expect(sent_mail.To&.value).to eq(admin.name_with_email) + expect(sent_mail.html_part.to_s).to include(dummy_download_link) + end + end +end From a6fcdb92ae0741b23570dd6c23b445d7302b7e16 Mon Sep 17 00:00:00 2001 From: Jeremy Date: Thu, 4 Feb 2021 22:42:12 -0500 Subject: [PATCH 6/7] patch: UI whereabouts, email dev mode, translations --- app/commands/send_grid_email.rb | 10 ++++++- client/src/i18n/locales/en.json | 3 -- client/src/pages/admin/AdminDashboardPage.tsx | 28 +++++++++++++++++-- .../pages/user-locations/UserLocationPage.tsx | 23 ++------------- 4 files changed, 36 insertions(+), 28 deletions(-) diff --git a/app/commands/send_grid_email.rb b/app/commands/send_grid_email.rb index 65d50f1..918ebc6 100644 --- a/app/commands/send_grid_email.rb +++ b/app/commands/send_grid_email.rb @@ -27,7 +27,15 @@ def pony_payload @pony_payload end + def logger + @logger ||= Logger.new(Rails.root.join('log', 'email.log')) + end + def work - Pony.mail(pony_payload) + if Rails.env.development? + logger.info(pony_payload.inspect) + else + Pony.mail(pony_payload) + end end end diff --git a/client/src/i18n/locales/en.json b/client/src/i18n/locales/en.json index 38139b6..d21232f 100644 --- a/client/src/i18n/locales/en.json +++ b/client/src/i18n/locales/en.json @@ -133,9 +133,6 @@ "LoadingPageContent.message": "Stuck here for too long? Try refreshing the page. If you still need help please email us at <0/>.", "LoadingPageContent.message2": "Stuck here for too long? If your connection is stable, try refreshing the page. If you still need help feel free to email support at <0/>.", "LoadingPageContent.title": "Loading...", - "Location.request_report": "Request Report", - "Location.requesting_report": "Requesting Report...", - "Location.request_report_success": "The generated report will be sent to your email.", "LocationDetailsForm.business_name": "{0} Name", "LocationDetailsForm.number_of_users": "How many people will use Greenlight?", "LocationDetailsForm.registration": "Users will be able to register for your {0} by visiting: glit.me/go/{1}", diff --git a/client/src/pages/admin/AdminDashboardPage.tsx b/client/src/pages/admin/AdminDashboardPage.tsx index 79eb8eb..8ff6849 100644 --- a/client/src/pages/admin/AdminDashboardPage.tsx +++ b/client/src/pages/admin/AdminDashboardPage.tsx @@ -1,6 +1,6 @@ import { - AccordionContent, - Block, Icon, List, ListItem, Navbar, Page, + AccordionContent, f7, + Block, Icon, List, ListItem, Navbar, Page, Button, } from 'framework7-react' import React from 'react' import { useEffect, useGlobal, useState } from 'reactn' @@ -13,11 +13,13 @@ import { dynamicPaths, paths } from 'src/config/routes' import { UsersFilter } from 'src/components/UsersFilter' import { assertNotNull, assertNotUndefined } from 'src/helpers/util' import { F7Props } from 'src/types' -import { getLocation, store, v1 } from 'src/api' +import { getLocation, store, v1, requestPeopleReport } from 'src/api' import { GreenlightStatus, Location } from 'src/models' import { GreenlightStatusTypes } from 'src/models/GreenlightStatus' import logger from 'src/helpers/logger' +import SubmitHandler from 'src/helpers/SubmitHandler' import FakeF7ListItem from 'src/components/FakeF7ListItem' +import Tr, { tr } from 'src/components/Tr' interface StatsSquareProps { title: string @@ -153,6 +155,20 @@ export default function AdminDashboardPage(props: F7Props): JSX.Element { ], }, } + + const reportHandler = new SubmitHandler(f7, { + onSubmit: async () => { + assertNotNull(state.location) + await requestPeopleReport(state.location) + }, + errorTitle: tr({ es: 'Solicitud fallida', en: 'Request failed.' }), + submittingMessage: tr({ es: 'Solicitando Informe ...', en: 'Requesting Report...' }), + successMessage: tr({ + es: 'El informe generado se enviará a su correo electrónico.', + en: 'The generated report will be sent to your email.', + }), + }) + content = ( <> @@ -254,6 +270,12 @@ export default function AdminDashboardPage(props: F7Props): JSX.Element { ) } + +

+ +

diff --git a/client/src/pages/user-locations/UserLocationPage.tsx b/client/src/pages/user-locations/UserLocationPage.tsx index 4ace455..caa0896 100644 --- a/client/src/pages/user-locations/UserLocationPage.tsx +++ b/client/src/pages/user-locations/UserLocationPage.tsx @@ -11,7 +11,7 @@ import { assertNotNull, assertNotUndefined, formatPhone } from 'src/helpers/util import { Location, User } from 'src/models' import { - getLocation, getUser, store, updateLocationAccount, requestPeopleReport, + getLocation, getUser, store, updateLocationAccount, } from 'src/api' import SubmitHandler from 'src/helpers/SubmitHandler' import { LocationAccount, PermissionLevels } from 'src/models/LocationAccount' @@ -63,15 +63,7 @@ export default function UserLocationPage(props: F7Props) { assertNotUndefined(state.user) const la = state.locationAccount const l = state.location - - const reportHandler = new SubmitHandler(f7, { - onSubmit: async () => { - await requestPeopleReport(l) - }, - errorTitle: t({ id: 'Common.failed', message: 'Action Failed' }), - submittingMessage: t({ id: 'Location.requesting_report', message: 'Requesting Report...' }), - successMessage: t({ id: 'Location.request_report_success', message: 'The generated report will be sent to your email.' }), - }) + const handler = new SubmitHandler(f7) content = ( <> @@ -84,17 +76,6 @@ export default function UserLocationPage(props: F7Props) {

You are linked to {l.name}. To request removal, please contact .

- - {la.isAdmin() - && ( -

- -

- )} From bd7795bf045ec0518d76b4b9582a94b8b0322001 Mon Sep 17 00:00:00 2001 From: Jeremy Date: Fri, 5 Feb 2021 07:52:53 -0500 Subject: [PATCH 7/7] patch: use ENV vars for S3 --- app/commands/upload_to_s3.rb | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/app/commands/upload_to_s3.rb b/app/commands/upload_to_s3.rb index c50bb12..c657c45 100644 --- a/app/commands/upload_to_s3.rb +++ b/app/commands/upload_to_s3.rb @@ -11,12 +11,12 @@ class UploadToS3 < ApplicationCommand def work s3 = Aws::S3::Resource.new( - region: 'us-east-1', + region: ENV['AWS_REGION'], access_key_id: ENV['AWS_ACCESS_KEY_ID'], secret_access_key: ENV['AWS_SECRET_ACCESS_KEY'], ) - bucket = s3.bucket(s3_bucket) + bucket = s3.bucket(ENV['AWS_BUCKET']) obj = bucket.object(self.path) obj.put(body: self.content, content_disposition: "attachment; filename=#{self.filename}") @@ -24,14 +24,4 @@ def work rescue => e puts e.inspect end - - private - - def s3_bucket - if Rails.env == 'development' - 'glit-dev' - else - 'glit-prod' - end - end end