diff --git a/README.md b/README.md index a921d94..30bd21a 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ The app in this repo was recently upgraded to Rails 7. If you had the earlier ve ``` bin/rails db:migrate bin/rails db:encryption:init -bin/rails create_initial_import +bin/rails create_initial_imports bin/rails migrate_partner_api_credentials ``` diff --git a/app/assets/stylesheets/polaris_overrides.css b/app/assets/stylesheets/polaris_overrides.css index e8422ec..6a1e5aa 100644 --- a/app/assets/stylesheets/polaris_overrides.css +++ b/app/assets/stylesheets/polaris_overrides.css @@ -23,4 +23,8 @@ .Polaris-HorizontalGrid { grid-template-columns: repeat(1, minmax(0, 1fr)) } + + .Polaris-LegacyStack.filter-stack { + margin-left: 0; + } } diff --git a/app/javascript/controllers/globe_controller.js b/app/javascript/controllers/globe_controller.js index eac6e9e..619b558 100644 --- a/app/javascript/controllers/globe_controller.js +++ b/app/javascript/controllers/globe_controller.js @@ -322,11 +322,11 @@ export default class extends Controller { // HELPER FUNCTIONS async setUserLocation() { - // Using http://ip-api.com/json/ - const response = await get("http://ip-api.com/json/?fields=countryCode"); + // Using https://ip-api.com/json/ + const response = await get("https://api.country.is"); if (response.ok) { const locationData = await response.json; - this.myLocationValue = locationData.countryCode; + this.myLocationValue = locationData.country; } } diff --git a/app/mailers/application_mailer.rb b/app/mailers/application_mailer.rb index 0d5138a..7135eaa 100644 --- a/app/mailers/application_mailer.rb +++ b/app/mailers/application_mailer.rb @@ -5,6 +5,6 @@ class ApplicationMailer < ActionMailer::Base private def default_from - Rails.application.credentials[:action_mailer][:email_from_address] + Rails.application.credentials[Rails.env.to_sym][:action_mailer][:email_from_address] end end diff --git a/app/models/import.rb b/app/models/import.rb index 7d3266f..a0e9c06 100644 --- a/app/models/import.rb +++ b/app/models/import.rb @@ -37,6 +37,7 @@ class Import < ApplicationRecord scope :in_progress, -> { where(status: %i[scheduled importing calculating]) } def schedule + return unless draft? scheduled! ImportPaymentsJob.perform_later(import: self) end diff --git a/app/models/import/adaptor/csv_file.rb b/app/models/import/adaptor/csv_file.rb index 14f63ae..ee2b264 100644 --- a/app/models/import/adaptor/csv_file.rb +++ b/app/models/import/adaptor/csv_file.rb @@ -1,4 +1,3 @@ -require "zip" require "csvreader" class Import::Adaptor::CsvFile diff --git a/app/views/home/index.html.erb b/app/views/home/index.html.erb index 0d1d0f2..24fc35e 100644 --- a/app/views/home/index.html.erb +++ b/app/views/home/index.html.erb @@ -3,7 +3,7 @@ <%= polaris_empty_state( heading: "A free metrics dashboard for Shopify Partners", classes: "empty-state", - image: image_path("empty_state/AnalyticsMinor"), + image: image_path("empty_state/AnalyticsMinor.svg"), ) do |state| %> <% state.with_primary_action(url: new_user_registration_path) { "Sign up" } %> diff --git a/app/views/imports/show.html.erb b/app/views/imports/show.html.erb index 60e474a..2f270ad 100644 --- a/app/views/imports/show.html.erb +++ b/app/views/imports/show.html.erb @@ -34,13 +34,16 @@ <% end %> <% end %> -
-<%= tag.div style: "width: 80%; height: 800px; margin: 0 auto; opacity: 0; transition: opacity 3s ease-in-out;", + +<% if @import.csv_file_source? %> + <%= polaris_spacer(vertical: :base) %> + <%= tag.div style: "width: 80%; height: 800px; margin: 0 auto; opacity: 0; transition: opacity 3s ease-in-out;", data: { controller: "globe", globe_target: "container", globe_fetch_url_value: import_globe_path(@import), } %> +<% end %> <%= render "modals/destroy", id: "destroy-modal", diff --git a/app/views/metrics/show.html.erb b/app/views/metrics/show.html.erb index e3d5588..ead0d0f 100644 --- a/app/views/metrics/show.html.erb +++ b/app/views/metrics/show.html.erb @@ -9,7 +9,7 @@ <%= polaris_vertical_stack(gap: "6") do %> - <%= polaris_stack(alignment: :center) do |stack| %> + <%= polaris_stack(alignment: :center, classes: "filter-stack") do |stack| %> <% stack.with_item(fill:true) do %> <%= render "filter", filter: @filter, app_titles: @app_titles %> diff --git a/app/views/shared/_empty_state.html.erb b/app/views/shared/_empty_state.html.erb index b085645..8fa1876 100644 --- a/app/views/shared/_empty_state.html.erb +++ b/app/views/shared/_empty_state.html.erb @@ -2,7 +2,7 @@ <%= polaris_empty_state( heading: t(".title", resource: resource_name_for(resource, true)), classes: "empty-state", - image: image_path("empty_state/ImportMinor"), + image: image_path("empty_state/ImportMinor.svg"), ) do |state| %> <% state.with_primary_action(url: new_import_path) { "New import" } %> diff --git a/config/cable.yml b/config/cable.yml index 5a93943..a399cc0 100644 --- a/config/cable.yml +++ b/config/cable.yml @@ -9,3 +9,5 @@ production: adapter: redis url: <%= ENV.fetch("REDIS_URL") { "redis://localhost:6379/1" } %> channel_prefix: partner_metrics_production + ssl_params: + verify_mode: <%= OpenSSL::SSL::VERIFY_NONE %> diff --git a/config/credentials.sample.yml b/config/credentials.sample.yml index 273cfd1..ec63c17 100644 --- a/config/credentials.sample.yml +++ b/config/credentials.sample.yml @@ -9,13 +9,26 @@ development: username: password: email_from_address: - + sendgrid: + api_key: + cloudflare: + account_id: + access_key_id: + secret_access_key: + bucket: test: secret_key_base: action_mailer: username: password: email_from_address: + sendgrid: + api_key: + cloudflare: + account_id: + access_key_id: + secret_access_key: + bucket: production: secret_key_base: @@ -23,6 +36,8 @@ production: username: password: email_from_address: + sendgrid: + api_key: cloudflare: account_id: access_key_id: diff --git a/config/credentials.yml.enc b/config/credentials.yml.enc index f3df277..46b7f15 100644 --- a/config/credentials.yml.enc +++ b/config/credentials.yml.enc @@ -1 +1 @@ -mGRLkQ8haPVqu3prCsxRTrnpFhO5WCIiCNSo6TilHmyzLSbfe+z4wiqIsbSVzHtdZA6aAE+2P4f14O745E8NsnZJaj+8Iop+Agln87Wa5zzfQ6sNvOAJK06fJIfwOkoo/rvG4S6zvDP3vSgGac/n9dcstKE2gCHrK3UB07K9HZ3BPoiyeGm/JYJUxoz3Secd5UsLF1c1BEkJMtIunwj/862YI/8Db+VBfGk3AbMc3gdIMhLzkvSsxDb8L3fLN+h2zRHGL+N5pk+KuSSpfA2UKSjTInlBSxBq2fK44hpuc1bhkaQWBlneP8iv1yy3itlO5nStLnsWXqe7kDqhLb1CwA3JOJ9fzAYHSBzHOmBfBuhrtWh/1w9A90fOgSO4S2MqClhDcS1ELx2fClY47tW2RfjUpyngb43GhK+oBf8feix3kNfTruzQwohAYUgW52rmanBO41Z5wytfYH+VnYMe8yRqflmYNrfJswlOBhxofYFQy4Y8/8Tp9b/zfVt+Yt+9nXyATg/m9S3hS1OVkAHrFvkCNnCQLhmYKDwilF4yzB2xOW8y6dkQQRBrVoQQSSatIuUipF+0Kt0Ac+I+HCtou7D3igvMPo83+v+1yCAPSt6bBTEpxf+ndY+8RXRu4KqHZiGnhJMYByQkexGjkvdmTv4IHi+27NR8mNnkLFO0SaGlzLdAB8RiwuqbiWp9iWi7YYqn++J03IyQDXTqV6DB2wS9rESrFB0TaLTSdQMMuopZIkd6qtEAFk2foCRwJll7chOqidguhx2cNNrS50VJf0fTSAENcIQZlLm70gUnD9VgVRY/vrmkv5nLUIL0wL8vgRI9MbRqDqrAo7iHRxtD3e+MrnCFCZamT5fjegUUPUpBWu/zupW0PbOBlwQt+TNWpiF2dID9tpwbHkjffvuoF+7HqdCp2N9Pbf3kuzLAge3EuEQG6nRNnbfNE//X886xM6R1I+Xm63TE5jbDC671Fwd/3mMURTJ3W3paYz2VA7Da4X2eg4sAALRLR46Nh42FkRqXk2QVS5OukJLx6rPN9Tl7yR+A0Cx8AnkMQCX2JH1I35NrrXadFaiuvTYERBJ6ielYZ0+YEG9ZUCgzgY7FBzfFtw8Wu3dP4CRNus+LJRDhs94RLLfYqqth9yASSAo54Vd6PUaPv6oDmDIZD6MVU/Km9SQRFRPa+1quCTav9BZAlBmNyD9Y21kX4/tmatHNIZmBeTfglbGrgO+SW56RdoNl6uROtaS3Ri+T/Lm8JGjG3F2WP0l0JKlZHKESEIpR+uOu15FLRx/+sjhyAC607LUZ2vt32d/sNFz3cjwDeVi1DXBonAlJWQR7R2O/24EeDkRihnrhl5onfLLuxFRiOp8o/ZQ+BM9k06YCQEwvUBNeK4ZsQ0dIqdSNotIZEjnbAuZCq5cbGv3zviYYhovTlT5mKUeHtcGHprSXfczYNvoAKCahHz6kW53z5w3yM2JyXhw1z2tEMkIBwwBWv652K8q0p4VQ2Hz+PTWq6+ErCpZlOjGTE8TZm9hB+V90Z860nGJ0yVTUH7tJLW0QEqjJ3nmI7A5x0ghw8es/vBUbsspHNAdHGH3BvZutSy/Y2dgd+YcyCQ04DUO1hgaTlHHQSdPpoY1M1e47CD9OKveOuUafxZ6csn7DItj+mDQUS9VTBAox8vK1Sln2l1ihSI35s+DcYVl5pXchfBw8/yVrPcPMwqazVJ50R3DK7pLX6qZiTEWViKZ9Ew+l2pUm0To8X/ZmT++8iqOgj4IAOLbpSXXiSrp1WKPpq2PQwHa6B9uZIw6f1NUOEP9lNIC08jBW+y+TZuecstqK--CxAz8DjUPAzKqGf1--asr5mlmkOFh3YML/RNsHBw== \ No newline at end of file +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--iTXmcHtzsIHTXXnk--RXkWKUk/pyl/uqk3pPuIvg== \ No newline at end of file diff --git a/config/environments/development.rb b/config/environments/development.rb index 1fb3c3f..c8f3aa1 100644 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -46,7 +46,7 @@ config.action_mailer.default_url_options = { host: "localhost:4000" } config.action_mailer.asset_host = "http://localhost:4000" config.action_mailer.smtp_settings = { - from: Rails.application.credentials.dig(:action_mailer, :from_email_address), + from: Rails.application.credentials[Rails.env.to_sym][:action_mailer][:from_email_address], } # Print deprecation notices to the Rails logger. diff --git a/config/environments/production.rb b/config/environments/production.rb index 02af045..7b99d84 100644 --- a/config/environments/production.rb +++ b/config/environments/production.rb @@ -56,7 +56,7 @@ config.log_tags = [ :request_id ] # Use a different cache store in production. - # config.cache_store = :mem_cache_store + config.cache_store = :redis_cache_store, { url: ENV['REDIS_URL'], ssl_params: { verify_mode: OpenSSL::SSL::VERIFY_NONE } } # Use a real queuing backend for Active Job (and separate queues per environment). # config.active_job.queue_adapter = :resque @@ -67,9 +67,9 @@ # Ignore bad email addresses and do not raise email delivery errors. # Set this to true and configure the email server for immediate delivery to raise delivery errors. config.action_mailer.default_url_options = {host: "partnermetrics.io"} - app.config.action_mailer.delivery_method = :sendgrid_actionmailer - app.config.action_mailer.sendgrid_actionmailer_settings = { - api_key: Rails.application.credentials[:sendgrid][:api_key], + config.action_mailer.delivery_method = :sendgrid_actionmailer + config.action_mailer.sendgrid_actionmailer_settings = { + api_key: Rails.application.credentials[Rails.env.to_sym][:sendgrid][:api_key], raise_delivery_errors: true } diff --git a/config/initializers/assets.rb b/config/initializers/assets.rb index 2eeef96..0b7acc2 100644 --- a/config/initializers/assets.rb +++ b/config/initializers/assets.rb @@ -9,4 +9,4 @@ # Precompile additional assets. # application.js, application.css, and all non-JS/CSS in the app/assets # folder are already added. -# Rails.application.config.assets.precompile += %w( admin.js admin.css ) +Rails.application.config.assets.precompile += %w( .svg ) diff --git a/config/initializers/sidekiq.rb b/config/initializers/sidekiq.rb new file mode 100644 index 0000000..17c2ff5 --- /dev/null +++ b/config/initializers/sidekiq.rb @@ -0,0 +1,13 @@ +Sidekiq.configure_server do |config| + config.redis = { + url: ENV["REDIS_URL"], + ssl_params: { verify_mode: OpenSSL::SSL::VERIFY_NONE } + } +end + +Sidekiq.configure_client do |config| + config.redis = { + url: ENV["REDIS_URL"], + ssl_params: { verify_mode: OpenSSL::SSL::VERIFY_NONE } + } +end diff --git a/config/storage.yml b/config/storage.yml index 2ffc223..78fca22 100644 --- a/config/storage.yml +++ b/config/storage.yml @@ -10,11 +10,11 @@ local: # Cloudflare tutorial: https://kirillplatonov.com/posts/activestorage-cloudflare-r2/ cloudflare: service: S3 - endpoint: https://<%= Rails.application.credentials[:cloudflare_account_id] %>.r2.cloudflarestorage.com - access_key_id: <%= Rails.application.credentials[:cloudflare_access_key_id] %> - secret_access_key: <%= Rails.application.credentials[:cloudflare_secret_access_key] %> + endpoint: https://<%= Rails.application.credentials[Rails.env.to_sym][:cloudflare][:account_id] %>.r2.cloudflarestorage.com + access_key_id: <%= Rails.application.credentials[Rails.env.to_sym][:cloudflare][:access_key_id] %> + secret_access_key: <%= Rails.application.credentials[Rails.env.to_sym][:cloudflare][:secret_access_key] %> region: auto - bucket: <%= Rails.application.credentials[:cloudflare_bucket] %> + bucket: <%= Rails.application.credentials[Rails.env.to_sym][:cloudflare][:bucket] %> # amazon: # service: S3 diff --git a/lib/tasks/create_initial_imports.rake b/lib/tasks/create_initial_imports.rake index d937c67..11e7b16 100644 --- a/lib/tasks/create_initial_imports.rake +++ b/lib/tasks/create_initial_imports.rake @@ -2,10 +2,10 @@ desc "Creates the inital import for all users, so all historical payments and me task create_initial_imports: :environment do User.find_each do |user| import = user.imports.create!( - source: Import.sources[:shopify_payments_api] + source: Import.sources[:shopify_payments_api], + status: Import.statuses[:completed] ) user.metrics.update_all(import_id: import.id) if user.metrics.any? user.payments.update_all(import_id: import.id) if user.payments.any? - import.completed! end end diff --git a/lib/tasks/create_partner_api_credentials.rake b/lib/tasks/create_partner_api_credentials.rake index 8f238ec..1cfe72c 100644 --- a/lib/tasks/create_partner_api_credentials.rake +++ b/lib/tasks/create_partner_api_credentials.rake @@ -3,7 +3,7 @@ task create_partner_api_credentials: :environment do User.find_each do |user| if user.partner_api_access_token.present? && user.partner_api_organization_id.present? && !user.partner_api_errors&.include?("Unauthorized") if user.partner_api_credential.blank? - user.create_partner_api_credential!( + user.create_partner_api_credential( organization_id: user.partner_api_organization_id, access_token: user.partner_api_access_token )