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 multiple policy types in details page #676

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 48 additions & 18 deletions eleventy.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,28 @@ import CleanCSS from "clean-css";
import { compileString as compileStringSass } from "sass";
import { capitalize } from "lodash-es";

import { readProcessedCompleteData } from "./scripts/lib/data.js";
import {
ProcessedCompletePolicy,
readProcessedCompleteData,
} from "./scripts/lib/data.js";
import { escapePlaceId } from "./src/js/data.js";

function processPolicyRecord(policy: ProcessedCompletePolicy): object {
return {
summary: policy.summary,
date: policy.date?.format(),
status: capitalize(policy.status),
scope: policy.scope.map(capitalize),
landUse: policy.land.map(capitalize),
requirements: policy.requirements.map(capitalize),
reporter: policy.reporter,
citations: policy.citations.map((citation) => ({
urlDomain: citation.url ? new URL(citation.url).hostname : null,
...citation,
})),
};
}

export default async function (eleventyConfig: any) {
eleventyConfig.setLiquidOptions({
jsTruthy: true,
Expand All @@ -23,25 +42,36 @@ export default async function (eleventyConfig: any) {
);

const completeData = await readProcessedCompleteData();
eleventyConfig.addGlobalData(
"entries",
Object.entries(completeData).map(([placeId, entry]) => ({
const legacy: object[] = [];
const revamp: object[] = [];
Object.entries(completeData).forEach(([placeId, entry]) => {
const common = {
placeId,
escapedPlaceId: escapePlaceId(placeId),
summary: entry.unifiedPolicy.summary,
date: entry.unifiedPolicy.date?.format(),
status: capitalize(entry.unifiedPolicy.status),
policyChange: entry.unifiedPolicy.policy.map(capitalize),
landUse: entry.unifiedPolicy.land.map(capitalize),
scope: entry.unifiedPolicy.scope.map(capitalize),
requirements: entry.unifiedPolicy.requirements.map(capitalize),
reporter: entry.unifiedPolicy.reporter,
citations: entry.unifiedPolicy.citations.map((citation) => ({
urlDomain: citation.url ? new URL(citation.url).hostname : null,
...citation,
})),
})),
);
population: entry.place.pop.toLocaleString("en-us"),
};
if (
entry.add_max?.length ||
entry.reduce_min?.length ||
entry.rm_min?.length
) {
revamp.push({
...common,
rmMin: entry.rm_min?.map(processPolicyRecord) || [],
reduceMin: entry.reduce_min?.map(processPolicyRecord) || [],
addMax: entry.add_max?.map(processPolicyRecord) || [],
});
} else {
legacy.push({
...common,
...processPolicyRecord(entry.unifiedPolicy),
policyChange: entry.unifiedPolicy.policy,
});
}
});

eleventyConfig.addGlobalData("legacyEntries", legacy);
eleventyConfig.addGlobalData("entries", revamp);

return {
dir: {
Expand Down
10 changes: 10 additions & 0 deletions scripts/11ty/_includes/policy-record-array.liquid
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{%- if array.size == 1 -%}
{% render "policy-record-body" record: array[0] %}
{%- else -%}
{%- for item in array -%}
<section>
<h3>Policy record {{forloop.index}}</h3>
{% render "policy-record-body" record: item %}
</section>
{%- endfor -%}
{%- endif -%}
24 changes: 24 additions & 0 deletions scripts/11ty/_includes/policy-record-body.liquid
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<p class="summary">{{ record.summary }}</p>
<dl>
{% if record.date -%}
<dt>Reform date</dt>
<dd>{{ record.date }}</dd>
{%- endif %}
<dt>Reform status</dt>
<dd>{{ record.status }}</dd>
<dt>Reform scope</dt>
<dd>{% render "string-array" array: record.scope %}</dd>
<dt>Affected land uses</dt>
<dd>{% render "string-array" array: record.landUse %}</dd>
{% if record.requirements.size > 0 -%}
<dt>Requirements</dt>
<dd>{% render "string-array" array: record.requirements %}</dd>
{%- endif %}
{% if record.reporter -%}
<dt>Reporter</dt>
<dd>{{ record.reporter }}</dd>
{%- endif %}
</dl>
{% for citation in record.citations -%}
{% render "citation" citation: citation numCitations: record.citations.size index: forloop.index %}
{%- endfor %}
14 changes: 9 additions & 5 deletions scripts/11ty/_includes/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -230,18 +230,22 @@ $logo-height: 75px;
}

// -------------------------------------------------------------------------
// Summary
// Place details
// -------------------------------------------------------------------------

.summary {
font-size: $font-size-md;
margin-bottom: $spacing-container-edge-spacing;
.place-details {
margin-top: $spacing-container-edge-spacing;
}

// -------------------------------------------------------------------------
// Metadata list
// Policy record
// -------------------------------------------------------------------------

.summary {
font-size: $font-size-md;
margin-bottom: $spacing-container-edge-spacing;
}

dl {
display: grid;
grid-template-columns: 1fr;
Expand Down
39 changes: 39 additions & 0 deletions scripts/11ty/legacy.liquid
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
---
pagination:
data: legacyEntries
size: 1
alias: entry
permalink: "{{ entry.escapedPlaceId }}.html"
layout: layout.liquid
---
<main>
<header>
<h1>Parking reforms in {{ entry.placeId }}</h1>
</header>
<p class="summary">{{ entry.summary }}</p>
<dl>
<dt>Reform type</dt>
<dd>{% render "string-array" array: entry.policyChange %}</dd>
{% if entry.date -%}
<dt>Reform date</dt>
<dd>{{ entry.date }}</dd>
{%- endif %}
<dt>Reform status</dt>
<dd>{{ entry.status }}</dd>
<dt>Reform scope</dt>
<dd>{% render "string-array" array: entry.scope %}</dd>
<dt>Affected land uses</dt>
<dd>{% render "string-array" array: entry.landUse %}</dd>
{% if entry.requirements.size > 0 -%}
<dt>Requirements</dt>
<dd>{% render "string-array" array: entry.requirements %}</dd>
{%- endif %}
{% if entry.reporter -%}
<dt>Reporter</dt>
<dd>{{ entry.reporter }}</dd>
{%- endif %}
</dl>
{% for citation in entry.citations -%}
{% render "citation" citation: citation numCitations: entry.citations.size index: forloop.index %}
{%- endfor %}
</main>
47 changes: 21 additions & 26 deletions scripts/11ty/template.liquid
Original file line number Diff line number Diff line change
Expand Up @@ -10,30 +10,25 @@ layout: layout.liquid
<header>
<h1>Parking reforms in {{ entry.placeId }}</h1>
</header>
<p class="summary">{{ entry.summary }}</p>
<dl>
<dt>Reform type</dt>
<dd>{% render "string-array" array: entry.policyChange %}</dd>
{% if entry.date -%}
<dt>Reform date</dt>
<dd>{{ entry.date }}</dd>
{%- endif %}
<dt>Reform status</dt>
<dd>{{ entry.status }}</dd>
<dt>Reform scope</dt>
<dd>{% render "string-array" array: entry.scope %}</dd>
<dt>Affected land uses</dt>
<dd>{% render "string-array" array: entry.landUse %}</dd>
{% if entry.requirements.size > 0 -%}
<dt>Requirements</dt>
<dd>{% render "string-array" array: entry.requirements %}</dd>
{%- endif %}
{% if entry.reporter -%}
<dt>Reporter</dt>
<dd>{{ entry.reporter }}</dd>
{%- endif %}
</dl>
{% for citation in entry.citations -%}
{% render "citation" citation: citation numCitations: entry.citations.size index: forloop.index %}
{%- endfor %}
<ul class="place-details">
<li>{{ entry.population }} residents</li>
</ul>
{% if entry.rmMin.size > 0 -%}
<section>
<h2>Parking minimum removal{% if entry.rmMin.size > 1 %}s{% endif %}</h2>
{% render "policy-record-array" array: entry.rmMin %}
</section>
{%- endif %}
{% if entry.reduceMin.size > 0 -%}
<section>
<h2>Parking minimum reduction{% if entry.addMax.size > 1 %}s{% endif %}</h2>
{% render "policy-record-array" array: entry.reduceMin %}
</section>
{%- endif %}
{% if entry.addMax.size > 0 -%}
<section>
<h2>Parking maximum{% if entry.addMax.size > 1 %}s{% endif %}</h2>
{% render "policy-record-array" array: entry.addMax %}
</section>
{%- endif %}
</main>
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<style>@import url(https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;600&display=swap);*,::after,::before{box-sizing:border-box}body,html{padding:0;margin:0;height:100%;width:100%;display:flex;flex-direction:column}button{background-color:transparent;border:none;padding:0;font:inherit;color:inherit;cursor:pointer}p{margin:0 0 10px}dl,ol,ul{margin:0;padding:0;padding-inline-start:20px}a,li,p{line-height:1.3}h1{font-size:36px;margin-bottom:10px;font-weight:500;line-height:1.1}h2{font-size:28px;margin-bottom:10px;font-weight:500;line-height:1.15}h3{font-size:24px;margin-bottom:10px;font-weight:500;line-height:1.2}a{color:#337ab7;text-decoration:none}a:focus,a:hover{color:#23527c;text-decoration:underline}.download-link:hover,.external-link:hover{text-decoration:none}.download-link svg,.external-link svg{width:1em;height:1em;vertical-align:-.125em}.external-link svg{transform:rotate(-45deg)}body{font-family:Poppins,Helvetica,Arial,sans-serif;font-size:18px}main{word-break:break-word;width:min(1000px,100%);margin:0 auto;padding:0 15px}.site-header{background-color:hsl(0,0%,25.88%);font-size:24px;padding:15px;display:flex;flex-direction:row;justify-content:space-between;align-items:center;border-bottom:4px solid #20c9b6}.site-header img{height:75px;cursor:pointer}.site-header-map-link{display:none}@media screen and (min-width:640px){.site-header-map-link{display:block}}.site-header-left{height:75px}.site-header-right ul{list-style:none;padding:0;margin:0;display:flex}.site-header-right a{color:#fff;text-decoration:none;display:flex;height:75px;padding:0 10px;align-items:center}.site-header-right a:hover{background-color:#515151}.summary{font-size:20px;margin-bottom:15px}dl{display:grid;grid-template-columns:1fr;column-gap:25px;align-items:start;padding-left:0}@media screen and (min-width:640px){dl{grid-template-columns:auto 1fr}}dt{font-weight:500}dd{margin-left:0;margin-bottom:10px}.citation{border:1px solid hsla(0,0%,0%,.4);border-radius:5px;padding:10px 15px;margin:10px 0}.citation[open]>summary{margin-bottom:10px}.citation summary{font-weight:500}.screenshots{list-style:none;padding-left:0;margin-top:10px}.screenshots li{margin-bottom:10px}.screenshots li:last-child{margin-bottom:0}.screenshots img{width:100%;border:1px solid hsla(0,0%,0%,.4);border-radius:5px}</style>
<style>@import url(https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;600&display=swap);*,::after,::before{box-sizing:border-box}body,html{padding:0;margin:0;height:100%;width:100%;display:flex;flex-direction:column}button{background-color:transparent;border:none;padding:0;font:inherit;color:inherit;cursor:pointer}p{margin:0 0 10px}dl,ol,ul{margin:0;padding:0;padding-inline-start:20px}a,li,p{line-height:1.3}h1{font-size:36px;margin-bottom:10px;font-weight:500;line-height:1.1}h2{font-size:28px;margin-bottom:10px;font-weight:500;line-height:1.15}h3{font-size:24px;margin-bottom:10px;font-weight:500;line-height:1.2}a{color:#337ab7;text-decoration:none}a:focus,a:hover{color:#23527c;text-decoration:underline}.download-link:hover,.external-link:hover{text-decoration:none}.download-link svg,.external-link svg{width:1em;height:1em;vertical-align:-.125em}.external-link svg{transform:rotate(-45deg)}body{font-family:Poppins,Helvetica,Arial,sans-serif;font-size:18px}main{word-break:break-word;width:min(1000px,100%);margin:0 auto;padding:0 15px}.site-header{background-color:hsl(0,0%,25.88%);font-size:24px;padding:15px;display:flex;flex-direction:row;justify-content:space-between;align-items:center;border-bottom:4px solid #20c9b6}.site-header img{height:75px;cursor:pointer}.site-header-map-link{display:none}@media screen and (min-width:640px){.site-header-map-link{display:block}}.site-header-left{height:75px}.site-header-right ul{list-style:none;padding:0;margin:0;display:flex}.site-header-right a{color:#fff;text-decoration:none;display:flex;height:75px;padding:0 10px;align-items:center}.site-header-right a:hover{background-color:#515151}.place-details{margin-top:15px}.summary{font-size:20px;margin-bottom:15px}dl{display:grid;grid-template-columns:1fr;column-gap:25px;align-items:start;padding-left:0}@media screen and (min-width:640px){dl{grid-template-columns:auto 1fr}}dt{font-weight:500}dd{margin-left:0;margin-bottom:10px}.citation{border:1px solid hsla(0,0%,0%,.4);border-radius:5px;padding:10px 15px;margin:10px 0}.citation[open]>summary{margin-bottom:10px}.citation summary{font-weight:500}.screenshots{list-style:none;padding-left:0;margin-top:10px}.screenshots li{margin-bottom:10px}.screenshots li:last-child{margin-bottom:0}.screenshots img{width:100%;border:1px solid hsla(0,0%,0%,.4);border-radius:5px}</style>
<title>Parking reforms in Abbottstown, PA | Parking Reform Network</title>
<script
async
Expand Down Expand Up @@ -39,37 +39,76 @@
<header>
<h1>Parking reforms in Abbottstown, PA</h1>
</header>
<p class="summary">Parking requirements may be reduced through on-street parking, public parking and proximity to transit. Parking maximums are set at 110% of the minimums for nonresidential uses.</p>
<ul class="place-details">
<li>1,022 residents</li>
</ul>

<section>
<h2>Parking minimum reduction</h2>
<p class="summary">Parking requirements may be reduced through on-street parking, public parking and proximity to transit.</p>
<dl>

<dt>Reform status</dt>
<dd>Implemented</dd>
<dt>Reform scope</dt>
<dd>Citywide</dd>
<dt>Affected land uses</dt>
<dd><ul><li>All uses</li><li>Commercial</li><li>Industrial</li><li>Medical</li><li>Other</li><li>Residential, multi-family</li></ul></dd>
<dt>Requirements</dt>
<dd><ul><li>Frequent transit</li><li>Other</li></ul></dd>
<dt>Reporter</dt>
<dd>Samuel Deetz</dd>
</dl>
<details class="citation">
<summary>Citation</summary>
<dl>
<dt>Reform type</dt>
<dd><ul><li>Add parking maximums</li><li>Reduce parking minimums</li></ul></dd>

<dt>Reform status</dt>
<dd>Implemented</dd>
<dt>Reform scope</dt>
<dd>Citywide</dd>
<dt>Affected land uses</dt>
<dd><ul><li>All uses</li><li>Commercial</li><li>Industrial</li><li>Other</li><li>Residential, multi-family</li></ul></dd>
<dt>Requirements</dt>
<dd><ul><li>Frequent transit</li><li>Other</li></ul></dd>
<dt>Reporter</dt>
<dd>Samuel Deetz</dd>
<dt>Source</dt>
<dd>Abbottstown Zoning Code</dd>
<dt>Notes</dt>
<dd>§ 204-49.B.
§ 204-50.</dd>
<dt>URL</dt>
<dd><a target="_blank" class="external-link" href="https://ecode360.com/33754474#33754521">ecode360.com <svg aria-label="external link icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--!Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2024 Fonticons, Inc.--><path fill="currentColor" d="M438.6 278.6c12.5-12.5 12.5-32.8 0-45.3l-160-160c-12.5-12.5-32.8-12.5-45.3 0s-12.5 32.8 0 45.3L338.8 224 32 224c-17.7 0-32 14.3-32 32s14.3 32 32 32l306.7 0L233.4 393.4c-12.5 12.5-12.5 32.8 0 45.3s32.8 12.5 45.3 0l160-160z"/></svg></a></dd>
</dl>
<details class="citation">
<ul class="screenshots">
<li><img alt="Screenshot of Abbottstown Zoning Code" src="https://mandates-map.directus.app/assets/4b1526ac-03cb-4854-b3a5-4267461e8081/abbottstown-pa-reduce-min-screenshot1.png" /></li><li><img alt="Screenshot of Abbottstown Zoning Code" src="https://mandates-map.directus.app/assets/0255803b-9ca1-409a-93e5-cd7666ac6222/abbottstown-pa-reduce-min-screenshot2.png" /></li>
</ul>
</details>

</section>
<section>
<h2>Parking maximum</h2>
<p class="summary">Parking maximums are set at 110% of the minimums for nonresidential uses.</p>
<dl>

<dt>Reform status</dt>
<dd>Implemented</dd>
<dt>Reform scope</dt>
<dd>Citywide</dd>
<dt>Affected land uses</dt>
<dd><ul><li>Commercial</li><li>Industrial</li><li>Medical</li><li>Other</li></ul></dd>
<dt>Requirements</dt>
<dd>By right</dd>
<dt>Reporter</dt>
<dd>Samuel Deetz</dd>
</dl>
<details class="citation">
<summary>Citation</summary>
<dl>
<dt>Source</dt>
<dd>Abbottstown Zoning Code</dd>
<dt>Notes</dt>
<dd>§ 204-49Maximum number of parking spaces.
§ 204-50Parking space reductions.</dd>
A.</dd>
<dt>URL</dt>
<dd><a target="_blank" class="external-link" href="https://ecode360.com/33754474#33754521">ecode360.com <svg aria-label="external link icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--!Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2024 Fonticons, Inc.--><path fill="currentColor" d="M438.6 278.6c12.5-12.5 12.5-32.8 0-45.3l-160-160c-12.5-12.5-32.8-12.5-45.3 0s-12.5 32.8 0 45.3L338.8 224 32 224c-17.7 0-32 14.3-32 32s14.3 32 32 32l306.7 0L233.4 393.4c-12.5 12.5-12.5 32.8 0 45.3s32.8 12.5 45.3 0l160-160z"/></svg></a></dd>
</dl>
<ul class="screenshots">
<li><img alt="Screenshot of Abbottstown Zoning Code" src="https://mandates-map.directus.app/assets/09f7dee6-0d7e-4c17-9dbc-eba33fa75c23/abbottstown-pa-screenshot1.png" /></li><li><img alt="Screenshot of Abbottstown Zoning Code" src="https://mandates-map.directus.app/assets/3cd722d2-bedb-4660-99c4-fc851b126c80/abbottstown-pa-screenshot2.png" /></li>
<li><img alt="Screenshot of Abbottstown Zoning Code" src="https://mandates-map.directus.app/assets/dcbf3e80-9927-4ef0-b46a-6b0a0fe6ec07/abbottstown-pa-add-max-screenshot.png" /></li>
</ul>
</details>

</section>
</main>

</body>
Expand Down
Loading
Loading