Revert "Merge pull request #2969 from alphagov/revert-2956-progressively-enhance-folder-permissions"

This reverts commit 8266f3d65c, reversing
changes made to b2a38fe222.
This commit is contained in:
Tom Byers
2019-05-15 14:26:51 +01:00
parent 00e7ccadad
commit ccd09b9fd7
13 changed files with 850 additions and 22 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 321 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 26 20" width="26" height="20"><polygon fill="#DEE0E2" points="1,19.1 1,1 9.8,1 11.3,5 25,5 25,19.1"/><path fill="0B0C0C" d="M9.2,1.9l1,2.8l0.5,1.2H12h12.1v12.2H1.9v-11V5.2V1.9H9.2 M10.5,0h-0.2H0v5.2v1.9V20h26V4H12L10.5,0L10.5,0z"/></svg>

After

Width:  |  Height:  |  Size: 291 B

View File

@@ -0,0 +1,170 @@
(function (global) {
"use strict";
const GOVUK = global.GOVUK;
function Summary (module) {
this.module = module;
this.$el = module.$formGroup.find('.selection-summary');
this.fieldLabel = module.fieldLabel;
this.total = module.total;
this.addContent();
this.update(module.getSelection());
}
Summary.prototype.templates = {
all: (selection, total, field) => `All ${field}s`,
some: (selection, total, field) => `${selection} of ${total} ${field}s`,
none: (selection, total, field) => ({
"folder": "No folders (only templates outside a folder)",
"team member": "No team members (only you)"
}[field] || `No ${field}s`)
};
Summary.prototype.addContent = function() {
this.$text = $(`<p class="selection-summary__text" />`);
if (this.fieldLabel === 'folder') { this.$text.addClass('selection-summary__text--folders'); }
this.$el.append(this.$text);
};
Summary.prototype.update = function(selection) {
let template;
if (selection === this.total) {
template = 'all';
} else if (selection > 0) {
template = 'some';
} else {
template = 'none';
}
this.$text.html(this.templates[template](selection, this.total, this.fieldLabel));
};
Summary.prototype.bindEvents = function () {
// take summary out of tab order when focus moves
this.$el.on('blur', (e) => $(this).attr('tabindex', '-1'));
};
function Footer (module) {
this.module = module;
this.fieldLabel = module.fieldLabel;
this.fieldsetId = module.$fieldset.attr('id');
this.$el = this.getEl(this.module.expanded);
this.module.$formGroup.append(this.$el);
}
Footer.prototype.buttonContent = {
change: (fieldLabel) => `Choose ${fieldLabel}s`,
done: (fieldLabel) => `Done<span class="visuallyhidden"> choosing ${fieldLabel}s</span>`
};
Footer.prototype.getEl = function (expanded) {
const buttonState = expanded ? 'done' : 'change';
const buttonContent = this.buttonContent[buttonState](this.fieldLabel);
const stickyClass = expanded ? ' js-stick-at-bottom-when-scrolling' : '';
return $(`<div class="selection-footer${stickyClass}">
<button
class="button button-secondary"
aria-expanded="${expanded ? 'true' : 'false'}"
aria-controls="${this.fieldsetId}">
${buttonContent}
</button>
</div>`);
};
Footer.prototype.update = function (expanded) {
this.$el.remove();
this.$el = this.getEl(expanded);
this.module.$formGroup.append(this.$el);
// make footer sticky if expanded, clear up from it being sticky if not
GOVUK.stickAtBottomWhenScrolling.recalculate();
};
function CollapsibleCheckboxes () {}
CollapsibleCheckboxes.prototype._focusTextElement = ($el) => {
$el
.attr('tabindex', '-1')
.focus();
};
CollapsibleCheckboxes.prototype.start = function(component) {
this.$formGroup = $(component);
this.$fieldset = this.$formGroup.find('fieldset');
this.$checkboxes = this.$fieldset.find('input[type=checkbox]');
this.fieldLabel = this.$formGroup.data('fieldLabel');
this.total = this.$checkboxes.length;
this.legendText = this.$fieldset.find('legend').text().trim();
this.expanded = false;
this.addHeadingHideLegend();
// generate summary and footer
this.footer = new Footer(this);
this.summary = new Summary(this);
this.$fieldset.before(this.summary.$el);
// add custom classes
this.$formGroup.addClass('selection-wrapper');
this.$fieldset.addClass('selection-content');
// hide checkboxes
this.$fieldset.hide();
this.bindEvents();
};
CollapsibleCheckboxes.prototype.getSelection = function() { return this.$checkboxes.filter(':checked').length; };
CollapsibleCheckboxes.prototype.addHeadingHideLegend = function() {
const headingLevel = this.$formGroup.data('heading-level') || '2';
this.$heading = $(`<h${headingLevel} class="heading-small">${this.legendText}</h${headingLevel}>`);
this.$fieldset.before(this.$heading);
this.$fieldset.find('legend').addClass('visuallyhidden');
};
CollapsibleCheckboxes.prototype.expand = function(e) {
if (e !== undefined) { e.preventDefault(); }
if (!this.expanded) {
this.$fieldset.show();
this.expanded = true;
this.summary.update(this.getSelection());
this.footer.update(this.expanded);
}
// shift focus whether expanded or not
this._focusTextElement(this.$fieldset);
};
CollapsibleCheckboxes.prototype.collapse = function(e) {
if (e !== undefined) { e.preventDefault(); }
if (this.expanded) {
this.$fieldset.hide();
this.expanded = false;
this.summary.update(this.getSelection());
this.footer.update(this.expanded);
}
// shift focus whether expanded or not
this._focusTextElement(this.summary.$text);
};
CollapsibleCheckboxes.prototype.handleClick = function(e) {
if (this.expanded) {
this.collapse(e);
} else {
this.expand(e);
}
};
CollapsibleCheckboxes.prototype.handleSelection = function(e) {
this.summary.update(this.getSelection(), this.total, this.fieldLabel);
};
CollapsibleCheckboxes.prototype.bindEvents = function() {
const self = this;
this.$formGroup.on('click', '.button', this.handleClick.bind(this));
this.$checkboxes.on('click', this.handleSelection.bind(this));
this.summary.bindEvents(this);
};
GOVUK.Modules.CollapsibleCheckboxes = CollapsibleCheckboxes;
}(window));

View File

@@ -11,12 +11,11 @@
var $scrollArea = $el.closest('.sticky-scroll-area');
$scrollArea = $scrollArea.length ? $scrollArea : $el.parent();
scrollArea = $scrollArea.get(0);
this._els = [el];
this.edge = edge;
this.selector = selector;
this.node = scrollArea;
this.node = $scrollArea.get(0);
this.setEvents();
};
ScrollArea.prototype.addEl = function (el) {
@@ -38,7 +37,7 @@
};
ScrollArea.prototype.getFocusedDetails = {
forElement: function ($focusedElement) {
focused = {
var focused = {
'top': $focusedElement.offset().top,
'height': $focusedElement.outerHeight(),
'type': 'element'

View File

@@ -124,10 +124,20 @@ td {
.form-label {
margin-bottom: 5px;
&.heading-small {
@include bold-19();
}
}
.hint {
color: $secondary-text-colour;
.form-label + & {
display: block;
margin-top: -5px;
margin-bottom: 5px;
}
}
.list-bullet {

View File

@@ -1,3 +1,37 @@
.selection-summary {
.selection-summary__text {
@include core-19($tabular-numbers: true);
padding: 5px 0 0 0;
margin-bottom: $gutter / 2;
&:focus {
outline: none;
}
}
.selection-summary__text--folders {
padding: 10px 15px 5px 51px;
background-image: file-url('folder-black.svg');
background-repeat: no-repeat;
background-size: 39px auto;
background-position: 0px 4px;
@include ie-lte(8) {
background-image: file-url('folder-black.png');
}
}
// revert full-width button for smaller screens
.button {
display: inline-block;
width: auto;
position: relative;
top: 1px;
}
}
.checkboxes-nested {
margin-bottom: 10px;
@@ -42,3 +76,29 @@
}
}
.selection-content {
margin-bottom: ($gutter / 3) * 2;
.checkboxes-nested {
margin-bottom: 0;
}
}
.selection-footer {
clear: both;
.button-secondary {
// revert full-width button for smaller screens
display: inline-block;
width: auto;
}
}
// styles specific to the collapsible checkboxes module
.selection-wrapper {
fieldset:focus {
outline: none;
}
}

View File

@@ -19,13 +19,13 @@
{% endmacro %}
{% macro checkboxes_nested(field, child_map, hint=None, disable=[], option_hints={}, hide_legend=False) %}
{{ select_nested(field, child_map, hint, disable, option_hints, hide_legend, input="checkbox") }}
{% macro checkboxes_nested(field, child_map, hint=None, disable=[], option_hints={}, hide_legend=False, collapsible_opts={}, legend_style="text") %}
{{ select_nested(field, child_map, hint, disable, option_hints, hide_legend, collapsible_opts, legend_style, input="checkbox") }}
{% endmacro %}
{% macro checkboxes(field, hint=None, disable=[], option_hints={}, hide_legend=False) %}
{{ select(field, hint, disable, option_hints, hide_legend, input="checkbox") }}
{% macro checkboxes(field, hint=None, disable=[], option_hints={}, hide_legend=False, collapsible_opts={}) %}
{{ select(field, hint, disable, option_hints, hide_legend, collapsible_opts, input="checkbox") }}
{% endmacro %}

View File

@@ -1,6 +1,6 @@
{% macro select(field, hint=None, disable=[], option_hints={}, hide_legend=False, input="radio") %}
{% macro select(field, hint=None, disable=[], option_hints={}, hide_legend=False, collapsible_opts={}, legend_style="text", input="radio") %}
{% call select_wrapper(
field, hint, disable, option_hints, hide_legend
field, hint, disable, option_hints, hide_legend, collapsible_opts, legend_style
) %}
{% for option in field %}
{{ select_input(option, disable, option_hints, input=input) }}
@@ -24,9 +24,9 @@
{% endmacro %}
{% macro select_nested(field, child_map, hint=None, disable=[], option_hints={}, hide_legend=False, input="radio") %}
{% macro select_nested(field, child_map, hint=None, disable=[], option_hints={}, hide_legend=False, collapsible_opts={}, legend_style="text", input="radio") %}
{% call select_wrapper(
field, hint, disable, option_hints, hide_legend
field, hint, disable, option_hints, hide_legend, collapsible_opts, legend_style
) %}
<div class="{{ "radios" if input == "radio" else "checkboxes" }}-nested">
{{ select_list(child_map[None], child_map, disable, option_hints, input=input) }}
@@ -35,10 +35,14 @@
{% endmacro %}
{% macro select_wrapper(field, hint=None, disable=[], option_hints={}, hide_legend=False) %}
<div class="form-group {% if field.errors %} form-group-error{% endif %}">
<fieldset>
<legend class="{{ 'form-label' if not hide_legend else '' }}">
{% macro select_wrapper(field, hint=None, disable=[], option_hints={}, hide_legend=False, collapsible_opts={}, legend_style="text") %}
{% set is_collapsible = collapsible_opts|length %}
<div class="form-group {% if field.errors %} form-group-error{% endif %}"{% if is_collapsible %} data-module="collapsible-checkboxes"{% if collapsible_opts.field %} data-field-label="{{ collapsible_opts.field }}"{% endif %}{% endif %}>
{% if is_collapsible %}
<div class="selection-summary" role="region" aria-live="polite"></div>
{% endif %}
<fieldset id="{{ field.id }}">
<legend class="{{ 'form-label' if not hide_legend else '' }}{% if legend_style != 'text' %} {{ legend_style }}{% endif %}">
{% if hide_legend %}<span class="visually-hidden">{% endif %}
{{ field.label.text|safe }}
{% if hide_legend %}</span>{% endif %}

View File

@@ -2,20 +2,19 @@
{% from "components/radios.html" import radio, radios, conditional_radio_panel %}
<fieldset class="form-group">
<legend class="form-label">
<legend class="form-label heading-small">
Permissions
</legend>
<span class="hint">
All team members can see sent messages.
</span>
{% for field in form.permissions_fields %}
{{ checkbox(field) }}
{% endfor %}
</fieldset>
<p class="bottom-gutter">
All team members can see sent messages.
</p>
{% if current_service.has_permission("edit_folder_permissions") and form.folder_permissions.all_template_folders %}
{{ checkboxes_nested(form.folder_permissions, form.folder_permissions.children()) }}
{{ checkboxes_nested(form.folder_permissions, form.folder_permissions.children(), hide_legend=True, collapsible_opts={ 'field': 'folder' }) }}
{% endif %}
{% if service_has_email_auth %}

View File

@@ -27,7 +27,7 @@
{{ textbox(form.name, width='1-1') }}
{% if current_service.has_permission("edit_folder_permissions") %}
{% if current_user.has_permissions("manage_service") and form.users_with_permission.all_service_users %}
{{ checkboxes(form.users_with_permission) }}
{{ checkboxes(form.users_with_permission, collapsible_opts={ 'field': 'team member' }) }}
{% endif %}
{% endif %}