Merge pull request #1081 from matkoniecz/feature/core-18-domestic-likes

Rework likes and upgrades to community section, ask is building domestic, deduplicate landuse section
This commit is contained in:
Mike Simpson 2023-02-15 09:14:02 +00:00 committed by GitHub
commit 4a0e65f8c4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 317 additions and 152 deletions

View File

@ -599,6 +599,30 @@
<LineSymbolizer stroke="#888" stroke-width="2.0"/> <LineSymbolizer stroke="#888" stroke-width="2.0"/>
</Rule> </Rule>
</Style> </Style>
<Style name="is_domestic">
<Rule>
<Filter>[is_domestic] = "yes"</Filter>
<PolygonSymbolizer fill="#f7ec25" />
</Rule>
<Rule>
<Filter>[is_domestic] = "mixed domestic/non-domestic"</Filter>
<PolygonSymbolizer fill="#fc9b2a" />
</Rule>
<Rule>
<Filter>[is_domestic] = "no"</Filter>
<PolygonSymbolizer fill="#ff2121" />
</Rule>
<Rule>
<MaxScaleDenominator>17061</MaxScaleDenominator>
<MinScaleDenominator>4264</MinScaleDenominator>
<LineSymbolizer stroke="#888" stroke-width="1.0"/>
</Rule>
<Rule>
<MaxScaleDenominator>4264</MaxScaleDenominator>
<MinScaleDenominator>0</MinScaleDenominator>
<LineSymbolizer stroke="#888" stroke-width="3.0"/>
</Rule>
</Style>
<Style name="likes"> <Style name="likes">
<Rule> <Rule>
<Filter>[likes] &gt;= 100</Filter> <Filter>[likes] &gt;= 100</Filter>
@ -640,6 +664,47 @@
<LineSymbolizer stroke="#888" stroke-width="3.0"/> <LineSymbolizer stroke="#888" stroke-width="3.0"/>
</Rule> </Rule>
</Style> </Style>
<Style name="typology_likes">
<Rule>
<Filter>[likes] &gt;= 100</Filter>
<PolygonSymbolizer fill="#bd0026" />
</Rule>
<Rule>
<Filter>[likes] &gt;= 50 and [likes] &lt; 100</Filter>
<PolygonSymbolizer fill="#e31a1c" />
</Rule>
<Rule>
<Filter>[likes] &gt;= 20 and [likes] &lt; 50</Filter>
<PolygonSymbolizer fill="#fc4e2a" />
</Rule>
<Rule>
<Filter>[likes] &gt;= 10 and [likes] &lt; 20</Filter>
<PolygonSymbolizer fill="#fd8d3c" />
</Rule>
<Rule>
<Filter>[likes] &gt;= 3 and [likes] &lt; 10</Filter>
<PolygonSymbolizer fill="#feb24c" />
</Rule>
<Rule>
<Filter>[likes] = 2</Filter>
<PolygonSymbolizer fill="#fed976" />
</Rule>
<Rule>
<Filter>[likes] = 1</Filter>
<PolygonSymbolizer fill="#ffe8a9" />
</Rule>
<Rule>
<MaxScaleDenominator>17061</MaxScaleDenominator>
<MinScaleDenominator>4264</MinScaleDenominator>
<LineSymbolizer stroke="#888" stroke-width="1.0"/>
</Rule>
<Rule>
<MaxScaleDenominator>4264</MaxScaleDenominator>
<MinScaleDenominator>0</MinScaleDenominator>
<LineSymbolizer stroke="#888" stroke-width="3.0"/>
</Rule>
</Style>
<Style name="community_local_significance_total"> <Style name="community_local_significance_total">
<Rule> <Rule>
<Filter>[community_local_significance_total] &gt;= 100</Filter> <Filter>[community_local_significance_total] &gt;= 100</Filter>

View File

@ -19,6 +19,12 @@ export const aggregationsConfig: { [key in keyof typeof buildingUserAttributesCo
aggregationMethod: 'countTrue' aggregationMethod: 'countTrue'
} }
], ],
community_type_worth_keeping: [
{
aggregateFieldName: 'community_type_worth_keeping_total',
aggregationMethod: 'countTrue'
}
],
community_local_significance: [ community_local_significance: [
{ {
aggregateFieldName: 'community_local_significance_total', aggregateFieldName: 'community_local_significance_total',

View File

@ -292,11 +292,20 @@ export const buildingAttributesConfig = valueType<DataFieldConfig>()({ /* eslint
sqlCast: 'jsonb', sqlCast: 'jsonb',
}, },
is_domestic: {
edit: true,
verify: true
},
likes_total: { likes_total: {
edit: false, edit: false,
derivedEdit: true, derivedEdit: true,
verify: false verify: false
}, },
community_type_worth_keeping_total: {
edit: false,
derivedEdit: true,
verify: false
},
community_local_significance_total: { community_local_significance_total: {
edit: false, edit: false,
derivedEdit: true, derivedEdit: true,

View File

@ -29,7 +29,7 @@ const UserOpinionEntry: React.FunctionComponent<UserOpinionEntryProps> = (props)
checked={!!props.userValue} checked={!!props.userValue}
disabled={props.mode === 'view'} disabled={props.mode === 'view'}
onChange={e => props.onChange(props.slug, e.target.checked)} onChange={e => props.onChange(props.slug, e.target.checked)}
/> Yes (tick here to add (or remove) your opinion, to this you need to be in the edit mode) /> Yes (tick to add or remove your edit)
</label> </label>
</> </>
); );

View File

@ -97,6 +97,7 @@ const withCopyEdit: (wc: React.ComponentType<CategoryViewProps>) => DataContaine
'current_landuse_verified', 'current_landuse_verified',
'planning_list_grade', 'planning_list_grade',
'likes_total', 'likes_total',
'community_type_worth_keeping_total',
'community_local_significance_total', 'community_local_significance_total',
'community_expected_planning_application_total' 'community_expected_planning_application_total'
] ]

View File

@ -4,10 +4,11 @@ import '../../map/map-button.css';
import withCopyEdit from '../data-container'; import withCopyEdit from '../data-container';
import UserOpinionEntry from '../data-components/user-opinion-data-entry'; import UserOpinionEntry from '../data-components/user-opinion-data-entry';
import { MultiSelectDataEntry } from '../data-components/multi-select-data-entry'; import { MultiSelectDataEntry } from '../data-components/multi-select-data-entry';
import { DataEntryGroup } from '../data-components/data-entry-group';
import { CategoryViewProps } from './category-view-props'; import { CategoryViewProps } from './category-view-props';
import InfoBox from '../../components/info-box'; import InfoBox from '../../components/info-box';
import { LogicalDataEntry } from '../data-components/logical-data-entry/logical-data-entry'; import { LogicalDataEntry, LogicalDataEntryYesOnly } from '../data-components/logical-data-entry/logical-data-entry';
import { buildingUserFields, dataFields } from '../../config/data-fields-config'; import { buildingUserFields, dataFields } from '../../config/data-fields-config';
import './community.css'; import './community.css';
@ -20,9 +21,9 @@ import { useDisplayPreferences } from '../../displayPreferences-context';
* Community view/edit section * Community view/edit section
*/ */
const CommunityView: React.FunctionComponent<CategoryViewProps> = (props) => { const CommunityView: React.FunctionComponent<CategoryViewProps> = (props) => {
const switchToLikesMapStyle = (e) => { const switchToTypologyMapStyle = (e) => {
e.preventDefault(); e.preventDefault();
props.onMapColourScale('likes') props.onMapColourScale('typology_likes')
} }
const switchToLocalSignificanceMapStyle = (e) => { const switchToLocalSignificanceMapStyle = (e) => {
e.preventDefault(); e.preventDefault();
@ -39,28 +40,33 @@ const CommunityView: React.FunctionComponent<CategoryViewProps> = (props) => {
const { darkLightTheme } = useDisplayPreferences(); const { darkLightTheme } = useDisplayPreferences();
const worthKeepingReasonsNonEmpty = Object.values(props.building.community_type_worth_keeping_reasons ?? {}).some(x => x); const worthKeepingReasonsNonEmpty = Object.values(props.building.community_type_worth_keeping_reasons ?? {}).some(x => x);
return <> return <>
<InfoBox type='warning'> <DataEntryGroup name="Community views on building types" collapsed={false} >
We are testing a new feature in this section! Switch between different colour maps by using the dropdown in the legend pane.
</InfoBox>
<div className='community-opinion-pane'> <div className='community-opinion-pane'>
<InfoBox> <InfoBox>
Can you share your opinion on how well the building works? Here we are collecting data on how well you think specific types of building work (rather than individual buildings), to help ensure we save and reuse all useful buildings and to help improve urban design quality in future.
</InfoBox> </InfoBox>
<UserOpinionEntry {
slug='community_like' /*
title={buildingUserFields.community_like.title} {(props.building.is_domestic === "no" || props.building.is_domestic === "mixed domestic/non-domestic") ?
<>
<UserOpinionEntry
slug='community_like'
title={buildingUserFields.community_like.title}
userValue={props.building.community_like} userValue={props.building.community_like}
onChange={props.onSaveChange} onChange={props.onSaveChange}
mode={props.mode} mode={props.mode}
copy={props.copy} copy={props.copy}
/>
/> <button className={`map-switcher-inline ${props.mapColourScale == "likes" ? "enabled-state" : "disabled-state"} btn btn-outline btn-outline-dark ${darkLightTheme}`} onClick={switchToLikesMapStyle}>
<button className={`map-switcher-inline ${props.mapColourScale == "likes" ? "enabled-state" : "disabled-state"} btn btn-outline btn-outline-dark ${darkLightTheme}`} onClick={switchToLikesMapStyle}> {(props.mapColourScale == "likes")? 'Showing likes for specific buildings' : 'Click to see likes for specific buildings mapped'}
{'Click here to switch map key to this info'} </button>
</button> </>
<LogicalDataEntry : <></>}
*/
}
<LogicalDataEntryYesOnly
slug='community_type_worth_keeping' slug='community_type_worth_keeping'
title={buildingUserFields.community_type_worth_keeping.title} title={buildingUserFields.community_type_worth_keeping.title}
@ -73,7 +79,7 @@ const CommunityView: React.FunctionComponent<CategoryViewProps> = (props) => {
/> />
{ {
props.building.community_type_worth_keeping !== false && props.building.community_type_worth_keeping === true &&
<MultiSelectDataEntry <MultiSelectDataEntry
slug='community_type_worth_keeping_reasons' slug='community_type_worth_keeping_reasons'
title={buildingUserFields.community_type_worth_keeping_reasons.title} title={buildingUserFields.community_type_worth_keeping_reasons.title}
@ -91,6 +97,14 @@ const CommunityView: React.FunctionComponent<CategoryViewProps> = (props) => {
mode={props.mode} mode={props.mode}
/> />
} }
{
/*
<button className={`map-switcher-inline ${props.mapColourScale == "typology_likes" ? "enabled-state" : "disabled-state"} btn btn-outline btn-outline-dark ${darkLightTheme}`} onClick={switchToTypologyMapStyle}>
{(props.mapColourScale == "typology_likes")? 'Showing likes for typologies (not about specific buildings)' : 'Click to see views on building typologies'}
</button>
*/
}
<hr />
<UserOpinionEntry <UserOpinionEntry
@ -103,9 +117,17 @@ const CommunityView: React.FunctionComponent<CategoryViewProps> = (props) => {
mode={props.mode} mode={props.mode}
copy={props.copy} copy={props.copy}
/> />
<button className={`map-switcher-inline ${props.mapColourScale == "community_local_significance_total" ? "enabled-state" : "disabled-state"} btn btn-outline btn-outline-dark ${darkLightTheme}`} onClick={switchToLocalSignificanceMapStyle}> {(props.mapColourScale == "community_local_significance_total") ?
{'Click here to switch map key to this info'} <button className={`map-switcher-inline enabled-state btn btn-outline btn-outline-dark ${darkLightTheme}`} onClick={switchToTypologyMapStyle}>
{'Click to return to liked typologies mapped.'}
</button>
:
<button className={`map-switcher-inline disabled-state btn btn-outline btn-outline-dark ${darkLightTheme}`} onClick={switchToLocalSignificanceMapStyle}>
{"Click here to change map to buildings of local interest."}
</button> </button>
}
<hr />
<UserOpinionEntry <UserOpinionEntry
slug='community_expected_planning_application' slug='community_expected_planning_application'
title={buildingUserFields.community_expected_planning_application.title} title={buildingUserFields.community_expected_planning_application.title}
@ -116,13 +138,23 @@ const CommunityView: React.FunctionComponent<CategoryViewProps> = (props) => {
mode={props.mode} mode={props.mode}
copy={props.copy} copy={props.copy}
/> />
<button className={`map-switcher-inline ${props.mapColourScale == "community_expected_planning_application_total" ? "enabled-state" : "disabled-state"} btn btn-outline btn-outline-dark ${darkLightTheme}`} onClick={switchToExpectedApplicationMapStyle}> {(props.mapColourScale == "community_expected_planning_application_total") ?
{'Click here to switch map key to this info'} <button className={`map-switcher-inline enabled-state btn btn-outline btn-outline-dark ${darkLightTheme}`} onClick={switchToTypologyMapStyle}>
{'Click to return to liked typologies mapped.'}
</button>
:
<button className={`map-switcher-inline disabled-state btn btn-outline btn-outline-dark ${darkLightTheme}`} onClick={switchToExpectedApplicationMapStyle}>
{"Click here to change map to planning applications expected by community."}
</button> </button>
<InfoBox>You can click and colour any other building on the map as well.</InfoBox> }
</div>
<InfoBox>Can you help add information on community use of buildings?</InfoBox>
</div>
</DataEntryGroup>
<DataEntryGroup name="Building use for community activities" collapsed={false} >
<InfoBox>
Here we are collecting information on the location of buildings used for community activities so we can track loss of/additions to community space over time
</InfoBox>
<LogicalDataEntry <LogicalDataEntry
slug='community_activities_current' slug='community_activities_current'
title={dataFields.community_activities_current.title} title={dataFields.community_activities_current.title}
@ -177,9 +209,6 @@ const CommunityView: React.FunctionComponent<CategoryViewProps> = (props) => {
mode={props.mode} mode={props.mode}
copy={props.copy} copy={props.copy}
/> />
<button className={`map-switcher-inline ${props.mapColourScale == "community_in_public_ownership" ? "enabled-state" : "disabled-state"} btn btn-outline btn-outline-dark ${darkLightTheme}`} onClick={switchToPublicOwnershipMapStyle}>
{'Click here to switch map key to this info'}
</button>
<Verification <Verification
slug="community_public_ownership" slug="community_public_ownership"
allow_verify={props.user !== undefined && props.building.community_public_ownership !== null && !props.edited} allow_verify={props.user !== undefined && props.building.community_public_ownership !== null && !props.edited}
@ -207,6 +236,16 @@ const CommunityView: React.FunctionComponent<CategoryViewProps> = (props) => {
user_verified_as={props.user_verified.community_public_ownership_sources} user_verified_as={props.user_verified.community_public_ownership_sources}
verified_count={props.building.verified.community_public_ownership_sources} verified_count={props.building.verified.community_public_ownership_sources}
/> />
{(props.mapColourScale == "community_in_public_ownership") ?
<button className={`map-switcher-inline enabled-state btn btn-outline btn-outline-dark ${darkLightTheme}`} onClick={switchToTypologyMapStyle}>
{'Click to return to liked typologies mapped.'}
</button>
:
<button className={`map-switcher-inline disabled-state btn btn-outline btn-outline-dark ${darkLightTheme}`} onClick={switchToPublicOwnershipMapStyle}>
{"Click here to see ownership type mapped."}
</button>
}
</DataEntryGroup>
</> </>
}; };
const CommunityContainer = withCopyEdit(CommunityView); const CommunityContainer = withCopyEdit(CommunityView);

View File

@ -106,11 +106,11 @@ const PlanningView: React.FunctionComponent<CategoryViewProps> = (props) => {
<InfoBox type='info'>Click and colour buildings here if you think they may be subject to a future planning application involving demolition. To add your opinion on how well this building works, please also visit the <Link to={communityLinkUrl}>Community</Link> section.</InfoBox> <InfoBox type='info'>Click and colour buildings here if you think they may be subject to a future planning application involving demolition. To add your opinion on how well this building works, please also visit the <Link to={communityLinkUrl}>Community</Link> section.</InfoBox>
{ {
props.mapColourScale != "community_expected_planning_application_total" ? props.mapColourScale != "community_expected_planning_application_total" ?
<button className={`map-switcher-inline no-applicable-state btn btn-outline btn-outline-dark ${darkLightTheme}`} onClick={switchToExpectedApplicationMapStyle}> <button className={`map-switcher-inline disabled-state btn btn-outline btn-outline-dark ${darkLightTheme}`} onClick={switchToExpectedApplicationMapStyle}>
{'Click here to view possible locations of future applications'} {'Click here to view possible locations of future applications'}
</button> </button>
: :
<button className={`map-switcher-inline no-applicable-state btn btn-outline btn-outline-dark ${darkLightTheme}`} onClick={switchToAllPlanningApplicationsMapStyle}> <button className={`map-switcher-inline enabled-state btn btn-outline btn-outline-dark ${darkLightTheme}`} onClick={switchToAllPlanningApplicationsMapStyle}>
{'Click to see planning applications'} {'Click to see planning applications'}
</button> </button>
} }
@ -210,11 +210,11 @@ const PlanningView: React.FunctionComponent<CategoryViewProps> = (props) => {
</div> </div>
{ {
props.mapColourScale != "planning_combined" ? props.mapColourScale != "planning_combined" ?
<button className={`map-switcher-inline no-applicable-state btn btn-outline btn-outline-dark ${darkLightTheme}`} onClick={switchToBuildingProtectionMapStyle}> <button className={`map-switcher-inline disabled-state btn btn-outline btn-outline-dark ${darkLightTheme}`} onClick={switchToBuildingProtectionMapStyle}>
{'Click to see individual protected buildings mapped'} {'Click to see individual protected buildings mapped'}
</button> </button>
: :
<button className={`map-switcher-inline no-applicable-state btn btn-outline btn-outline-dark ${darkLightTheme}`} onClick={switchToAllPlanningApplicationsMapStyle}> <button className={`map-switcher-inline enabled-state btn btn-outline btn-outline-dark ${darkLightTheme}`} onClick={switchToAllPlanningApplicationsMapStyle}>
{'Click to see planning applications'} {'Click to see planning applications'}
</button> </button>
} }

View File

@ -5,22 +5,47 @@ import { dataFields } from '../../config/data-fields-config';
import DataEntry from '../data-components/data-entry'; import DataEntry from '../data-components/data-entry';
import { MultiDataEntry } from '../data-components/multi-data-entry/multi-data-entry'; import { MultiDataEntry } from '../data-components/multi-data-entry/multi-data-entry';
import SelectDataEntry from '../data-components/select-data-entry'; import SelectDataEntry from '../data-components/select-data-entry';
import { LogicalDataEntry } from '../data-components/logical-data-entry/logical-data-entry';
import TextboxDataEntry from '../data-components/textbox-data-entry'; import TextboxDataEntry from '../data-components/textbox-data-entry';
import withCopyEdit from '../data-container'; import withCopyEdit from '../data-container';
import { CategoryViewProps } from './category-view-props'; import { CategoryViewProps } from './category-view-props';
import Verification from '../data-components/verification'; import Verification from '../data-components/verification';
import { useDisplayPreferences } from '../../displayPreferences-context';
/** /**
* Use view/edit section * Use view/edit section
*/ */
const UseView: React.FunctionComponent<CategoryViewProps> = (props) => { const UseView: React.FunctionComponent<CategoryViewProps> = (props) => {
if (props.building.current_landuse_source == "Expert/personal knowledge of building" || const switchToIsDomesticMapStyle = (e) => {
props.building.current_landuse_source == "Online streetview image" || e.preventDefault();
props.building.current_landuse_source == null props.onMapColourScale('is_domestic')
){ }
const { darkLightTheme } = useDisplayPreferences();
return ( return (
<Fragment> <Fragment>
<SelectDataEntry
title={dataFields.is_domestic.title}
slug="is_domestic"
value={props.building.is_domestic}
options={["yes", "no", "mixed domestic/non-domestic"]}
mode={props.mode}
copy={props.copy}
onChange={props.onChange}
tooltip={dataFields.is_domestic.tooltip}
/>
<Verification
slug="is_domestic"
allow_verify={props.user !== undefined && props.building.is_domestic !== null && !props.edited}
onVerify={props.onVerify}
user_verified={props.user_verified.hasOwnProperty("is_domestic")}
user_verified_as={props.user_verified.is_domestic}
verified_count={props.building.verified.is_domestic}
/>
Work from home does not count as office and does not make building non-domestic.
<button className={`map-switcher-inline ${props.mapColourScale == "is_domestic" ? "enabled-state" : "disabled-state"} btn btn-outline btn-outline-dark ${darkLightTheme}`} onClick={switchToIsDomesticMapStyle}>
{(props.mapColourScale == "is_domestic")? 'Showing domestic status for specific buildings' : 'Click to see domestic status for specific buildings mapped'}
</button>
<InfoBox msg="93% of properties in UK are dwellings so we have set this as the default colour. Can you help us colour-in all non-residential and mixed use buildings, and verify residential buildings too?"></InfoBox> <InfoBox msg="93% of properties in UK are dwellings so we have set this as the default colour. Can you help us colour-in all non-residential and mixed use buildings, and verify residential buildings too?"></InfoBox>
<MultiDataEntry <MultiDataEntry
title={dataFields.current_landuse_group.title} title={dataFields.current_landuse_group.title}
@ -77,68 +102,10 @@ const UseView: React.FunctionComponent<CategoryViewProps> = (props) => {
user_verified_as={props.user_verified.current_landuse_source} user_verified_as={props.user_verified.current_landuse_source}
verified_count={props.building.verified.current_landuse_source} verified_count={props.building.verified.current_landuse_source}
/> />
</Fragment> {(props.building.current_landuse_source == "Expert/personal knowledge of building" ||
); props.building.current_landuse_source == "Online streetview image" ||
}; props.building.current_landuse_source == null) ? <></> :
return ( <><MultiDataEntry
<Fragment>
<InfoBox msg="93% of properties in UK are dwellings so we have set this as the default colour. Can you help us colour-in all non-residential and mixed use buildings, and verify residential buildings too?"></InfoBox>
<MultiDataEntry
title={dataFields.current_landuse_group.title}
slug="current_landuse_group"
value={props.building.current_landuse_group}
mode={props.mode}
copy={props.copy}
onChange={props.onChange}
confirmOnEnter={true}
tooltip={dataFields.current_landuse_group.tooltip}
placeholder="Type new land use group here"
copyable={true}
autofill={true}
showAllOptionsOnEmpty={true}
/>
<Verification
slug="current_landuse_group"
allow_verify={props.user !== undefined && props.building.current_landuse_group !== null && !props.edited}
onVerify={props.onVerify}
user_verified={props.user_verified.hasOwnProperty("current_landuse_group")}
user_verified_as={props.user_verified.current_landuse_group && props.user_verified.current_landuse_group.join(", ")}
verified_count={props.building.verified.current_landuse_group}
/>
{
props.mode != 'view' &&
<InfoBox msg="Land use order, shown below, is automatically derived from the land use groups"></InfoBox>
}
<DataEntry
title={dataFields.current_landuse_order.title}
tooltip={dataFields.current_landuse_order.tooltip}
slug="current_landuse_order"
value={props.building.current_landuse_order}
mode={props.mode}
disabled={true}
copy={props.copy}
onChange={props.onChange}
/>
<SelectDataEntry
title={dataFields.current_landuse_source.title}
slug="current_landuse_source"
value={props.building.current_landuse_source}
mode={props.mode}
copy={props.copy}
onChange={props.onChange}
tooltip={dataFields.current_landuse_source.tooltip}
placeholder={dataFields.current_landuse_source.example}
options={dataFields.current_landuse_source.items}
/>
<Verification
slug="current_landuse_source"
allow_verify={props.user !== undefined && props.building.current_landuse_source !== null && !props.edited}
onVerify={props.onVerify}
user_verified={props.user_verified.hasOwnProperty("current_landuse_source")}
user_verified_as={props.user_verified.current_landuse_source}
verified_count={props.building.verified.current_landuse_source}
/>
<MultiDataEntry
title={dataFields.current_landuse_link.title} title={dataFields.current_landuse_link.title}
slug="current_landuse_link" slug="current_landuse_link"
value={props.building.current_landuse_link} value={props.building.current_landuse_link}
@ -158,8 +125,10 @@ const UseView: React.FunctionComponent<CategoryViewProps> = (props) => {
user_verified_as={props.user_verified.current_landuse_link} user_verified_as={props.user_verified.current_landuse_link}
verified_count={props.building.verified.current_landuse_link} verified_count={props.building.verified.current_landuse_link}
/> />
</Fragment> </>
); }
</Fragment>
);
}; };
const UseContainer = withCopyEdit(UseView); const UseContainer = withCopyEdit(UseView);

View File

@ -108,6 +108,7 @@ export const categoryMapsConfig: {[key in Category]: CategoryMapDefinition[]} =
}, },
}], }],
[Category.Community]: [ [Category.Community]: [
/*
{ {
mapStyle: 'likes', mapStyle: 'likes',
legend: { legend: {
@ -123,11 +124,27 @@ export const categoryMapsConfig: {[key in Category]: CategoryMapDefinition[]} =
] ]
} }
}, },
*/
{
mapStyle: 'typology_likes',
legend: {
title: 'Liked typologies',
elements: [
{ color: '#bd0026', text: '👍👍👍👍 100+' },
{ color: '#e31a1c', text: '👍👍👍 5099' },
{ color: '#fc4e2a', text: '👍👍 2049' },
{ color: '#fd8d3c', text: '👍👍 1019' },
{ color: '#feb24c', text: '👍 39' },
{ color: '#fed976', text: '👍 2' },
{ color: '#ffe8a9', text: '👍 1'}
]
}
},
{ {
mapStyle: 'community_local_significance_total', mapStyle: 'community_local_significance_total',
legend: { legend: {
title: 'Local Significance', title: 'Local Interest',
description: 'People who think the building should be locally listed', description: 'People who think the building is of a local interest',
elements: [ elements: [
{ color: '#bd0026', text: '100+' }, { color: '#bd0026', text: '100+' },
{ color: '#e31a1c', text: '5099' }, { color: '#e31a1c', text: '5099' },
@ -278,29 +295,42 @@ export const categoryMapsConfig: {[key in Category]: CategoryMapDefinition[]} =
] ]
}, },
}], }],
[Category.LandUse]: [{ [Category.LandUse]: [
mapStyle: 'landuse', {
legend: { mapStyle: 'is_domestic',
title: 'Land Use', legend: {
elements: [ title: 'Is domestic building?',
{ color: '#e5050d', text: 'Mixed Use' }, elements: [
{ subtitle: 'Single use:'}, { color: '#f7ec25', text: 'Domestic' },
{ color: '#252aa6', text: 'Residential (unverified)' }, { color: '#fc9b2a', text: 'Mixed' },
{ color: '#7025a6', text: 'Residential (verified)' }, { color: '#ff2121', text: 'Non-domestic' },
{ color: '#ff8c00', text: 'Retail' }, ]
{ color: '#f5f58f', text: 'Industry & Business' }, }
{ color: '#fa667d', text: 'Community Services' }, },
{ color: '#ffbfbf', text: 'Recreation & Leisure' }, {
{ color: '#b3de69', text: 'Transport' }, mapStyle: 'landuse',
{ color: '#cccccc', text: 'Utilities & Infrastructure' }, legend: {
{ color: '#898944', text: 'Defence' }, title: 'Land Use',
{ color: '#73ccd1', text: 'Agriculture' }, elements: [
{ color: '#45cce3', text: 'Minerals' }, { color: '#e5050d', text: 'Mixed Use' },
{ color: '#ffffff', text: 'Vacant & Derelict' }, { subtitle: 'Single use:'},
{ color: '#6c6f8e', text: 'Unclassified, presumed non-residential' } { color: '#252aa6', text: 'Residential (unverified)' },
] { color: '#7025a6', text: 'Residential (verified)' },
}, { color: '#ff8c00', text: 'Retail' },
}], { color: '#f5f58f', text: 'Industry & Business' },
{ color: '#fa667d', text: 'Community Services' },
{ color: '#ffbfbf', text: 'Recreation & Leisure' },
{ color: '#b3de69', text: 'Transport' },
{ color: '#cccccc', text: 'Utilities & Infrastructure' },
{ color: '#898944', text: 'Defence' },
{ color: '#73ccd1', text: 'Agriculture' },
{ color: '#45cce3', text: 'Minerals' },
{ color: '#ffffff', text: 'Vacant & Derelict' },
{ color: '#6c6f8e', text: 'Unclassified, presumed non-residential' }
]
},
}
],
[Category.Streetscape]: [{ [Category.Streetscape]: [{
mapStyle: undefined, mapStyle: undefined,
legend: { legend: {

View File

@ -73,22 +73,28 @@ export const buildingUserFields = {
community_type_worth_keeping: { community_type_worth_keeping: {
perUser: true, perUser: true,
category: Category.Community, category: Category.Community,
title: "Do you think this **type** of building is generally worth keeping?", title: "Do you think this **type** of building is contributes to the city?",
example: true, example: true,
}, },
community_type_worth_keeping_reasons: { community_type_worth_keeping_reasons: {
perUser: true, perUser: true,
category: Category.Community, category: Category.Community,
title: 'Why is this type of building worth keeping?', title: 'Please tick one or more boxes below',
fields: { fields: {
external_design: { external_design: {
title: "because the external design contributes to the streetscape" title: "Because the external design contributes to the streetscape"
}, },
internal_design: { internal_design: {
title: 'because the internal design works well' title: 'Because the internal layout works well'
}, },
adaptable: { adaptable: {
title: 'because the building is adaptable / can be reused to make the city more sustainable' title: 'Because the building can be easily adapted and reused'
},
using_outside_space: {
title: 'Because the building incorporates outside space'
},
durable: {
title: 'Because the construction method and materials are likely to be long-lasting'
}, },
other: { other: {
title: 'other' title: 'other'
@ -98,6 +104,8 @@ export const buildingUserFields = {
external_design: true, external_design: true,
internal_design: true, internal_design: true,
adaptable: false, adaptable: false,
using_outside_space: true,
durable: true,
other: false other: false
} }
}, },
@ -105,7 +113,7 @@ export const buildingUserFields = {
community_local_significance: { community_local_significance: {
perUser: true, perUser: true,
category: Category.Community, category: Category.Community,
title: "Do you think this building should be recorded as a local heritage asset?", title: "Do you think this building should be recorded as being of special local interest?",
example: true example: true
}, },
community_expected_planning_application: { community_expected_planning_application: {
@ -563,16 +571,26 @@ export const dataFields = { /* eslint-disable @typescript-eslint/camelcase */
//tooltip: , //tooltip: ,
}, },
is_domestic: {
category: Category.Team,
title: "Is the building a home/domestic building?",
tooltip: "",
example: "mixed domestic/non-domestic"
},
likes_total: { likes_total: {
category: Category.Community, category: Category.Community,
title: "Total number of likes", title: "Total number of likes",
example: 100, example: 100,
tooltip: "People who like the building and think it contributes to the city.", tooltip: "People who like the building and think it contributes to the city.",
}, },
community_type_worth_keeping_total: {
category: Category.Community,
title: "People who think this type of building is contributes to the city.",
example: 100,
},
community_local_significance_total: { community_local_significance_total: {
category: Category.Community, category: Category.Community,
title: "People who think the building should be recorded as one of local significance", title: "People who think the building should be recorded as one of local interest",
example: 100, example: 100,
}, },

View File

@ -7,7 +7,9 @@ export type BuildingMapTileset = 'date_year' |
'size_height' | 'size_height' |
'construction_core_material' | 'construction_core_material' |
'location' | 'location' |
'is_domestic' |
'likes' | 'likes' |
'typology_likes' |
'community_local_significance_total' | 'community_local_significance_total' |
'community_expected_planning_application_total' | 'community_expected_planning_application_total' |
'community_in_public_ownership' | 'community_in_public_ownership' |

View File

@ -22,6 +22,7 @@
.map-button .btn:hover { .map-button .btn:hover {
color: #fff; color: #fff;
} }
.map-button.night .btn { .map-button.night .btn {
color: #fff; color: #fff;
background-color: #343a40; background-color: #343a40;
@ -33,9 +34,6 @@
background-image: none; background-image: none;
border-color: #343a40; border-color: #343a40;
} }
.map-switcher-inline.night.no-applicable-state {
color: #191b1d;
}
.map-switcher-inline.disabled-state, .map-switcher-inline.disabled-state,
.map-button.disabled-state, .map-button.disabled-state,
.map-button.disabled-state .btn{ .map-button.disabled-state .btn{
@ -63,7 +61,6 @@
background-color: #448844; background-color: #448844;
} }
.map-switcher-inline.night.no-applicable-state,
.map-button.enabled .btn:hover, .map-button.enabled .btn:hover,
.map-button.night.enabled .btn:hover { .map-button.night.enabled .btn:hover {
background-color: transparent; background-color: transparent;
@ -125,23 +122,15 @@
border-radius: 4px; border-radius: 4px;
/*background: #FFC0CB;*/ /*background: #FFC0CB;*/
margin: 12px; margin: 12px;
min-width: 400px; width: 400px;
color: #343a40; color: #343a40;
} }
.map-switcher-inline.night { .map-switcher-inline.night {
color: #d4d7da;
}
/*
.map-switcher-inline.night {
background: #FFC0CB;
color: #fff; color: #fff;
background-color: #343a40;
border-color: #ff6065;
} }
.map-switcher-inline.night .btn:hover { .map-switcher-inline.night :hover {
color: #343a40; color: #d4d7da;
background-color: transparent; background-color: transparent;
background-image: none; background-image: none;
border-color: #ff6065; border-color: #ff6065;
} }
*/

View File

@ -109,6 +109,14 @@ const LAYER_QUERIES = {
) AS team_info_count ) AS team_info_count
FROM FROM
buildings`, buildings`,
is_domestic: `
SELECT
geometry_id,
is_domestic
FROM
buildings
WHERE
is_domestic IS NOT NULL`,
likes: ` likes: `
SELECT SELECT
geometry_id, geometry_id,
@ -116,7 +124,17 @@ const LAYER_QUERIES = {
FROM FROM
buildings buildings
WHERE WHERE
is_domestic <> 'yes'
AND
likes_total > 0`, likes_total > 0`,
typology_likes: `
SELECT
geometry_id,
community_type_worth_keeping_total AS likes
FROM
buildings
WHERE
community_type_worth_keeping_total > 0`,
community_local_significance_total: ` community_local_significance_total: `
SELECT SELECT
geometry_id, geometry_id,

View File

@ -54,6 +54,8 @@ COPY (SELECT
planning_in_apa_url, planning_in_apa_url,
planning_local_list_url, planning_local_list_url,
planning_historic_area_assessment_url, planning_historic_area_assessment_url,
is_domestic,
community_type_worth_keeping_total,
likes_total likes_total
FROM buildings) FROM buildings)
TO '/tmp/building_attributes.csv' TO '/tmp/building_attributes.csv'

View File

@ -0,0 +1,2 @@
ALTER TABLE buildings DROP COLUMN IF EXISTS is_domestic;
ALTER TABLE buildings DROP COLUMN IF EXISTS community_type_worth_keeping_total;

View File

@ -0,0 +1,15 @@
ALTER TABLE buildings ADD COLUMN IF NOT EXISTS is_domestic text null;
ALTER TABLE buildings ADD COLUMN IF NOT EXISTS community_type_worth_keeping_total integer DEFAULT 0;
-- Provide counts for already liked typologies
UPDATE buildings
SET community_type_worth_keeping_total = (
SELECT count(*)
FROM building_user_attributes
WHERE buildings.building_id = building_user_attributes.building_id
AND community_type_worth_keeping = TRUE
)
WHERE buildings.building_id in (
SELECT DISTINCT building_id
FROM building_user_attributes
);