Add logical toggle for demolished buildings
This commit is contained in:
parent
26a91a229e
commit
4aa35b94dd
@ -508,6 +508,10 @@
|
||||
</Rule>
|
||||
</Style>
|
||||
<Style name="dynamics_demolished_count">
|
||||
<Rule>
|
||||
<Filter>[dynamics_has_demolished_buildings] = false</Filter>
|
||||
<PolygonSymbolizer fill="#0C7BDC" />
|
||||
</Rule>
|
||||
<Rule>
|
||||
<Filter>[demolished_buildings_count] >= 7</Filter>
|
||||
<PolygonSymbolizer fill="#bd0026" />
|
||||
|
@ -239,6 +239,11 @@ export const dataFieldsConfig = valueType<DataFieldConfig>()({ /* eslint-disable
|
||||
verify: false,
|
||||
},
|
||||
|
||||
dynamics_has_demolished_buildings: {
|
||||
edit: true,
|
||||
verify: true
|
||||
},
|
||||
|
||||
demolished_buildings: {
|
||||
edit: true,
|
||||
verify: false,
|
||||
@ -246,3 +251,6 @@ export const dataFieldsConfig = valueType<DataFieldConfig>()({ /* eslint-disable
|
||||
sqlCast: 'jsonb',
|
||||
},
|
||||
});
|
||||
|
||||
export type Building = { [k in keyof typeof dataFieldsConfig]: any };
|
||||
export type BuildingUpdate = Partial<Building>;
|
||||
|
@ -1,6 +1,7 @@
|
||||
import * as _ from 'lodash';
|
||||
|
||||
import { hasAnyOwnProperty } from '../../../helpers';
|
||||
import { Building, BuildingUpdate } from '../../config/dataFields';
|
||||
import { getBuildingData } from '../../dataAccess/building';
|
||||
import { ArgumentError } from '../../errors/general';
|
||||
|
||||
@ -36,10 +37,30 @@ async function processCurrentLandUseClassifications(buildingId: number, building
|
||||
|
||||
|
||||
/**
|
||||
* Process Dynamics data - sort past buildings by construction date
|
||||
* Process Dynamics data - check field relationships and sort demolished buildings by construction date
|
||||
*/
|
||||
async function processDynamicsPastBuildings(buildingId: number, buildingUpdate: any): Promise<any> {
|
||||
buildingUpdate.demolished_buildings = buildingUpdate.demolished_buildings.sort((a, b) => b.year_constructed.min - a.year_constructed.min);
|
||||
async function processDynamicsDemolishedBuildings(buildingId: number, buildingUpdate: BuildingUpdate): Promise<BuildingUpdate> {
|
||||
const currentBuildingData = await getBuildingData(buildingId);
|
||||
|
||||
const afterUpdate: Building = Object.assign({}, currentBuildingData, buildingUpdate);
|
||||
|
||||
const hasDemolished: boolean = afterUpdate.dynamics_has_demolished_buildings;
|
||||
const demolishedList: any[] = afterUpdate.demolished_buildings;
|
||||
|
||||
if(currentBuildingData.date_year == undefined) {
|
||||
throw new ArgumentError('Cannot edit demolished buildings data if data on current building age is missing', 'buildingUpdate');
|
||||
}
|
||||
|
||||
if(hasDemolished === false || hasDemolished == undefined) {
|
||||
if(demolishedList.length > 0) {
|
||||
throw new ArgumentError('Inconsistent data on whether there were any other buildings on this site', 'buildingUpdate');
|
||||
}
|
||||
}
|
||||
|
||||
if(buildingUpdate.demolished_buildings != undefined) {
|
||||
buildingUpdate.demolished_buildings = buildingUpdate.demolished_buildings.sort((a, b) => b.year_constructed.min - a.year_constructed.min);
|
||||
}
|
||||
|
||||
return buildingUpdate;
|
||||
}
|
||||
|
||||
@ -47,12 +68,12 @@ async function processDynamicsPastBuildings(buildingId: number, buildingUpdate:
|
||||
/**
|
||||
* Define any custom processing logic for specific building attributes
|
||||
*/
|
||||
export async function processBuildingUpdate(buildingId: number, buildingUpdate: any): Promise<any> {
|
||||
export async function processBuildingUpdate(buildingId: number, buildingUpdate: BuildingUpdate): Promise<any> {
|
||||
if(hasAnyOwnProperty(buildingUpdate, ['current_landuse_group'])) {
|
||||
buildingUpdate = await processCurrentLandUseClassifications(buildingId, buildingUpdate);
|
||||
}
|
||||
if('demolished_buildings' in buildingUpdate) {
|
||||
buildingUpdate = await processDynamicsPastBuildings(buildingId, buildingUpdate);
|
||||
if(hasAnyOwnProperty(buildingUpdate, ['demolished_buildings', 'dynamics_has_demolished_buildings'])) {
|
||||
buildingUpdate = await processDynamicsDemolishedBuildings(buildingId, buildingUpdate);
|
||||
}
|
||||
|
||||
return buildingUpdate;
|
||||
|
@ -11,6 +11,7 @@ import { NumberRangeDataEntry } from './number-range-data-entry';
|
||||
|
||||
import './dynamics-data-entry.css';
|
||||
import { CloseIcon } from '../../../components/icons';
|
||||
import DataTitle, { DataTitleCopyable } from '../../data-components/data-title';
|
||||
|
||||
type DemolishedBuilding = (BuildingAttributes['demolished_buildings'][number]);
|
||||
|
||||
@ -147,6 +148,7 @@ const DynamicsDataRow: React.FC<DynamicsDataRowProps> = ({
|
||||
};
|
||||
|
||||
interface DynamicsDataEntryProps extends BaseDataEntryProps {
|
||||
title: string;
|
||||
value: DemolishedBuilding[];
|
||||
editableEntries: boolean;
|
||||
maxYear: number;
|
||||
@ -206,11 +208,13 @@ export const DynamicsDataEntry: React.FC<DynamicsDataEntryProps> = (props) => {
|
||||
<>
|
||||
<div>
|
||||
{
|
||||
isEditing &&
|
||||
isEditing ?
|
||||
<>
|
||||
<h6 className="h6">Existing records for demolished buildings</h6>
|
||||
<label>Please supply sources for any edits of existing records</label>
|
||||
</>
|
||||
</> :
|
||||
|
||||
<DataTitleCopyable slug={props.slug} title={props.title} tooltip={null}/>
|
||||
}
|
||||
<ul className="data-entry-list">
|
||||
{
|
||||
|
@ -13,6 +13,7 @@ import NumericDataEntry from '../../data-components/numeric-data-entry';
|
||||
import withCopyEdit from '../../data-container';
|
||||
|
||||
import { CategoryViewProps } from '../category-view-props';
|
||||
import { LogicalDataEntry } from '../../data-components/logical-data-entry/logical-data-entry';
|
||||
|
||||
/**
|
||||
* Dynamics view/edit section
|
||||
@ -60,35 +61,51 @@ const DynamicsView: React.FunctionComponent<CategoryViewProps> = (props) => {
|
||||
</FieldRow>
|
||||
</DynamicsBuildingPane>
|
||||
{
|
||||
currentBuildingConstructionYear != undefined ?
|
||||
currentBuildingConstructionYear == undefined ?
|
||||
<InfoBox>To add historical records, fill in the <Link to={ageLinkUrl}>Age</Link> data first.</InfoBox> :
|
||||
|
||||
<>
|
||||
<DynamicsDataEntry
|
||||
|
||||
/*
|
||||
Will clear the edits and new record data upon navigating to another building.
|
||||
Should get a better way to do this, plus a way to actually keep unsaved edits.
|
||||
*/
|
||||
key={building.building_id}
|
||||
|
||||
value={building.demolished_buildings}
|
||||
editableEntries={true}
|
||||
slug='demolished_buildings'
|
||||
title={undefined}
|
||||
mode={props.mode}
|
||||
<LogicalDataEntry
|
||||
slug='dynamics_has_demolished_buildings'
|
||||
title={dataFields.dynamics_has_demolished_buildings.title}
|
||||
value={building.dynamics_has_demolished_buildings}
|
||||
disallowFalse={(building.demolished_buildings?.length ?? 0) > 0}
|
||||
disallowNull={(building.demolished_buildings?.length ?? 0) > 0}
|
||||
|
||||
onChange={props.onChange}
|
||||
onSaveAdd={props.onSaveAdd}
|
||||
hasEdits={props.edited}
|
||||
maxYear={currentBuildingConstructionYear}
|
||||
minYear={50}
|
||||
mode={props.mode}
|
||||
copy={props.copy}
|
||||
/>
|
||||
{
|
||||
props.mode === 'view' &&
|
||||
<InfoBox>Switch to edit mode to add/edit past building records</InfoBox>
|
||||
building.dynamics_has_demolished_buildings &&
|
||||
<>
|
||||
<DynamicsDataEntry
|
||||
|
||||
/*
|
||||
Will clear the edits and new record data upon navigating to another building.
|
||||
Should get a better way to do this, plus a way to actually keep unsaved edits.
|
||||
*/
|
||||
key={building.building_id}
|
||||
|
||||
value={building.demolished_buildings}
|
||||
editableEntries={true}
|
||||
slug='demolished_buildings'
|
||||
title={dataFields.demolished_buildings.title}
|
||||
mode={props.mode}
|
||||
onChange={props.onChange}
|
||||
onSaveAdd={props.onSaveAdd}
|
||||
hasEdits={props.edited}
|
||||
maxYear={currentBuildingConstructionYear}
|
||||
minYear={50}
|
||||
/>
|
||||
{
|
||||
props.mode === 'view' &&
|
||||
<InfoBox>Switch to edit mode to add/edit past building records</InfoBox>
|
||||
}
|
||||
</>
|
||||
}
|
||||
</> :
|
||||
<InfoBox>To add historical records, fill in the <Link to={ageLinkUrl}>Age</Link> data first.</InfoBox>
|
||||
</>
|
||||
}
|
||||
|
||||
</DataEntryGroup>
|
||||
|
||||
<DataEntryGroup name="Future planned data collection" collapsed={false} showCount={false}>
|
||||
|
@ -188,7 +188,7 @@ export const categoryMapsConfig: {[key in Category]: CategoryMapDefinition} = {
|
||||
mapStyle: 'dynamics_demolished_count',
|
||||
legend: {
|
||||
title: 'Dynamics',
|
||||
description: 'Past (demolished) buildings on site',
|
||||
description: 'Demolished buildings on the same site',
|
||||
elements: [
|
||||
{
|
||||
text: '7+',
|
||||
@ -211,6 +211,9 @@ export const categoryMapsConfig: {[key in Category]: CategoryMapDefinition} = {
|
||||
}, {
|
||||
text: '1',
|
||||
color: '#ffe8a9',
|
||||
}, {
|
||||
text: 'None',
|
||||
color: '#0C7BDC'
|
||||
}
|
||||
],
|
||||
},
|
||||
|
@ -445,6 +445,12 @@ export const dataFields = { /* eslint-disable @typescript-eslint/camelcase */
|
||||
example: 100,
|
||||
},
|
||||
|
||||
dynamics_has_demolished_buildings: {
|
||||
category: Category.Dynamics,
|
||||
title: 'Where any other buildings ever built on this site?',
|
||||
example: true,
|
||||
},
|
||||
|
||||
demolished_buildings: {
|
||||
category: Category.Dynamics,
|
||||
title: 'Past (demolished) buildings on this site',
|
||||
|
@ -24,7 +24,7 @@ export function parseJsonOrDefault(jsonString: string) {
|
||||
}
|
||||
}
|
||||
|
||||
export function hasAnyOwnProperty(obj: {}, keys: string[]) {
|
||||
export function hasAnyOwnProperty<T>(obj: T, keys: (keyof T)[]) {
|
||||
return keys.some(k => obj.hasOwnProperty(k));
|
||||
}
|
||||
|
||||
|
@ -136,10 +136,11 @@ const LAYER_QUERIES = {
|
||||
dynamics_demolished_count: `
|
||||
SELECT
|
||||
geometry_id,
|
||||
jsonb_array_length(demolished_buildings) as demolished_buildings_count
|
||||
jsonb_array_length(demolished_buildings) as demolished_buildings_count,
|
||||
dynamics_has_demolished_buildings
|
||||
FROM
|
||||
buildings
|
||||
WHERE jsonb_array_length(demolished_buildings) > 0`,
|
||||
WHERE jsonb_array_length(demolished_buildings) > 0 OR dynamics_has_demolished_buildings = FALSE`,
|
||||
};
|
||||
|
||||
const GEOMETRY_FIELD = 'geometry_geom';
|
||||
|
1
migrations/unreleased/0xx.dynamics-bool.down.sql
Normal file
1
migrations/unreleased/0xx.dynamics-bool.down.sql
Normal file
@ -0,0 +1 @@
|
||||
ALTER TABLE buildings DROP COLUMN IF EXISTS dynamics_has_demolished_buildings;
|
7
migrations/unreleased/0xx.dynamics-bool.up.sql
Normal file
7
migrations/unreleased/0xx.dynamics-bool.up.sql
Normal file
@ -0,0 +1,7 @@
|
||||
ALTER TABLE buildings
|
||||
ADD COLUMN dynamics_has_demolished_buildings BOOLEAN;
|
||||
|
||||
|
||||
UPDATE buildings
|
||||
SET dynamics_has_demolished_buildings = TRUE
|
||||
WHERE jsonb_array_length(demolished_buildings) > 0;
|
Loading…
Reference in New Issue
Block a user