Location + Land Use Sources

- Add sources to multiple fields on Location + Land Use Categories
- Use data-fields-config properly instead of hard-coding some values
This commit is contained in:
Mike Simpson 2023-05-19 11:55:32 +01:00
parent 715cdfaa02
commit 4e348e7b54
8 changed files with 209 additions and 75 deletions

View File

@ -79,6 +79,14 @@ export const buildingAttributesConfig = valueType<DataFieldConfig>()({ /* eslint
edit: true, edit: true,
verify: true verify: true
}, },
location_address_source: {
edit: true,
verify: true
},
location_address_links: {
edit: true,
verify: true
},
location_latitude: { location_latitude: {
edit: true, edit: true,
verify: true, verify: true,
@ -87,6 +95,14 @@ export const buildingAttributesConfig = valueType<DataFieldConfig>()({ /* eslint
edit: true, edit: true,
verify: true, verify: true,
}, },
location_coordinates_source: {
edit: true,
verify: true
},
location_coordinates_links: {
edit: true,
verify: true
},
date_year: { date_year: {
edit: true, edit: true,
verify: true, verify: true,
@ -284,18 +300,24 @@ export const buildingAttributesConfig = valueType<DataFieldConfig>()({ /* eslint
edit: true, edit: true,
verify: true verify: true
}, },
demolished_buildings: { demolished_buildings: {
edit: true, edit: true,
verify: false, verify: false,
asJson: true, asJson: true,
sqlCast: 'jsonb', sqlCast: 'jsonb',
}, },
is_domestic: { is_domestic: {
edit: true, edit: true,
verify: true verify: true
}, },
is_domestic_source: {
edit: true,
verify: true
},
is_domestic_links: {
edit: true,
verify: true
},
survival_status: { survival_status: {
edit: true, edit: true,
verify: true verify: true

View File

@ -38,7 +38,7 @@ const UseView: React.FunctionComponent<CategoryViewProps> = (props) => {
title={dataFields.is_domestic.title} title={dataFields.is_domestic.title}
slug="is_domestic" slug="is_domestic"
value={props.building.is_domestic} value={props.building.is_domestic}
options={["yes", "no", "mixed domestic/non-domestic"]} options={dataFields.is_domestic.items}
mode={props.mode} mode={props.mode}
copy={props.copy} copy={props.copy}
onChange={props.onChange} onChange={props.onChange}
@ -55,29 +55,30 @@ const UseView: React.FunctionComponent<CategoryViewProps> = (props) => {
<SelectDataEntry <SelectDataEntry
title={dataFields.is_domestic_source.title} title={dataFields.is_domestic_source.title}
slug="is_domestic_source" slug="is_domestic_source"
value={props.building.is_domestic} value={props.building.is_domestic_source}
options={ options={dataFields.is_domestic_source.items}
[
"Expert knowledge",
"Observed from the street",
"Google or other photograph/satellite imagery",
"Government/public record/database",
"Independently managed record/database",
"Other type of record/database"
]
}
mode={props.mode} mode={props.mode}
copy={props.copy} copy={props.copy}
onChange={props.onChange} onChange={props.onChange}
tooltip={dataFields.is_domestic_source.tooltip} tooltip={dataFields.is_domestic_source.tooltip}
/> />
<DataEntry {(props.building.is_domestic_source == "Expert knowledge" ||
title="Source link" props.building.is_domestic_source == "Observed from the street" ||
slug="" props.building.is_domestic_source == null) ? <></> :
value="" <><MultiDataEntry
mode='view' title={dataFields.is_domestic_links.title}
tooltip="Coming Soon" slug="is_domestic_links"
/> value={props.building.is_domestic_links}
mode={props.mode}
copy={props.copy}
onChange={props.onChange}
tooltip={dataFields.is_domestic_links.tooltip}
placeholder="https://..."
editableEntries={true}
isUrl={true}
/>
</>
}
</DataEntryGroup> </DataEntryGroup>
<DataEntryGroup name="Specific land use data"> <DataEntryGroup name="Specific land use data">
<MultiDataEntry <MultiDataEntry

View File

@ -1,6 +1,4 @@
import React, { Fragment } from 'react'; import React, { Fragment } from 'react';
import InfoBox from '../../components/info-box';
import { dataFields } from '../../config/data-fields-config'; import { dataFields } from '../../config/data-fields-config';
import DataEntry from '../data-components/data-entry'; import DataEntry from '../data-components/data-entry';
import NumericDataEntry from '../data-components/numeric-data-entry'; import NumericDataEntry from '../data-components/numeric-data-entry';
@ -8,15 +6,15 @@ import UPRNsDataEntry from '../data-components/uprns-data-entry';
import Verification from '../data-components/verification'; import Verification from '../data-components/verification';
import withCopyEdit from '../data-container'; import withCopyEdit from '../data-container';
import { PatternDataEntry } from '../data-components/pattern-data-entry'; import { PatternDataEntry } from '../data-components/pattern-data-entry';
import { CategoryViewProps } from './category-view-props'; import { CategoryViewProps } from './category-view-props';
import { DataEntryGroup } from '../data-components/data-entry-group'; import { DataEntryGroup } from '../data-components/data-entry-group';
import SelectDataEntry from '../data-components/select-data-entry';
import { MultiDataEntry } from '../data-components/multi-data-entry/multi-data-entry';
const locationNumberPattern = "[1-9]\\d*[a-z]?(-([1-9]\\d*))?"; ///[1-9]\d*[a-z]?(-([1-9]\d*))?/; const locationNumberPattern = "[1-9]\\d*[a-z]?(-([1-9]\\d*))?"; ///[1-9]\d*[a-z]?(-([1-9]\d*))?/;
const LocationView: React.FunctionComponent<CategoryViewProps> = (props) => ( const LocationView: React.FunctionComponent<CategoryViewProps> = (props) => (
<Fragment> <Fragment>
<DataEntryGroup name="Address data"> <DataEntryGroup name="Address data">
<DataEntry <DataEntry
title={dataFields.location_name.title} title={dataFields.location_name.title}
@ -44,21 +42,6 @@ const LocationView: React.FunctionComponent<CategoryViewProps> = (props) => (
mode='view' mode='view'
tooltip="Not yet activated.<br><br>For security reasons, we do not allow the use of free text boxes and are currently looking into alternative ways to collect this data." tooltip="Not yet activated.<br><br>For security reasons, we do not allow the use of free text boxes and are currently looking into alternative ways to collect this data."
/> />
<Verification
slug="location_name"
allow_verify={props.user !== undefined && props.building.location_name !== null && !props.edited}
onVerify={props.onVerify}
user_verified={props.user_verified.hasOwnProperty("location_name")}
user_verified_as={props.user_verified.location_name}
verified_count={props.building.verified.location_name}
/>
<DataEntry
title="Source"
slug=""
value=""
mode='view'
tooltip="Coming Soon"
/>
<hr/> <hr/>
<PatternDataEntry <PatternDataEntry
title={dataFields.location_number.title} title={dataFields.location_number.title}
@ -137,7 +120,6 @@ const LocationView: React.FunctionComponent<CategoryViewProps> = (props) => (
onChange={props.onChange} onChange={props.onChange}
maxLength={8} maxLength={8}
valueTransform={x=>x.toUpperCase()} valueTransform={x=>x.toUpperCase()}
/> />
<Verification <Verification
slug="location_postcode" slug="location_postcode"
@ -147,13 +129,35 @@ const LocationView: React.FunctionComponent<CategoryViewProps> = (props) => (
user_verified_as={props.user_verified.location_postcode} user_verified_as={props.user_verified.location_postcode}
verified_count={props.building.verified.location_postcode} verified_count={props.building.verified.location_postcode}
/> />
<DataEntry <SelectDataEntry
title="Source" title={dataFields.location_address_source.title}
slug="" slug="location_address_source"
value="" value={props.building.location_address_source}
mode='view' mode={props.mode}
tooltip="Coming Soon" copy={props.copy}
/> onChange={props.onChange}
tooltip={dataFields.location_address_source.tooltip}
placeholder={dataFields.location_address_source.example}
options={dataFields.location_address_source.items}
/>
{(props.building.location_address_source == "Expert/personal knowledge of building" ||
props.building.location_address_source == "Online streetview image" ||
props.building.location_address_source == null) ? <></> :
<>
<MultiDataEntry
title={dataFields.location_address_links.title}
slug="location_address_links"
value={props.building.location_address_links}
mode={props.mode}
copy={props.copy}
onChange={props.onChange}
tooltip={dataFields.location_address_links.tooltip}
placeholder="https://..."
editableEntries={true}
isUrl={true}
/>
</>
}
</DataEntryGroup> </DataEntryGroup>
<DataEntryGroup name="Property/footprint IDs and coordinate data"> <DataEntryGroup name="Property/footprint IDs and coordinate data">
<DataEntry <DataEntry
@ -233,13 +237,35 @@ const LocationView: React.FunctionComponent<CategoryViewProps> = (props) => (
user_verified_as={props.user_verified.location_longitude} user_verified_as={props.user_verified.location_longitude}
verified_count={props.building.verified.location_longitude} verified_count={props.building.verified.location_longitude}
/> />
<DataEntry <SelectDataEntry
title="Source" title={dataFields.location_coordinates_source.title}
slug="" slug="location_coordinates_source"
value="" value={props.building.location_coordinates_source}
mode='view' mode={props.mode}
tooltip="Coming Soon" copy={props.copy}
onChange={props.onChange}
tooltip={dataFields.location_coordinates_source.tooltip}
placeholder={dataFields.location_coordinates_source.example}
options={dataFields.location_coordinates_source.items}
/> />
{(props.building.location_coordinates_source == "Expert/personal knowledge of building" ||
props.building.location_coordinates_source == "Online streetview image" ||
props.building.location_coordinates_source == null) ? <></> :
<>
<MultiDataEntry
title={dataFields.location_coordinates_links.title}
slug="location_coordinates_links"
value={props.building.location_coordinates_links}
mode={props.mode}
copy={props.copy}
onChange={props.onChange}
tooltip={dataFields.location_coordinates_links.tooltip}
placeholder="https://..."
editableEntries={true}
isUrl={true}
/>
</>
}
</DataEntryGroup> </DataEntryGroup>
</Fragment> </Fragment>
); );

View File

@ -15,7 +15,7 @@ export interface DataFieldDefinition {
* A field could be displayed in several categories, but this value will be used * A field could be displayed in several categories, but this value will be used
* when a single category needs to be shown in the context of a field, e.g. * when a single category needs to be shown in the context of a field, e.g.
* in the case of edit history or the copy-paste tool (multi-edit) * in the case of edit history or the copy-paste tool (multi-edit)
* */ * */
category: Category; category: Category;
/** /**
@ -41,7 +41,7 @@ export interface DataFieldDefinition {
/** /**
* If the defined type is a dictionary, this describes the types of the dictionary's fields * If the defined type is a dictionary, this describes the types of the dictionary's fields
*/ */
fields?: { [key: string]: Omit<DataFieldDefinition, 'category'>} fields?: { [key: string]: Omit<DataFieldDefinition, 'category'> }
/** /**
* The example is used to determine the runtime type in which the attribute data is stored (e.g. number, string, object) * The example is used to determine the runtime type in which the attribute data is stored (e.g. number, string, object)
@ -110,7 +110,7 @@ export const buildingUserFields = {
other: false other: false
} }
}, },
community_local_significance: { community_local_significance: {
perUser: true, perUser: true,
category: Category.Community, category: Category.Community,
@ -163,13 +163,34 @@ export const dataFields = { /* eslint-disable @typescript-eslint/camelcase */
example: "W1W 6TR", example: "W1W 6TR",
//tooltip: , //tooltip: ,
}, },
location_address_source: {
category: Category.Location,
title: "Source",
example: "",
tooltip: "Source of address data.",
items: [
"Expert/personal knowledge of building",
"Online streetview image",
"Open planning authority dataset",
"Open property tax dataset",
"Open housing dataset",
"Open address dataset",
"Other"
]
},
location_address_links: {
category: Category.Location,
title: "Source link(s)",
tooltip: "URL(s) for building address data source(s).",
example: ["", "", ""],
},
ref_toid: { ref_toid: {
category: Category.Location, category: Category.Location,
title: "Building footprint ID", title: "Building footprint ID",
tooltip: "Ordnance Survey Topography Layer ID (TOID) [<a href='https://www.ordnancesurvey.co.uk/business-government/products/open-toid'>link</a>]", tooltip: "Ordnance Survey Topography Layer ID (TOID) [<a href='https://www.ordnancesurvey.co.uk/business-government/products/open-toid'>link</a>]",
example: "", example: "",
}, },
/** /**
* UPRNs is not part of the buildings table, but the string fields * UPRNs is not part of the buildings table, but the string fields
* are included here for completeness * are included here for completeness
@ -178,16 +199,16 @@ export const dataFields = { /* eslint-disable @typescript-eslint/camelcase */
category: Category.Location, category: Category.Location,
title: "Unique Property Reference Number(s) (UPRN)", title: "Unique Property Reference Number(s) (UPRN)",
tooltip: "Unique Property Reference Numbers (to be filled automatically) [<a href='https://beta.ordnancesurvey.co.uk/products/os-open-uprn'>LINK</a>]", tooltip: "Unique Property Reference Numbers (to be filled automatically) [<a href='https://beta.ordnancesurvey.co.uk/products/os-open-uprn'>LINK</a>]",
example: [{uprn: "", parent_uprn: "" }, {uprn: "", parent_uprn: "" }], example: [{ uprn: "", parent_uprn: "" }, { uprn: "", parent_uprn: "" }],
}, },
planning_data: { planning_data: {
category: Category.Location, category: Category.Location,
title: "PLANNING DATA", title: "PLANNING DATA",
tooltip: "PLANNING DATA", tooltip: "PLANNING DATA",
example: [{uprn: "", building_id: 1, data_source: ""}, example: [{ uprn: "", building_id: 1, data_source: "" },
{uprn: "", building_id: 1, data_source: "", status: "", status_before_aliasing: "", decision_date: "", description: "", planning_application_link: "", registered_with_local_authority_date: "", last_synced_date: "", data_source_link: "", address: ""}, { uprn: "", building_id: 1, data_source: "", status: "", status_before_aliasing: "", decision_date: "", description: "", planning_application_link: "", registered_with_local_authority_date: "", last_synced_date: "", data_source_link: "", address: "" },
], ],
}, },
@ -209,6 +230,27 @@ export const dataFields = { /* eslint-disable @typescript-eslint/camelcase */
tooltip: "Longitude of building centroid", tooltip: "Longitude of building centroid",
example: 0.12124, example: 0.12124,
}, },
location_coordinates_source: {
category: Category.Location,
title: "Source",
example: "",
tooltip: "Source of lcoordinate data.",
items: [
"Expert/personal knowledge of building",
"Online streetview image",
"Open planning authority dataset",
"Open property tax dataset",
"Open housing dataset",
"Open address dataset",
"Other"
]
},
location_coordinates_links: {
category: Category.Location,
title: "Source link(s)",
tooltip: "URL(s) for building coordinate data source(s).",
example: ["", "", ""],
},
current_landuse_group: { current_landuse_group: {
category: Category.LandUse, category: Category.LandUse,
title: "Current land use(s)", title: "Current land use(s)",
@ -223,7 +265,7 @@ export const dataFields = { /* eslint-disable @typescript-eslint/camelcase */
}, },
current_landuse_source: { current_landuse_source: {
category: Category.LandUse, category: Category.LandUse,
title: "Source of information", title: "Source type",
tooltip: "Source for the current land use", tooltip: "Source for the current land use",
example: "", example: "",
items: [ items: [
@ -244,8 +286,8 @@ export const dataFields = { /* eslint-disable @typescript-eslint/camelcase */
}, },
current_landuse_link: { current_landuse_link: {
category: Category.LandUse, category: Category.LandUse,
title: "Source links", title: "Source link(s)",
tooltip: "URL for current land use reference", tooltip: "URL(s) for current land use reference",
example: ["", "", ""], example: ["", "", ""],
}, },
current_landuse_verified: { current_landuse_verified: {
@ -261,7 +303,7 @@ export const dataFields = { /* eslint-disable @typescript-eslint/camelcase */
}, },
date_change_building_use: { date_change_building_use: {
category: Category.Typology, category: Category.Typology,
title:"When did use change?", title: "When did use change?",
tooltip: "This is the date the building stopped being used for for the function it was built for. I.e. if it was Victorian warehouse which is now an office this would be when it became an office or if it was something before that, maybe a garage then the date that happened", tooltip: "This is the date the building stopped being used for for the function it was built for. I.e. if it was Victorian warehouse which is now an office this would be when it became an office or if it was something before that, maybe a garage then the date that happened",
example: 1920, example: 1920,
}, },
@ -287,7 +329,7 @@ export const dataFields = { /* eslint-disable @typescript-eslint/camelcase */
tooltip: "Best estimate for construction of main body of the building.", tooltip: "Best estimate for construction of main body of the building.",
example: 1924, example: 1924,
}, },
date_lower : { date_lower: {
category: Category.Age, category: Category.Age,
title: "Earliest possible start year", title: "Earliest possible start year",
tooltip: "This should be the earliest year in which construction could have started.", tooltip: "This should be the earliest year in which construction could have started.",
@ -412,21 +454,21 @@ export const dataFields = { /* eslint-disable @typescript-eslint/camelcase */
construction_core_material: { construction_core_material: {
category: Category.Construction, category: Category.Construction,
title: "Core material", title: "Core material",
tooltip:"The main structural material", tooltip: "The main structural material",
example: "", example: "",
}, },
construction_secondary_materials: { construction_secondary_materials: {
category: Category.Construction, category: Category.Construction,
title: "Main secondary construction material/s", title: "Main secondary construction material/s",
tooltip:"Other construction materials", tooltip: "Other construction materials",
example: "", example: "",
}, },
construction_roof_covering: { construction_roof_covering: {
category: Category.Construction, category: Category.Construction,
title: "Main roof covering", title: "Main roof covering",
tooltip:'Main roof covering material', tooltip: 'Main roof covering material',
example: "", example: "",
}, },
@ -602,13 +644,32 @@ export const dataFields = { /* eslint-disable @typescript-eslint/camelcase */
category: Category.Team, category: Category.Team,
title: "Is the building a home/domestic building?", title: "Is the building a home/domestic building?",
tooltip: "Note: Homes used as offices for working from home should be classified as domestic.", tooltip: "Note: Homes used as offices for working from home should be classified as domestic.",
example: "mixed domestic/non-domestic" example: "mixed domestic/non-domestic",
items: [
"Yes",
"No",
"Mixed domestic/non-domestic"
]
}, },
is_domestic_source: { is_domestic_source: {
category: Category.Team, category: Category.Team,
title: "Source type", title: "Source type",
tooltip: "", tooltip: "Source of domestic/non-domestic data",
example: "" example: "",
items: [
"Expert knowledge",
"Observed from the street",
"Google or other photograph/satellite imagery",
"Government/public record/database",
"Independently managed record/database",
"Other type of record/database"
]
},
is_domestic_links: {
category: Category.Team,
title: "Source links",
tooltip: "URL(s) for domestic/non-domestic data source(s)",
example: ["", "", ""],
}, },
likes_total: { likes_total: {
category: Category.Community, category: Category.Community,
@ -705,7 +766,8 @@ export const dataFields = { /* eslint-disable @typescript-eslint/camelcase */
{ {
year_constructed: { min: 1989, max: 1991 }, year_constructed: { min: 1989, max: 1991 },
year_demolished: { min: 1993, max: 1994 }, year_demolished: { min: 1993, max: 1994 },
lifespan: "2-5", overlap_present: "50%", links: ["", ""]} lifespan: "2-5", overlap_present: "50%", links: ["", ""]
}
] ]
}, },
has_extension: { has_extension: {
@ -850,4 +912,4 @@ export const dataFields = { /* eslint-disable @typescript-eslint/camelcase */
}, },
}; };
export const allFieldsConfig = {...dataFields, ...buildingUserFields}; export const allFieldsConfig = { ...dataFields, ...buildingUserFields };

View File

@ -39,8 +39,12 @@ This is the main table, containing almost all data collected by Colouring London
- `location_line_two`: additional address line - `location_line_two`: additional address line
- `location_town`: town - `location_town`: town
- `location_postcode`: postcode - `location_postcode`: postcode
- `location_address_source`: type of source used for address data
- `location_address_links`: link to source used for address data
- `location_latitude`: latitude - `location_latitude`: latitude
- `location_longitude`: longitude - `location_longitude`: longitude
- `location_coordinates_source`: source type of coordinate data
- `location_coordinates_links`: source links for coordinate data
- `current_landuse_group`: current land use group - `current_landuse_group`: current land use group
- `current_landuse_order`: current land use order - `current_landuse_order`: current land use order
- `building_attachment_form`: building attachment form - `building_attachment_form`: building attachment form
@ -85,6 +89,9 @@ This is the main table, containing almost all data collected by Colouring London
- `planning_local_list_url`: local list reference link - `planning_local_list_url`: local list reference link
- `planning_historic_area_assessment_url`: historic area assessment reference link - `planning_historic_area_assessment_url`: historic area assessment reference link
- `likes_total`: number of times the building has been liked by Colouring London users - `likes_total`: number of times the building has been liked by Colouring London users
- `is_domestic`: is the building domestic/non-domestic/mixed
- `is_domestic_source`: domestic data source type,
-`is_domestic_links`: domestic data source links,
## Building UPRNs ## Building UPRNs

View File

@ -9,6 +9,8 @@ COPY (SELECT
location_line_two, location_line_two,
location_town, location_town,
location_postcode, location_postcode,
location_address_source,
location_address_links,
location_latitude, location_latitude,
location_longitude, location_longitude,
current_landuse_group, current_landuse_group,
@ -55,6 +57,8 @@ COPY (SELECT
planning_local_list_url, planning_local_list_url,
planning_historic_area_assessment_url, planning_historic_area_assessment_url,
is_domestic, is_domestic,
is_domestic_source,
is_domestic_links,
community_type_worth_keeping_total, community_type_worth_keeping_total,
likes_total, likes_total,
survival_status, survival_status,

View File

@ -0,0 +1,6 @@
ALTER TABLE buildings DROP COLUMN IF EXISTS location_address_source;
ALTER TABLE buildings DROP COLUMN IF EXISTS location_address_links;
ALTER TABLE buildings DROP COLUMN IF EXISTS location_coordinates_source;
ALTER TABLE buildings DROP COLUMN IF EXISTS location_coordinates_links;
ALTER TABLE buildings DROP COLUMN IF EXISTS is_domestic_source;
ALTER TABLE buildings DROP COLUMN IF EXISTS is_domestic_links;

View File

@ -0,0 +1,6 @@
ALTER TABLE buildings ADD COLUMN IF NOT EXISTS location_address_source text;
ALTER TABLE buildings ADD COLUMN IF NOT EXISTS location_address_links text[];
ALTER TABLE buildings ADD COLUMN IF NOT EXISTS location_coordinates_source text;
ALTER TABLE buildings ADD COLUMN IF NOT EXISTS location_coordinates_links text[];
ALTER TABLE buildings ADD COLUMN IF NOT EXISTS is_domestic_source text;
ALTER TABLE buildings ADD COLUMN IF NOT EXISTS is_domestic_links text[];