Merge remote-tracking branch 'upstream/master'
This commit is contained in:
commit
4c4cfdc145
2
.github/ISSUE_TEMPLATE/bug_report.md
vendored
2
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@ -1,6 +1,6 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Describe a problem to help us improve Colouring London
|
||||
about: Describe a problem to help us improve Colouring Cities
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
@ -6,8 +6,8 @@ The format is `fix/123-short-description`, `feature/description` or `feature/123
|
||||
|
||||
|
||||
For example
|
||||
* [PR 648](https://github.com/colouring-london/colouring-london/pull/684) used branch `fix/681-land-use-edit` referencing [#681](https://github.com/colouring-london/colouring-london/issues/681)
|
||||
* [PR 625](https://github.com/colouring-london/colouring-london/pull/625) used branch `feature/verification`
|
||||
* [PR 648](https://github.com/colouring-cities/colouring-core/pull/684) used branch `fix/681-land-use-edit` referencing [#681](https://github.com/colouring-cities/colouring-core/issues/681)
|
||||
* [PR 625](https://github.com/colouring-cities/colouring-core/pull/625) used branch `feature/verification`
|
||||
|
||||
## Commits
|
||||
|
||||
|
26
README.md
26
README.md
@ -1,15 +1,15 @@
|
||||
# Colouring London
|
||||
# Colouring Cities Core Platform
|
||||
[![All Contributors](https://img.shields.io/badge/all_contributors-12-orange.svg?style=flat-square)](#contributors)
|
||||
![Build status](https://github.com/colouring-london/colouring-london/workflows/Node.js%20CI/badge.svg)
|
||||
![Build status](https://github.com/colouring-cities/colouring-core/workflows/Node.js%20CI/badge.svg)
|
||||
|
||||
How many buildings are there in London? What are their characteristics? Where
|
||||
How many buildings are there in a city? What are their characteristics? Where
|
||||
are they located and how do they contribute to the city? How adaptable are
|
||||
they? How long will they last, and what are the environmental and
|
||||
socio-economic implications of demolition?
|
||||
|
||||
[Colouring London](http://colouring.london/) is a web-based citizen social
|
||||
Colouring Cities is a web-based citizen social
|
||||
science project designed to help address these questions by crowdsourcing and
|
||||
visualising twelve categories of information on London’s buildings.
|
||||
visualising twelve categories of information on the buildings in our cities.
|
||||
|
||||
## Structure
|
||||
|
||||
@ -26,9 +26,17 @@ for download under a liberal open data license
|
||||
|
||||
## Setup and run
|
||||
|
||||
#### Customise the Application:
|
||||
|
||||
You can customise the Colouring Cities application by changing the values in the following file:
|
||||
|
||||
`app/src/cc-config.json`
|
||||
|
||||
For more information on the config system, see [docs/configuring-colouring-cities](docs/configuring-colouring-cities.md).
|
||||
|
||||
#### Test the application:
|
||||
|
||||
You can try out the Colouring London application by setting up your own development environment, which includes the option to load test data from OpenStreetMaps (OSM). See [docs/setup-dev-environment](docs/setup-dev-environment.md).
|
||||
You can try out the Colouring Cities application by setting up your own development environment, which includes the option to load test data from OpenStreetMaps (OSM). See [docs/setup-dev-environment](docs/setup-dev-environment.md).
|
||||
|
||||
_Last updated March 2022_
|
||||
|
||||
@ -50,8 +58,8 @@ and technical support.
|
||||
|
||||
## License
|
||||
|
||||
Colouring London
|
||||
Copyright (C) 2018-2022 Tom Russell and Colouring London contributors
|
||||
Colouring London/Colouring Cities
|
||||
Copyright (C) 2018-2022 Tom Russell and Colouring Cities contributors
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@ -107,6 +115,6 @@ Thanks goes to these wonderful people ([emoji key](https://github.com/all-contri
|
||||
|
||||
This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome!
|
||||
|
||||
Even more thanks go to Colouring London contributors, funders, project partners, consultees,
|
||||
Even more thanks go to Colouring Cities contributors, funders, project partners, consultees,
|
||||
advisers, supporters and friends - [everyone involved in the
|
||||
project](https://www.pages.colouring.london/whoisinvolved).
|
||||
|
@ -599,6 +599,30 @@
|
||||
<LineSymbolizer stroke="#888" stroke-width="2.0"/>
|
||||
</Rule>
|
||||
</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">
|
||||
<Rule>
|
||||
<Filter>[likes] >= 100</Filter>
|
||||
@ -640,6 +664,47 @@
|
||||
<LineSymbolizer stroke="#888" stroke-width="3.0"/>
|
||||
</Rule>
|
||||
</Style>
|
||||
<Style name="typology_likes">
|
||||
<Rule>
|
||||
<Filter>[likes] >= 100</Filter>
|
||||
<PolygonSymbolizer fill="#bd0026" />
|
||||
</Rule>
|
||||
<Rule>
|
||||
<Filter>[likes] >= 50 and [likes] < 100</Filter>
|
||||
<PolygonSymbolizer fill="#e31a1c" />
|
||||
</Rule>
|
||||
<Rule>
|
||||
<Filter>[likes] >= 20 and [likes] < 50</Filter>
|
||||
<PolygonSymbolizer fill="#fc4e2a" />
|
||||
</Rule>
|
||||
<Rule>
|
||||
<Filter>[likes] >= 10 and [likes] < 20</Filter>
|
||||
<PolygonSymbolizer fill="#fd8d3c" />
|
||||
</Rule>
|
||||
<Rule>
|
||||
<Filter>[likes] >= 3 and [likes] < 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">
|
||||
<Rule>
|
||||
<Filter>[community_local_significance_total] >= 100</Filter>
|
||||
|
@ -19,6 +19,12 @@ export const aggregationsConfig: { [key in keyof typeof buildingUserAttributesCo
|
||||
aggregationMethod: 'countTrue'
|
||||
}
|
||||
],
|
||||
community_type_worth_keeping: [
|
||||
{
|
||||
aggregateFieldName: 'community_type_worth_keeping_total',
|
||||
aggregationMethod: 'countTrue'
|
||||
}
|
||||
],
|
||||
community_local_significance: [
|
||||
{
|
||||
aggregateFieldName: 'community_local_significance_total',
|
||||
|
@ -292,11 +292,20 @@ export const buildingAttributesConfig = valueType<DataFieldConfig>()({ /* eslint
|
||||
sqlCast: 'jsonb',
|
||||
},
|
||||
|
||||
is_domestic: {
|
||||
edit: true,
|
||||
verify: true
|
||||
},
|
||||
likes_total: {
|
||||
edit: false,
|
||||
derivedEdit: true,
|
||||
verify: false
|
||||
},
|
||||
community_type_worth_keeping_total: {
|
||||
edit: false,
|
||||
derivedEdit: true,
|
||||
verify: false
|
||||
},
|
||||
community_local_significance_total: {
|
||||
edit: false,
|
||||
derivedEdit: true,
|
||||
|
@ -6,4 +6,4 @@
|
||||
|
||||
"initialMapPosition": [ 51.5245255, -0.1338422 ],
|
||||
"initialZoomLevel": 16
|
||||
}
|
||||
}
|
||||
|
@ -5,8 +5,7 @@
|
||||
font-weight: 410;
|
||||
}
|
||||
.data-entry-group-header .data-entry-group-title {
|
||||
position: absolute;
|
||||
left: 1rem;
|
||||
padding-left: 0.6rem;
|
||||
}
|
||||
|
||||
.data-entry-group-count {
|
||||
|
@ -145,3 +145,31 @@ export const LogicalDataEntryYesOnly: React.FC<LogicalDataEntryProps> = (props)
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export const LogicalDataEntryYesOnlyWithExplanation: React.FC<LogicalDataEntryProps> = (props) => {
|
||||
function handleValueChange(e: React.ChangeEvent<HTMLInputElement>) {
|
||||
props.onChange?.(props.slug, e.target.checked);
|
||||
}
|
||||
|
||||
const isDisabled = props.mode === 'view' || props.disabled;
|
||||
|
||||
return (
|
||||
<>
|
||||
<DataTitleCopyable
|
||||
slug={props.slug}
|
||||
title={props.title}
|
||||
tooltip={props.tooltip}
|
||||
disabled={props.disabled || props.value == undefined}
|
||||
copy={props.copy}
|
||||
/>
|
||||
<label className="form-check-label">
|
||||
<input className="form-check-input" type="checkbox"
|
||||
name={props.slug}
|
||||
checked={props.value === true}
|
||||
disabled={isDisabled || props.disallowTrue}
|
||||
onChange={handleValueChange}
|
||||
/> Yes (tick to add or remove your edit)
|
||||
</label>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
@ -29,7 +29,7 @@ const UserOpinionEntry: React.FunctionComponent<UserOpinionEntryProps> = (props)
|
||||
checked={!!props.userValue}
|
||||
disabled={props.mode === 'view'}
|
||||
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>
|
||||
</>
|
||||
);
|
||||
|
@ -97,6 +97,7 @@ const withCopyEdit: (wc: React.ComponentType<CategoryViewProps>) => DataContaine
|
||||
'current_landuse_verified',
|
||||
'planning_list_grade',
|
||||
'likes_total',
|
||||
'community_type_worth_keeping_total',
|
||||
'community_local_significance_total',
|
||||
'community_expected_planning_application_total'
|
||||
]
|
||||
|
@ -4,10 +4,11 @@ import '../../map/map-button.css';
|
||||
import withCopyEdit from '../data-container';
|
||||
import UserOpinionEntry from '../data-components/user-opinion-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 InfoBox from '../../components/info-box';
|
||||
import { LogicalDataEntry } from '../data-components/logical-data-entry/logical-data-entry';
|
||||
import { LogicalDataEntry, LogicalDataEntryYesOnlyWithExplanation } from '../data-components/logical-data-entry/logical-data-entry';
|
||||
import { buildingUserFields, dataFields } from '../../config/data-fields-config';
|
||||
|
||||
import './community.css';
|
||||
@ -20,9 +21,9 @@ import { useDisplayPreferences } from '../../displayPreferences-context';
|
||||
* Community view/edit section
|
||||
*/
|
||||
const CommunityView: React.FunctionComponent<CategoryViewProps> = (props) => {
|
||||
const switchToLikesMapStyle = (e) => {
|
||||
const switchToTypologyMapStyle = (e) => {
|
||||
e.preventDefault();
|
||||
props.onMapColourScale('likes')
|
||||
props.onMapColourScale('typology_likes')
|
||||
}
|
||||
const switchToLocalSignificanceMapStyle = (e) => {
|
||||
e.preventDefault();
|
||||
@ -39,28 +40,33 @@ const CommunityView: React.FunctionComponent<CategoryViewProps> = (props) => {
|
||||
const { darkLightTheme } = useDisplayPreferences();
|
||||
const worthKeepingReasonsNonEmpty = Object.values(props.building.community_type_worth_keeping_reasons ?? {}).some(x => x);
|
||||
return <>
|
||||
<InfoBox type='warning'>
|
||||
We are testing a new feature in this section! Switch between different colour maps by using the dropdown in the legend pane.
|
||||
</InfoBox>
|
||||
<DataEntryGroup name="Community views on building types" collapsed={false} >
|
||||
<div className='community-opinion-pane'>
|
||||
<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>
|
||||
<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}
|
||||
mode={props.mode}
|
||||
copy={props.copy}
|
||||
|
||||
/>
|
||||
<button className={`map-switcher-inline ${props.mapColourScale == "likes" ? "enabled-state" : "disabled-state"} btn btn-outline btn-outline-dark ${darkLightTheme}`} onClick={switchToLikesMapStyle}>
|
||||
{'Click here to switch map key to this info'}
|
||||
</button>
|
||||
<LogicalDataEntry
|
||||
onChange={props.onSaveChange}
|
||||
mode={props.mode}
|
||||
copy={props.copy}
|
||||
/>
|
||||
<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'}
|
||||
</button>
|
||||
</>
|
||||
: <></>}
|
||||
*/
|
||||
}
|
||||
<LogicalDataEntryYesOnlyWithExplanation
|
||||
slug='community_type_worth_keeping'
|
||||
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
|
||||
slug='community_type_worth_keeping_reasons'
|
||||
title={buildingUserFields.community_type_worth_keeping_reasons.title}
|
||||
@ -91,6 +97,14 @@ const CommunityView: React.FunctionComponent<CategoryViewProps> = (props) => {
|
||||
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
|
||||
@ -103,9 +117,17 @@ const CommunityView: React.FunctionComponent<CategoryViewProps> = (props) => {
|
||||
mode={props.mode}
|
||||
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}>
|
||||
{'Click here to switch map key to this info'}
|
||||
{(props.mapColourScale == "community_local_significance_total") ?
|
||||
<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>
|
||||
}
|
||||
|
||||
<hr />
|
||||
<UserOpinionEntry
|
||||
slug='community_expected_planning_application'
|
||||
title={buildingUserFields.community_expected_planning_application.title}
|
||||
@ -116,13 +138,23 @@ const CommunityView: React.FunctionComponent<CategoryViewProps> = (props) => {
|
||||
mode={props.mode}
|
||||
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}>
|
||||
{'Click here to switch map key to this info'}
|
||||
{(props.mapColourScale == "community_expected_planning_application_total") ?
|
||||
<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>
|
||||
<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
|
||||
slug='community_activities_current'
|
||||
title={dataFields.community_activities_current.title}
|
||||
@ -177,9 +209,6 @@ const CommunityView: React.FunctionComponent<CategoryViewProps> = (props) => {
|
||||
mode={props.mode}
|
||||
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
|
||||
slug="community_public_ownership"
|
||||
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}
|
||||
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);
|
||||
|
@ -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>
|
||||
{
|
||||
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'}
|
||||
</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'}
|
||||
</button>
|
||||
}
|
||||
@ -210,11 +210,11 @@ const PlanningView: React.FunctionComponent<CategoryViewProps> = (props) => {
|
||||
</div>
|
||||
{
|
||||
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'}
|
||||
</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'}
|
||||
</button>
|
||||
}
|
||||
|
@ -5,22 +5,47 @@ import { dataFields } from '../../config/data-fields-config';
|
||||
import DataEntry from '../data-components/data-entry';
|
||||
import { MultiDataEntry } from '../data-components/multi-data-entry/multi-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 withCopyEdit from '../data-container';
|
||||
|
||||
import { CategoryViewProps } from './category-view-props';
|
||||
import Verification from '../data-components/verification';
|
||||
import { useDisplayPreferences } from '../../displayPreferences-context';
|
||||
|
||||
/**
|
||||
* Use view/edit section
|
||||
*/
|
||||
const UseView: React.FunctionComponent<CategoryViewProps> = (props) => {
|
||||
if (props.building.current_landuse_source == "Expert/personal knowledge of building" ||
|
||||
props.building.current_landuse_source == "Online streetview image" ||
|
||||
props.building.current_landuse_source == null
|
||||
){
|
||||
const switchToIsDomesticMapStyle = (e) => {
|
||||
e.preventDefault();
|
||||
props.onMapColourScale('is_domestic')
|
||||
}
|
||||
const { darkLightTheme } = useDisplayPreferences();
|
||||
return (
|
||||
<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>
|
||||
<MultiDataEntry
|
||||
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}
|
||||
verified_count={props.building.verified.current_landuse_source}
|
||||
/>
|
||||
</Fragment>
|
||||
);
|
||||
};
|
||||
return (
|
||||
<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
|
||||
{(props.building.current_landuse_source == "Expert/personal knowledge of building" ||
|
||||
props.building.current_landuse_source == "Online streetview image" ||
|
||||
props.building.current_landuse_source == null) ? <></> :
|
||||
<><MultiDataEntry
|
||||
title={dataFields.current_landuse_link.title}
|
||||
slug="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}
|
||||
verified_count={props.building.verified.current_landuse_link}
|
||||
/>
|
||||
</Fragment>
|
||||
);
|
||||
</>
|
||||
}
|
||||
</Fragment>
|
||||
);
|
||||
};
|
||||
const UseContainer = withCopyEdit(UseView);
|
||||
|
||||
|
@ -108,6 +108,7 @@ export const categoryMapsConfig: {[key in Category]: CategoryMapDefinition[]} =
|
||||
},
|
||||
}],
|
||||
[Category.Community]: [
|
||||
/*
|
||||
{
|
||||
mapStyle: 'likes',
|
||||
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: '👍👍👍 50–99' },
|
||||
{ color: '#fc4e2a', text: '👍👍 20–49' },
|
||||
{ color: '#fd8d3c', text: '👍👍 10–19' },
|
||||
{ color: '#feb24c', text: '👍 3–9' },
|
||||
{ color: '#fed976', text: '👍 2' },
|
||||
{ color: '#ffe8a9', text: '👍 1'}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
mapStyle: 'community_local_significance_total',
|
||||
legend: {
|
||||
title: 'Local Significance',
|
||||
description: 'People who think the building should be locally listed',
|
||||
title: 'Local Interest',
|
||||
description: 'People who think the building is of a local interest',
|
||||
elements: [
|
||||
{ color: '#bd0026', text: '100+' },
|
||||
{ color: '#e31a1c', text: '50–99' },
|
||||
@ -278,29 +295,42 @@ export const categoryMapsConfig: {[key in Category]: CategoryMapDefinition[]} =
|
||||
]
|
||||
},
|
||||
}],
|
||||
[Category.LandUse]: [{
|
||||
mapStyle: 'landuse',
|
||||
legend: {
|
||||
title: 'Land Use',
|
||||
elements: [
|
||||
{ color: '#e5050d', text: 'Mixed Use' },
|
||||
{ subtitle: 'Single use:'},
|
||||
{ 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.LandUse]: [
|
||||
{
|
||||
mapStyle: 'is_domestic',
|
||||
legend: {
|
||||
title: 'Is domestic building?',
|
||||
elements: [
|
||||
{ color: '#f7ec25', text: 'Domestic' },
|
||||
{ color: '#fc9b2a', text: 'Mixed' },
|
||||
{ color: '#ff2121', text: 'Non-domestic' },
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
mapStyle: 'landuse',
|
||||
legend: {
|
||||
title: 'Land Use',
|
||||
elements: [
|
||||
{ color: '#e5050d', text: 'Mixed Use' },
|
||||
{ subtitle: 'Single use:'},
|
||||
{ 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]: [{
|
||||
mapStyle: undefined,
|
||||
legend: {
|
||||
|
@ -73,22 +73,28 @@ export const buildingUserFields = {
|
||||
community_type_worth_keeping: {
|
||||
perUser: true,
|
||||
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,
|
||||
},
|
||||
community_type_worth_keeping_reasons: {
|
||||
perUser: true,
|
||||
category: Category.Community,
|
||||
title: 'Why is this type of building worth keeping?',
|
||||
title: 'Please tick one or more boxes below',
|
||||
fields: {
|
||||
external_design: {
|
||||
title: "because the external design contributes to the streetscape"
|
||||
title: "Because the external design contributes to the streetscape"
|
||||
},
|
||||
internal_design: {
|
||||
title: 'because the internal design works well'
|
||||
title: 'Because the internal layout works well'
|
||||
},
|
||||
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: {
|
||||
title: 'other'
|
||||
@ -98,6 +104,8 @@ export const buildingUserFields = {
|
||||
external_design: true,
|
||||
internal_design: true,
|
||||
adaptable: false,
|
||||
using_outside_space: true,
|
||||
durable: true,
|
||||
other: false
|
||||
}
|
||||
},
|
||||
@ -105,7 +113,7 @@ export const buildingUserFields = {
|
||||
community_local_significance: {
|
||||
perUser: true,
|
||||
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
|
||||
},
|
||||
community_expected_planning_application: {
|
||||
@ -280,7 +288,7 @@ export const dataFields = { /* eslint-disable @typescript-eslint/camelcase */
|
||||
},
|
||||
date_lower : {
|
||||
category: Category.Age,
|
||||
title: "Earliest possible start date",
|
||||
title: "Earliest possible start year",
|
||||
tooltip: "This should be the earliest year in which building could have started.",
|
||||
example: 1900,
|
||||
},
|
||||
@ -563,16 +571,26 @@ export const dataFields = { /* eslint-disable @typescript-eslint/camelcase */
|
||||
//tooltip: ,
|
||||
},
|
||||
|
||||
is_domestic: {
|
||||
category: Category.Team,
|
||||
title: "Is the building a home/domestic building?",
|
||||
tooltip: "",
|
||||
example: "mixed domestic/non-domestic"
|
||||
},
|
||||
likes_total: {
|
||||
category: Category.Community,
|
||||
title: "Total number of likes",
|
||||
example: 100,
|
||||
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: {
|
||||
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,
|
||||
},
|
||||
|
||||
|
@ -7,7 +7,9 @@ export type BuildingMapTileset = 'date_year' |
|
||||
'size_height' |
|
||||
'construction_core_material' |
|
||||
'location' |
|
||||
'is_domestic' |
|
||||
'likes' |
|
||||
'typology_likes' |
|
||||
'community_local_significance_total' |
|
||||
'community_expected_planning_application_total' |
|
||||
'community_in_public_ownership' |
|
||||
|
@ -22,6 +22,7 @@
|
||||
.map-button .btn:hover {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.map-button.night .btn {
|
||||
color: #fff;
|
||||
background-color: #343a40;
|
||||
@ -33,9 +34,6 @@
|
||||
background-image: none;
|
||||
border-color: #343a40;
|
||||
}
|
||||
.map-switcher-inline.night.no-applicable-state {
|
||||
color: #191b1d;
|
||||
}
|
||||
.map-switcher-inline.disabled-state,
|
||||
.map-button.disabled-state,
|
||||
.map-button.disabled-state .btn{
|
||||
@ -63,7 +61,6 @@
|
||||
background-color: #448844;
|
||||
}
|
||||
|
||||
.map-switcher-inline.night.no-applicable-state,
|
||||
.map-button.enabled .btn:hover,
|
||||
.map-button.night.enabled .btn:hover {
|
||||
background-color: transparent;
|
||||
@ -125,23 +122,15 @@
|
||||
border-radius: 4px;
|
||||
/*background: #FFC0CB;*/
|
||||
margin: 12px;
|
||||
min-width: 400px;
|
||||
width: 400px;
|
||||
color: #343a40;
|
||||
}
|
||||
.map-switcher-inline.night {
|
||||
color: #d4d7da;
|
||||
}
|
||||
/*
|
||||
.map-switcher-inline.night {
|
||||
background: #FFC0CB;
|
||||
color: #fff;
|
||||
background-color: #343a40;
|
||||
border-color: #ff6065;
|
||||
}
|
||||
.map-switcher-inline.night .btn:hover {
|
||||
color: #343a40;
|
||||
.map-switcher-inline.night :hover {
|
||||
color: #d4d7da;
|
||||
background-color: transparent;
|
||||
background-image: none;
|
||||
border-color: #ff6065;
|
||||
}
|
||||
*/
|
@ -16,7 +16,7 @@ const ContactPage = () => (
|
||||
|
||||
<p> You can send us comments or ask questions on our discussion threads at <a href="https://discuss.colouring.london/">https://discuss.colouring.london/</a>.</p>
|
||||
|
||||
<p> To view our technical site and platform code please visit Github at: <a href={ccconfig.githubURL}>https://github.com/colouring-london/colouring-london</a>.</p>
|
||||
<p> To view our technical site and platform code please visit Github at: <a href={ccconfig.githubURL}>https://github.com/colouring-cities/colouring-core</a>.</p>
|
||||
|
||||
<p>For press enquiries please contact <a href="https://www.turing.ac.uk/contact-us/press-office">The Alan Turing Institute press office</a></p>
|
||||
|
||||
|
@ -54,7 +54,7 @@ const ContributorAgreementPage : React.SFC<any> = () => (
|
||||
<h3 className='h3'>What you are contributing to</h3>
|
||||
|
||||
<p>
|
||||
Colouring {config.cityName} is a free knowledge exchange platform and open database designed for public use. It has been set up to support a whole-of-society approach to improving the sustainability, resilience and inclusivity of cities. Colouring {config.cityName} is also part of the international Colouring Cities Research Programme (CCRP) run at the Alan Turing Institute. Its design is guided by principles set out in the United Nations New Urban Agenda, the Open Data Charter, the General Data Protection Regulation (GDPR), The Gemini Principles, the Open Data Institute's recommendations on personal data and data infrastructure, and specific Articles within the Declaration of Human rights. These are discussed on our <a href="https://github.com/colouring-london/colouring-london/issues/687">'Data ethics'</a> page, where we also use the Open Data Institute's data ethics canvas to answer questions on how we use and manage our data. We capture spatial statistics and do not collect text or images, though images may be integrated in the future. The type of spatial data we collect can be viewed by clicking on each data category, on 'Info' buttons and on the 'Building data categories' page. We are also planning a 'Showcase section' to enable platform users to share, and view, ways in which Colouring {config.cityName} data are used.
|
||||
Colouring {config.cityName} is a free knowledge exchange platform and open database designed for public use. It has been set up to support a whole-of-society approach to improving the sustainability, resilience and inclusivity of cities. Colouring {config.cityName} is also part of the international Colouring Cities Research Programme (CCRP) run at the Alan Turing Institute. Its design is guided by principles set out in the United Nations New Urban Agenda, the Open Data Charter, the General Data Protection Regulation (GDPR), The Gemini Principles, the Open Data Institute's recommendations on personal data and data infrastructure, and specific Articles within the Declaration of Human rights. These are discussed on our <a href="https://github.com/colouring-cities/colouring-core/issues/687">'Data ethics'</a> page, where we also use the Open Data Institute's data ethics canvas to answer questions on how we use and manage our data. We capture spatial statistics and do not collect text or images, though images may be integrated in the future. The type of spatial data we collect can be viewed by clicking on each data category, on 'Info' buttons and on the 'Building data categories' page. We are also planning a 'Showcase section' to enable platform users to share, and view, ways in which Colouring {config.cityName} data are used.
|
||||
</p>
|
||||
|
||||
<h3 className='h3'>Diversity and inclusivity</h3>
|
||||
|
@ -35,7 +35,7 @@ export const Login: React.FC = () => {
|
||||
<InfoBox msg={msgText}>
|
||||
<br/>Please <a href="https://discuss.colouring.london/">discuss
|
||||
suggestions for improvements</a> and <a
|
||||
href="https://github.com/colouring-london/colouring-london/issues">
|
||||
href="https://github.com/colouring-cities/colouring-core/issues">
|
||||
report issues or problems</a>.
|
||||
</InfoBox>
|
||||
<ErrorBox msg={error} />
|
||||
|
@ -38,7 +38,7 @@ export const SignUp: React.FC = () => {
|
||||
<InfoBox msg={msgName}>
|
||||
<br/>Please <a href="https://discuss.colouring.london/">discuss
|
||||
suggestions for improvements</a> and <a
|
||||
href="https://github.com/colouring-london/colouring-london/issues">
|
||||
href="https://github.com/colouring-cities/colouring-core/issues">
|
||||
report issues or problems</a>.
|
||||
</InfoBox>
|
||||
<p>
|
||||
|
@ -109,6 +109,14 @@ const LAYER_QUERIES = {
|
||||
) AS team_info_count
|
||||
FROM
|
||||
buildings`,
|
||||
is_domestic: `
|
||||
SELECT
|
||||
geometry_id,
|
||||
is_domestic
|
||||
FROM
|
||||
buildings
|
||||
WHERE
|
||||
is_domestic IS NOT NULL`,
|
||||
likes: `
|
||||
SELECT
|
||||
geometry_id,
|
||||
@ -116,7 +124,17 @@ const LAYER_QUERIES = {
|
||||
FROM
|
||||
buildings
|
||||
WHERE
|
||||
is_domestic <> 'yes'
|
||||
AND
|
||||
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: `
|
||||
SELECT
|
||||
geometry_id,
|
||||
|
47
docs/configuring-colouring-cities.md
Normal file
47
docs/configuring-colouring-cities.md
Normal file
@ -0,0 +1,47 @@
|
||||
# Configuring the Colouring Cities Core Platform
|
||||
|
||||
## Introduction
|
||||
|
||||
We have added new configuration options to the Colouring Cities Core Platform, in order to make it easier to customise the platform for different cities/countries without unnecessary custom code and diverging codebases.
|
||||
|
||||
This is done using configuration files, which are described in detail later in this document.
|
||||
|
||||
Our hope is that every project in the Colouring Cities Research Programme (CCRP) will use this method to customise the interfaces of the Colouring Cities Platform for their own use as the programme moves forwards.
|
||||
|
||||
## The Config Files
|
||||
The configuration files are located here:
|
||||
|
||||
`app/src/cc-config.ts`
|
||||
`app/src/cc-config.json`
|
||||
|
||||
### > cc-config.json
|
||||
The JSON file contains the definition of the values of the variables.
|
||||
|
||||
Currently, these parameters are:
|
||||
|
||||
- **'cityName'** (string) - The name of the city/country.
|
||||
- **'projectBlurb'** (string) - A line of text describing the relationship of the project to the CCRP
|
||||
- **'githubURL'** (string) - The URL of the *project specific* GitHub repository
|
||||
- **'privacyStatement'** (string) - A description of where user data is stored and what safeguards are in place
|
||||
|
||||
These text strings are then used at various points throughout the Platform's interface.
|
||||
|
||||
There are also some other values to customise the behaviour of the application:
|
||||
|
||||
- **'initialMapPosition'** (string) - The default latitude and longitude of the map when the page loads.
|
||||
- **'initialZoomLevel'** (string) - The default zoom level when the map loads.
|
||||
|
||||
For example, the JSON file for Colouring London looks like this:
|
||||
|
||||
![alt text](images/cc-config-json.jpg "Title")
|
||||
|
||||
### > cc-config.ts
|
||||
This file contains the declaration of the variables that can be configured.
|
||||
|
||||
If you want to add additional parameters into the configuration framework, then they will need to be declared in this file and then defined in the JSON file (see below).
|
||||
|
||||
---
|
||||
|
||||
**NOTE: Any additional project specific text strings and parameters should be added to this file and the JSON file.**
|
||||
|
||||
*REQUEST: If you find any Colouring London-specific text or values, please report them or create a pull request to move them into the configuration framework.*
|
BIN
docs/images/cc-config-json.jpg
Normal file
BIN
docs/images/cc-config-json.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 47 KiB |
@ -2,7 +2,10 @@
|
||||
|
||||
### WARNING: Setup document suitable for development environment, not production server
|
||||
|
||||
This document is intended to guide you through setting up a local development environment for the Colouring London application. This guide assumes you already have either already have access to an machine with Ubuntu 18.04 installed, or can use VirtualBox to set up an Ubuntu virtual machine as below.
|
||||
This document is intended to guide you through setting up a local development environment for the Colouring Cities application. This guide assumes you already have either already have access to an machine with Ubuntu 18.04 installed, or can use VirtualBox to set up an Ubuntu virtual machine as below.
|
||||
|
||||
#### Note
|
||||
This guide assumes you are working with the ['colouring-core'](https://github.com/colouring-cities/colouring-core) repository. If you are creating your own fork, or want to use a custom city name, then you may wish to change `'colouring-core'` to `'colouring-[your city name]'`.
|
||||
|
||||
<details>
|
||||
<summary>
|
||||
@ -46,7 +49,7 @@ ssh <linuxusername>@localhost -p 4022
|
||||
|
||||
- [:tulip: Installing the tools and components](#tulip-installing-the-tools-and-components)
|
||||
- [:red_circle: Installing PostgreSQL](#red_circle-installing-postgresql)
|
||||
- [:rainbow: Installing Colouring London](#rainbow-installing-colouring-london)
|
||||
- [:rainbow: Installing Colouring Cities Core Platform](#rainbow-installing-colouring-cities-core-platform)
|
||||
- [:arrow_down: Installing Node.js](#arrow_down-installing-nodejs)
|
||||
- [:large_blue_circle: Configuring PostgreSQL](#large_blue_circle-configuring-postgresql)
|
||||
- [:space_invader: Create an empty database](#space_invader-create-an-empty-database)
|
||||
@ -99,15 +102,15 @@ and additional geo-spatial tools
|
||||
sudo apt-get install -y gdal-bin libspatialindex-dev libgeos-dev libproj-dev
|
||||
```
|
||||
|
||||
### :rainbow: Installing Colouring London
|
||||
### :rainbow: Installing Colouring Cities Core Platform
|
||||
|
||||
Now clone the `colouring-london` codebase.
|
||||
Now clone the `colouring-core` codebase.
|
||||
|
||||
```bash
|
||||
cd ~ && git clone https://github.com/colouring-cities/colouring-london.git
|
||||
cd ~ && git clone https://github.com/colouring-cities/colouring-core.git
|
||||
```
|
||||
|
||||
**Note:** We assume here that you will clone the repo into the home directory of your Ubuntu installation. Watch out for later commands in this guide that assume the repo is located at `~/colouring-london` and modify the path if appropriate.
|
||||
**Note:** We assume here that you will clone the repo into the home directory of your Ubuntu installation. Watch out for later commands in this guide that assume the repo is located at `~/colouring-core` and modify the path if appropriate.
|
||||
|
||||
### :arrow_down: Installing Node.js
|
||||
|
||||
@ -185,7 +188,7 @@ sudo -u postgres psql -c "SELECT 1 FROM pg_user WHERE usename = '<username>';" |
|
||||
```
|
||||
|
||||
<details>
|
||||
<summary>Note for "Colouring London" devs</summary><p></p>
|
||||
<summary>Note for "Colouring Cities" devs</summary><p></p>
|
||||
|
||||
If you intend to load the full CL database from a dump file into your dev environment, run the above `psql` command with `<username>` as "cldbadmin" and use that username in subsequent steps, but also run the above a second time with `<username>` as "clwebapp" (see section [:house: Loading the building data](#house-loading-the-building-data) for more details).
|
||||
|
||||
@ -193,7 +196,7 @@ If you intend to load the full CL database from a dump file into your dev enviro
|
||||
|
||||
### :space_invader: Create an empty database
|
||||
|
||||
Now create an empty database configured with geo-spatial tools. The database name (`<colouringlondondb>`) is arbitrary.
|
||||
Now create an empty database configured with geo-spatial tools. The database name (`<colouringcitiesdb>`) is arbitrary.
|
||||
|
||||
Set environment variables, which will simplify running subsequent `psql` commands.
|
||||
|
||||
@ -201,13 +204,13 @@ Set environment variables, which will simplify running subsequent `psql` command
|
||||
export PGPASSWORD=<pgpassword>
|
||||
export PGUSER=<username>
|
||||
export PGHOST=localhost
|
||||
export PGDATABASE=<colouringlondondb>
|
||||
export PGDATABASE=<colouringcitiesdb>
|
||||
```
|
||||
|
||||
Create the database.
|
||||
|
||||
```bash
|
||||
sudo -u postgres psql -c "SELECT 1 FROM pg_database WHERE datname = '<colouringlondondb>';" | grep -q 1 || sudo -u postgres createdb -E UTF8 -T template0 --locale=en_US.utf8 -O <username> <colouringlondondb>
|
||||
sudo -u postgres psql -c "SELECT 1 FROM pg_database WHERE datname = '<colouringcitiesdb>';" | grep -q 1 || sudo -u postgres createdb -E UTF8 -T template0 --locale=en_US.utf8 -O <username> <colouringcitiesdb>
|
||||
```
|
||||
|
||||
```bash
|
||||
@ -230,7 +233,7 @@ Now install the required Node packages. This needs to done from the `app` direct
|
||||
local repository, so that it can read from the `package.json` file.
|
||||
|
||||
```bash
|
||||
cd ~/colouring-london/app
|
||||
cd ~/colouring-core/app
|
||||
npm install
|
||||
```
|
||||
|
||||
@ -244,7 +247,7 @@ sudo apt-get install -y python3 python3-pip python3-dev python3-venv
|
||||
|
||||
## :house: Loading the building data
|
||||
|
||||
There are several ways to create the Colouring London database in your environment. The simplest way if you are just trying out the application would be to use test data from OSM, but otherwise you should follow one of the instructions below to create the full database either from scratch, or from a previously made db (via a dump file).
|
||||
There are several ways to create the Colouring Cities database in your environment. The simplest way if you are just trying out the application would be to use test data from OSM, but otherwise you should follow one of the instructions below to create the full database either from scratch, or from a previously made db (via a dump file).
|
||||
|
||||
To create the full database from scratch, follow [these instructions](../etl/README.md), otherwise choose one of the following:
|
||||
|
||||
@ -256,7 +259,7 @@ If you are a developer on the Colouring London project (or another Colouring Cit
|
||||
Log into the environment where your production database is kept and create a dump file from the db.
|
||||
|
||||
```bash
|
||||
pg_dump <colouringlondondb> > <dumpfile>
|
||||
pg_dump <colouringcitiesdb> > <dumpfile>
|
||||
```
|
||||
|
||||
You should then download the file to the machine where you are setting up your development environment. If you are using Virtualbox, you could host share the dump file with the VM via a shared folder (e.g. [see these instructions for Mac](https://medium.com/macoclock/share-folder-between-macos-and-ubuntu-4ce84fb5c1ad)).
|
||||
@ -269,7 +272,7 @@ psql < <dumpfile>
|
||||
|
||||
Alternatively, if you get errors using the above command, use pg_restore:
|
||||
```bash
|
||||
pg_restore -d <colouringlondondb> <dumpfile>
|
||||
pg_restore -d <colouringcitiesdb> <dumpfile>
|
||||
```
|
||||
|
||||
#### Run migrations
|
||||
@ -278,13 +281,13 @@ Now run all 'up' migrations to create tables, data types, indexes etc. The `.sql
|
||||
do this are located in the `migrations` folder of your local repository.
|
||||
|
||||
```bash
|
||||
ls ~/colouring-london/migrations/*.up.sql 2>/dev/null | while read -r migration; do psql < $migration; done;
|
||||
ls ~/colouring-core/migrations/*.up.sql 2>/dev/null | while read -r migration; do psql < $migration; done;
|
||||
```
|
||||
|
||||
Again, if you get errors, you may need to manually specify the database name
|
||||
|
||||
```bash
|
||||
ls ~/colouring-london/migrations/*.up.sql 2>/dev/null | while read -r migration; do psql -d <colouringlondondb> < $migration; done;
|
||||
ls ~/colouring-core/migrations/*.up.sql 2>/dev/null | while read -r migration; do psql -d <colouringcitiesdb> < $migration; done;
|
||||
```
|
||||
</details>
|
||||
|
||||
@ -295,17 +298,17 @@ This section shows how to load test buildings into the application from OpenStre
|
||||
|
||||
#### Load OpenStreetMap test polygons
|
||||
|
||||
Create a virtual environment for python in the `etl` folder of your repository. In the following example we have name the virtual environment *colouringlondon* but it can have any name.
|
||||
Create a virtual environment for python in the `etl` folder of your repository. In the following example we have name the virtual environment *colouringcities* but it can have any name.
|
||||
|
||||
```bash
|
||||
cd ~/colouring-london/etl
|
||||
pyvenv colouringlondon
|
||||
cd ~/colouring-core/etl
|
||||
pyvenv colouringcities
|
||||
```
|
||||
|
||||
Activate the virtual environment so we can install python packages into it.
|
||||
|
||||
```bash
|
||||
source colouringlondon/bin/activate
|
||||
source colouringcities/bin/activate
|
||||
```
|
||||
|
||||
Install python pip package manager and related tools.
|
||||
@ -321,7 +324,7 @@ Install the required python packages.
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
|
||||
To help test the Colouring London application, `get_test_polygons.py` will attempt to save a small (1.5km²) extract from OpenStreetMap to a format suitable for loading to the database.
|
||||
To help test the Colouring Cities application, `get_test_polygons.py` will attempt to save a small (1.5km²) extract from OpenStreetMap to a format suitable for loading to the database.
|
||||
|
||||
Download the test data.
|
||||
|
||||
@ -341,7 +344,7 @@ Now run all 'up' migrations to create tables, data types, indexes etc. The `.sql
|
||||
do this are located in the `migrations` folder of your local repository.
|
||||
|
||||
```bash
|
||||
ls ~/colouring-london/migrations/*.up.sql 2>/dev/null | while read -r migration; do psql < $migration; done;
|
||||
ls ~/colouring-core/migrations/*.up.sql 2>/dev/null | while read -r migration; do psql < $migration; done;
|
||||
```
|
||||
|
||||
#### Load buildings
|
||||
@ -366,7 +369,7 @@ Now we are ready to run the application.
|
||||
First enter the app directory.
|
||||
|
||||
```bash
|
||||
cd ~/colouring-london/app
|
||||
cd ~/colouring-core/app
|
||||
```
|
||||
|
||||
Then create a folder for the tilecache.
|
||||
@ -380,7 +383,7 @@ Create some additional variables for running the application (the `APP_COOKIE_SE
|
||||
```bash
|
||||
export PGPORT=5432
|
||||
export APP_COOKIE_SECRET=123456
|
||||
export TILECACHE_PATH=~/colouring-london/app/tilecache
|
||||
export TILECACHE_PATH=~/colouring-core/app/tilecache
|
||||
```
|
||||
|
||||
Finally, simply run the application with npm.
|
||||
@ -396,7 +399,7 @@ Specify variables
|
||||
</summary>
|
||||
|
||||
```bash
|
||||
PGPASSWORD=<pgpassword> PGDATABASE=<colouringlondondb> PGUSER=<username> PGHOST=localhost PGPORT=5432 APP_COOKIE_SECRET=123456 TILECACHE_PATH=~/colouring-london/app/tilecache npm start
|
||||
PGPASSWORD=<pgpassword> PGDATABASE=<colouringcitiesdb> PGUSER=<username> PGHOST=localhost PGPORT=5432 APP_COOKIE_SECRET=123456 TILECACHE_PATH=~/colouring-core/app/tilecache npm start
|
||||
```
|
||||
|
||||
</details><p></p>
|
||||
|
@ -1,5 +1,7 @@
|
||||
# Setting Up A Production Environment
|
||||
|
||||
#### Note
|
||||
This guide assumes you are working with the ['colouring-core'](https://github.com/colouring-cities/colouring-core) repository. If you are creating your own fork, or want to use a custom city name, then you may wish to change `'colouring-core'` to `'colouring-[your city name]'`.
|
||||
|
||||
#### Preliminaries
|
||||
|
||||
@ -42,13 +44,13 @@ Install Nginx
|
||||
`sudo apt install nginx`
|
||||
|
||||
|
||||
Clone the remote Colouring London GitHub repository into `/var/www`
|
||||
Clone the remote Colouring Cities GitHub repository into `/var/www`
|
||||
|
||||
`cd /var/www`
|
||||
|
||||
`sudo git clone https://github.com/colouring-london/colouring-london.git`
|
||||
`sudo git clone https://github.com/colouring-cities/colouring-core.git`
|
||||
|
||||
Create a system user (`nodeapp`) to `chown` the `colouring-london` directory
|
||||
Create a system user (`nodeapp`) to `chown` the `colouring-core` directory
|
||||
|
||||
`useradd -r -s /bin/nologin nodeapp`
|
||||
|
||||
@ -56,13 +58,13 @@ Add the current user to the `nodeapp` group
|
||||
|
||||
`sudo usermod -a -G nodeapp <your_ubuntu_username>`
|
||||
|
||||
Make the `nodeapp` user/group `chown` the `colouring-london` directory and its subdirectories
|
||||
Make the `nodeapp` user/group `chown` the `colouring-core` directory and its subdirectories
|
||||
|
||||
`sudo chown -R nodeapp:nodeapp /var/www/colouring-london`
|
||||
`sudo chown -R nodeapp:nodeapp /var/www/colouring-core`
|
||||
|
||||
Now set appropriate permissions on the `colouring-london` directory
|
||||
Now set appropriate permissions on the `colouring-core` directory
|
||||
|
||||
`sudo chmod -R 775 /var/www/colouring-london`
|
||||
`sudo chmod -R 775 /var/www/colouring-core`
|
||||
|
||||
|
||||
***
|
||||
@ -121,7 +123,7 @@ Now upgrade the `npm` package manager to the most recent release with global pri
|
||||
|
||||
Now install the required Node packages as designated in `package.json`
|
||||
|
||||
`cd /var/www/colouring-london/app && npm install`
|
||||
`cd /var/www/colouring-core/app && npm install`
|
||||
|
||||
|
||||
***
|
||||
@ -152,20 +154,20 @@ Create a distinct Postgres user
|
||||
`sudo -u postgres psql -c "SELECT 1 FROM pg_user WHERE usename = '<postgres_username>';" | grep -q 1 || sudo -u postgres psql -c "CREATE ROLE <postgres_username> SUPERUSER LOGIN PASSWORD '<postgres_password>';"`
|
||||
|
||||
|
||||
Create default colouring london database
|
||||
Create default colouring cities database
|
||||
|
||||
`sudo -u postgres psql -c "SELECT 1 FROM pg_database WHERE datname = 'colouringlondondb';" | grep -q 1 || sudo -u postgres createdb -E UTF8 -T template0 --locale=en_US.utf8 -O <postgres_username> colouringlondondb`
|
||||
`sudo -u postgres psql -c "SELECT 1 FROM pg_database WHERE datname = 'colouringcitiesdb';" | grep -q 1 || sudo -u postgres createdb -E UTF8 -T template0 --locale=en_US.utf8 -O <postgres_username> colouringcitiesdb`
|
||||
|
||||
`psql -d colouringlondondb -U <postgres_username> -c "create extension postgis;"`
|
||||
`psql -d colouringcitiesdb -U <postgres_username> -c "create extension postgis;"`
|
||||
|
||||
`psql -d colouringlondondb -U <postgres_username> -c "create extension pgcrypto;"`
|
||||
`psql -d colouringcitiesdb -U <postgres_username> -c "create extension pgcrypto;"`
|
||||
|
||||
`psql -d colouringlondondb -U <postgres_username> -c "create extension pg_trgm;"`
|
||||
`psql -d colouringcitiesdb -U <postgres_username> -c "create extension pg_trgm;"`
|
||||
|
||||
|
||||
Import data from the most recent colouring london database dump
|
||||
Import data from the most recent colouring cities database dump
|
||||
|
||||
`pg_restore --no-privileges --no-owner --username "<postgres_username>" --dbname "colouringlondondb" --clean "<path/to/database/dump/file>"`
|
||||
`pg_restore --no-privileges --no-owner --username "<postgres_username>" --dbname "colouringcitiesdb" --clean "<path/to/database/dump/file>"`
|
||||
|
||||
|
||||
***
|
||||
@ -196,7 +198,7 @@ Now edit `sites-available/default` to create a minimal Nginx configuration to te
|
||||
server {
|
||||
listen 80 default_server;
|
||||
listen [::]:80 default_server;
|
||||
server_name colouring-london;
|
||||
server_name colouring-core;
|
||||
|
||||
location / {
|
||||
proxy_pass http://localhost:3000/;
|
||||
@ -220,19 +222,19 @@ If all is well, restart Nginx
|
||||
|
||||
Test out the configuration
|
||||
|
||||
`cd /var/www/colouring-london/app`
|
||||
`cd /var/www/colouring-core/app`
|
||||
|
||||
|
||||
`npm run build`
|
||||
|
||||
|
||||
`PGPASSWORD=<postgres_password> PGDATABASE=colouringlondondb PGUSER=<postgres_username> PGHOST=localhost PGPORT=5432 APP_COOKIE_SECRET=<secret> npm run start:prod`
|
||||
`PGPASSWORD=<postgres_password> PGDATABASE=colouringcitiesdb PGUSER=<postgres_username> PGHOST=localhost PGPORT=5432 APP_COOKIE_SECRET=<secret> npm run start:prod`
|
||||
|
||||
Now open a browser window on a client machine and navigate to the IP Address of your VM
|
||||
|
||||
`http://<ip_address_of_vm>`
|
||||
|
||||
You should see the Colouring London homepage.
|
||||
You should see the Colouring Cities homepage.
|
||||
|
||||
|
||||
***
|
||||
@ -255,7 +257,7 @@ Perform a global install of PM2
|
||||
|
||||
Create an `ecosystem.config.js` file from the template file
|
||||
|
||||
`cd /var/www/colouring-london`
|
||||
`cd /var/www/colouring-core`
|
||||
|
||||
`nano ecosystem.config.template.js`
|
||||
|
||||
@ -268,18 +270,18 @@ Create an `ecosystem.config.js` file from the template file
|
||||
module.exports = {
|
||||
apps: [
|
||||
{
|
||||
name: "colouringlondon",
|
||||
name: "colouringcities",
|
||||
script: "./app/build/server.js",
|
||||
instances: 6,
|
||||
env: {
|
||||
NODE_ENV: "production",
|
||||
PGHOST: "localhost",
|
||||
PGPORT: 5432,
|
||||
PGDATABASE: "colouringlondondb",
|
||||
PGDATABASE: "colouringcitiesdb",
|
||||
PGUSER: "<postgres_username>",
|
||||
PGPASSWORD: "<postgres_password>",
|
||||
APP_COOKIE_SECRET: "<longrandomsecret>",
|
||||
TILECACHE_PATH: "/var/www/colouring-london/app/tilecache"
|
||||
TILECACHE_PATH: "/var/www/colouring-core/app/tilecache"
|
||||
}
|
||||
}
|
||||
]
|
||||
@ -288,9 +290,9 @@ Create an `ecosystem.config.js` file from the template file
|
||||
Edit the above file as appropriate and save as `ecosystem.config.js`
|
||||
|
||||
|
||||
Start the colouring-london app
|
||||
Start the colouring-core app
|
||||
|
||||
`cd /var/www/colouring-london`
|
||||
`cd /var/www/colouring-core`
|
||||
|
||||
`pm2 start ecosystem.config.js`
|
||||
|
||||
@ -298,9 +300,9 @@ Open a browser window on a client machine and navigate to the IP Address of your
|
||||
|
||||
`http://<ip_address_of_vm>`
|
||||
|
||||
You should see the Colouring London homepage.
|
||||
You should see the Colouring Cities homepage.
|
||||
|
||||
To stop the colouring-london app type:
|
||||
To stop the colouring-core app type:
|
||||
|
||||
`pm2 stop ecosystem.config.js`
|
||||
|
||||
@ -311,14 +313,14 @@ To stop the colouring-london app type:
|
||||
|
||||
Install requirements for the maintenance Python scripts
|
||||
|
||||
`cd /var/www/colouring-london/maintenance`
|
||||
`cd /var/www/colouring-core/maintenance`
|
||||
|
||||
`sudo pip3 install -r requirements.txt`
|
||||
|
||||
The maintenance scripts might need environment variables present at the time of execution, notably the database connection details.
|
||||
If running the scripts manually, the variables can be provided just before execution, for example
|
||||
|
||||
`PGHOST=localhost PGPORT=5432 PGDATABASE=dbname PGUSER=username PGPASSWORD=secretpassword EXTRACTS_DIRECTORY=/var/www/colouring-london/downloads python3 maintenance/extract_data/extract_data.py`
|
||||
`PGHOST=localhost PGPORT=5432 PGDATABASE=dbname PGUSER=username PGPASSWORD=secretpassword EXTRACTS_DIRECTORY=/var/www/colouring-core/downloads python3 maintenance/extract_data/extract_data.py`
|
||||
|
||||
If the maintenance script is to be run on a schedule, the variables should be loaded before running the script, for example from a `.env` file.
|
||||
|
||||
|
@ -54,6 +54,8 @@ COPY (SELECT
|
||||
planning_in_apa_url,
|
||||
planning_local_list_url,
|
||||
planning_historic_area_assessment_url,
|
||||
is_domestic,
|
||||
community_type_worth_keeping_total,
|
||||
likes_total
|
||||
FROM buildings)
|
||||
TO '/tmp/building_attributes.csv'
|
||||
|
2
migrations/037.is_domestic.down.sql
Normal file
2
migrations/037.is_domestic.down.sql
Normal 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;
|
15
migrations/037.is_domestic.up.sql
Normal file
15
migrations/037.is_domestic.up.sql
Normal 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
|
||||
);
|
Loading…
Reference in New Issue
Block a user