Skip to content

Commit 2a35494

Browse files
committed
Merge branch 'release/1.10.0'
2 parents 61ae7ba + 736ad3f commit 2a35494

58 files changed

Lines changed: 2357 additions & 704 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

CHANGELOG.md

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1010
### Changed
1111
### Fixed
1212

13+
## [1.10.0] - 2021-09-28
14+
### Added
15+
- Add support for uploading reference layers to a project [#902](https://github.com/PublicMapping/districtbuilder/pull/902)
16+
- Show / delete reference layers for a project [#999](https://github.com/PublicMapping/districtbuilder/pull/999)
17+
- Copy project template reference layers to project [#1018](https://github.com/PublicMapping/districtbuilder/pull/1018)
18+
19+
### Changed
20+
- Support extra demographic fields on metrics viewer [#984](https://github.com/PublicMapping/districtbuilder/pull/984)
21+
- Sort region configs by region code [#1004](https://github.com/PublicMapping/districtbuilder/pull/1004)
22+
- Fix mini-maps for DC and other small regions [#1009](https://github.com/PublicMapping/districtbuilder/pull/1009)
23+
1324
## [1.9.0] - 2021-08-30
1425

1526
### Changed
@@ -32,6 +43,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
3243
### Added
3344
- Add levers to tune LB health check configuration [#950](https://github.com/PublicMapping/districtbuilder/pull/950)
3445

46+
3547
### Changed
3648
- Parameterize `max_old_space_size` [#942](https://github.com/PublicMapping/districtbuilder/pull/942)
3749
- Don't define container-level CPU reservation [#942](https://github.com/PublicMapping/districtbuilder/pull/942)
@@ -322,7 +334,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
322334

323335
- Initial release.
324336

325-
[unreleased]: https://github.com/publicmapping/districtbuilder/compare/1.9.0...HEAD
337+
[unreleased]: https://github.com/publicmapping/districtbuilder/compare/1.10.0...HEAD
338+
[1.10.0]: https://github.com/publicmapping/districtbuilder/compare/1.9.0...1.10.0
326339
[1.9.0]: https://github.com/publicmapping/districtbuilder/compare/1.8.0...1.9.0
327340
[1.8.0]: https://github.com/publicmapping/districtbuilder/compare/1.7.2...1.8.0
328341
[1.7.2]: https://github.com/publicmapping/districtbuilder/compare/1.7.1...1.7.2

deployment/README.md

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -113,12 +113,27 @@ This will attempt to apply the plan assembled in the previous step using Amazon'
113113

114114
## Restart services
115115

116-
After updating TopoJSON assets using the `update-region` command, you will need to restart the ECS services to refresh the cached TopoJSON assets.
116+
### Starting new tasks
117117

118-
To do so, go to the [ECS task definition](https://console.aws.amazon.com/ecs/home?region=us-east-1#/taskDefinitions) and force a new deployment for the environment (select either `StagingApp_EC2LaunchType` or `ProductionApp_EC2LaunchType` as appropriate).
118+
After updating TopoJSON assets using the `update-region` command, updating data in S3 directly, or updating the `region_config` table in the staging / production database, you will need to restart the ECS services to refresh the cached TopoJSON assets.
119119

120-
On the next screen, ensure "Force new deployment" is checked and that the selected cluster matches the selected task definition:
121-
![image](https://user-images.githubusercontent.com/4432106/120369867-e4fabd80-c2e1-11eb-9679-c0a7fa76868d.png)
120+
Go to the [auto scaling group](https://console.aws.amazon.com/ec2autoscaling/home?region=us-east-1#/details) for the environment you are interested in. Click the Edit button for "Group Details" and set the desired group capacity to be equal to the maximum capacity.
122121

123-
For the next two screens ("Configure network" and "Set Auto Scaling") use the defaults.
122+
Next, go to the [Staging](https://console.aws.amazon.com/ecs/home?region=us-east-1#/clusters/ecsStagingCluster/services/StagingApp_EC2LaunchType/details) or [Production](https://console.aws.amazon.com/ecs/home?region=us-east-1#/clusters/ecsProductionCluster/services/ProductionApp_EC2LaunchType/details) "EC2LaunchType" service and click "Update".
124123

124+
On the next screen, increase the "Number of tasks" to match the amount you set for the auto-scaling group, and leave everything else as-is.
125+
126+
It will take some time (approx. 20-25 mins) for the new tasks to finish loading all TopoJSON data. You can monitor the progress by looking for `HealthCheckService` logs in the [`logStagingApp` / `logProductionApp` Cloudwatch logs](https://console.aws.amazon.com/cloudwatch/home?region=us-east-1#logsV2:log-groups) or by looking at the number of healthy hosts in the [appropriate target group](https://console.aws.amazon.com/ec2/v2/home?region=us-east-1#TargetGroups:).
127+
128+
### Stopping old tasks
129+
130+
Once all the new tasks are healthy, you will need to stop the old tasks.
131+
Go to the task list for [staging](https://console.aws.amazon.com/ecs/home?region=us-east-1#/clusters/ecsStagingCluster/tasks) / [production](https://console.aws.amazon.com/ecs/home?region=us-east-1#/clusters/ecsProductionCluster/tasks) and stop any tasks whose "Started At" date is from before increasing the auto scaling group / number of desired tasks (this should be as many tasks as there were before you increased the total).
132+
133+
Next, revert your changes to the [Staging](https://console.aws.amazon.com/ecs/home?region=us-east-1#/clusters/ecsStagingCluster/services/StagingApp_EC2LaunchType/details) or [Production](https://console.aws.amazon.com/ecs/home?region=us-east-1#/clusters/ecsProductionCluster/services/ProductionApp_EC2LaunchType/details) "EC2LaunchType" service to bring the desired number of tasks back down to the previous amount.
134+
135+
The auto-scaling group will automatically reduce in size over time until it is back at the minimum amount again - there is no need to revert the changes to it.
136+
137+
### Updating cache keys
138+
139+
After all of the old tasks have been stopped, you need to update the `region_config.version` column in the database for every region that was updated, in order to trigger updates to cached data for maps in those regions. If you didn't update any existing regions, only added new ones, you can skip this step.

package.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
"@szhsin/react-menu": "^1.9.1",
2121
"@theme-ui/color": "0.4.0-rc.1",
2222
"@tippyjs/react": "^4.1.0",
23-
"@turf/bbox": "^6.0.1",
23+
"@turf/bbox": "^6.5.0",
2424
"@turf/boolean-intersects": "^6.4.0",
2525
"@turf/circle": "^6.4.0",
2626
"@turf/distance": "^6.4.0",
@@ -33,14 +33,15 @@
3333
"@visx/group": "^1.7.0",
3434
"@visx/responsive": "^1.10.1",
3535
"@visx/scale": "^1.14.0",
36-
"axios": "0.21.1",
36+
"axios": "0.21.2",
3737
"date-fns": "^2.19.0",
3838
"file-saver": "2.0.1",
3939
"json-stable-stringify": "^1.0.1",
4040
"jwt-decode": "2.2.0",
4141
"lodash": "^4.17.21",
4242
"mapbox-gl": "1.6.1",
4343
"memoizee": "0.4.14",
44+
"papaparse": "^5.3.1",
4445
"polylabel": "^1.1.0",
4546
"prop-types": "15.7.2",
4647
"query-string": "^7.0.1",
@@ -52,6 +53,7 @@
5253
"react-dom": "16.11.0",
5354
"react-file-drop": "3.1.2",
5455
"react-joyride": "^2.2.1",
56+
"react-papaparse": "^3.17.1",
5557
"react-redux": "7.1.3",
5658
"react-router": "5.1.2",
5759
"react-router-dom": "5.1.2",

scripts/load-dev-data

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ if [ "${BASH_SOURCE[0]}" = "${0}" ]; then
3838
'Dane County',
3939
'US',
4040
'WI',
41-
's3://global-districtbuilder-dev-us-east-1/regions/US/WI/2021-02-08T15:19:22.145Z/',
41+
's3://global-districtbuilder-dev-us-east-1/regions/US/WI/2021-09-02T18:57:17.123Z/',
4242
DEFAULT,
4343
TRUE,
4444
DEFAULT
@@ -68,7 +68,7 @@ if [ "${BASH_SOURCE[0]}" = "${0}" ]; then
6868
's3://global-districtbuilder-dev-us-east-1/regions/US/DE/2020-09-09T19:50:10.921Z/',
6969
DEFAULT,
7070
DEFAULT,
71-
FALSE
71+
TRUE
7272
), (
7373
'411c5908-2a83-40e9-863b-303931a1c119',
7474
'Delaware',
@@ -77,7 +77,7 @@ if [ "${BASH_SOURCE[0]}" = "${0}" ]; then
7777
's3://global-districtbuilder-dev-us-east-1/regions/US/DE/2021-06-11T23:03:36.938Z/',
7878
DEFAULT,
7979
DEFAULT,
80-
TRUE
80+
FALSE
8181
)
8282
ON CONFLICT DO NOTHING;
8383
"

src/client/actions/districtDrawing.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { createAction } from "typesafe-actions";
2-
import { DistrictId, GeoUnits } from "../../shared/entities";
2+
import { DistrictId, GeoUnits, ReferenceLayerId } from "../../shared/entities";
33
import { SavingState, ElectionYear, EvaluateMetricWithValue } from "../types";
44

55
export enum SelectionTool {
@@ -79,6 +79,11 @@ export const selectEvaluationMetric = createAction("Select evaluation metric")<
7979
EvaluateMetricWithValue | undefined
8080
>();
8181

82+
export const toggleReferenceLayer = createAction("Show or hide reference layer on map")<{
83+
readonly id: ReferenceLayerId;
84+
readonly show: boolean;
85+
}>();
86+
8287
export const saveDistrictsDefinition = createAction("Save districts definition")();
8388

8489
export const setSavingState = createAction("Set saving state")<SavingState>();

src/client/actions/projectData.ts

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,16 @@ import { ProjectVisibility } from "../../shared/constants";
33
import {
44
DistrictsDefinition,
55
IProject,
6+
IReferenceLayer,
67
LockedDistricts,
7-
MetricField,
8-
ProjectId
8+
ProjectId,
9+
ReferenceLayerId
910
} from "../../shared/entities";
1011
import { DynamicProjectData, StaticProjectData } from "../types";
1112
import { ResourceFailure } from "../resource";
1213

1314
interface PinnedMetrics {
14-
readonly pinnedMetricFields: readonly MetricField[];
15+
readonly pinnedMetricFields: readonly string[];
1516
readonly isReadOnly: boolean;
1617
}
1718

@@ -27,6 +28,28 @@ export const projectDataFetchFailure = createAction("Project data fetch failure"
2728
ResourceFailure
2829
>();
2930

31+
export const projectReferenceLayersFetch = createAction("Project reference layers fetch")<
32+
ProjectId
33+
>();
34+
export const projectReferenceLayersFetchSuccess = createAction(
35+
"Project reference layers fetch success"
36+
)<readonly IReferenceLayer[]>();
37+
export const projectReferenceLayersFetchFailure = createAction(
38+
"Project reference layers fetch failure"
39+
)<ResourceFailure>();
40+
41+
export const referenceLayerDelete = createAction("Reference layer delete")<ReferenceLayerId>();
42+
export const referenceLayerDeleteSuccess = createAction("Reference layer delete success")<
43+
ReferenceLayerId
44+
>();
45+
export const referenceLayerDeleteFailure = createAction("Reference layer delete failure")<
46+
ResourceFailure
47+
>();
48+
49+
export const setDeleteReferenceLayer = createAction(
50+
"Set the id for the delete reference layer modal"
51+
)<IReferenceLayer | undefined>();
52+
3053
export const staticDataFetchSuccess = createAction("Static data fetch success")<
3154
StaticProjectData
3255
>();
@@ -74,6 +97,8 @@ export const duplicateProject = createAction("Duplicate project")<IProject>();
7497
export const duplicateProjectSuccess = createAction("Duplicate project success")<IProject>();
7598
export const duplicateProjectFailure = createAction("Duplicate project failure")<string>();
7699

100+
export const toggleReferenceLayersModal = createAction("Toggle reference layers modal")();
101+
77102
export const clearDuplicationState = createAction("Clear duplication state")();
78103

79104
export const exportCsv = createAction("Export project CSV")<IProject>();

src/client/api.ts

Lines changed: 50 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,17 @@ import {
1717
RegionConfigId,
1818
ProjectNest,
1919
DistrictsImportApiResponse,
20-
PlanScoreAPIResponse
20+
PlanScoreAPIResponse,
21+
IReferenceLayer,
22+
ReferenceLayerId,
23+
CreateReferenceLayerData
2124
} from "../shared/entities";
22-
import { DistrictsGeoJSON, DynamicProjectData, PaginatedResponse } from "./types";
25+
import {
26+
DistrictsGeoJSON,
27+
DynamicProjectData,
28+
PaginatedResponse,
29+
ReferenceLayerWithGeojson
30+
} from "./types";
2331
import { getJWT, setJWT } from "./jwt";
2432

2533
const apiAxios = axios.create();
@@ -124,26 +132,10 @@ export async function resetPassword(token: string, password: string): Promise<vo
124132
});
125133
}
126134

127-
export async function createProject({
128-
name,
129-
numberOfDistricts,
130-
chamber,
131-
regionConfig,
132-
districtsDefinition,
133-
projectTemplate,
134-
populationDeviation
135-
}: CreateProjectData): Promise<IProject> {
135+
export async function createProject(data: CreateProjectData): Promise<IProject> {
136136
return new Promise((resolve, reject) => {
137137
apiAxios
138-
.post("/api/projects", {
139-
name,
140-
numberOfDistricts,
141-
regionConfig,
142-
districtsDefinition,
143-
chamber,
144-
populationDeviation,
145-
projectTemplate
146-
})
138+
.post("/api/projects", data)
147139
.then(response => resolve(response.data))
148140
.catch(error => reject(error.response?.data || error));
149141
});
@@ -187,6 +179,17 @@ export async function fetchProjectGeoJson(id: ProjectId): Promise<DistrictsGeoJS
187179
});
188180
}
189181

182+
export async function fetchProjectReferenceLayers(
183+
id: ProjectId
184+
): Promise<readonly IReferenceLayer[]> {
185+
return new Promise((resolve, reject) => {
186+
apiAxios
187+
.get(`/api/reference-layer/project/${id}`)
188+
.then(response => resolve(response.data))
189+
.catch(error => reject(error.response.data));
190+
});
191+
}
192+
190193
export async function fetchProjects(
191194
page: number,
192195
limit: number
@@ -228,7 +231,9 @@ export async function fetchRegionConfigs(): Promise<IRegionConfig> {
228231
return new Promise((resolve, reject) => {
229232
apiAxios
230233
.get("/api/region-configs?sort=name,ASC")
231-
.then(response => resolve(response.data))
234+
.then(response => {
235+
resolve(response.data);
236+
})
232237
.catch(error => reject(error.message));
233238
});
234239
}
@@ -319,6 +324,30 @@ export async function importCsv(file: Blob): Promise<DistrictsImportApiResponse>
319324
});
320325
}
321326

327+
export async function createReferenceLayer(
328+
referenceLayer: CreateReferenceLayerData
329+
): Promise<ReferenceLayerWithGeojson> {
330+
return new Promise((resolve, reject) => {
331+
apiAxios
332+
.post(`/api/reference-layer/`, referenceLayer)
333+
.then(response => {
334+
return resolve(response.data);
335+
})
336+
.catch(error => reject(error.message));
337+
});
338+
}
339+
340+
export async function deleteReferenceLayer(
341+
referenceLayerId: ReferenceLayerId
342+
): Promise<ReferenceLayerId> {
343+
return new Promise((resolve, reject) => {
344+
apiAxios
345+
.delete(`/api/reference-layer/${referenceLayerId}`)
346+
.then(() => resolve(referenceLayerId))
347+
.catch(error => reject(error.message));
348+
});
349+
}
350+
322351
export async function fetchOrganization(slug: OrganizationSlug): Promise<IOrganization> {
323352
return new Promise((resolve, reject) => {
324353
apiAxios

0 commit comments

Comments
 (0)