Skip to content

Commit

Permalink
Merge pull request #4323 from quintel/ctm-etm-coupling-4
Browse files Browse the repository at this point in the history
CTM-ETM coupling: external input groups
  • Loading branch information
mabijkerk authored Aug 27, 2024
2 parents 4ec5c9b + a4ebae8 commit 61c30fa
Show file tree
Hide file tree
Showing 45 changed files with 4,824 additions and 49 deletions.
6 changes: 3 additions & 3 deletions app/assets/javascripts/lib/models/input_element.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ class @InputElement extends Backbone.Model
@get('disabled') || App.scenario.isReadOnly()

isCoupled: ->
this.isDisabled() && @get('coupling_groups')
this.isDisabled() && @get('coupling_disabled')

conversions: ->
conversions = @get('conversions') or []
Expand Down Expand Up @@ -191,8 +191,8 @@ class @InputElementList extends Backbone.Collection
i.set({
user_value: def
disabled: dis
# Was it disabled by a coupling?
coupled: values.coupling_groups && dis
coupled: dis && values.coupling_disabled
coupling_groups: values.coupling_groups
}, { silent: true })

i.trigger('initial-set:user_value')
Expand Down
5 changes: 5 additions & 0 deletions app/assets/javascripts/lib/views/input_element_view.js
Original file line number Diff line number Diff line change
Expand Up @@ -439,7 +439,10 @@
input_element_key: this.model.get('key'),
end_year: App.settings.get('end_year'),
info_link: I18n.t('input_elements.common.info_link'),
coupling_icon: this.model.get('coupling_icon'),
coupling_groups: this.model.get('coupling_groups'),
info_coupling: I18n.t('input_elements.common.info_coupling'),
label_groups: I18n.t('input_elements.common.coupling_groups_label'),
})
);

Expand Down Expand Up @@ -596,13 +599,15 @@
}

if (this.model.get('coupled')) {
this.$el.addClass('hidden');
this.valueElement.addClass('coupled');
this.valueElement.html('');
}

this.quinn.disable();
} else {
this.$el.removeClass('disabled');
this.$el.removeClass('hidden');
this.valueElement.removeClass('coupled');
this.setTransientValue(this.quinn.model.value);
this.quinn.enable();
Expand Down
36 changes: 31 additions & 5 deletions app/assets/stylesheets/_slider.sass
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,17 @@ $slider-box-height: 22px
margin-left: 4px
width: 20px

.show-info.coupling-icon
background: asset-url("icons/link.svg") right no-repeat
color: #8f8f8f
width: 20px
display: inline-block
height: 20px
margin-bottom: -3px
&:hover
background: asset-url("icons/link.svg") right no-repeat
filter: brightness(0.5)

.reset
@include input-slider-button(0px)
margin-left: 0
Expand Down Expand Up @@ -142,13 +153,24 @@ $slider-box-height: 22px
margin: -0.75rem 0 0
svg
margin-bottom: -0.2rem
.coupling-groups
margin-bottom: 0.75rem
.group
background: #fff
padding: 0.2rem 0.5rem
border-radius: 2px
color: $landing-grey
margin-left: 0.25rem

&.info-box-visible
.show-info
@include input-slider-button(120px)
-webkit-user-select: none
-moz-user-select: none
user-select: none
&.coupling-icon
background: asset-url("icons/link.svg") right no-repeat
filter: brightness(0.5)

// Adjustment to vertical alignment of label and value text.
label, .output
Expand All @@ -162,11 +184,8 @@ $slider-box-height: 22px
.output
background: none
cursor: default

.output.coupled
background: asset-url("icons/link.svg") right no-repeat
color: #aaa

&.hidden
display: none

// Buttons are only visible on hovering the slider div.
.reset, .decrease, .increase
Expand Down Expand Up @@ -398,6 +417,13 @@ html.no-opacity .quinn.disabled
border-top: none
padding-top: 0

// Hide coupled sliders
.with-group.unmixed:has(.hidden)
display: none
.slider:has(.hidden)
display: none


// Inputs where values are rendered as a radio button list.
.radio-collection-view
Expand Down
6 changes: 6 additions & 0 deletions app/helpers/application_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,12 @@ def format_description(text)
end
end

# Public: returns true if the sliders are a mix of coupling and
# ordinary sliders
def mixed_coupled?(sliders)
sliders.any?(&:coupling_icon) && !sliders.all?(&:coupling_icon)
end

# Public: Receives a settings object and converts it to a hash suitable for
# serialization as JSON.
def settings_as_json(setting)
Expand Down
2 changes: 1 addition & 1 deletion app/models/engine/input.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,6 @@ class Input < Dry::Struct
attribute :default, Dry::Types['nominal.float'] | Dry::Types['nominal.string'] | Dry::Types['nominal.nil']
attribute :unit, Dry::Types['nominal.string'] | Dry::Types['nominal.nil']
attribute? :disabled, Dry::Types['nominal.bool'] | Dry::Types['nominal.nil']
attribute? :coupling_groups, Dry::Types['nominal.bool'] | Dry::Types['nominal.nil']
attribute? :coupling_disabled, Dry::Types['nominal.bool'] | Dry::Types['nominal.nil']
end
end
8 changes: 6 additions & 2 deletions app/models/engine/scenario.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ class Scenario < Dry::Struct

attribute :area_code, Dry::Types['strict.string']
attribute :balanced_values, Dry::Types['strict.hash']
attribute :coupling, Dry::Types['strict.bool']
attribute :active_couplings, Dry::Types['strict.array']
attribute :inactive_couplings, Dry::Types['strict.array']
attribute :end_year, Dry::Types['strict.integer']
attribute :id, Dry::Types['strict.integer']
attribute :keep_compatible, Dry::Types['strict.bool']
Expand All @@ -29,7 +30,6 @@ class Scenario < Dry::Struct
alias_method :keep_compatible?, :keep_compatible
alias_method :private?, :private
alias_method :edsl_exportable?, :esdl_exportable
alias_method :coupled?, :coupling

# Loads multiple scenarios by ID. Excludes any missing or inaccessable scenarios.
#
Expand Down Expand Up @@ -67,6 +67,10 @@ def owned?
owner.present?
end

def coupled?
active_couplings.present? || inactive_couplings.present?
end

def inputs(http_client)
http_client.get("/api/v3/scenarios/#{id}/inputs").body
end
Expand Down
2 changes: 1 addition & 1 deletion app/models/input_element.rb
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ def json_attributes
self, :unit, :share_group, :key, :related_node,
:node_source_url, :step_value, :draw_to_min, :draw_to_max,
:disabled, :translated_name, :sanitized_description, :fixed,
:has_flash_movie, :additional_specs, :config
:has_flash_movie, :additional_specs, :config, :coupling_icon
)
end
end
Expand Down
2 changes: 1 addition & 1 deletion app/services/uncouple_api_scenario.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ def initialize(http_client, id)
end

def call
@http_client.put("/api/v3/scenarios/#{@id}", coupling: false)
@http_client.post("/api/v3/scenarios/#{@id}/uncouple", force: true)
ServiceResult.success
rescue Faraday::ResourceNotFound
ServiceResult.failure('Scenario not found')
Expand Down
14 changes: 12 additions & 2 deletions app/views/input_elements/_input_element.html
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,17 @@

<div class="increase"></div>
<div class="output"></div>
<div class="show-info"></div>
<% if (coupling_icon) { %>
<div class="show-info coupling-icon"></div>
<% } else { %>
<div class="show-info"></div>
<% } %>
</div>
</div>

<div class="info-wrap">
<div class="info">
<% if (coupling) { %>
<% if (coupling_icon) { %>
<div class="node-detail-wrapper coupling-info">
<a href="https://docs.energytransitionmodel.com/main/external-coupling#coupling-external-inputs" target=\"_blank\">
<span>
Expand All @@ -38,6 +42,12 @@
</span>
<span class="text"><%= info_coupling %></span>
</a>
<div class="coupling-groups">
<span><%= label_groups %></span>
<% _.each(coupling_groups, function (coupling_group) { %>
<span class="group"><%= coupling_group %></span>
<% }); %>
</div>
</div>
<% } %>
<%= info %>
Expand Down
21 changes: 11 additions & 10 deletions app/views/scenarios/_slide.html.haml
Original file line number Diff line number Diff line change
Expand Up @@ -25,16 +25,17 @@
= render :partial => 'input_elements/slider', :object => input_element

- slide.grouped_input_elements.each do |group, sliders|
.interface_group
%hr
%span.label
= t("accordion.#{to_yml_syntax(group)}").html_safe
- unless slide.group_sub_header.blank?
%span.sub_header_arrow
.arrow-down
= t("subheaders.#{to_yml_syntax(group)}", default: t("subheaders.#{to_yml_syntax(slide.group_sub_header)}"))
- sliders.each do |input_element|
= render :partial => 'input_elements/slider', :object => input_element
.with-group{ class: mixed_coupled?(sliders) ? 'mixed' : 'unmixed' }
.interface_group
%hr
%span.label
= t("accordion.#{to_yml_syntax(group)}").html_safe
- unless slide.group_sub_header.blank?
%span.sub_header_arrow
.arrow-down
= t("subheaders.#{to_yml_syntax(group)}", default: t("subheaders.#{to_yml_syntax(slide.group_sub_header)}"))
- sliders.each do |input_element|
= render :partial => 'input_elements/slider', :object => input_element

-if lookup_context.exists?(slide.key.to_s, ['scenarios/slides'], true)
= render partial: "scenarios/slides/#{slide.key}"
25 changes: 25 additions & 0 deletions config/interface/input_elements/external_coupling_ccus.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
---
- key: external_coupling_molecules_other_utilisation_demand
step_value: 0.1
unit: Mton
position: 100
slide_key: supply_ccus_utilisation_storage
share_group: ''
interface_group: external_coupling_ccus_utilisation
coupling_icon: true
- key: external_coupling_energy_production_synthetic_kerosene_demand
step_value: 0.1
unit: PJ
position: 105
slide_key: supply_ccus_utilisation_storage
share_group: ''
interface_group: external_coupling_ccus_utilisation
coupling_icon: true
- key: external_coupling_energy_production_synthetic_methanol_demand
step_value: 0.1
unit: PJ
position: 110
slide_key: supply_ccus_utilisation_storage
share_group: ''
interface_group: external_coupling_ccus_utilisation
coupling_icon: true
Loading

0 comments on commit 61c30fa

Please sign in to comment.