Merge pull request #1214 from colouring-cities/interface/typology-updates

Interface/typology updates
This commit is contained in:
Mike Simpson 2023-07-26 16:59:50 +01:00 committed by GitHub
commit fd698062ea
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 300 additions and 29 deletions

View File

@ -973,4 +973,143 @@
<PolygonSymbolizer fill="#ffe8a9" /> <PolygonSymbolizer fill="#ffe8a9" />
</Rule> </Rule>
</Style> </Style>
<Style name="typology_classification">
<Rule>
<Filter>[typology_classification] = "Low-rise: Not part of a group/cluster (1-3 core floors- excluding extensions)"</Filter>
<PolygonSymbolizer fill="#0311AB" />
</Rule>
<Rule>
<Filter>[typology_classification] = "Low-rise: Part of dense block/row/terrace"</Filter>
<PolygonSymbolizer fill="#3845D4" />
</Rule>
<Rule>
<Filter>[typology_classification] = "Low-rise: Part of group of widely spaced blocks (includes semi-detached houses)"</Filter>
<PolygonSymbolizer fill="#6D79FD" />
</Rule>
<Rule>
<Filter>[typology_classification] = "Mid-rise: Not part of a group/cluster (4-7 core floors)"</Filter>
<PolygonSymbolizer fill="#FF5D00" />
</Rule>
<Rule>
<Filter>[typology_classification] = "Mid-rise: Part of group of densely spaced blocks"</Filter>
<PolygonSymbolizer fill="#FF8000" />
</Rule>
<Rule>
<Filter>[typology_classification] = "Mid-rise: Part of group of widely spaced blocks"</Filter>
<PolygonSymbolizer fill="#FFA200" />
</Rule>
<Rule>
<Filter>[typology_classification] = "High rise: Not part of a group/cluster"</Filter>
<PolygonSymbolizer fill="#AB1303" />
</Rule>
<Rule>
<Filter>[typology_classification] = "High-rise: Part of group of densely spaced blocks (8 + core floors)"</Filter>
<PolygonSymbolizer fill="#D43A29" />
</Rule>
<Rule>
<Filter>[typology_classification] = "High-rise: Part of group of widely spaced blocks"</Filter>
<PolygonSymbolizer fill="#FC604F" />
</Rule>
<Rule>
<MaxScaleDenominator>17061</MaxScaleDenominator>
<MinScaleDenominator>4264</MinScaleDenominator>
<LineSymbolizer stroke="#888" stroke-width="0.8"/>
</Rule>
<Rule>
<MaxScaleDenominator>4264</MaxScaleDenominator>
<MinScaleDenominator>0</MinScaleDenominator>
<LineSymbolizer stroke="#888" stroke-width="2.0"/>
</Rule>
</Style>
<Style name="typology_style_period">
<Rule>
<Filter>[typology_style_period] = "Roman (43AD-410)"</Filter>
<PolygonSymbolizer fill="#00B2CB" />
</Rule>
<Rule>
<Filter>[typology_style_period] = "Medieval (410-1485)"</Filter>
<PolygonSymbolizer fill="#00A9C6" />
</Rule>
<Rule>
<Filter>[typology_style_period] = "Tudor (1485-1603)"</Filter>
<PolygonSymbolizer fill="#0097BC" />
</Rule>
<Rule>
<Filter>[typology_style_period] = "Stuart (1603 -1714)"</Filter>
<PolygonSymbolizer fill="#008EB7" />
</Rule>
<Rule>
<Filter>[typology_style_period] = "Georgian (1714-1837)"</Filter>
<PolygonSymbolizer fill="#0085B2" />
</Rule>
<Rule>
<Filter>[typology_style_period] = "Victorian (1837-1901)"</Filter>
<PolygonSymbolizer fill="#007CAD" />
</Rule>
<Rule>
<Filter>[typology_style_period] = "Edwardian (1901-1914)"</Filter>
<PolygonSymbolizer fill="#0073A8" />
</Rule>
<Rule>
<Filter>[typology_style_period] = "WWI - WWII (1914-45)"</Filter>
<PolygonSymbolizer fill="#006AA3" />
</Rule>
<Rule>
<Filter>[typology_style_period] = "Post war (1945-1975)"</Filter>
<PolygonSymbolizer fill="#004F94" />
</Rule>
<Rule>
<Filter>[typology_style_period] = "Postmodern (1975-1990)"</Filter>
<PolygonSymbolizer fill="#00468F" />
</Rule>
<Rule>
<Filter>[typology_style_period] = "1990s"</Filter>
<PolygonSymbolizer fill="#003D8A" />
</Rule>
<Rule>
<Filter>[typology_style_period] = "2000s"</Filter>
<PolygonSymbolizer fill="#003485" />
</Rule>
<Rule>
<MaxScaleDenominator>17061</MaxScaleDenominator>
<MinScaleDenominator>4264</MinScaleDenominator>
<LineSymbolizer stroke="#888" stroke-width="0.8"/>
</Rule>
<Rule>
<MaxScaleDenominator>4264</MaxScaleDenominator>
<MinScaleDenominator>0</MinScaleDenominator>
<LineSymbolizer stroke="#888" stroke-width="2.0"/>
</Rule>
</Style>
<Style name="typology_dynamic_classification">
<Rule>
<Filter>[typology_dynamic_classification] = "Repetitive small, domestic plots"</Filter>
<PolygonSymbolizer fill="#F2E5FF" />
</Rule>
<Rule>
<Filter>[typology_dynamic_classification] = "Linear non-domestic, i.e. high streets"</Filter>
<PolygonSymbolizer fill="#CBABEA" />
</Rule>
<Rule>
<Filter>[typology_dynamic_classification] = "Large plots with internal roads"</Filter>
<PolygonSymbolizer fill="#A272D4" />
</Rule>
<Rule>
<Filter>[typology_dynamic_classification] = "Other"</Filter>
<PolygonSymbolizer fill="#EEEEEE" />
</Rule>
<Rule>
<MaxScaleDenominator>17061</MaxScaleDenominator>
<MinScaleDenominator>4264</MinScaleDenominator>
<LineSymbolizer stroke="#888" stroke-width="0.8"/>
</Rule>
<Rule>
<MaxScaleDenominator>4264</MaxScaleDenominator>
<MinScaleDenominator>0</MinScaleDenominator>
<LineSymbolizer stroke="#888" stroke-width="2.0"/>
</Rule>
</Style>
</Map> </Map>

View File

@ -21,6 +21,7 @@ function getLanduseGroupOptions(value: string, all: boolean = false) {
landuse_id AS id, landuse_id AS id,
description AS value description AS value
FROM reference_tables.buildings_landuse_group FROM reference_tables.buildings_landuse_group
ORDER BY description
` `
); );
} }

View File

@ -11,6 +11,7 @@ import { CategoryViewProps } from './category-view-props';
import InfoBox from '../../components/info-box'; import InfoBox from '../../components/info-box';
import { DataEntryGroup } from '../data-components/data-entry-group'; import { DataEntryGroup } from '../data-components/data-entry-group';
import { MultiDataEntry } from '../data-components/multi-data-entry/multi-data-entry'; import { MultiDataEntry } from '../data-components/multi-data-entry/multi-data-entry';
import { useDisplayPreferences } from '../../displayPreferences-context';
const AttachmentFormOptions = [ const AttachmentFormOptions = [
"Detached", "Detached",
@ -23,9 +24,37 @@ const AttachmentFormOptions = [
* Type view/edit section * Type view/edit section
*/ */
const TypeView: React.FunctionComponent<CategoryViewProps> = (props) => { const TypeView: React.FunctionComponent<CategoryViewProps> = (props) => {
const { darkLightTheme } = useDisplayPreferences();
const switchToClassificationMapStyle = (e) => {
e.preventDefault();
props.onMapColourScale('typology_classification')
}
const switchToStylePeriodMapStyle = (e) => {
e.preventDefault();
props.onMapColourScale('typology_style_period')
}
const switchToDynamicClassificationMapStyle = (e) => {
e.preventDefault();
props.onMapColourScale('typology_dynamic_classification')
}
const switchToAttachmentMapStyle = (e) => {
e.preventDefault();
props.onMapColourScale('building_attachment_form')
}
return ( return (
<Fragment> <Fragment>
<DataEntryGroup name="Basic typology classification"> <DataEntryGroup name="Basic typology classification">
{(props.mapColourScale == "typology_classification") ?
<button className={`map-switcher-inline enabled-state btn btn-outline btn-outline-dark ${darkLightTheme}`} onClick={switchToStylePeriodMapStyle}>
{'Click here to change map to show architectural style/historical period.'}
</button>
:
<button className={`map-switcher-inline disabled-state btn btn-outline btn-outline-dark ${darkLightTheme}`} onClick={switchToClassificationMapStyle}>
{"Click to change map to show typology classification."}
</button>
}
<SelectDataEntry <SelectDataEntry
title={dataFields.typology_classification.title} title={dataFields.typology_classification.title}
slug="typology_classification" slug="typology_classification"
@ -75,6 +104,15 @@ const TypeView: React.FunctionComponent<CategoryViewProps> = (props) => {
} }
</DataEntryGroup> </DataEntryGroup>
<DataEntryGroup name="Architectural style/Historical period"> <DataEntryGroup name="Architectural style/Historical period">
{(props.mapColourScale == "typology_style_period") ?
<button className={`map-switcher-inline enabled-state btn btn-outline btn-outline-dark ${darkLightTheme}`} onClick={switchToClassificationMapStyle}>
{'Click to change map to show typology classification.'}
</button>
:
<button className={`map-switcher-inline disabled-state btn btn-outline btn-outline-dark ${darkLightTheme}`} onClick={switchToStylePeriodMapStyle}>
{"Click here to change map to show architectural style/historical period."}
</button>
}
<SelectDataEntry <SelectDataEntry
title={dataFields.typology_style_period.title} title={dataFields.typology_style_period.title}
slug="typology_style_period" slug="typology_style_period"
@ -93,6 +131,9 @@ const TypeView: React.FunctionComponent<CategoryViewProps> = (props) => {
user_verified_as={props.user_verified.typology_style_period} user_verified_as={props.user_verified.typology_style_period}
verified_count={props.building.verified.typology_style_period} verified_count={props.building.verified.typology_style_period}
/> />
<div className={`alert alert-dark`} role="alert" style={{ fontSize: 14, backgroundColor: "#f6f8f9" }}>
<i className="source-url">For building age by year see <a href={"http://localhost:8080/edit/age/"+props.building.building_id}>Age & History</a>.</i>
</div>
<SelectDataEntry <SelectDataEntry
title={dataFields.typology_style_period_source_type.title} title={dataFields.typology_style_period_source_type.title}
slug="typology_style_period_source_type" slug="typology_style_period_source_type"
@ -123,7 +164,16 @@ const TypeView: React.FunctionComponent<CategoryViewProps> = (props) => {
</> </>
} }
</DataEntryGroup> </DataEntryGroup>
<DataEntryGroup name="Dynamic classification"> <DataEntryGroup name="Dynamic tissue classification">
{(props.mapColourScale == "typology_dynamic_classification") ?
<button className={`map-switcher-inline enabled-state btn btn-outline btn-outline-dark ${darkLightTheme}`} onClick={switchToClassificationMapStyle}>
{'Click to change map to show typology classification.'}
</button>
:
<button className={`map-switcher-inline disabled-state btn btn-outline btn-outline-dark ${darkLightTheme}`} onClick={switchToDynamicClassificationMapStyle}>
{"Click here to change map to show dynamic classification."}
</button>
}
<SelectDataEntry <SelectDataEntry
title={dataFields.typology_dynamic_classification.title} title={dataFields.typology_dynamic_classification.title}
slug="typology_dynamic_classification" slug="typology_dynamic_classification"
@ -226,6 +276,15 @@ const TypeView: React.FunctionComponent<CategoryViewProps> = (props) => {
} }
</DataEntryGroup> </DataEntryGroup>
<DataEntryGroup name="Attachment/Adjacency"> <DataEntryGroup name="Attachment/Adjacency">
{(props.mapColourScale == "building_attachment_form") ?
<button className={`map-switcher-inline enabled-state btn btn-outline btn-outline-dark ${darkLightTheme}`} onClick={switchToClassificationMapStyle}>
{'Click to change map to show typology classification.'}
</button>
:
<button className={`map-switcher-inline disabled-state btn btn-outline btn-outline-dark ${darkLightTheme}`} onClick={switchToAttachmentMapStyle}>
{"Click here to change map to show attachment/adjacency."}
</button>
}
<SelectDataEntry <SelectDataEntry
title={dataFields.building_attachment_form.title} title={dataFields.building_attachment_form.title}
slug="building_attachment_form" slug="building_attachment_form"

View File

@ -98,7 +98,7 @@ export const categoriesConfig: {[key in Category]: CategoryDefinition} = {
slug: 'typology', slug: 'typology',
name: 'Typology', name: 'Typology',
aboutUrl: 'https://pages.colouring.london/buildingtypology', aboutUrl: 'https://pages.colouring.london/buildingtypology',
intro: 'Note: This section is currently under development, we are working to activate it as soon as possible. This section provides open data on the typology of the building.', intro: 'This section provides open data on the typology of the building.',
}, },
[Category.LandUse]: { [Category.LandUse]: {
slug: 'land-use', slug: 'land-use',

View File

@ -299,18 +299,69 @@ export const categoryMapsConfig: {[key in Category]: CategoryMapDefinition[]} =
] ]
}, },
}], }],
[Category.Typology]: [{ [Category.Typology]: [
mapStyle: 'building_attachment_form', {
legend: { mapStyle: 'typology_classification',
title: 'Adjacency/Configuration', legend: {
elements: [ title: 'Typology classification',
{ color: "#f2a2b9", text: "Detached" }, elements: [
{ color: "#ab8fb0", text: "Semi-Detached" }, { color: '#0311AB', text: '1-3 storeys: Detached' },
{ color: "#3891d1", text: "End-Terrace" }, { color: '#3845D4', text: '1-3 storeys: Tightly grouped' },
{ color: "#226291", text: "Mid-Terrace" } { color: '#6D79FD', text: '1-3 storeys: Loosely grouped' },
] { color: '#FF5D00', text: '4-7 storeys: Detached' },
{ color: '#FF8000', text: '4-7 storeys: Tightly grouped' },
{ color: '#FFA200', text: '4-7 storeys: Loosely grouped' },
{ color: '#AB1303', text: '8+ storeys: Detached' },
{ color: '#D43A29', text: '8+ storeys: Tightly grouped' },
{ color: '#FC604F', text: '8+ storeys: Loosely grouped' },
]
}
}, },
}], {
mapStyle: 'typology_style_period',
legend: {
title: 'Architectural style',
elements: [
{ color: '#00B2CB', text: 'Roman (43AD-410)' },
{ color: '#00A9C6', text: 'Medieval (410-1485)' },
{ color: '#0097BC', text: 'Tudor (1485-1603)' },
{ color: '#008EB7', text: 'Stuart (1603 -1714)' },
{ color: '#0085B2', text: 'Georgian (1714-1837)' },
{ color: '#007CAD', text: 'Victorian (1837-1901)' },
{ color: '#0073A8', text: 'Edwardian (1901-1914)' },
{ color: '#006AA3', text: 'WWI - WWII (1914-45)' },
{ color: '#004F94', text: 'Post war (1945-1975)' },
{ color: '#00468F', text: 'Postmodern (1975-1990)' },
{ color: '#003D8A', text: '1990s' },
{ color: '#003485', text: '2000s' },
]
}
},
{
mapStyle: 'typology_dynamic_classification',
legend: {
title: 'Dynamic classification',
elements: [
{ color: '#F2E5FF', text: 'Repetitive small, domestic plots' },
{ color: '#CBABEA', text: 'Linear non-domestic, i.e. high streets' },
{ color: '#A272D4', text: 'Large plots with internal roads' },
{ color: '#EEEEEE', text: 'Other' },
]
}
},
{
mapStyle: 'building_attachment_form',
legend: {
title: 'Attachment/Adjacency',
elements: [
{ color: "#f2a2b9", text: "Detached" },
{ color: "#ab8fb0", text: "Semi-Detached" },
{ color: "#3891d1", text: "End-Terrace" },
{ color: "#226291", text: "Mid-Terrace" }
]
},
},
],
[Category.LandUse]: [ [Category.LandUse]: [
{ {
mapStyle: 'landuse', mapStyle: 'landuse',

View File

@ -1468,7 +1468,7 @@ export const dataFields = { /* eslint-disable @typescript-eslint/camelcase */
category: Category.Typology, category: Category.Typology,
title: "Which description best suits the building and its context?", title: "Which description best suits the building and its context?",
tooltip: "HINT: Adapted from building type classifications developed in urban morphology. See <a href=\"https://www.smog.chalmers.se/\">https://www.smog.chalmers.se/</a> 'Space Matrix' for further information.", tooltip: "HINT: Adapted from building type classifications developed in urban morphology. See <a href=\"https://www.smog.chalmers.se/\">https://www.smog.chalmers.se/</a> 'Space Matrix' for further information.",
example: "High rise: Not part of a group/cluster", example: "8+ storeys: Detached",
items: [ items: [
'Low-rise: Not part of a group/cluster (1-3 core floors- excluding extensions)', 'Low-rise: Not part of a group/cluster (1-3 core floors- excluding extensions)',
'Low-rise: Part of dense block/row/terrace', 'Low-rise: Part of dense block/row/terrace',
@ -1498,24 +1498,20 @@ export const dataFields = { /* eslint-disable @typescript-eslint/camelcase */
category: Category.Typology, category: Category.Typology,
title: "Which description best suits the building's architectural style/historical period?", title: "Which description best suits the building's architectural style/historical period?",
tooltip: "", tooltip: "",
example: "High rise: Not part of a group/cluster", example: "Georgian (1714-1837)",
items: [ items: [
'Roman (43AD-410)', 'Roman (43AD-410)',
'Early Medieval (410-1066)', 'Medieval (410-1485)',
'Mid- Late Medieval (1066-1485)',
'Tudor (1485-1603)', 'Tudor (1485-1603)',
'Stuart (1603 -1714)', 'Stuart (1603 -1714)',
'Georgian/William IV (1714-1837)', 'Georgian (1714-1837)',
'Victorian (1837-1901)', 'Victorian (1837-1901)',
'Edwardian (1901-1914)', 'Edwardian (1901-1914)',
'World War I (1914-18)', 'WWI - WWII (1914-45)',,
'Interwar (1918-39)',
'World War II (1939-45)',
'Post war (1945-1975)', 'Post war (1945-1975)',
'Postmodern (1975-1990)', 'Postmodern (1975-1990)',
'1990s', '1990s',
'2000s/2010s', '2000s',
'2020s',
] ]
}, },
typology_style_period_source_type: { typology_style_period_source_type: {
@ -1535,11 +1531,12 @@ export const dataFields = { /* eslint-disable @typescript-eslint/camelcase */
category: Category.Typology, category: Category.Typology,
title: "Which description best suits the building's plot?", title: "Which description best suits the building's plot?",
tooltip: "HINT: Based on a dynamic classification system for urban tissue developed by Brenda Case Scheer. For further information see: <a href=\"https://www.researchgate.net/publication/242150847_The_Anatomy_of_Sprawl\">https://www.researchgate.net/publication/242150847_The_Anatomy_of_Sprawl</a>.", tooltip: "HINT: Based on a dynamic classification system for urban tissue developed by Brenda Case Scheer. For further information see: <a href=\"https://www.researchgate.net/publication/242150847_The_Anatomy_of_Sprawl\">https://www.researchgate.net/publication/242150847_The_Anatomy_of_Sprawl</a>.",
example: "High rise: Not part of a group/cluster", example: "Large plots with internal roads",
items: [ items: [
'Small fairly regular plot part of repetitive domestic streets', 'Repetitive small, domestic plots',
'Irregular shaped plots built along the edge of long established routes (e.g high streets)', 'Linear non-domestic, i.e. high streets',
'Large plot with internal access roads (e.g. infrastructure hubs/large institution such as hospitals/universities/airports)', 'Large plots with internal roads',
'Other'
] ]
}, },
typology_dynamic_classification_source_type: { typology_dynamic_classification_source_type: {

View File

@ -24,7 +24,10 @@ export type BuildingMapTileset =
'dynamics_demolished_count' | 'dynamics_demolished_count' |
'disaster_severity' | 'disaster_severity' |
'team' | 'team' |
'survival_status'; 'survival_status'|
'typology_classification'|
'typology_style_period' |
'typology_dynamic_classification';
export type SpecialMapTileset = 'base_light' | 'base_night' | 'base_night_outlines' | 'highlight' | 'number_labels' | 'base_boroughs'; export type SpecialMapTileset = 'base_light' | 'base_night' | 'base_night_outlines' | 'highlight' | 'number_labels' | 'base_boroughs';

View File

@ -57,7 +57,7 @@
padding: 0.5rem 0.25rem; padding: 0.5rem 0.25rem;
margin: 0.25rem 0.5rem; margin: 0.25rem 0.5rem;
width: auto; width: auto;
font-size: 18px; font-size: 17px;
border: 1px solid; border: 1px solid;
border-radius: 4px; border-radius: 4px;
} }

View File

@ -281,6 +281,27 @@ const LAYER_QUERIES = {
FROM FROM
buildings buildings
WHERE jsonb_array_length(demolished_buildings) > 0 OR dynamics_has_demolished_buildings = FALSE`, WHERE jsonb_array_length(demolished_buildings) > 0 OR dynamics_has_demolished_buildings = FALSE`,
typology_classification: `
SELECT
geometry_id,
typology_classification
FROM
buildings
WHERE typology_classification IS NOT NULL`,
typology_style_period: `
SELECT
geometry_id,
typology_style_period
FROM
buildings
WHERE typology_style_period IS NOT NULL`,
typology_dynamic_classification: `
SELECT
geometry_id,
typology_dynamic_classification
FROM
buildings
WHERE typology_dynamic_classification IS NOT NULL`,
}; };
const GEOMETRY_FIELD = 'geometry_geom'; const GEOMETRY_FIELD = 'geometry_geom';