Skip to content

Commit

Permalink
Merge pull request #193 from alces-flight/enh/better-cluster-launch-p…
Browse files Browse the repository at this point in the history
…ages

Improvements to cluster launch pages
  • Loading branch information
benarmston authored Mar 11, 2024
2 parents 4c088e3 + 18628bc commit 8fb6adf
Show file tree
Hide file tree
Showing 40 changed files with 908 additions and 64 deletions.
1 change: 1 addition & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ gem "cells-erb", "~> 0.1.0"
gem "rabl", "~> 0.16.1"
gem "pagy", "~> 6.4"
gem "simple_form", "~> 5.3"
gem "commonmarker", "~> 1.0"

# Use Active Model has_secure_password [https://guides.rubyonrails.org/active_model_basics.html#securepassword]
# gem "bcrypt", "~> 3.1.7"
Expand Down
2 changes: 2 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ GEM
cells-rails (0.1.5)
actionpack (>= 5.0)
cells (>= 4.1.6, < 5.0.0)
commonmarker (1.0.4-x86_64-linux)
concurrent-ruby (1.2.3)
connection_pool (2.4.1)
crack (0.4.5)
Expand Down Expand Up @@ -351,6 +352,7 @@ DEPENDENCIES
capybara
cells-erb (~> 0.1.0)
cells-rails (~> 0.1.5)
commonmarker (~> 1.0)
crack (~> 0.4.5)
dartsass-rails (= 0.4.1)
debug
Expand Down
1 change: 1 addition & 0 deletions app/assets/stylesheets/application.scss
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@
@import "components/simple_form";
@import "components/tabs";
@import "components/ct_widget";
@import "components/rack_show_page";

/*
Components/Widgets
Expand Down
114 changes: 99 additions & 15 deletions app/assets/stylesheets/components/_cluster_types_view.scss
Original file line number Diff line number Diff line change
@@ -1,17 +1,101 @@
.cluster-types-card-deck {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(28em, 1fr));
grid-gap: 1rem;
justify-content: space-between;
justify-items: center;
padding: 1.25rem 2.5rem;
}


.cluster-type-card {
width: 19rem;
border: darkgray 1px solid;
padding: 0.5em;
margin-left: 0.5rem;
margin-right: 0.5rem;

.card-divider {
border-bottom: darkgray 1px solid;
}

.disabled-cluster-link {
color: #63666A;
cursor: not-allowed;
font-weight: bold;
}
border: solid #3b5168 1px;
border-radius: 2px;
padding: 1.5rem;
font-weight: 400;
transition: background 125ms;
}

.cluster-type-card {
display: grid;
grid-template-rows: [row1-start] auto [row1-end row2-start] auto [row2-end row3-start] auto [row3-end];
grid-template-columns: 1fr 1fr;
grid-template-areas: "header header" "icon description" ". button";

column-gap: 1.2rem;
row-gap: 0.3rem;

align-items: center;
margin: 0 !important;
width: 100%;
min-height: 14.2rem;
}

.cluster-type-card-title {
grid-area: header;
text-align: center;
margin: 0;
line-height: 1.8;
font-weight: 400;
}

.cluster-type-card-icon {
grid-area: icon;
margin: 10px 0 10px 10px;
justify-self: end;
max-height: 10rem;
max-width: calc(100% - 0.5rem) !important;
}

.cluster-type-card-description {
font-size: larger;
color: #3b5168;
}

.cluster-type-select-link {
grid-area: button;
justify-self: end;

.disabled-cluster-link {
color: #63666A;
cursor: not-allowed;
font-weight: bold;
}
}

.cluster-type-card:hover {
background: $lightest-blue;
.cluster-type-card-title { }
.cluster-type-card-description { }
}

.cluster-type-card--disabled {
background: $lighter-grey;
&:hover {
background: $lighter-grey;
}
}


.cluster-type-header {
display: grid;
grid-template-rows: [row1-start] auto [row1-end row2-start] auto [row2-end];
grid-template-columns: auto auto;
grid-template-areas: "icon header" "icon description";
column-gap: 1.2rem;
row-gap: 0.3rem;
justify-content: start;
margin-bottom: 0.625rem;

.cluster-type-card-title {
justify-self: left;
align-self: end;
max-width: 28em;
}

.cluster-type-card-description {
justify-self: left;
align-self: start;
max-width: 28em;
}
}
14 changes: 13 additions & 1 deletion app/assets/stylesheets/components/_new_cluster_form.scss
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#new_cluster {
border: none;
.formItem {
margin-bottom: 1rem;
}
Expand All @@ -18,7 +19,7 @@
}

.cluster-field-group {
margin-bottom: 2rem;
margin-bottom: 0.625rem;
}
.cluster-field-group-label { }
.cluster-field-group-description {
Expand All @@ -37,3 +38,14 @@
margin-left: 1rem;
}
}

.cluster-form-instructions {
padding-left: 10px;
margin-bottom: 0.625rem;
}

.cluster-launch-instructions {
max-width: 30rem;
margin-bottom: 1rem;
margin-left: 1rem;
}
14 changes: 14 additions & 0 deletions app/assets/stylesheets/components/_rack_show_page.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
.usage-instructions {
margin-bottom: 2em;

&:last-child {
margin-bottom: 0;
}

pre {
background: #fff !important;
code {
background: #2b303b;
}
}
}
13 changes: 12 additions & 1 deletion app/cells/cluster_form_name_cell.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,22 @@ def show(cluster, form)
@form = form
@errors = @record.errors
@attribute = :name
render
if has_clustername_parameter?
# We don't render anything here. Instead the value provided for the
# 'clustername' parameter will be used.
else
render
end
end

private

def has_clustername_parameter?
@record.fields.any? do |field|
field.id == Cluster::NAME_FIELD
end
end

def label_text
'Cluster name'
end
Expand Down
1 change: 1 addition & 0 deletions app/controllers/cluster_types_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,6 @@ def index
result = SyncAllClusterTypesJob.perform_now(@cloud_service_config, use_cache)
flash.now.alert = result.error_message unless result.success?
end
@cluster_types = @cluster_types.reorder(:order, :id)
end
end
6 changes: 5 additions & 1 deletion app/controllers/clusters_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,11 @@ def permitted_params
valid_selections = @cluster_type.field_groups
.select { |group| group["optional"].present? }
.map { |group| group["optional"]["name"] }
params.require(:cluster).permit(:name, cluster_params: @cluster_type.fields.keys, selections: valid_selections)
params.require(:cluster).permit(:name, cluster_params: @cluster_type.fields.keys, selections: valid_selections).tap do |h|
if !h.key?(:name) && h[:cluster_params].key?(Cluster::NAME_FIELD.to_sym)
h[:name] = h[:cluster_params][Cluster::NAME_FIELD.to_sym]
end
end
end

def set_cloud_assets
Expand Down
4 changes: 4 additions & 0 deletions app/controllers/racks_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,8 @@ def show
def devices
@devices = resource_table_collection(@rack.devices, model: Device)
end

def instructions
@instruction_id = params[:instruction_id]
end
end
3 changes: 3 additions & 0 deletions app/jobs/sync_all_cluster_types_job.rb
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,9 @@ def sync_data(types)
type.fields = ordered_fields(type_details["parameters"])
type.field_groups = type_details["parameter_groups"]
type.version = type_details["last_modified"]
type.order = type_details["order"]
type.logo_url = type_details["logo_url"]
type.instructions = type_details["instructions"]
unless type.save
errors << "Unable to #{type.persisted? ? "update" : "create"} type '#{type.descriptive_name}': #{type.errors.full_messages.join("; ")}"
end
Expand Down
3 changes: 3 additions & 0 deletions app/jobs/sync_individual_cluster_type_job.rb
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ def sync_data(type_details)
@cluster_type.fields = ordered_fields(type_details["parameters"])
@cluster_type.field_groups = type_details["parameter_groups"]
@cluster_type.version = type_details["last_modified"]
@cluster_type.order = type_details["order"]
@cluster_type.logo_url = type_details["logo_url"]
@cluster_type.instructions = type_details["instructions"]
unless @cluster_type.save
["Unable to update type '#{@cluster_type.descriptive_name}': #{@cluster_type.errors.full_messages.join("; ")}"]
else
Expand Down
13 changes: 13 additions & 0 deletions app/lib/markdown_renderer.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
module MarkdownRenderer
class << self
def render(markdown_text)
Commonmarker.to_html(
markdown_text,
options: {
parse: { smart: true },
render: { hardbreaks: false },
}
).html_safe
end
end
end
4 changes: 4 additions & 0 deletions app/models/cluster.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
class Cluster
include ActiveModel::API

# The field from which the cluster name will be copied if such a field
# exists.
NAME_FIELD = 'clustername'.freeze

####################################
#
# Properties
Expand Down
6 changes: 5 additions & 1 deletion app/models/cluster_type.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,11 @@ class ClusterType < ApplicationRecord

# fields will require some sophisticated validation
validates :fields,
presence: true
presence: true

validates :order,
presence: true,
numericality: true

validate :valid_fields_structure?

Expand Down
10 changes: 9 additions & 1 deletion app/presenters/cluster/field_presenter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,13 @@ def initialize(object, view_context, cloud_assets)
end

def form_field_type
select_box? ? 'select' : "#{MAPPED_FIELD_TYPES[type]}"
if select_box?
'select'
elsif type == 'string' && hidden
'password_field'
else
MAPPED_FIELD_TYPES[type]
end
end

def select_box?
Expand Down Expand Up @@ -68,6 +74,8 @@ def form_input(form)
@cloud_assets[cloud_asset].map { |a| [a["name"], a["id"]] }
end
form.send(form_field_type, :value, values, {prompt: true}, form_options)
elsif form_field_type == 'password_field'
form.send(form_field_type, :value, form_options.merge(autocomplete: 'off'))
else
form.send(form_field_type, :value, form_options)
end
Expand Down
10 changes: 10 additions & 0 deletions app/presenters/cluster_type_presenter.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
class ClusterTypePresenter < Presenter

delegate :instructions, to: :o

def instruction(id)
o.instructions.detect do |instruction|
instruction['id'] == id
end
end
end
24 changes: 24 additions & 0 deletions app/presenters/rack_presenter.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,27 @@
class RackPresenter < Presenter
include Costed

delegate :instructions, :instruction,
to: :cluster_type,
allow_nil: true

def creation_output
outputs = o.creation_output.split(', ').map { |output| output.split('=') }
Hash[outputs].tap do |h|
if h.key?('web_access')
h['web_access'] = @view_context.link_to(h['web_access'], h['web_access'], target: '_blank')
end
end
end

private

def cluster_type
@cluster_type ||=
begin
cluster_type_id = creation_output['concertim_cluster_type']
ct = ClusterType.find_by(foreign_id: cluster_type_id)
h.presenter_for(ct) if ct
end
end
end
7 changes: 0 additions & 7 deletions app/views/cluster_types/_actions.html.erb

This file was deleted.

Loading

0 comments on commit 8fb6adf

Please sign in to comment.