Skip to content

Commit

Permalink
Merge c938a43 into b6d1dba
Browse files Browse the repository at this point in the history
  • Loading branch information
willbarton committed Jun 20, 2019
2 parents b6d1dba + c938a43 commit 1eab958
Show file tree
Hide file tree
Showing 23 changed files with 719 additions and 124 deletions.
19 changes: 12 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@
[![Build Status](https://travis-ci.org/cfpb/wagtail-flags.svg?branch=master)](https://travis-ci.org/cfpb/wagtail-flags)
[![Coverage Status](https://coveralls.io/repos/github/cfpb/wagtail-flags/badge.svg?branch=master)](https://coveralls.io/github/cfpb/wagtail-flags?branch=master)

Feature flags allow you to toggle functionality in the Wagtail based on configurable conditions.
Feature flags allow you to toggle functionality based on configurable conditions.

Wagtail-Flags adds a Wagtail admin UI and Wagtail Site-based condition on top of [Django-Flags](https://github.com/cfpb/django-flags). For a more complete overview of feature flags and how to use them, please see the [Django-Flags documentation](https://cfpb.github.io/django-flags).

![Feature flags in the Wagtail admin](https://raw.githubusercontent.com/cfpb/wagtail-flags/master/screenshot_list.png)
![Feature flags in the Wagtail admin](wagtailflags.gif)

- [Dependencies](#dependencies)
- [Installation](#installation)
Expand All @@ -27,9 +27,10 @@ Wagtail-Flags adds a Wagtail admin UI and Wagtail Site-based condition on top of

## Installation

1. Install wagtail-flags:
1. Install Django-Flags and Wagtail-Flags:

```shell
pip install django-flags
pip install wagtail-flags
```

Expand All @@ -52,7 +53,7 @@ First, define the flag in Django `settings.py`:

```python
FLAGS = {
'MY_FLAG': {}
'MY_FLAG': []
}
```

Expand Down Expand Up @@ -80,9 +81,9 @@ urlpatterns = [
]
```

Finally, add conditions for the flag in the Wagtail admin under "Settings", "Flags":
Finally, add conditions for the flag in the Wagtail admin under "Settings", "Flags", "MY_FLAG":

![Creating conditions in the Wagtail admin](https://raw.githubusercontent.com/cfpb/wagtail-flags/master/screenshot_create.png)
![Creating conditions in the Wagtail admin](screenshot_create.png)

## Extended conditions

Expand All @@ -93,7 +94,11 @@ Wagtail-Flags adds the following conditions to Django-Flags:
Allows a flag to be enabled for a Wagtail site that matches the hostname and port in the condition value.

```python
FLAGS = {'MY_FLAG': {'site': 'staging.mysite.com'}}
FLAGS = {
'MY_FLAG': [
{'condition': 'site', 'value': 'staging.mysite.com'}
],
}
```

## Getting help
Expand Down
Binary file modified screenshot_create.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file removed screenshot_list.png
Binary file not shown.
5 changes: 2 additions & 3 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
long_description = open('README.md', 'r').read()

install_requires = [
'wagtail>=1.10,<2.5',
'django-flags>=4.0,<5.0'
'wagtail>=1.13,<2.5',
'django-flags>=4.2,<5.0'
]

testing_extras = [
Expand All @@ -31,7 +31,6 @@
classifiers=[
'Framework :: Django',
'Framework :: Django :: 1.11',
'Framework :: Django :: 1.8',
'Framework :: Django :: 2.0',
'Framework :: Django :: 2.1',
'Framework :: Django :: 2.2',
Expand Down
Binary file added wagtailflags.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
65 changes: 65 additions & 0 deletions wagtailflags/forms.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
from django import forms

from flags.conditions import get_conditions
from flags.models import FlagState
from flags.sources import get_flags


class NewFlagForm(forms.ModelForm):
name = forms.CharField(
label='Name',
required=True
)

def clean_name(self):
name = self.cleaned_data['name']
if name in get_flags():
raise forms.ValidationError(
"Flag named {} already exists".format(name)
)
return name

def save(self, commit=True):
obj = super(NewFlagForm, self).save(commit=False)
obj.condition = 'boolean'
obj.value = 'False'
obj.required = False
obj.save()
return obj

class Meta:
model = FlagState
fields = ('name', )


class FlagStateForm(forms.ModelForm):
name = forms.CharField(
label='Flag',
required=True,
disabled=True,
)
condition = forms.ChoiceField(
label='Condition name',
required=True
)
value = forms.CharField(
label='Expected value',
required=True
)
required = forms.BooleanField(
label='Required',
required=False,
help_text=('All conditions marked "required" must be met to enable '
'the flag'),
)

def __init__(self, *args, **kwargs):
super(FlagStateForm, self).__init__(*args, **kwargs)

self.fields['condition'].choices = [
(c, c) for c in sorted(get_conditions()) if c != 'boolean'
]

class Meta:
model = FlagState
fields = ('name', 'condition', 'value', 'required')
6 changes: 6 additions & 0 deletions wagtailflags/static/wagtailflags/css/wagtailflags.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
.flags-breadcrumb {
margin-left: 0;
}
section.flag {
margin-top: 4em;
}
8 changes: 8 additions & 0 deletions wagtailflags/templates/wagtailflags/base.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{% extends "wagtailadmin/base.html" %}

<ul class="breadcrumb">
<li class="home"><a href="#" class="icon icon-home text-replace">Home</a></li>
<li><a href="#">Various</a></li>
<li><a href="#">Subpages</a></li>
<li><a href="#">There is a max length of this many</a></li>
</ul>
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
{% extends "wagtailadmin/base.html" %}
{% load i18n %}
{% block titletag %}{% trans "Create a flag condition" as flags_str %}{% endblock %}
{% block titletag %}Create a flag{% endblock %}

{% block content %}
{% trans "Create a flag condition" as flags_str %}
{% include "wagtailadmin/shared/header.html" with title=flags_str icon="tag" %}
{% include "wagtailadmin/shared/header.html" with title=flag.name icon="tag" %}

<h2 class="nice-padding">New flag condition:</h2>
<form class="nice-padding" method="POST" action="{% url 'wagtailflags:create' %}">
<h2 class="nice-padding">
Create a flag
</h2>

<form class="nice-padding" method="POST" action="{% url 'wagtailflags:create_flag' %}">
{% csrf_token %}
<ul class="fields">
<li class="actions">
Expand All @@ -28,8 +30,8 @@ <h2 class="nice-padding">New flag condition:</h2>
{% endfor %}
</li>
<li class="actions">
<input class="button action-save button-longrunning" type="submit" value="Save new condition" />
<a class="button bicolor icon icon-cog" href="{% url 'wagtailflags:list' %}">Back to flag conditions…</a>
<input class="button action-save button-longrunning" type="submit" value="Save flag" />
<a class="button bicolor icon icon-cog" href="{% url 'wagtailflags:list' %}">Back to flags</a>
</li>
</ul>
</form>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,22 @@
{% extends "wagtailadmin/base.html" %}
{% load i18n %}
{% load i18n feature_flags %}
{% block titletag %}{% trans "Delete" as delete_str %}: {{ flag_id }}{% endblock %}

{% block content %}
{% trans "Delete flag condition:" as delete_str %}
{% include "wagtailadmin/shared/header.html" with title=delete_str subtitle=state_str %}
{% include "wagtailadmin/shared/header.html" with title=delete_str subtitle=condition_str %}
{% flag_enabled 'WAGTAILFLAGS_ADMIN_BIG_LIST' as big_list_flag %}

<form class="nice-padding" method="POST" action="{% url 'wagtailflags:delete' state_id %}">
<form class="nice-padding" method="POST" action="{% url 'wagtailflags:delete_condition' flag.name condition_pk %}">
{% csrf_token %}

<p>Are you sure you want to delete this flag condition?</p>
<input type="submit" value="Yes, delete it" class="button serious">
<a href="{% url 'wagtailflags:list' %}" class="button button-secondary">No, don't delete it</a>

{% if big_list_flag %}
<a href="{% url 'wagtailflags:list' %}#{{ flag.name }}" class="button button-secondary">No, don't delete it</a>
{% else %}
<a href="{% url 'wagtailflags:flag_index' flag.name %}" class="button button-secondary">No, don't delete it</a>
{% endif %}
</form>
{% endblock %}
49 changes: 49 additions & 0 deletions wagtailflags/templates/wagtailflags/flags/edit_condition.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
{% extends "wagtailadmin/base.html" %}
{% load i18n feature_flags %}
{% block titletag %}{% if form.instance %}Edit {{ form.instance.condition }}{% else %}Create condition{% endif %}{% endblock %}

{% block content %}
{% include "wagtailadmin/shared/header.html" with title=flag.name icon="tag" %}
{% flag_enabled 'WAGTAILFLAGS_ADMIN_BIG_LIST' as big_list_flag %}

<h2 class="nice-padding">
{% if form.instance %}Edit {{ form.instance.condition }}{% else %}Create condition{% endif %}
</h2>

{{ form.errors }}

{% if condition_pk %}
<form class="nice-padding" method="POST" action="{% url 'wagtailflags:edit_condition' flag.name condition_pk %}">
{% else %}
<form class="nice-padding" method="POST" action="{% url 'wagtailflags:create_condition' flag.name %}">
{% endif %}
{% csrf_token %}
<ul class="fields">
<li class="actions">
{% for field in form %}
{% if field.errors %}
<div class="help-block help-critical" style="margin-top:0;">
{{ field.errors }}
</div>
{% endif %}
<label>{{ field.label }}</label>
<div class="field-content">
<div class="input">
{{ field }}
<span></span>
</div>
<p class="help"></p>
</div>
{% endfor %}
</li>
<li class="actions">
<input class="button action-save button-longrunning" type="submit" value="Save condition" />
{% if big_list_flag %}
<a class="button bicolor icon icon-cog" href="{% url 'wagtailflags:list' %}#{{ flag.name }}">Back to {{ flag.name }}</a>
{% else %}
<a class="button bicolor icon icon-cog" href="{% url 'wagtailflags:flag_index' flag.name %}">Back to {{ flag.name }}</a>
{% endif %}
</li>
</ul>
</form>
{% endblock %}
13 changes: 13 additions & 0 deletions wagtailflags/templates/wagtailflags/flags/flag_index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{% extends "wagtailadmin/base.html" %}
{% load i18n %}
{% block titletag %}{% trans "Flags" %}: {{ flag.name }}{% endblock %}

{% block content %}
{% include "wagtailflags/includes/header.html" with title=flag.name icon="tag" %}

<div class="nice-padding">

{% include "wagtailflags/includes/flag_index.html" with flag=flag %}

</div>
{% endblock %}
63 changes: 63 additions & 0 deletions wagtailflags/templates/wagtailflags/includes/flag_index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
{% load i18n %}
{% load wagtailflags_admin %}
{% load i18n feature_flags flags_debug wagtailflags_admin %}

<section class="flag" id="{{ flag.name }}">
<div class="help-block help-info">
<p>{{ flag|state_str }}</p>
</div>

{% with flag|conditions_without_bool as conditions %}
{% if conditions|length > 0 %}
<table class="listing">
<thead>
<tr>
<th>Condition</th>
<th>Value</th>
<th></th>
</tr>
</thead>
<tbody>
{% for condition in conditions %}
<tr>
<td>
<b>{{ condition.condition }}</b>
</td>
<td>
{{ condition.value }}
</td>
<td>
{% if condition.required %}
Required
{% else %}
Optional
{% endif %}
</td>
<td>
{% if condition.obj %}
<div class="button-group">
<a href="{% url 'wagtailflags:edit_condition' flag.name condition.obj.pk %}" class="button button-small button-secondary">Edit</a>
<a href="{% url 'wagtailflags:delete_condition' flag.name condition.obj.pk %}" class="button button-small no">Delete</a>
</div>
{% endif %}
</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endif %}
{% endwith %}

{% if flag|enablable or flag|disablable %}
<a href="{% url 'wagtailflags:flag_index' flag.name %}?{% if flag|bool_enabled %}disable{% else %}enable{% endif %}"
class="button button-secondary{% if flag|bool_enabled %} no{% endif %}">
{% if flag|bool_enabled %}Disable{% else %}Enable{% endif %} {{ flag.name }}
{% if flag|required_conditions_without_bool|length > 0 %}
when required conditions are met
{% else %}
for all requests
{% endif %}
</a>
{% endif %}
<a href="{% url 'wagtailflags:create_condition' flag.name %}" class="button bicolor icon icon-plus">Add a condition</a>
</section>
9 changes: 9 additions & 0 deletions wagtailflags/templates/wagtailflags/includes/header.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{% if flag %}
<ul class="breadcrumb flags-breadcrumb">
<li><a href="{% url 'wagtailflags:list' %}">Flags</a></li>
<li>{{ title }}</li>
</ul>
{% include "wagtailadmin/shared/header.html" with title=title icon=icon %}
{% else %}
{% include "wagtailadmin/shared/header.html" with title=title icon=icon add_text='Add flag' add_link='wagtailflags:create_flag' %}
{% endif %}
Loading

0 comments on commit 1eab958

Please sign in to comment.