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

Support rendering of service manual document types #2583

Merged
merged 13 commits into from
Feb 8, 2023
Merged
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions app/assets/images/service-manual/icons-plus-minus.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added app/assets/images/service-manual/mail-icon-x2.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 added app/assets/images/service-manual/placeholder.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added app/assets/images/service-manual/search-button.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
156 changes: 156 additions & 0 deletions app/assets/javascripts/modules/highlight-active-section-heading.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
window.GOVUK = window.GOVUK || {}
window.GOVUK.Modules = window.GOVUK.Modules || {};

(function (Modules) {
function HighlightActiveSectionHeading ($module) {
this.$module = $module
this._hasResized = true
this._hasScrolled = true
this._interval = 50
this.anchorIDs = []
}

HighlightActiveSectionHeading.prototype.init = function () {
window.addEventListener('resize', function () { this._hasResized = true }.bind(this))
window.addEventListener('scroll', function () { this._hasScrolled = true }.bind(this))

setInterval(this.checkResize.bind(this), this._interval)
setInterval(this.checkScroll.bind(this), this._interval)

this.anchors = this.$module.querySelectorAll('.js-page-contents a')
this.getAnchors()

this.checkResize()
this.checkScroll()
}

HighlightActiveSectionHeading.prototype.checkResize = function () {
if (this._hasResized) {
this._hasResized = false
this._hasScrolled = true
}
}

HighlightActiveSectionHeading.prototype.checkScroll = function () {
if (this._hasScrolled) {
this._hasScrolled = false
var windowDimensions = this.getWindowDimensions()
if (windowDimensions.width <= 768) {
this.removeActiveItem()
} else {
this.updateActiveNavItem()
}
}
}

HighlightActiveSectionHeading.prototype.getWindowDimensions = function () {
return {
height: window.innerHeight,
width: window.innerWidth
}
}

HighlightActiveSectionHeading.prototype.getAnchors = function () {
for (var i = 0; i < this.anchors.length; i++) {
var anchorID = this.anchors[i].getAttribute('href')
// e.g. anchorIDs['#meeting-the-digital-service-standard', '#understand-your-users', '#research-continually']
this.anchorIDs.push(anchorID)
}
}

HighlightActiveSectionHeading.prototype.updateActiveNavItem = function () {
var windowVerticalPosition = this.getWindowPositions()
var footerPosition = this.getFooterPosition()

for (var i = 0; i < this.anchors.length; i++) {
var theID = this.anchorIDs[i]
var theNextID = this.anchorIDs[i + 1]

var $theID = document.getElementById(theID.substring(1)) // remove the # at the start
var $theNextID = theNextID ? document.getElementById(theNextID.substring(1)) : null // remove the # at the start

var headingPosition = this.getHeadingPosition($theID)
if (!headingPosition) {
return
}

headingPosition = headingPosition - 53 // fix the offset from top of page

if (theNextID) {
var nextHeadingPosition = this.getNextHeadingPosition($theNextID)
}

var distanceBetweenHeadings = this.getDistanceBetweenHeadings(headingPosition, nextHeadingPosition)
var isPastHeading

if (distanceBetweenHeadings) {
isPastHeading = (windowVerticalPosition >= headingPosition && windowVerticalPosition < (headingPosition + distanceBetweenHeadings))
} else {
// when distanceBetweenHeadings is false (as there isn't a next heading)
isPastHeading = (windowVerticalPosition >= headingPosition && windowVerticalPosition < footerPosition)
}

if (isPastHeading) {
this.setActiveItem(theID)
}
}
}

HighlightActiveSectionHeading.prototype.getFooterPosition = function () {
var footer = document.querySelector('.govuk-footer')
if (footer) {
return this.getElementPosition(footer)
}
}

// these two functions call getElementPosition because the test needs to individually
// override them - otherwise we could combine these four functions into one
HighlightActiveSectionHeading.prototype.getHeadingPosition = function (element) {
return this.getElementPosition(element)
}

HighlightActiveSectionHeading.prototype.getNextHeadingPosition = function (element) {
return this.getHeadingPosition(element)
}

HighlightActiveSectionHeading.prototype.getElementPosition = function (element) {
if (element) {
var rect = element.getBoundingClientRect()
var offset = {
top: rect.top + window.scrollY,
left: rect.left + window.scrollX
}
return offset.top
}
}

HighlightActiveSectionHeading.prototype.getDistanceBetweenHeadings = function (headingPosition, nextHeadingPosition) {
var distanceBetweenHeadings = (nextHeadingPosition - headingPosition)
return distanceBetweenHeadings
}

HighlightActiveSectionHeading.prototype.setActiveItem = function (theID) {
for (var i = 0; i < this.anchors.length; i++) {
var href = this.anchors[i].getAttribute('href')
if (href === theID) {
this.anchors[i].classList.add('active')
} else {
this.anchors[i].classList.remove('active')
}
}
}

HighlightActiveSectionHeading.prototype.removeActiveItem = function () {
for (var i = 0; i < this.anchors.length; i++) {
this.anchors[i].classList.remove('active')
}
}

HighlightActiveSectionHeading.prototype.getWindowPositions = function () {
var doc = document.documentElement
var top = (window.pageYOffset || doc.scrollTop) - (doc.clientTop || 0)
return top
}

Modules.HighlightActiveSectionHeading = HighlightActiveSectionHeading
})(window.GOVUK.Modules)
18 changes: 17 additions & 1 deletion app/assets/stylesheets/application.scss
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ $govuk-include-default-font-face: false;

// Components from govuk_publishing_components gem
@import "govuk_publishing_components/govuk_frontend_support";

@import "govuk_publishing_components/components/accordion";
@import "govuk_publishing_components/components/attachment";
@import "govuk_publishing_components/components/back-link";
Expand Down Expand Up @@ -62,6 +61,22 @@ $govuk-include-default-font-face: false;
@import "helpers/publisher-metadata-with-logo";
@import "helpers/attachments";
@import "helpers/sticky-element-container";
@import "helpers/full-width";

// modules for service-manual pages
@import "modules/change-history";
@import "modules/collection";
@import "modules/community-contact";
@import "modules/govspeak-wrapper";
@import "modules/hero";
@import "modules/notice";
@import "modules/page-contents";
@import "modules/page-header";
@import "modules/panel";
@import "modules/related-content";
@import "modules/service-standard-point";
@import "modules/sticky";
@import "modules/typography";

// Components from this application
@import "components/*";
Expand All @@ -86,6 +101,7 @@ $govuk-include-default-font-face: false;
@import "views/corporate-information-page";
@import "views/travel-advice";
@import "views/contact";
@import "views/service_manual_guide";
@import "views/specialist-document";
@import "views/answer";
@import "views/help-page";
Expand Down
11 changes: 11 additions & 0 deletions app/assets/stylesheets/helpers/_full-width.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
.app-full-width {
#global-header-bar { // stylelint-disable-line selector-max-id
display: none;
}
}

// stylelint-disable declaration-no-important
.app-\!-full-width-override {
margin: auto !important;
max-width: none !important;
}
22 changes: 22 additions & 0 deletions app/assets/stylesheets/mixins/_margins.scss
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,25 @@
.responsive-bottom-margin {
@include responsive-bottom-margin;
}

// Service Manuals
@mixin gutter-bottom-margin {
margin-bottom: govuk-spacing(6);
}

@mixin gutter-top-margin {
margin-top: govuk-spacing(6);
}

@mixin gutter-vertical-margins {
@include gutter-bottom-margin;
@include gutter-top-margin;
}

@mixin gutter-bottom-margin-to-double {
margin-bottom: govuk-spacing(3);

@include govuk-media-query($from: tablet) {
margin-bottom: govuk-spacing(9);
}
}
11 changes: 11 additions & 0 deletions app/assets/stylesheets/modules/_change-history.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
.app-change-history__latest-change {
dd {
margin: 0;
padding: 0;
}
}

.app-change-history__change-note {
color: $govuk-secondary-text-colour;
white-space: pre-line;
}
19 changes: 19 additions & 0 deletions app/assets/stylesheets/modules/_collection.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
.app-collection {
border-bottom: 1px solid $govuk-border-colour;
margin-bottom: govuk-spacing(3);
padding-bottom: govuk-spacing(3);

@include govuk-media-query($from: tablet) {
margin-bottom: govuk-spacing(9);
padding-bottom: govuk-spacing(6);
}

&:last-child {
border-bottom: none;
margin-bottom: 0;
}

&__description {
color: $govuk-secondary-text-colour;
}
}
6 changes: 6 additions & 0 deletions app/assets/stylesheets/modules/_community-contact.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
.app-community-contact {
@include govuk-media-query($from: tablet) {
text-align: right;
padding-top: govuk-spacing(8);
}
}
7 changes: 7 additions & 0 deletions app/assets/stylesheets/modules/_govspeak-wrapper.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
.govspeak-wrapper {
padding-top: .9375em;

@include govuk-media-query($from: tablet) {
padding-top: 1.875em;
}
}
25 changes: 25 additions & 0 deletions app/assets/stylesheets/modules/_hero.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
.app-hero {
background-color: $govuk-brand-colour;
color: govuk-colour("white");
margin-bottom: govuk-spacing(3);
position: relative;
top: -1px;

@include govuk-media-query($from: tablet) {
margin-bottom: govuk-spacing(6);
}

a:link,
a:visited {
@include govuk-typography-weight-bold;
}
}

.app-hero-lead {
line-height: 1.35;
}

.app-hero__heading--inverse,
.app-hero__body--inverse {
color: govuk-colour("white");
}
20 changes: 20 additions & 0 deletions app/assets/stylesheets/modules/_notice.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
.notice {
clear: both;
@include responsive-bottom-margin;
padding: govuk-spacing(3);

border: 5px solid $govuk-brand-colour;

@include govuk-media-query($from: tablet) {
padding: govuk-spacing(4);
}

&__title {
@include govuk-font(36, $weight: bold);
margin-bottom: govuk-spacing(2);
}

&__description {
@include govuk-font(19);
}
}
18 changes: 18 additions & 0 deletions app/assets/stylesheets/modules/_page-contents.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
.app-page-contents {
&__list li {
margin-left: govuk-spacing(0);
padding-right: govuk-spacing(3);

&:before {
content: "– ";
display: inline-block;
padding-right: govuk-spacing(1);
}
}

// Styles required by GOVUK.HighlightActiveNavItem JS
&__list .active {
letter-spacing: 0;
font-weight: bold;
}
}
23 changes: 23 additions & 0 deletions app/assets/stylesheets/modules/_page-header.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
.app-page-header {
&__intro {
p {
@include govuk-text-colour;
@include govuk-font($size: 19);
@include govuk-responsive-margin(4, "bottom");
}

a {
@include govuk-link-common;
@include govuk-link-style-default;
}
}

&__heading {
margin-bottom: govuk-spacing(3);

@include govuk-media-query($from: tablet) {
margin-bottom: govuk-spacing(7) + govuk-spacing(1);
margin-top: govuk-spacing(7) + govuk-spacing(1);
}
}
}
3 changes: 3 additions & 0 deletions app/assets/stylesheets/modules/_panel.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.panel {
border-top: 1px solid $govuk-border-colour;
}
14 changes: 14 additions & 0 deletions app/assets/stylesheets/modules/_related-content.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
.related {
@include govuk-media-query($from: tablet) {
border-top: 1px solid $govuk-border-colour;
}
}

.related-item {
&__email-link {
padding-left: 25px;
font-weight: bold;
background: image-url("service-manual/mail-icon-x2.png") 0 40% no-repeat;
background-size: 20px 14px;
}
}
Loading