diff --git a/hub/static/css/_area.scss b/hub/static/css/_area.scss index 78025dca9..93e45010e 100644 --- a/hub/static/css/_area.scss +++ b/hub/static/css/_area.scss @@ -33,23 +33,100 @@ } } -.area-section { - padding-top: 4rem; // leave space for the sticky subnav when jumping to section +.area-tabs { + overflow-x: auto; + background: linear-gradient(0deg, var(--bs-border-color-translucent) 1px, transparent 1px); + + .nav { + --bs-nav-tabs-link-active-bg: var(--bs-light); + --bs-nav-tabs-border-color: var(--bs-border-color-translucent); + --bs-nav-tabs-link-active-border-color: var(--bs-nav-tabs-border-color) var(--bs-nav-tabs-border-color) var(--bs-light); + --bs-nav-link-padding-y: 1em; + --bs-nav-link-padding-x: 1.5em; + + flex-wrap: nowrap; + align-items: flex-end; + border-bottom: none; + } + + .nav-link { + margin-bottom: 0; + border-bottom: none; + white-space: nowrap; + + display: flex; + align-items: center; + flex-wrap: nowrap; + gap: map-get($spacers, 2); + + // TODO: Better :focus style + } +} + +.area-data-grid { + display: grid; + grid-gap: 1rem; + grid-template-columns: 1fr; + grid-auto-flow: row dense; + + @include media-breakpoint-up('md') { + grid-template-columns: repeat(2, 1fr); + grid-gap: $grid-gutter-width; + } @include media-breakpoint-up('lg') { - padding-top: 2rem; // no sticky subnav, but still want a bit of clear space below window top when jumping - margin-top: 2rem; // compensate for smaller padding, still want lots of space between sections + grid-template-columns: repeat(3, 1fr); } +} + +.area-data--sm { + grid-row: span 1; +} - &:first-child { - margin-top: -4rem; // don't want to see the padding, but still want it there when we jump +.area-data--md { + grid-row: span 2; +} - @include media-breakpoint-up('lg') { - margin-top: -2rem; +.area-data--lg { + grid-row: span 3; +} + +.area-data-more { + display: none; // will be shown later on + margin-top: map-get($spacers, 3); + + a { + display: flex; + align-items: center; + justify-content: center; + gap: map-get($spacers, 1); + border-radius: $border-radius; + background: rgba(#fff, 0.5); + border: 1px solid rgba(#000, 0.1); + padding: $card-spacer-y $card-spacer-x; + + &:hover, &:focus { + background: $card-bg; + border-color: $card-border-color; } } +} + +@each $tab in ("mp", "opinion", "place", "movement") { + .area-content[data-section="#{$tab}"] { + .area-section:not(##{$tab}), + .area-data-more { + display: none; + } + } +} + +.area-content[data-section="featured"] { + .area-data-more { + display: block; + } - .row .card + .card { - margin-top: var(--bs-gutter-y); // vertical space between cards in a column + .area-data-grid > :not(.area-data--featured) { + display: none; } } diff --git a/hub/static/css/_dataset-card.scss b/hub/static/css/_dataset-card.scss index 8f72100c3..fc693fa98 100644 --- a/hub/static/css/_dataset-card.scss +++ b/hub/static/css/_dataset-card.scss @@ -37,50 +37,61 @@ } } } -} - -.dataset-card--favourite { - .js-unfavourite-this-dataset { - display: block; - } - - .js-favourite-this-dataset { - display: none; - } -} -.dataset-card-header { - display: flex; - - h5 { - margin-bottom: 0; - margin-right: auto; - padding: var(--bs-card-spacer-y) 0 var(--bs-card-spacer-y) var(--bs-card-spacer-x); - - // If not followed by a favouriting control - &:last-child { - padding-right: var(--bs-card-spacer-x); + .card-header { + display: flex; + padding: var(--bs-card-spacer-y) var(--bs-card-spacer-x) 0; + border-bottom: none; + + h1, h2, h3, h4, h5 { + margin-bottom: 0; + margin-right: auto; + } + + form { + margin: calc(var(--bs-card-spacer-y) * -1) calc(var(--bs-card-spacer-x) * -1); + } + + button { + background: transparent; + border: none; + line-height: 1.25em; // match h5 + font-size: 1em; + color: $gray-500; + padding: var(--bs-card-spacer-y) var(--bs-card-spacer-x); + + &:focus { + color: inherit; + } + + &:hover { + color: $link-color; + } } } - button { - background: transparent; - border: none; - line-height: 1.25em; // match h5 - font-size: 1em; - color: $gray-500; - padding: var(--bs-card-spacer-y) var(--bs-card-spacer-x); + .card-footer { + color: $text-muted; + font-size: map-get($font-sizes, 8); - &:focus { + a { color: inherit; - } + text-decoration: none; - &:hover { - color: $link-color; + &:hover, &:focus { + color: $link-color; + text-decoration: underline; + } } } +} - & + .card-body { - padding-top: 0; +.dataset-card--favourite { + .js-unfavourite-this-dataset { + display: block; + } + + .js-favourite-this-dataset { + display: none; } } diff --git a/hub/static/css/_variables.scss b/hub/static/css/_variables.scss index 433a085ab..4e00f9c50 100644 --- a/hub/static/css/_variables.scss +++ b/hub/static/css/_variables.scss @@ -106,23 +106,8 @@ $link-hover-color: shift-color($link-color, $link-shade-percentage); // Grid breakpoints -$grid-breakpoints: ( - xs: 0, - sm: 576px, - md: 768px, - lg: 992px, - xl: 1200px -); - // Grid containers -$container-max-widths: ( - sm: 540px, - md: 720px, - lg: 960px, - xl: 1140px -); - // Grid columns // Container padding @@ -222,6 +207,9 @@ $navbar-light-toggler-icon-bg: url("data:image/svg+xml,< \ No newline at end of file diff --git a/hub/templates/hub/includes/icons/share.html b/hub/templates/hub/includes/icons/share.html new file mode 100644 index 000000000..17e64204e --- /dev/null +++ b/hub/templates/hub/includes/icons/share.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/hub/templates/hub/new_area_page.html b/hub/templates/hub/new_area_page.html new file mode 100644 index 000000000..49200c0ee --- /dev/null +++ b/hub/templates/hub/new_area_page.html @@ -0,0 +1,760 @@ +{% extends 'hub/base.html' %} + +{% load humanize %} +{% load hub_filters %} + +{% block content %} + +
+
+
+
+

{{ area.name }}

+

Current parliamentary constituency

+
+ +
+
+
+ +
+
+ +
+
+ +
+
+ +
+

MP

+
+ + + +
+
+

MP profiles

+
+
+ +
+ +
+ + + + + + + +
+
+

Date elected

+
+ +
+
+
+

+ {{ mp.mp_first_elected|naturalday:"jS M Y" }} +

+
+ +
+ +
+ +
+ +
+

Public opinion

+
+ + + + + + + +
+
+

Policies for tackling the cost of living crisis should go hand in hand with policies to tackle the climate crisis

+
+ +
+
+
+

55%

+

58% national average

+
+ +
+ + + + + +
+ +
+ +
+

Place

+
+ + + +
+
+

Child poverty

+
+ +
+
+
+

24.4%

+

28.2% national average

+
+ +
+ +
+
+

Socio-economic status

+
+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
StatusThis areaUK average
Full-time students29.3%7.4%
Higher managerial, administrative and professional occupations10.5%12.9%
Intermediate occupations8.0%11.5%
Lower managerial, administrative and professional occupations15.3%19.9%
Lower supervisory and technical occupations3.3%5.5%
Never worked / long-term unemployed10.9%8.5%
Routine occupations9.4%12.2%
Semi-routine occupations7.8%11.5%
Small employers and own account workers5.5%10.6%
+
+ +
+ + + + + +
+
+

Index of Multiple Deprivation

+
+ +
+
+
+

2

+

Very deprived

+
+ +
+ +
+
+

Country of the UK

+
+ +
+
+
+

England

+
+ +
+ +
+ +
+ +
+

Movement

+
+ + + + + + + +
+
+

CAFOD activists

+
+ +
+
+
+

6

+

4.3 national average

+
+ +
+ + + + + + + +
+
+

CAFOD parishes

+
+ +
+
+
+

5

+

1.4 national average

+
+ +
+ +
+
+

CAFOD schools

+
+ +
+
+
+

9

+

2.3 national average

+
+ +
+ +
+
+

Save The Children shops

+
+ +
+
+
+

0

+

0.2 national average

+
+ +
+ +
+ +
+ +
+
+ +{% endblock %} diff --git a/hub/templatetags/hub_filters.py b/hub/templatetags/hub_filters.py index 20f2857d1..969a4d2e2 100644 --- a/hub/templatetags/hub_filters.py +++ b/hub/templatetags/hub_filters.py @@ -12,6 +12,11 @@ User = get_user_model() +@register.filter(name="split") +def split(value, key): + return value.split(key) + + @register.filter(name="highlight") def highlight(text, search): rgx = re.compile(re.escape(search), re.IGNORECASE) diff --git a/hub/views/area.py b/hub/views/area.py index aa30034b2..82f31f274 100644 --- a/hub/views/area.py +++ b/hub/views/area.py @@ -1,3 +1,4 @@ +import random from collections import defaultdict from django.db.models import Count, OuterRef, Subquery @@ -377,3 +378,44 @@ def post(self, request, data_set): "deleted": True, } return JsonResponse(data) + + +class NewAreaPageView(TitleMixin, TemplateView): + page_title = "Borsetshire South" + template_name = "hub/new_area_page.html" + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + + context["area"] = { + "name": "Borsetshire South", + } + + person_pks = Person.objects.values_list("pk", flat=True) + mp = Person.objects.get(pk=random.choice(person_pks)) + mp_data = PersonData.objects.filter(person=mp).select_related("data_type") + context["mp"] = {"person": mp} + for item in mp_data.all(): + context["mp"][item.data_type.name] = item.value() + context["mp"]["appg_memberships"] = [ + item.value() + for item in mp_data.filter(data_type__name="mp_appg_memberships") + ] + context["mp"]["votes"] = [ + { + "name": item.data_type.data_set.label, + "vote": item.value(), + "url": f"https://votes.parliament.uk/Votes/Commons/Division/{item.data_type.name.split('_')[0]}", + } + for item in mp_data.filter(data_type__data_set__subcategory="vote") + ] + context["mp"]["support"] = [ + { + "name": item.data_type.data_set.label, + "position": item.value(), + "url": f"https://edm.parliament.uk/early-day-motion/{item.data_type.name.split('_')[0]}", + } + for item in mp_data.filter(data_type__data_set__subcategory="supporter") + ] + + return context diff --git a/local_intelligence_hub/urls.py b/local_intelligence_hub/urls.py index 2b870388e..6d8830dcd 100644 --- a/local_intelligence_hub/urls.py +++ b/local_intelligence_hub/urls.py @@ -39,6 +39,7 @@ path("explore.json", explore.ExploreJSON.as_view(), name="explore_json"), path("explore.csv", explore.ExploreCSV.as_view(), name="explore_csv"), path("area//", area.AreaView.as_view(), name="area"), + path("new-area-page", area.NewAreaPageView.as_view(), name="new_area"), path( "data_set//favourite", area.FavouriteDataSetView.as_view(),