Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Feature Toggle #23633

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
80 changes: 80 additions & 0 deletions app/models/reader_preferences.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
# frozen_string_literal: true
class ReaderPreferences

def self.get(preference)
preference_name = preference.to_s.upcase
value = client.get(preference_name) || ENV[preference_name]

if value
return value.to_i
end

"#{preference_name} is not in the list of allowed preferences.. #{valid_preferences}"
end

def self.set(preference, new_value)
preference_name = preference.to_s.upcase

current_value = client.get(preference_name) || ENV[preference_name]

if current_value
client.set(preference_name, new_value.to_s)
"#{preference_name} set to #{new_value}"
else
"#{preference_name} is not in the list of allowed preferences.. #{valid_preferences}"
end
end

def self.delete(preference)
preference_name = preference.to_s.upcase

current_value = client.get(preference_name)

if current_value
client.del preference_name

"#{preference_name} was reset to default value #{ENV[preference_name]}"
else
"#{preference_name} is not set to a custom value"
end
end

def self.client
# Use separate Redis namespace for test to avoid conflicts between test and dev environments
@cache_namespace ||= Rails.env.test? ? :reader_preferences_test : :reader_preferences
@client ||= Redis::Namespace.new(@cache_namespace, redis: redis)
end

def self.redis
@redis ||= Redis.new(url: Rails.application.secrets.redis_url_cache)
end

# Default values are stored as ENV enviroment dependent values in the file
# appeals-deployment/ansible/roles/caseflow-certification/defaults/main.yml
# Example:
# http_env_specific_environment:
# prod:
# READER_DELAY_BEFORE_PROGRESS_BAR: 1000
# READER_SHOW_PROGRESS_BAR_THRESHOLD: 3000

# prodtest:
# READER_DELAY_BEFORE_PROGRESS_BAR: 1000
# READER_SHOW_PROGRESS_BAR_THRESHOLD: 3000

# preprod:
# READER_DELAY_BEFORE_PROGRESS_BAR: 1000
# READER_SHOW_PROGRESS_BAR_THRESHOLD: 3000

# uat:
# READER_DELAY_BEFORE_PROGRESS_BAR: 1000
# READER_SHOW_PROGRESS_BAR_THRESHOLD: 3000

def self.bandwidth_warning_enabled?
max_file_wait_time = ENV.fetch("MAX_FILE_WAIT_TIME", nil)
max_file_wait_time.present? && max_file_wait_time.to_i > 0
end

def self.valid_preferences
@valid_preferences ||= ENV.select { |feature, value| feature.include?("READER") }.keys
end
end
9 changes: 8 additions & 1 deletion app/views/reader/appeal/index.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
featureToggles: {
interfaceVersion2: FeatureToggle.enabled?(:interface_version_2, user: current_user),
bandwidthBanner: FeatureToggle.enabled?(:bandwidth_banner, user: current_user),
warningIconAndBanner: FeatureToggle.enabled?(:warning_icon_and_banner, user: current_user),
windowSlider: FeatureToggle.enabled?(:window_slider, user: current_user),
readerSelectorsMemoized: FeatureToggle.enabled?(:bulk_upload_documents, user: current_user),
readerGetDocumentLogging: FeatureToggle.enabled?(:reader_get_document_logging, user: current_user),
Expand All @@ -25,7 +26,13 @@
pdfPageRenderTimeInMs: FeatureToggle.enabled?(:pdf_page_render_time_in_ms, user: current_user),
prefetchDisabled: FeatureToggle.enabled?(:prefetch_disabled, user: current_user),
readerSearchImprovements: FeatureToggle.enabled?(:reader_search_improvements, user: current_user),
readerPrototype: FeatureToggle.enabled?(:reader_prototype, user: current_user)
readerPrototype: FeatureToggle.enabled?(:reader_prototype, user: current_user),
readerProgressBar: FeatureToggle.enabled?(:reader_progress_bar, user: current_user),
},
readerPreferences: {
delayBeforeProgressBar: ReaderPreferences.get(:delay_before_progress_bar),
showProgressBarThreshold: ReaderPreferences.get(:show_progress_bar_threshold),
maximumFileWaitTime: ReaderPreferences.get(:maximum_file_wait_time),
},
buildDate: build_date
}) %>
Expand Down
7 changes: 7 additions & 0 deletions client/app/components/common/actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,13 @@ export const setScheduledHearing = (payload) => ({
payload,
});

export const setFeatureToggles = (toggles) => ({
type: ACTIONS.SET_FEATURE_TOGGLES,
payload: {
toggles
},
});

export const fetchScheduledHearings = (hearingDay) => (dispatch) => {
// Dispatch the action to set the pending state for the hearing time
dispatch({ type: ACTIONS.REQUEST_SCHEDULED_HEARINGS });
Expand Down
12 changes: 12 additions & 0 deletions client/app/components/common/reducers.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { update } from '../../util/ReducerUtil';
export const initialState = {
scheduledHearingsList: [],
fetchingHearings: false,
isWarningIconAndBannerEnabled: false,
dropdowns: {
judges: {},
hearingCoordinators: {},
Expand Down Expand Up @@ -188,4 +189,15 @@ const commonComponentsReducer = (state = initialState, action = {}) => {
}
};

const featureTogglesReducer = (state = initialState, action) => {
switch (action.type) {
case ACTIONS.SET_FEATURE_TOGGLES:
return {
...state,
...action.payload,
};
default:
return state;
}
};
export default commonComponentsReducer;
49 changes: 49 additions & 0 deletions client/app/components/icons/SizeWarningIcon.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import React from 'react';
import PropTypes from 'prop-types';
import { ICON_SIZES } from '../../constants/AppConstants';

export const SizeWarningIcon = (props) => {
const { size, className, isWarningIconAndBannerEnabled } = props;

if (!isWarningIconAndBannerEnabled) {
return null;
}

return ( <svg aria-title="Large File Warning"
title="Large File Warning" xmlns="http://www.w3.org/2000/svg"
height={size}
viewBox="0 0 512 512" className={className}>
<path d="M256 32c14.2 0 27.3 7.5 34.5 19.8l216
368c7.3 12.4 7.3 27.7 .2 40.1S486.3 480 472 480L40
480c-14.3 0-27.6-7.7-34.7-20.1s-7-27.8 .2-40.1l216-368C228.7
39.5 241.8 32 256 32zm0 128c-13.3 0-24 10.7-24 24l0
112c0 13.3 10.7 24 24 24s24-10.7 24-24l0-112c0-13.3-10.7-24-24-24zm32
224a32 32 0 1 0 -64 0 32 32 0 1 0 64 0z" />
</svg>
);
};


SizeWarningIcon.propTypes = {

/**
Sets height of the component, width is set automatically by the svg viewbox property.
Default height is 'ICON_SIZES.MEDIUM'.
*/
size: PropTypes.number,

/**
Adds class to the component. Default value is ''.
*/
className: PropTypes.string,

/**
Enables or disables the Size Warning Icon based on the feature toggle.
*/
isWarningIconAndBannerEnabled: PropTypes.bool.isRequired
};

SizeWarningIcon.defaultProps = {
size: ICON_SIZES.MEDIUM,
className: ''
};
12 changes: 11 additions & 1 deletion client/app/reader/BandwidthAlert.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import Alert from '../components/Alert';
import { css } from 'glamor';
import { storeMetrics } from '../util/Metrics';
import uuid from 'uuid';
import PropTypes from 'prop-types';

// variables being defined are in mbps
const bandwidthThreshold = 1.5;
Expand All @@ -20,7 +21,7 @@ class BandwidthAlert extends React.Component {
}

componentDidMount() {
if ('connection' in navigator) {
if (this.props.isWarningIconAndBannerEnabled && 'connection' in navigator) {
this.updateConnectionInfo();
}
}
Expand All @@ -42,6 +43,11 @@ class BandwidthAlert extends React.Component {
};

render() {
const { isWarningIconAndBannerEnabled } = this.props;

if (!isWarningIconAndBannerEnabled) {
return null;
}

if (this.state.displayBandwidthAlert) {
return (
Expand All @@ -59,4 +65,8 @@ class BandwidthAlert extends React.Component {
}
}

BandwidthAlert.propTypes = {
isWarningIconAndBannerEnabled: PropTypes.bool.isRequired
};

export default BandwidthAlert;
Loading
Loading