Skip to content

Commit

Permalink
Improve integration/config onboarding wizard
Browse files Browse the repository at this point in the history
- Add separate configuration wizard for all required integrations
- Allows modals to be hard-linked
  • Loading branch information
kitallis committed Sep 12, 2024
1 parent b7497f1 commit aa78729
Show file tree
Hide file tree
Showing 16 changed files with 330 additions and 257 deletions.
7 changes: 5 additions & 2 deletions app/components/v2/integration_list_component.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,14 @@

<% if connected_integrations?(integrations) %>
<% sc.with_sidenote do %>
<%= render V2::ModalComponent.new(title: "Configure #{Integration.human_enum_name(:category, category)}") do |modal| %>
<%= render V2::ModalComponent.new(title: title(category), open: pre_open?(category)) do |modal| %>
<% modal.with_button(label: "Configure", scheme: :light, type: :action, size: :xxs, arrow: :none)
.with_icon("v2/cog.svg", size: :md) %>
<% modal.with_body do %>
<%= tag.turbo_frame id: "#{category}_config", src: edit_app_app_config_path(@app, integration_category: category), loading: :lazy, class: "with-turbo-frame-loader" do %>
<%= tag.turbo_frame id: "#{category}_config",
src: edit_app_app_config_path(@app, integration_category: category),
loading: :lazy,
class: "with-turbo-frame-loader" do %>
<%= render V2::LoadingIndicatorComponent.new(skeleton_only: true, turbo_frame: true) %>
<% end %>
<% end %>
Expand Down
11 changes: 10 additions & 1 deletion app/components/v2/integration_list_component.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,16 @@
class V2::IntegrationListComponent < V2::BaseComponent
def initialize(app, integrations)
def initialize(app, integrations, pre_open_category: nil)
@app = app
@integrations_by_categories = integrations
@pre_open_category = pre_open_category
end

def title(category)
"Configure #{Integration.human_enum_name(:category, category)}"
end

def pre_open?(category)
@pre_open_category == category
end

def connected_integrations?(integrations)
Expand Down
2 changes: 1 addition & 1 deletion app/components/v2/modal_component.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
type: :action,
size: :none,
authz: false,
html_options: { data: { action: "dialog#close" } }) do |b|
html_options: { autofocus: false, tabindex: "-1", data: { action: "dialog#close" } }) do |b|
b.with_icon("close_icon.svg", size: :md)
end %>
</div>
Expand Down
7 changes: 4 additions & 3 deletions app/components/v2/modal_component.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ class V2::ModalComponent < V2::BaseComponent

renders_one :body

def initialize(title:, type: :dialog, subtitle: nil, size: :default, authz: true, dismissable: true)
def initialize(title:, type: :dialog, subtitle: nil, size: :default, authz: true, dismissable: true, open: false)
raise ArgumentError, "Invalid size" unless SIZE_TO_WIDTH.key?(size.to_sym)

@title = title
Expand All @@ -27,15 +27,16 @@ def initialize(title:, type: :dialog, subtitle: nil, size: :default, authz: true
@size = size
@authz = authz
@dismissable = dismissable
@open = open
end

attr_reader :title, :subtitle, :dismissable
attr_reader :title, :subtitle, :dismissable, :open

def reveal_data_attrs
if disabled?
{}
elsif dialog?
{class: "inline-flex items-center", data: {controller: "dialog", dialog_dismissable_value: dismissable}}
{class: "inline-flex items-center", data: {controller: "dialog", dialog_dismissable_value: dismissable, dialog_open_value: open}}
elsif drawer?
{class: "inline-flex items-center", data: {controller: "reveal", reveal_away_value: dismissable, reveal_target_selector_value: "[data-drawer-reveal]"}}
end
Expand Down
30 changes: 19 additions & 11 deletions app/controllers/app_configs_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -44,23 +44,23 @@ def edit_category_partial
end

def configure_version_control
set_code_repositories if @config.further_code_repository_setup?
set_code_repositories if further_setup_by_category?.dig(:version_control, :further_setup)
end

def configure_notification_channel
set_notification_channels if @app.notifications_set_up?
end

def configure_build_channel
set_firebase_apps if @config.further_build_channel_setup?
def configure_ci_cd
set_ci_cd_projects if further_setup_by_category?.dig(:ci_cd, :further_setup)
end

def configure_monitoring
set_monitoring_projects if @config.further_monitoring_setup?
def configure_build_channel
set_firebase_apps if further_setup_by_category?.dig(:build_channel, :further_setup)
end

def configure_ci_cd
set_ci_cd_projects if @config.further_ci_cd_setup?
def configure_monitoring
set_monitoring_projects if further_setup_by_category?.dig(:monitoring, :further_setup)
end

def set_app_config
Expand Down Expand Up @@ -128,15 +128,23 @@ def bugsnag_config(config_params)
config = {}

if config_params[:bugsnag_ios_release_stage].present?
config[:bugsnag_ios_config] = {project_id: config_params[:bugsnag_ios_project_id].safe_json_parse,
release_stage: config_params[:bugsnag_ios_release_stage]}
config[:bugsnag_ios_config] = {
project_id: config_params[:bugsnag_ios_project_id].safe_json_parse,
release_stage: config_params[:bugsnag_ios_release_stage]
}
end

if config_params[:bugsnag_android_release_stage].present?
config[:bugsnag_android_config] = {project_id: config_params[:bugsnag_android_project_id].safe_json_parse,
release_stage: config_params[:bugsnag_android_release_stage]}
config[:bugsnag_android_config] = {
project_id: config_params[:bugsnag_android_project_id].safe_json_parse,
release_stage: config_params[:bugsnag_android_release_stage]
}
end

config
end

def further_setup_by_category?
@further_setup_by_category ||= @config.further_setup_by_category?
end
end
1 change: 1 addition & 0 deletions app/controllers/integrations_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ def connect
end

def index
@pre_open_category = Integration.categories[params[:integration_category]]
set_integrations_by_categories
set_tab_configuration
end
Expand Down
19 changes: 0 additions & 19 deletions app/helpers/apps_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,23 +7,4 @@ def store_logo(app)
return "integrations/logo_app_store.png" if app.ios?
"integrations/logo_google_play_store.png" if app.android?
end

MOVEMENT_STATUS_COLORS = {
in_progress: "bg-amber-500",
done: "bg-indigo-500",
failed: "bg-red-500",
not_started: "bg-slate-300"
}.freeze

def movement_status(status_summary)
status_summary.key(true)
end

def movement_status_text(status_summary)
(movement_status(status_summary) || :processing).to_s.titleize
end

def movement_status_color(status_summary)
MOVEMENT_STATUS_COLORS.fetch(movement_status(status_summary), "bg-slate-100")
end
end
22 changes: 20 additions & 2 deletions app/javascript/controllers/dialog_controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,29 @@ export default class extends Controller {
static targets = ["dialog"]
static values = {
dismissable: Boolean,
open: {
type: Boolean,
default: false
}
}

connect() {
if (this.openValue) {
this.open(null)
}
}

open(event) {
event.preventDefault();
this.dialogTarget.showModal();
if (event) {
event.preventDefault();
}

this.dialogTarget.showModal(); // Show the dialog

/* Remove focus from the dialog */
this.dialogTarget.focus();
this.dialogTarget.blur();

if (this.dismissableValue) {
this.dialogTarget.addEventListener('click', (e) => this.backdropClick(e));
}
Expand Down
26 changes: 13 additions & 13 deletions app/models/app.rb
Original file line number Diff line number Diff line change
Expand Up @@ -172,13 +172,19 @@ def app_setup_instructions

app_config_setup = {
app_config: {
visible: integrations.ready?, completed: ready?
visible: integrations.ready?,
completed: ready?,
integrations: {}
}
}

[app_setup, integration_setup, app_config_setup]
.flatten
.reduce(:merge)
config.further_setup_by_category?.each do |category, status_map|
app_config_setup[:app_config][:integrations][category] = {
visible: true, completed: status_map[:ready]
}
end

[app_setup, integration_setup, app_config_setup].flatten.reduce(:merge)
end

def train_setup_instructions
Expand All @@ -202,15 +208,9 @@ def train_setup_instructions
}
}

instructions =
if cross_platform?
[train_setup, ios_steps_setup, android_steps_setup]
elsif android?
[train_setup, android_steps_setup]
else
[train_setup, ios_steps_setup]
end

instructions = [train_setup]
instructions += [ios_steps_setup] if ios? || cross_platform?
instructions += [android_steps_setup] if android? || cross_platform?
instructions.flatten.reduce(:merge)
end

Expand Down
54 changes: 37 additions & 17 deletions app/models/app_config.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,7 @@ class AppConfig < ApplicationRecord
include Notifiable
include PlatformAwareness

MINIMUM_REQUIRED_CONFIG = %i[code_repository]
PLATFORM_AWARE_CONFIG_SCHEMA = Rails.root.join("config/schema/platform_aware_integration_config.json")

# self.ignored_columns += ["bugsnag_project_id"]

belongs_to :app
Expand All @@ -40,7 +38,10 @@ class AppConfig < ApplicationRecord
after_initialize :set_bugsnag_config, if: :persisted?

def ready?
MINIMUM_REQUIRED_CONFIG.all? { |config| public_send(config).present? } && firebase_ready? && bitrise_ready? && bugsnag_ready?
further_setup_by_category?
.values
.pluck(:ready)
.all?
end

def code_repository_name
Expand All @@ -64,20 +65,39 @@ def bitrise_project
bitrise_project_id&.fetch("id", nil)
end

def further_build_channel_setup?
app.integrations.build_channel.map(&:providable).any?(&:further_setup?)
end

def further_ci_cd_setup?
app.integrations.ci_cd_provider.further_setup?
end

def further_monitoring_setup?
app.integrations.monitoring_provider&.further_setup?
end

def further_code_repository_setup?
app.integrations.vcs_provider.further_setup?
def further_setup_by_category?
integrations = app.integrations
categories = {}.with_indifferent_access

if integrations.vcs_provider.present?
categories[:version_control] = {
further_setup: integrations.vcs_provider.further_setup?,
ready: code_repository.present?
}
end

if integrations.ci_cd_provider.present?
categories[:ci_cd] = {
further_setup: integrations.ci_cd_provider.further_setup?,
ready: bitrise_ready?
}
end

if integrations.build_channel.present?
categories[:build_channel] = {
further_setup: integrations.build_channel.map(&:providable).any?(&:further_setup?),
ready: firebase_ready?
}
end

if integrations.monitoring_provider.present?
categories[:monitoring] = {
further_setup: integrations.monitoring_provider.further_setup?,
ready: bugsnag_ready?
}
end

categories
end

def firebase_app(platform, variant: nil)
Expand Down
6 changes: 2 additions & 4 deletions app/views/app_configs/version_control.html+turbo_frame.erb
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,8 @@
<div>
<%= section.F.labeled_select :code_repository,
"Code Repository",
options_for_select(
display_channels(@code_repositories) { |chan| chan[:full_name] },
@config.code_repository.to_json
) %>
options_for_select(display_channels(@code_repositories) { |chan| chan[:full_name] },
@config.code_repository.to_json) %>
</div>
<% end %>

Expand Down
Loading

0 comments on commit aa78729

Please sign in to comment.