Release Management - launchdarkly/SupportService GitHub Wiki
This is a great implementation of a front end feature flag that can be accessed from the home page. When enabled, it will display widgets for comments, tasks, and tickets. It will dynamically update the page and show the widgets to the user, without requiring them to refresh the page.
You can try this out with the following steps.
- In LaunchDarkly, create a new boolean feature flag called 'display-map-view'
- Under the feature flag targeting rules select "false" as the variation to serve when targeting is turned off.
- Turn on targeting. You will now see that the widgets being displayed on the home page.
- Turn off targeting. You will now see that the widgets are not being displayed on the home page.
This feature flag has been implemented using both our python SDK + our Javascript SDK. As part of the setup, we are bootstrapping the values from the backend to the front end. This is implemented across the following files:
base.html
- This where we are initializing the Javascript SDK for the given user. The initial set of feature flag values are bootstrapped from the Python SDK (being passed in from jinja).
var ldclient = LDClient.initialize("{{ LD_FRONTEND_KEY }}", {{ user | safe }}, options = {
bootstrap: {{ all_flags | safe }}
});
index.html
- This is the HTML that is dynamically appearing/disappearing based on the state of the feature flag. When the page initially loads, this section is not being displayed as indicated by the attribute style="display:none"
<div id="widgets" class="row" style="display:none">
partials/footer.html
- The footer is where the logic is taking place to control when the widgets appear/disappear. We are grabbing the div element for the widgets and tying it to the variable displayWidget
. The variable renderButton
is then responsible for calling the function to determine whether or not the widgets are being displayed. The way we trigger the function is by subscribing to feature flag changes so that when an update to the flag has been made, renderButton
is called.
var displayWidget = document.getElementById('widgets');
var renderButton = function() {
var showFeature = ldclient.variation("show-widgets", false);
if (showFeature) {
displayWidget.style.display = "block";
} else {
displayWidget.style.display = "none";
}
}
...
ldclient.on('change', function() {
renderButton();
});
This feature flag will change the layout of the site from a light theme to a dark theme. I usually like talking about this in the context of releasing new functionality to beta testers, by creating a rule specifically targeting any user that the customer attribute user_type
set to Beta
. Once enabled, the drop down in the user section of the navbar, will then display a new option for dark theme.
You can try this out with the following steps.
- In LaunchDarkly, create a new boolean feature flag called 'dark-theme'
- Under the feature flag targeting rules select "false" as the variation to serve when targeting is turned off.
- Turn on targeting. In the navbar, select the user icon and you will see an option for dark theme enabled. Selecting it will change the site layout.
- Turn off targeting. In the navbar, select the user icon and you will notice that there is no option for dark theme (note this only disables it while you are currently in the light theme).
This feature flag is a using a combination of routes and the user model in order properly display the expected UI. In particular, we are checking to see what the value is set for the column user_type
. If its set to Beta
then we are updating the set_path
and changing where the user is navigating to. Here is a breakdown of the different files being used:
routes.py
- There are several moving pieces here to determine which set of html files to direct the user down. The index route is checking to see if the url requesting it is passing an argument and if that is the case then it is calling the method updateTheme
to change the set_path
column. The set_path
column ultimately determines which route to take the user down. If it is set to 'default', then we show the light theme and if it is set to 'beta' then we show the dark theme. This is indicated by the set_theme variable that we define in index and subsequently pass via the render_template. We are also using the feature flag beta_features to determine whether we show the button or not.
def index():
theme = request.args.get("theme")
if theme:
updateTheme(theme)
set_theme = '{0}/index.html'.format(current_user.set_path)
beta_features = ldclient.get().variation('dark-theme', current_user.get_ld_user(), False)
return render_template(set_theme, title='Home', display_widgets=display_widgets,
all_flags=all_flags, show_beta=beta_features, LD_FRONTEND_KEY=LD_FRONTEND_KEY, user=user)
def updateTheme(theme):
if theme == "dark":
current_user.set_path = 'beta'
else:
current_user.set_path = 'default'
db.session.commit()
nav.html
- Here we are checking to see if show_beta is set to true and if that is the case then we will display the button for the user. Else, the user will not see the option.
{% if show_beta %}
<li><a href="{{ url_for('core.index', theme='dark') }}"><i class="fa fa-adjust fa-fw"></i> Dark Theme</a>
</li>
{% endif %}