From 8f1897693a0d120ff9d7dd3d2e2a3916f03ea3f1 Mon Sep 17 00:00:00 2001 From: Sergio Garcia Date: Thu, 3 Jun 2021 11:15:02 -0500 Subject: [PATCH 001/130] Adds ProjectComponent to the tabs --- moped-editor/src/views/projects/projectView/ProjectView.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/moped-editor/src/views/projects/projectView/ProjectView.js b/moped-editor/src/views/projects/projectView/ProjectView.js index 1bdfdebbfe..ff6a89be44 100644 --- a/moped-editor/src/views/projects/projectView/ProjectView.js +++ b/moped-editor/src/views/projects/projectView/ProjectView.js @@ -31,6 +31,7 @@ import { import Page from "src/components/Page"; import ProjectSummary from "./ProjectSummary"; +import ProjectComponents from "./ProjectComponents"; import ProjectTeam from "./ProjectTeam"; import ProjectTimeline from "./ProjectTimeline"; import ProjectTabPlaceholder from "./ProjectTabPlaceholder"; @@ -95,6 +96,7 @@ function useQueryParams() { const TABS = [ { label: "Summary", Component: ProjectSummary, param: "summary" }, + { label: "Map", Component: ProjectComponents, param: "map" }, { label: "Files", Component: ProjectFiles, param: "files" }, { label: "Team", Component: ProjectTeam, param: "team" }, { label: "Timeline", Component: ProjectTimeline, param: "timeline" }, @@ -380,7 +382,7 @@ const ProjectView = () => { const TabComponent = tab.Component; return ( - Date: Thu, 3 Jun 2021 11:15:35 -0500 Subject: [PATCH 002/130] Creates new react component ProjectComponents --- .../views/projects/projectView/ProjectComponents.js | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 moped-editor/src/views/projects/projectView/ProjectComponents.js diff --git a/moped-editor/src/views/projects/projectView/ProjectComponents.js b/moped-editor/src/views/projects/projectView/ProjectComponents.js new file mode 100644 index 0000000000..9d31c793f9 --- /dev/null +++ b/moped-editor/src/views/projects/projectView/ProjectComponents.js @@ -0,0 +1,12 @@ +import React, {useState} from "react"; + +const ProjectComponents = () => { + + const [componentsList, setComponentsList] = useState({}); + + return
+ Project Components +
; +}; + +export default ProjectComponents; From b23167d00ec58ac70b2d4e411ce5242716eb0f7b Mon Sep 17 00:00:00 2001 From: Sergio Garcia Date: Thu, 3 Jun 2021 14:12:14 -0500 Subject: [PATCH 003/130] Establish row relationships --- moped-database/metadata/tables.yaml | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/moped-database/metadata/tables.yaml b/moped-database/metadata/tables.yaml index 3a3ba560bf..3f25bf2d5a 100644 --- a/moped-database/metadata/tables.yaml +++ b/moped-database/metadata/tables.yaml @@ -998,6 +998,23 @@ - table: schema: public name: moped_proj_components + object_relationships: + - name: moped_components + using: + manual_configuration: + remote_table: + schema: public + name: moped_components + column_mapping: + project_component_id: component_id + array_relationships: + - name: moped_proj_features_components + using: + foreign_key_constraint_on: + column: moped_proj_component_id + table: + schema: public + name: moped_proj_features_components insert_permissions: - role: moped-admin permission: @@ -1482,6 +1499,15 @@ - table: schema: public name: moped_proj_features_components + array_relationships: + - name: moped_proj_feature + using: + manual_configuration: + remote_table: + schema: public + name: moped_proj_features + column_mapping: + moped_proj_features_id: feature_id insert_permissions: - role: moped-admin permission: From 9959b88f702b0faa52fa4582ad7ff23ff4c3878a Mon Sep 17 00:00:00 2001 From: Sergio Garcia Date: Thu, 3 Jun 2021 14:12:28 -0500 Subject: [PATCH 004/130] Update components query --- moped-editor/src/queries/project.js | 150 +++++++++++++++------------- 1 file changed, 79 insertions(+), 71 deletions(-) diff --git a/moped-editor/src/queries/project.js b/moped-editor/src/queries/project.js index 616c0b77fc..7b2e4029f8 100644 --- a/moped-editor/src/queries/project.js +++ b/moped-editor/src/queries/project.js @@ -1,12 +1,8 @@ import { gql } from "@apollo/client"; export const ADD_PROJECT = gql` - mutation AddProject( - $object: moped_project_insert_input! - ) { - insert_moped_project_one( - object: $object - ) { + mutation AddProject($object: moped_project_insert_input!) { + insert_moped_project_one(object: $object) { project_id project_name project_description @@ -34,7 +30,7 @@ export const SUMMARY_QUERY = gql` ecapris_subproject_id fiscal_year project_priority - moped_proj_features(where: {status_id: {_eq: 1}}) { + moped_proj_features(where: { status_id: { _eq: 1 } }) { feature_id project_id location @@ -84,7 +80,10 @@ export const TEAM_QUERY = gql` workgroup_id workgroup_name } - moped_project_roles(order_by: {role_order: asc}, where: {project_role_id: {_gt: 0}}) { + moped_project_roles( + order_by: { role_order: asc } + where: { project_role_id: { _gt: 0 } } + ) { project_role_id project_role_name project_role_description @@ -106,16 +105,10 @@ export const UPSERT_PROJECT_PERSONNEL = gql` $objects: [moped_proj_personnel_insert_input!]! ) { insert_moped_proj_personnel( - objects: $objects, + objects: $objects on_conflict: { - constraint: moped_proj_personnel_project_id_user_id_role_id_key, - update_columns: [ - project_id, - user_id, - role_id - status_id, - notes, - ] + constraint: moped_proj_personnel_project_id_user_id_role_id_key + update_columns: [project_id, user_id, role_id, status_id, notes] } ) { affected_rows @@ -156,17 +149,20 @@ export const UPDATE_PROJECT_PERSONNEL = gql` export const TIMELINE_QUERY = gql` query TeamTimeline($projectId: Int) { - moped_phases(where: { phase_id: {_gt: 0} }) { + moped_phases(where: { phase_id: { _gt: 0 } }) { phase_id phase_name subphases } - moped_subphases(where: { subphase_id: {_gt: 0} }, order_by: { subphase_order: asc }) { + moped_subphases( + where: { subphase_id: { _gt: 0 } } + order_by: { subphase_order: asc } + ) { subphase_id subphase_name } moped_proj_phases( - where: { project_id: { _eq: $projectId }, status_id: {_eq: 1} } + where: { project_id: { _eq: $projectId }, status_id: { _eq: 1 } } order_by: { phase_start: desc } ) { phase_name @@ -178,12 +174,12 @@ export const TIMELINE_QUERY = gql` subphase_name subphase_id } - moped_milestones(where: { milestone_id: {_gt: 0} }) { + moped_milestones(where: { milestone_id: { _gt: 0 } }) { milestone_id milestone_name } moped_proj_milestones( - where: { project_id: { _eq: $projectId }, status_id: {_eq: 1} } + where: { project_id: { _eq: $projectId }, status_id: { _eq: 1 } } order_by: { milestone_end: desc } ) { milestone_name @@ -204,8 +200,8 @@ export const UPDATE_PROJECT_PHASES_MUTATION = gql` $phase_end: date = null $project_phase_id: Int! $phase_name: String! - $subphase_id: Int = 0, - $subphase_name: String = null, + $subphase_id: Int = 0 + $subphase_name: String = null ) { update_moped_proj_phases_by_pk( pk_columns: { project_phase_id: $project_phase_id } @@ -261,19 +257,25 @@ export const UPDATE_PROJECT_MILESTONES_MUTATION = gql` `; export const DELETE_PROJECT_PHASE = gql` - mutation DeleteProjectPhase($project_phase_id: Int!) { - update_moped_proj_phases(_set: {status_id: 0}, where: {project_phase_id: {_eq: $project_phase_id}}) { - affected_rows - } + mutation DeleteProjectPhase($project_phase_id: Int!) { + update_moped_proj_phases( + _set: { status_id: 0 } + where: { project_phase_id: { _eq: $project_phase_id } } + ) { + affected_rows } + } `; export const DELETE_PROJECT_MILESTONE = gql` - mutation DeleteProjectMilestone($project_milestone_id: Int!) { - update_moped_proj_milestones(_set: {status_id: 0}, where: {project_milestone_id: {_eq: $project_milestone_id}}) { - affected_rows - } + mutation DeleteProjectMilestone($project_milestone_id: Int!) { + update_moped_proj_milestones( + _set: { status_id: 0 } + where: { project_milestone_id: { _eq: $project_milestone_id } } + ) { + affected_rows } + } `; export const ADD_PROJECT_PHASE = gql` @@ -295,7 +297,9 @@ export const ADD_PROJECT_PHASE = gql` `; export const ADD_PROJECT_MILESTONE = gql` - mutation AddProjectMilestone($objects: [moped_proj_milestones_insert_input!]!) { + mutation AddProjectMilestone( + $objects: [moped_proj_milestones_insert_input!]! + ) { insert_moped_proj_milestones(objects: $objects) { returning { milestone_name @@ -312,9 +316,7 @@ export const ADD_PROJECT_MILESTONE = gql` `; export const UPSERT_PROJECT_EXTENT = gql` - mutation UpsertProjectExtent( - $upserts: [moped_proj_features_insert_input!]! - ) { + mutation UpsertProjectExtent($upserts: [moped_proj_features_insert_input!]!) { insert_moped_proj_features( objects: $upserts on_conflict: { @@ -346,9 +348,7 @@ export const PROJECT_ACTIVITY_LOG = gql` user_id } } - moped_users(where:{ - status_id:{_eq: 1} - }) { + moped_users(where: { status_id: { _eq: 1 } }) { first_name last_name user_id @@ -391,10 +391,7 @@ export const PROJECT_ACTIVITY_LOG_DETAILS = gql` export const PROJECT_FILE_ATTACHMENTS = gql` query MopedProjectFiles($projectId: Int!) { moped_project_files( - where: { - project_id: {_eq: $projectId}, - is_retired: {_eq: false} - } + where: { project_id: { _eq: $projectId }, is_retired: { _eq: false } } ) { project_file_id project_id @@ -417,20 +414,13 @@ export const PROJECT_FILE_ATTACHMENTS = gql` export const PROJECT_FILE_ATTACHMENTS_UPDATE = gql` mutation UpdateProjectFileAttachment( - $fileId: Int!, - $fileName: String!, + $fileId: Int! + $fileName: String! $fileDescription: String! ) { update_moped_project_files( - where: { - project_file_id: { - _eq: $fileId - } - }, - _set: { - file_name: $fileName, - file_description: $fileDescription - } + where: { project_file_id: { _eq: $fileId } } + _set: { file_name: $fileName, file_description: $fileDescription } ) { affected_rows } @@ -438,18 +428,10 @@ export const PROJECT_FILE_ATTACHMENTS_UPDATE = gql` `; export const PROJECT_FILE_ATTACHMENTS_DELETE = gql` - mutation DeleteProjectFileAttachment( - $fileId: Int!, - ) { + mutation DeleteProjectFileAttachment($fileId: Int!) { update_moped_project_files( - where: { - project_file_id: { - _eq: $fileId - } - }, - _set: { - is_retired: true, - } + where: { project_file_id: { _eq: $fileId } } + _set: { is_retired: true } ) { affected_rows } @@ -457,23 +439,25 @@ export const PROJECT_FILE_ATTACHMENTS_DELETE = gql` `; export const PROJECT_FILE_ATTACHMENTS_CREATE = gql` - mutation insert_single_article($object: moped_project_files_insert_input! ) { + mutation insert_single_article($object: moped_project_files_insert_input!) { insert_moped_project_files(objects: [$object]) { affected_rows } } `; -export const PROJECT_ARCHIVE= gql` +export const PROJECT_ARCHIVE = gql` mutation ArchiveMopedProject($projectId: Int!) { - update_moped_project(where: {project_id: {_eq: $projectId}}, _set: {is_retired: true}) { + update_moped_project( + where: { project_id: { _eq: $projectId } } + _set: { is_retired: true } + ) { affected_rows } } -` +`; -export const PROJECT_CLEAR_MAP_DATA_TEMPLATE = - `mutation ClearProjectMapData($projectId: Int!) { +export const PROJECT_CLEAR_MAP_DATA_TEMPLATE = `mutation ClearProjectMapData($projectId: Int!) { update_moped_proj_features( where: { project_id: { _eq: $projectId } } _set: { @@ -505,3 +489,27 @@ export const PROJECT_CLEAR_MAP_DATA_TEMPLATE = } } `; + +export const COMPONENTS_QUERY = gql` + query getComponents($projectId: Int) { + moped_proj_components( + where: { project_id: { _eq: $projectId } } + ) { + project_component_id + project_id + component_id + name + description + moped_components { + component_type: component_name + component_subtype + } + moped_proj_features_components { + name + moped_proj_feature { + location + } + } + } + } +`; From fbe938edd3e18302d1f2d649af988783fe019988 Mon Sep 17 00:00:00 2001 From: Sergio Garcia Date: Thu, 3 Jun 2021 14:12:42 -0500 Subject: [PATCH 005/130] Update ProjectComponents --- .../projects/projectView/ProjectComponents.js | 141 +++++++++++++++++- 1 file changed, 136 insertions(+), 5 deletions(-) diff --git a/moped-editor/src/views/projects/projectView/ProjectComponents.js b/moped-editor/src/views/projects/projectView/ProjectComponents.js index 9d31c793f9..14c1ac13da 100644 --- a/moped-editor/src/views/projects/projectView/ProjectComponents.js +++ b/moped-editor/src/views/projects/projectView/ProjectComponents.js @@ -1,12 +1,143 @@ -import React, {useState} from "react"; +import React, { useState } from "react"; +import { useQuery } from "@apollo/client"; +import { useParams } from "react-router-dom"; +import { makeStyles } from "@material-ui/core/styles"; +import { COMPONENTS_QUERY } from "../../../queries/project"; +import { + CardContent, + Grid, + Icon, + Paper, + Table, + TableBody, + TableContainer, + TableHead, + TableRow, + TableCell, + CircularProgress, +} from "@material-ui/core"; +import DoubleArrowIcon from "@material-ui/icons/DoubleArrow"; +import { ErrorBoundary } from "react-error-boundary"; +import ApolloErrorHandler from "../../../components/ApolloErrorHandler"; +import ProjectComponentsMap from "./ProjectComponentsMap"; +import { createFeatureCollectionFromProjectFeatures } from "../../../utils/mapHelpers"; + +const useStyles = makeStyles(theme => ({ + root: { + flexGrow: 1, + backgroundColor: theme.palette.background.paper, + }, + componentItem: { + cursor: "pointer", + }, +})); +/** + * Project Component Page + * @return {JSX.Element} + * @constructor + */ const ProjectComponents = () => { + const { projectId } = useParams(); + const classes = useStyles(); + + const [componentsList, setComponentsList] = useState({}); + const [mapError, setMapError] = useState(false); + + const { error, loading, data, refetch } = useQuery(COMPONENTS_QUERY, { + variables: { + projectId, + }, + }); + + const projectFeatureRecords = + data?.moped_proj_components[0]?.moped_proj_features_components + ?.moped_proj_features ?? []; + + const projectFeatureCollection = createFeatureCollectionFromProjectFeatures( + projectFeatureRecords + ); + + if (loading) return ; - const [componentsList, setComponentsList] = useState({}); + const handleComponentClick = e => { + debugger; + }; - return
- Project Components -
; + return ( + + + + + + + + + + Component + Type + Subtype + Sub-Components + Details + + + + {data.moped_proj_components.map((component, compIndex) => { + const componentId = component.project_component_id; + return ( + handleComponentClick(componentId)} + > + {component?.name} + + {component?.moped_components?.component_type} + + + {component?.moped_components?.component_subtype} + + SubComponents + + + + + ); + })} + +
+
+
+
+ + ( + // +
Something bad happened: {error}
+ )} + onReset={() => setMapError(false)} + resetKeys={[mapError]} + > + +
+
+
+
+
+ ); }; export default ProjectComponents; From 74f0519503180bad6f51abe3653499b661da827e Mon Sep 17 00:00:00 2001 From: Sergio Garcia Date: Thu, 3 Jun 2021 14:12:54 -0500 Subject: [PATCH 006/130] Implement ProjectComponentsMap --- .../projectView/ProjectComponentsMap.js | 112 ++++++++++++++++++ 1 file changed, 112 insertions(+) create mode 100644 moped-editor/src/views/projects/projectView/ProjectComponentsMap.js diff --git a/moped-editor/src/views/projects/projectView/ProjectComponentsMap.js b/moped-editor/src/views/projects/projectView/ProjectComponentsMap.js new file mode 100644 index 0000000000..0a7bc01cc1 --- /dev/null +++ b/moped-editor/src/views/projects/projectView/ProjectComponentsMap.js @@ -0,0 +1,112 @@ +import React, { useRef } from "react"; +import ReactMapGL, { NavigationControl } from "react-map-gl"; +import { Box, Button, makeStyles } from "@material-ui/core"; +import { EditLocation as EditLocationIcon } from "@material-ui/icons"; +import "mapbox-gl/dist/mapbox-gl.css"; +import "react-map-gl-geocoder/dist/mapbox-gl-geocoder.css"; + +import { + createSummaryMapLayers, + getSummaryMapInteractiveIds, + MAPBOX_TOKEN, + mapStyles, + renderTooltip, + renderFeatureCount, + countFeatures, + useHoverLayer, + useFeatureCollectionToFitBounds, +} from "../../../utils/mapHelpers"; + +const useStyles = makeStyles({ + locationCountText: { + fontSize: "0.875rem", + fontWeight: 500, + }, + toolTip: mapStyles.toolTipStyles, + navStyle: { + position: "absolute", + top: 0, + left: 0, + padding: "10px", + }, + editButton: { + position: "absolute", + top: 8, + right: 8, + }, +}); + +const ProjectComponentsMap = ({ projectExtentGeoJSON, setIsEditing }) => { + const classes = useStyles(); + const mapRef = useRef(); + const featureCount = countFeatures(projectExtentGeoJSON); + + /** + * Make use of a custom hook that returns a vector tile layer hover event handler + * and the details to place and populate a tooltip. + */ + const { handleLayerHover, featureText, hoveredCoords } = useHoverLayer(); + + /** + * Make use of a custom hook that initializes a map viewport + * and fits it to a provided feature collection. + */ + const [viewport, setViewport] = useFeatureCollectionToFitBounds( + mapRef, + projectExtentGeoJSON + ); + + /** + * Updates viewport on zoom, scroll, and other events + * @param {Object} updatedViewPort - Mapbox object that stores properties of the map view + */ + const handleViewportChange = updatedViewPort => setViewport(updatedViewPort); + + /** + * Let's throw an error intentionally if there are no features for a project. + */ + // if (featureCount < 1) { + // throw Error("Map error: Cannot render or edit maps with no features"); + // } + + /** + * If we do have features, proceed to render map. + */ + return ( + + + {/* Draw Navigation controls with specific styles */} +
+ +
+ {/* + If there is GeoJSON data, create sources and layers for + each source layer in the project's GeoJSON FeatureCollection + */} + {projectExtentGeoJSON && createSummaryMapLayers(projectExtentGeoJSON)} + {/* Draw tooltip on feature hover */} + {renderTooltip(featureText, hoveredCoords, classes.toolTip)} +
+ {renderFeatureCount(featureCount)} +
+ ); +}; + +export default ProjectComponentsMap; From 9f63c67a1073abcf21f8e412cb799a6c7034c1f2 Mon Sep 17 00:00:00 2001 From: Sergio Garcia Date: Thu, 3 Jun 2021 15:48:57 -0500 Subject: [PATCH 007/130] Manage click and hover states --- .../projects/projectView/ProjectComponents.js | 120 ++++++++++++------ 1 file changed, 78 insertions(+), 42 deletions(-) diff --git a/moped-editor/src/views/projects/projectView/ProjectComponents.js b/moped-editor/src/views/projects/projectView/ProjectComponents.js index 14c1ac13da..b8cc4785e9 100644 --- a/moped-editor/src/views/projects/projectView/ProjectComponents.js +++ b/moped-editor/src/views/projects/projectView/ProjectComponents.js @@ -15,6 +15,7 @@ import { TableRow, TableCell, CircularProgress, + ClickAwayListener, } from "@material-ui/core"; import DoubleArrowIcon from "@material-ui/icons/DoubleArrow"; @@ -30,8 +31,20 @@ const useStyles = makeStyles(theme => ({ }, componentItem: { cursor: "pointer", + backgroundColor: theme.palette.background.paper, + "&:hover": { + background: "#f5f5f5", + } + }, + componentItemBlue: { + cursor: "pointer", // b3e5fc 90caf9 + backgroundColor: "#e1f5fe", // Lightblue 100 + "&:hover": { + background: "#b3e5fc", // Lightblue 200 + } }, })); + /** * Project Component Page * @return {JSX.Element} @@ -42,6 +55,9 @@ const ProjectComponents = () => { const classes = useStyles(); const [componentsList, setComponentsList] = useState({}); + const [componentCurrentlySelected, setComponentCurrentlySelected] = useState( + 0 + ); const [mapError, setMapError] = useState(false); const { error, loading, data, refetch } = useQuery(COMPONENTS_QUERY, { @@ -60,56 +76,76 @@ const ProjectComponents = () => { if (loading) return ; - const handleComponentClick = e => { - debugger; + /** + * Handles logic whenever a component is clicked + * @param componentId - The Database id of the component in question + */ + const handleComponentClick = componentId => { + setComponentCurrentlySelected(componentId); }; + /** + * Resets the color of a selected component back to white + */ + const handleComponentClickAway = () => setComponentCurrentlySelected(0); + return ( - - - - - Component - Type - Subtype - Sub-Components - Details - - - - {data.moped_proj_components.map((component, compIndex) => { - const componentId = component.project_component_id; - return ( - handleComponentClick(componentId)} - > - {component?.name} - - {component?.moped_components?.component_type} - - - {component?.moped_components?.component_subtype} - - SubComponents - - - - - ); - })} - -
-
+ + + + + + Component + Type + Subtype + Sub-Components + Details + + + + {data.moped_proj_components.map( + (component, compIndex) => { + const componentId = component.project_component_id; + return ( + handleComponentClick(componentId)} + className={ + componentId === componentCurrentlySelected + ? classes.componentItemBlue + : classes.componentItem + } + > + {component?.name} + + {component?.moped_components?.component_type} + + + {component?.moped_components?.component_subtype} + + + {[...new Set(component.moped_proj_features_components.map( + subcomponent => subcomponent.name + ))].join(", ")} + + + + + + ); + } + )} + +
+
+
From c5e713710ea7375b8f83b6913eb3906f00306f47 Mon Sep 17 00:00:00 2001 From: Sergio Garcia Date: Thu, 3 Jun 2021 15:49:22 -0500 Subject: [PATCH 008/130] Color commentary --- .../src/views/projects/projectView/ProjectComponents.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/moped-editor/src/views/projects/projectView/ProjectComponents.js b/moped-editor/src/views/projects/projectView/ProjectComponents.js index b8cc4785e9..1b04dd3be4 100644 --- a/moped-editor/src/views/projects/projectView/ProjectComponents.js +++ b/moped-editor/src/views/projects/projectView/ProjectComponents.js @@ -33,11 +33,11 @@ const useStyles = makeStyles(theme => ({ cursor: "pointer", backgroundColor: theme.palette.background.paper, "&:hover": { - background: "#f5f5f5", + background: "#f5f5f5", // Gray 50 } }, componentItemBlue: { - cursor: "pointer", // b3e5fc 90caf9 + cursor: "pointer", backgroundColor: "#e1f5fe", // Lightblue 100 "&:hover": { background: "#b3e5fc", // Lightblue 200 From ea7618b94d2ddd6c699bcf5114dbae291459b96a Mon Sep 17 00:00:00 2001 From: Sergio Garcia Date: Thu, 3 Jun 2021 15:49:39 -0500 Subject: [PATCH 009/130] Color commentary --- .../src/views/projects/projectView/ProjectComponents.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/moped-editor/src/views/projects/projectView/ProjectComponents.js b/moped-editor/src/views/projects/projectView/ProjectComponents.js index 1b04dd3be4..c5a587e66d 100644 --- a/moped-editor/src/views/projects/projectView/ProjectComponents.js +++ b/moped-editor/src/views/projects/projectView/ProjectComponents.js @@ -38,9 +38,9 @@ const useStyles = makeStyles(theme => ({ }, componentItemBlue: { cursor: "pointer", - backgroundColor: "#e1f5fe", // Lightblue 100 + backgroundColor: "#e1f5fe", // Lightblue 50 "&:hover": { - background: "#b3e5fc", // Lightblue 200 + background: "#b3e5fc", // Lightblue 100 } }, })); From 8f79fbd14200fb1e8ecd5275cdbd7c252650c695 Mon Sep 17 00:00:00 2001 From: Sergio Garcia Date: Thu, 3 Jun 2021 19:33:12 -0500 Subject: [PATCH 010/130] Cleanup & refactor projectFeatureRecords --- .../projects/projectView/ProjectComponents.js | 53 +++++++++++++------ 1 file changed, 37 insertions(+), 16 deletions(-) diff --git a/moped-editor/src/views/projects/projectView/ProjectComponents.js b/moped-editor/src/views/projects/projectView/ProjectComponents.js index c5a587e66d..4c9ba74b9f 100644 --- a/moped-editor/src/views/projects/projectView/ProjectComponents.js +++ b/moped-editor/src/views/projects/projectView/ProjectComponents.js @@ -6,7 +6,6 @@ import { COMPONENTS_QUERY } from "../../../queries/project"; import { CardContent, Grid, - Icon, Paper, Table, TableBody, @@ -34,14 +33,14 @@ const useStyles = makeStyles(theme => ({ backgroundColor: theme.palette.background.paper, "&:hover": { background: "#f5f5f5", // Gray 50 - } + }, }, componentItemBlue: { cursor: "pointer", backgroundColor: "#e1f5fe", // Lightblue 50 "&:hover": { background: "#b3e5fc", // Lightblue 100 - } + }, }, })); @@ -55,9 +54,7 @@ const ProjectComponents = () => { const classes = useStyles(); const [componentsList, setComponentsList] = useState({}); - const [componentCurrentlySelected, setComponentCurrentlySelected] = useState( - 0 - ); + const [selectedComp, setSelectedComp] = useState(0); const [mapError, setMapError] = useState(false); const { error, loading, data, refetch } = useQuery(COMPONENTS_QUERY, { @@ -66,28 +63,48 @@ const ProjectComponents = () => { }, }); - const projectFeatureRecords = - data?.moped_proj_components[0]?.moped_proj_features_components - ?.moped_proj_features ?? []; + // Return loading if not in progress + if (loading) return ; + /** + * Retrieve and flatten a nested list of features: + * moped_proj_components -> moped_proj_features_components -> moped_proj_feature + */ + const projectFeatureRecords = data.moped_proj_components.reduce( + (accumulator, component) => [ + ...accumulator, + ...// Append if current component is selected, or none are selected (0) + (selectedComp === component.component_id || selectedComp === 0 + ? component.moped_proj_features_components.map( + feature_comp => + feature_comp.moped_proj_feature.map(feature => feature)[0] + ) + : []), + ], + [] + ); + + /** + * Reuses this function to generate a collection for the map + * @type {Object} + */ const projectFeatureCollection = createFeatureCollectionFromProjectFeatures( projectFeatureRecords ); - if (loading) return ; /** * Handles logic whenever a component is clicked * @param componentId - The Database id of the component in question */ const handleComponentClick = componentId => { - setComponentCurrentlySelected(componentId); + setSelectedComp(componentId); }; /** * Resets the color of a selected component back to white */ - const handleComponentClickAway = () => setComponentCurrentlySelected(0); + const handleComponentClickAway = () => setSelectedComp(0); return ( @@ -118,7 +135,7 @@ const ProjectComponents = () => { key={"mcTableRow-" + componentId} onClick={() => handleComponentClick(componentId)} className={ - componentId === componentCurrentlySelected + componentId === selectedComp ? classes.componentItemBlue : classes.componentItem } @@ -131,9 +148,13 @@ const ProjectComponents = () => { {component?.moped_components?.component_subtype} - {[...new Set(component.moped_proj_features_components.map( - subcomponent => subcomponent.name - ))].join(", ")} + {[ + ...new Set( + component.moped_proj_features_components.map( + subcomponent => subcomponent.name + ) + ), + ].join(", ")} From f0b1c2d09553f3b5ede4845047a532f60562b499 Mon Sep 17 00:00:00 2001 From: Sergio Garcia Date: Fri, 4 Jun 2021 12:34:28 -0500 Subject: [PATCH 011/130] Clean up --- .../projects/projectView/ProjectComponents.js | 24 +++++++++---------- .../projectView/ProjectComponentsMap.js | 9 ++++--- 2 files changed, 15 insertions(+), 18 deletions(-) diff --git a/moped-editor/src/views/projects/projectView/ProjectComponents.js b/moped-editor/src/views/projects/projectView/ProjectComponents.js index 4c9ba74b9f..e69eb7c2f5 100644 --- a/moped-editor/src/views/projects/projectView/ProjectComponents.js +++ b/moped-editor/src/views/projects/projectView/ProjectComponents.js @@ -22,6 +22,7 @@ import { ErrorBoundary } from "react-error-boundary"; import ApolloErrorHandler from "../../../components/ApolloErrorHandler"; import ProjectComponentsMap from "./ProjectComponentsMap"; import { createFeatureCollectionFromProjectFeatures } from "../../../utils/mapHelpers"; +import ProjectSummaryMapFallback from "./ProjectSummaryMapFallback"; const useStyles = makeStyles(theme => ({ root: { @@ -53,7 +54,6 @@ const ProjectComponents = () => { const { projectId } = useParams(); const classes = useStyles(); - const [componentsList, setComponentsList] = useState({}); const [selectedComp, setSelectedComp] = useState(0); const [mapError, setMapError] = useState(false); @@ -73,8 +73,8 @@ const ProjectComponents = () => { const projectFeatureRecords = data.moped_proj_components.reduce( (accumulator, component) => [ ...accumulator, - ...// Append if current component is selected, or none are selected (0) - (selectedComp === component.component_id || selectedComp === 0 + // Append if current component is selected, or none are selected (0) + ...(selectedComp === component.component_id || selectedComp === 0 ? component.moped_proj_features_components.map( feature_comp => feature_comp.moped_proj_feature.map(feature => feature)[0] @@ -92,7 +92,6 @@ const ProjectComponents = () => { projectFeatureRecords ); - /** * Handles logic whenever a component is clicked * @param componentId - The Database id of the component in question @@ -172,15 +171,14 @@ const ProjectComponents = () => { ( - // -
Something bad happened: {error}
+ )} onReset={() => setMapError(false)} resetKeys={[mapError]} diff --git a/moped-editor/src/views/projects/projectView/ProjectComponentsMap.js b/moped-editor/src/views/projects/projectView/ProjectComponentsMap.js index 0a7bc01cc1..936a46d7c5 100644 --- a/moped-editor/src/views/projects/projectView/ProjectComponentsMap.js +++ b/moped-editor/src/views/projects/projectView/ProjectComponentsMap.js @@ -1,7 +1,6 @@ import React, { useRef } from "react"; import ReactMapGL, { NavigationControl } from "react-map-gl"; -import { Box, Button, makeStyles } from "@material-ui/core"; -import { EditLocation as EditLocationIcon } from "@material-ui/icons"; +import { Box, makeStyles } from "@material-ui/core"; import "mapbox-gl/dist/mapbox-gl.css"; import "react-map-gl-geocoder/dist/mapbox-gl-geocoder.css"; @@ -65,9 +64,9 @@ const ProjectComponentsMap = ({ projectExtentGeoJSON, setIsEditing }) => { /** * Let's throw an error intentionally if there are no features for a project. */ - // if (featureCount < 1) { - // throw Error("Map error: Cannot render or edit maps with no features"); - // } + if (featureCount < 1) { + throw Error("Map error: Cannot render or edit maps with no features"); + } /** * If we do have features, proceed to render map. From 56786ce8a930906723d8bab9b36d5b0602f8fd4d Mon Sep 17 00:00:00 2001 From: Sergio Garcia Date: Fri, 4 Jun 2021 13:53:14 -0500 Subject: [PATCH 012/130] Update relationships --- moped-database/metadata/tables.yaml | 67 +++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) diff --git a/moped-database/metadata/tables.yaml b/moped-database/metadata/tables.yaml index 3f25bf2d5a..a8ad1aa459 100644 --- a/moped-database/metadata/tables.yaml +++ b/moped-database/metadata/tables.yaml @@ -1008,6 +1008,13 @@ column_mapping: project_component_id: component_id array_relationships: + - name: moped_proj_components_subcomponents + using: + foreign_key_constraint_on: + column: project_component_id + table: + schema: public + name: moped_proj_components_subcomponents - name: moped_proj_features_components using: foreign_key_constraint_on: @@ -1088,6 +1095,10 @@ - table: schema: public name: moped_proj_components_subcomponents + object_relationships: + - name: moped_subcomponent + using: + foreign_key_constraint_on: subcomponent_id insert_permissions: - role: moped-admin permission: @@ -4262,6 +4273,62 @@ - table: schema: public name: moped_subcomponents + insert_permissions: + - role: moped-admin + permission: + check: {} + columns: + - subcomponent_id + - subcomponent_name + - component_id + backend_only: false + - role: moped-editor + permission: + check: {} + columns: + - subcomponent_id + - subcomponent_name + - component_id + backend_only: false + select_permissions: + - role: moped-admin + permission: + columns: + - component_id + - subcomponent_id + - subcomponent_name + filter: {} + - role: moped-editor + permission: + columns: + - component_id + - subcomponent_id + - subcomponent_name + filter: {} + - role: moped-viewer + permission: + columns: + - component_id + - subcomponent_id + - subcomponent_name + filter: {} + update_permissions: + - role: moped-admin + permission: + columns: + - component_id + - subcomponent_id + - subcomponent_name + filter: {} + check: null + - role: moped-editor + permission: + columns: + - component_id + - subcomponent_id + - subcomponent_name + filter: {} + check: null - table: schema: public name: moped_subphases From d19689080e90cde72a815bd802313604a0385744 Mon Sep 17 00:00:00 2001 From: Sergio Garcia Date: Fri, 4 Jun 2021 13:53:23 -0500 Subject: [PATCH 013/130] Add seed features --- .../1602292389297_initial_seed_staging.sql | 52 ++++++++++++++++++- 1 file changed, 51 insertions(+), 1 deletion(-) diff --git a/moped-database/seeds/1602292389297_initial_seed_staging.sql b/moped-database/seeds/1602292389297_initial_seed_staging.sql index 29d7d66c77..873358e808 100644 --- a/moped-database/seeds/1602292389297_initial_seed_staging.sql +++ b/moped-database/seeds/1602292389297_initial_seed_staging.sql @@ -262,7 +262,7 @@ INSERT INTO public.moped_activity_log (activity_id, record_id, record_type, reco INSERT INTO public.moped_activity_log (activity_id, record_id, record_type, record_data, description, created_at, updated_by, record_project_id, operation_type) VALUES ('6ec15fe6-5080-4447-99f9-6e2fdc1a7c33', 187, 'moped_project', '{"id": "03b87f84-c895-4723-b6b2-482bec2346ec", "event": {"op": "INSERT", "data": {"new": {"added_by": null, "end_date": null, "date_added": "2021-03-23T01:36:54.42012+00:00", "eCapris_id": "1234", "is_retired": false, "project_id": 187, "start_date": "2021-03-22", "fiscal_year": "2017", "timeline_id": null, "project_name": "This is a test project", "project_uuid": "6fdfcab8-5149-4dea-8816-77a11ccf9c42", "current_phase": "construction", "project_order": null, "current_status": "canceled", "project_length": 0, "capitally_funded": true, "project_priority": "", "project_importance": null, "project_description": "This is a new test project", "project_extent_geojson": {"type": "FeatureCollection", "features": [{"id": 50194, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.7268167026341, 30.28892818871917], [-97.72716572508216, 30.290033236814793], [-97.72719472646713, 30.290154684228455], [-97.72721484303474, 30.290250944586575], [-97.72722624242306, 30.29032737379613]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 150194}}]}, "project_description_public": null}, "old": null}, "trace_context": {"span_id": 1157060217750187198, "trace_id": 16547921757380504472}, "session_variables": {"x-hasura-role": "moped-admin", "x-hasura-user-id": "20c20b28-3b20-4e9e-a0bc-e1ef4e512f2c", "x-hasura-user-db-id": "7", "x-hasura-user-wg-id": "3"}}, "table": {"name": "moped_project", "schema": "public"}, "trigger": {"name": "activity_log_moped_project"}, "created_at": "2021-03-23T01:36:54.416039Z", "delivery_info": {"max_retries": 0, "current_retry": 0}}', '[]', '2021-03-23 01:37:05.743857+00', '20c20b28-3b20-4e9e-a0bc-e1ef4e512f2c', 187, 'INSERT'); INSERT INTO public.moped_activity_log (activity_id, record_id, record_type, record_data, description, created_at, updated_by, record_project_id, operation_type) VALUES ('41e05e8c-1d2b-45b3-934e-2184cba30c9e', 187, 'moped_project', '{"id": "8b5f0893-544f-46a1-ba5f-8803f9471b29", "event": {"op": "UPDATE", "data": {"new": {"added_by": null, "end_date": null, "date_added": "2021-03-23T01:36:54.42012+00:00", "eCapris_id": "1234", "is_retired": false, "project_id": 187, "start_date": "2021-03-22", "fiscal_year": "2017", "timeline_id": null, "project_name": "Checking on the project created log", "project_uuid": "6fdfcab8-5149-4dea-8816-77a11ccf9c42", "current_phase": "construction", "project_order": null, "current_status": "canceled", "project_length": 0, "capitally_funded": true, "project_priority": "", "project_importance": null, "project_description": "This is a new test project", "project_extent_geojson": {"type": "FeatureCollection", "features": [{"id": 50194, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.7268167026341, 30.28892818871917], [-97.72716572508216, 30.290033236814793], [-97.72719472646713, 30.290154684228455], [-97.72721484303474, 30.290250944586575], [-97.72722624242306, 30.29032737379613]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 150194}}]}, "project_description_public": null}, "old": {"added_by": null, "end_date": null, "date_added": "2021-03-23T01:36:54.42012+00:00", "eCapris_id": "1234", "is_retired": false, "project_id": 187, "start_date": "2021-03-22", "fiscal_year": "2017", "timeline_id": null, "project_name": "This is a test project", "project_uuid": "6fdfcab8-5149-4dea-8816-77a11ccf9c42", "current_phase": "construction", "project_order": null, "current_status": "canceled", "project_length": 0, "capitally_funded": true, "project_priority": "", "project_importance": null, "project_description": "This is a new test project", "project_extent_geojson": {"type": "FeatureCollection", "features": [{"id": 50194, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.7268167026341, 30.28892818871917], [-97.72716572508216, 30.290033236814793], [-97.72719472646713, 30.290154684228455], [-97.72721484303474, 30.290250944586575], [-97.72722624242306, 30.29032737379613]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 150194}}]}, "project_description_public": null}}, "trace_context": {"span_id": 5288847825067306386, "trace_id": 18346729627000287658}, "session_variables": {"x-hasura-role": "moped-admin", "x-hasura-user-id": "20c20b28-3b20-4e9e-a0bc-e1ef4e512f2c", "x-hasura-user-db-id": "7", "x-hasura-user-wg-id": "3"}}, "table": {"name": "moped_project", "schema": "public"}, "trigger": {"name": "activity_log_moped_project"}, "created_at": "2021-03-23T01:37:09.945328Z", "delivery_info": {"max_retries": 0, "current_retry": 0}}', '[{"new": "Checking on the project created log", "old": "This is a test project", "field": "project_name"}]', '2021-03-23 01:37:21.343012+00', '20c20b28-3b20-4e9e-a0bc-e1ef4e512f2c', 187, 'UPDATE'); INSERT INTO public.moped_activity_log (activity_id, record_id, record_type, record_data, description, created_at, updated_by, record_project_id, operation_type) VALUES ('66a57080-70cf-419a-b5e9-f8ed4dc080ed', 188, 'moped_project', '{"id": "8031dfb9-45a2-4f26-a751-811cc2831820", "event": {"op": "INSERT", "data": {"new": {"added_by": null, "end_date": null, "date_added": "2021-03-23T16:56:35.754826+00:00", "eCapris_id": "", "is_retired": false, "project_id": 188, "start_date": "2021-03-23", "fiscal_year": "2021", "timeline_id": null, "project_name": "Another John Project", "project_uuid": "892a57ab-74d1-4033-8920-4084d6117c41", "current_phase": "complete", "project_order": null, "current_status": "active", "project_length": 0, "capitally_funded": false, "project_priority": "", "project_importance": null, "project_description": "This is gonna be good", "project_extent_geojson": {"type": "FeatureCollection", "features": [{"id": 54325, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.74485321715474, 30.269660368310596], [-97.74449598044157, 30.270580023866273]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 154325}}, {"id": 54442, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.74521112442017, 30.268721592638997], [-97.74485321715474, 30.269660368310596]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 154442}}, {"id": 54443, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.74521112442017, 30.268721592638997], [-97.7462675794959, 30.269028968820365]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 154443}}, {"id": 48417, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.7462675794959, 30.269028968820365], [-97.74594135582447, 30.269968465464004]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 148417}}, {"id": 54312, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.7441355586052, 30.26842203386127], [-97.74378100410104, 30.269352704539784]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 154312}}, {"id": 47473, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.74247946217656, 30.26897163447613], [-97.74378100410104, 30.269352704539784]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 147473}}, {"id": 53749, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.74282043799758, 30.26807093069874], [-97.7441355586052, 30.26842203386127]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 153749}}, {"id": 53748, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.74282043799758, 30.26807093069874], [-97.74247946217656, 30.26897163447613]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 153748}}, {"id": 52382, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.74111723527312, 30.268608516185054], [-97.74078816175461, 30.269537013352178]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 152382}}, {"id": 54322, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.74146189913154, 30.267688697374666], [-97.74111723527312, 30.268608516185054]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 154322}}, {"id": 47852, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.74111723527312, 30.268608516185054], [-97.74004502221942, 30.268300849117793]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 147852}}, {"id": 48531, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.7403829805553, 30.267399994400208], [-97.74004502221942, 30.268300849117793]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 148531}}, {"id": 51717, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.73934295400977, 30.267073646083887], [-97.73895654827356, 30.26801200315832]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 151717}}, {"id": 47863, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.73895654827356, 30.26801200315832], [-97.7379254065454, 30.2677050581497]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 147863}}, {"id": 6518, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.73825431242585, 30.26678754746615], [-97.7379254065454, 30.2677050581497]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 106518}}, {"id": 47866, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.74343013763428, 30.270261214776838], [-97.74450302124023, 30.270594791564676]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 147866}}]}, "project_description_public": null}, "old": null}, "trace_context": {"span_id": 12892454171637769490, "trace_id": 12471440775515417897}, "session_variables": {"x-hasura-role": "moped-admin", "x-hasura-user-id": "40422ee4-4aca-43b3-898c-ed2ad2f88f6d", "x-hasura-user-db-id": "10", "x-hasura-user-wg-id": "3"}}, "table": {"name": "moped_project", "schema": "public"}, "trigger": {"name": "activity_log_moped_project"}, "created_at": "2021-03-23T16:56:35.749854Z", "delivery_info": {"max_retries": 0, "current_retry": 0}}', '[]', '2021-03-23 16:56:48.283344+00', '40422ee4-4aca-43b3-898c-ed2ad2f88f6d', 188, 'INSERT'); -INSERT INTO public.moped_activity_log (activity_id, record_id, record_type, record_data, description, created_at, updated_by, record_project_id, operation_type) VALUES ('aed04c89-dc0e-469a-99d2-e0bfc184c9fa', 159, 'moped_project', '{"id": "b28c5a6e-5a54-4bda-91db-12b227cedbd4", "event": {"op": "UPDATE", "data": {"new": {"added_by": null, "end_date": null, "date_added": "2021-01-26T10:06:41.4938+00:00", "eCapris_id": "5771.072", "is_retired": false, "project_id": 159, "start_date": "2021-03-23", "fiscal_year": "2018", "timeline_id": null, "project_name": "Avenue G Healthy Street", "project_uuid": "f95c4c47-6099-49a2-9513-376c34459cf8", "current_phase": "construction", "project_order": null, "current_status": "potential", "project_length": 106, "capitally_funded": true, "project_priority": "Low", "project_importance": null, "project_description": "Installation of semi-permanent traffic barriers based on community demand", "project_extent_geojson": {"type": "FeatureCollection", "features": [{"id": 38528, "type": "Feature", "source": "jsx-source-0", "geometry": {"type": "LineString", "coordinates": [[-97.73157846182585, 30.299585000265452], [-97.73083079606295, 30.300865204565497]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 138528}}, {"id": 2479, "type": "Feature", "source": "jsx-source-0", "geometry": {"type": "LineString", "coordinates": [[-97.73083079606295, 30.300865204565497], [-97.73008245974779, 30.302170141796154]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 102479}}, {"id": 23584, "type": "Feature", "source": "jsx-source-0", "geometry": {"type": "LineString", "coordinates": [[-97.73008245974779, 30.302170141796154], [-97.72937687113881, 30.303294434922478]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 123584}}, {"id": 25049, "type": "Feature", "source": "jsx-source-0", "geometry": {"type": "LineString", "coordinates": [[-97.72937687113881, 30.303294434922478], [-97.72867178544402, 30.304407715565787]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 125049}}, {"id": 29536, "type": "Feature", "source": "jsx-source-0", "geometry": {"type": "LineString", "coordinates": [[-97.72867178544402, 30.304407715565787], [-97.72792797535658, 30.30553675911436]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 129536}}, {"id": 39707, "type": "Feature", "source": "jsx-source-0", "geometry": {"type": "LineString", "coordinates": [[-97.72792797535658, 30.30553675911436], [-97.72720964625478, 30.306666368571754]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 139707}}, {"id": 23598, "type": "Feature", "source": "jsx-source-0", "geometry": {"type": "LineString", "coordinates": [[-97.72720964625478, 30.306666368571754], [-97.72683581337333, 30.307250055327543], [-97.72650389000773, 30.307713615628003]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 123598}}, {"id": 6478, "type": "Feature", "source": "jsx-source-0", "geometry": {"type": "LineString", "coordinates": [[-97.72650389000773, 30.307713615628003], [-97.72520100697875, 30.309708651094596]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 106478}}, {"id": 28790, "type": "Feature", "source": "jsx-source-0", "geometry": {"type": "LineString", "coordinates": [[-97.72464444860816, 30.31059667123114], [-97.72388169541955, 30.311755600662806]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 128790}}, {"id": 27487, "type": "Feature", "source": "jsx-source-0", "geometry": {"type": "LineString", "coordinates": [[-97.72388169541955, 30.311755600662806], [-97.72316671907902, 30.312876889471113]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 127487}}, {"id": 37217, "type": "Feature", "source": "jsx-source-0", "geometry": {"type": "LineString", "coordinates": [[-97.72520100697875, 30.309708651094596], [-97.72464444860816, 30.31059667123114]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 137217}}, {"id": 27815, "type": "Feature", "source": "jsx-source-0", "geometry": {"type": "LineString", "coordinates": [[-97.72316671907902, 30.312876889471113], [-97.72241871803999, 30.31403883100012]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 127815}}, {"id": 34837, "type": "Feature", "source": "jsx-source-0", "geometry": {"type": "LineString", "coordinates": [[-97.72241871803999, 30.31403883100012], [-97.7217498421669, 30.31512261234316]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 134837}}, {"id": 33035, "type": "Feature", "source": "jsx-source-0", "geometry": {"type": "LineString", "coordinates": [[-97.7217498421669, 30.31512261234316], [-97.72102111950517, 30.316191476153534]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 133035}}, {"id": 25270, "type": "Feature", "source": "jsx-source-0", "geometry": {"type": "LineString", "coordinates": [[-97.72102111950517, 30.316191476153534], [-97.72029139101505, 30.317271181739386]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 125270}}, {"id": 25101, "type": "Feature", "source": "jsx-source-0", "geometry": {"type": "LineString", "coordinates": [[-97.72029139101505, 30.317271181739386], [-97.71960692480206, 30.318340890377684]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 125101}}, {"id": 24260, "type": "Feature", "source": "jsx-source-0", "geometry": {"type": "LineString", "coordinates": [[-97.71960692480206, 30.318340890377684], [-97.71889278665185, 30.319423755882283]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 124260}}, {"id": 33003, "type": "Feature", "source": "jsx-source-0", "geometry": {"type": "LineString", "coordinates": [[-97.71889278665185, 30.319423755882283], [-97.7181132696569, 30.32063728036431]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 133003}}]}, "project_description_public": null}, "old": {"added_by": null, "end_date": null, "date_added": "2021-01-26T10:06:41.4938+00:00", "eCapris_id": "5771.072", "is_retired": false, "project_id": 159, "start_date": "2021-03-23", "fiscal_year": "2018", "timeline_id": null, "project_name": "Avenue G Healthy Street", "project_uuid": "f95c4c47-6099-49a2-9513-376c34459cf8", "current_phase": "construction", "project_order": null, "current_status": "active", "project_length": 106, "capitally_funded": true, "project_priority": "Low", "project_importance": null, "project_description": "Installation of semi-permanent traffic barriers based on community demand", "project_extent_geojson": {"type": "FeatureCollection", "features": [{"id": 38528, "type": "Feature", "source": "jsx-source-0", "geometry": {"type": "LineString", "coordinates": [[-97.73157846182585, 30.299585000265452], [-97.73083079606295, 30.300865204565497]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 138528}}, {"id": 2479, "type": "Feature", "source": "jsx-source-0", "geometry": {"type": "LineString", "coordinates": [[-97.73083079606295, 30.300865204565497], [-97.73008245974779, 30.302170141796154]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 102479}}, {"id": 23584, "type": "Feature", "source": "jsx-source-0", "geometry": {"type": "LineString", "coordinates": [[-97.73008245974779, 30.302170141796154], [-97.72937687113881, 30.303294434922478]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 123584}}, {"id": 25049, "type": "Feature", "source": "jsx-source-0", "geometry": {"type": "LineString", "coordinates": [[-97.72937687113881, 30.303294434922478], [-97.72867178544402, 30.304407715565787]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 125049}}, {"id": 29536, "type": "Feature", "source": "jsx-source-0", "geometry": {"type": "LineString", "coordinates": [[-97.72867178544402, 30.304407715565787], [-97.72792797535658, 30.30553675911436]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 129536}}, {"id": 39707, "type": "Feature", "source": "jsx-source-0", "geometry": {"type": "LineString", "coordinates": [[-97.72792797535658, 30.30553675911436], [-97.72720964625478, 30.306666368571754]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 139707}}, {"id": 23598, "type": "Feature", "source": "jsx-source-0", "geometry": {"type": "LineString", "coordinates": [[-97.72720964625478, 30.306666368571754], [-97.72683581337333, 30.307250055327543], [-97.72650389000773, 30.307713615628003]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 123598}}, {"id": 6478, "type": "Feature", "source": "jsx-source-0", "geometry": {"type": "LineString", "coordinates": [[-97.72650389000773, 30.307713615628003], [-97.72520100697875, 30.309708651094596]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 106478}}, {"id": 28790, "type": "Feature", "source": "jsx-source-0", "geometry": {"type": "LineString", "coordinates": [[-97.72464444860816, 30.31059667123114], [-97.72388169541955, 30.311755600662806]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 128790}}, {"id": 27487, "type": "Feature", "source": "jsx-source-0", "geometry": {"type": "LineString", "coordinates": [[-97.72388169541955, 30.311755600662806], [-97.72316671907902, 30.312876889471113]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 127487}}, {"id": 37217, "type": "Feature", "source": "jsx-source-0", "geometry": {"type": "LineString", "coordinates": [[-97.72520100697875, 30.309708651094596], [-97.72464444860816, 30.31059667123114]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 137217}}, {"id": 27815, "type": "Feature", "source": "jsx-source-0", "geometry": {"type": "LineString", "coordinates": [[-97.72316671907902, 30.312876889471113], [-97.72241871803999, 30.31403883100012]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 127815}}, {"id": 34837, "type": "Feature", "source": "jsx-source-0", "geometry": {"type": "LineString", "coordinates": [[-97.72241871803999, 30.31403883100012], [-97.7217498421669, 30.31512261234316]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 134837}}, {"id": 33035, "type": "Feature", "source": "jsx-source-0", "geometry": {"type": "LineString", "coordinates": [[-97.7217498421669, 30.31512261234316], [-97.72102111950517, 30.316191476153534]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 133035}}, {"id": 25270, "type": "Feature", "source": "jsx-source-0", "geometry": {"type": "LineString", "coordinates": [[-97.72102111950517, 30.316191476153534], [-97.72029139101505, 30.317271181739386]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 125270}}, {"id": 25101, "type": "Feature", "source": "jsx-source-0", "geometry": {"type": "LineString", "coordinates": [[-97.72029139101505, 30.317271181739386], [-97.71960692480206, 30.318340890377684]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 125101}}, {"id": 24260, "type": "Feature", "source": "jsx-source-0", "geometry": {"type": "LineString", "coordinates": [[-97.71960692480206, 30.318340890377684], [-97.71889278665185, 30.319423755882283]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 124260}}, {"id": 33003, "type": "Feature", "source": "jsx-source-0", "geometry": {"type": "LineString", "coordinates": [[-97.71889278665185, 30.319423755882283], [-97.7181132696569, 30.32063728036431]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 133003}}]}, "project_description_public": null}}, "trace_context": {"span_id": 17784305494158522556, "trace_id": 578298752847253035}, "session_variables": {"x-hasura-role": "moped-admin", "x-hasura-user-id": "ec609228-4442-41e5-a0dc-2c417af00c6b", "x-hasura-user-db-id": "1", "x-hasura-user-wg-id": "18"}}, "table": {"name": "moped_project", "schema": "public"}, "trigger": {"name": "activity_log_moped_project"}, "created_at": "2021-03-23T16:56:56.885225Z", "delivery_info": {"max_retries": 0, "current_retry": 0}}', '[{"new": "potential", "old": "active", "field": "current_status"}]', '2021-03-23 16:57:08.622478+00', 'ec609228-4442-41e5-a0dc-2c417af00c6b', 159, 'UPDATE'); +INSERT INTO public.moped_activity_log (activity_id, record_id, record_type, record_data, description, created_at, updated_by, record_project_id, operation_type) VALUES ('aed04c89-dc0e-469a-99d2-e0bfc184c9fa', 159, 'moped_project', '{"id": "b28c5a6e-5a54-4bda-91db-12b227cedbd4", "event": {"op": "UPDATE", "data": {"new": {"added_by": null, "end_date": null, "date_added": "2021-01-26T10:06:41.4938+00:00", "eCapris_id": "5771.072", "is_retired": false, "project_id": 159, "start_date": "2021-03-23", "fiscal_year": "2018", "timeline_id": null, "project_name": "Downtown 6th & Congress", "project_uuid": "f95c4c47-6099-49a2-9513-376c34459cf8", "current_phase": "construction", "project_order": null, "current_status": "potential", "project_length": 106, "capitally_funded": true, "project_priority": "Low", "project_importance": null, "project_description": "Installation of semi-permanent traffic barriers based on community demand", "project_extent_geojson": {"type": "FeatureCollection", "features": [{"id": 38528, "type": "Feature", "source": "jsx-source-0", "geometry": {"type": "LineString", "coordinates": [[-97.73157846182585, 30.299585000265452], [-97.73083079606295, 30.300865204565497]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 138528}}, {"id": 2479, "type": "Feature", "source": "jsx-source-0", "geometry": {"type": "LineString", "coordinates": [[-97.73083079606295, 30.300865204565497], [-97.73008245974779, 30.302170141796154]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 102479}}, {"id": 23584, "type": "Feature", "source": "jsx-source-0", "geometry": {"type": "LineString", "coordinates": [[-97.73008245974779, 30.302170141796154], [-97.72937687113881, 30.303294434922478]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 123584}}, {"id": 25049, "type": "Feature", "source": "jsx-source-0", "geometry": {"type": "LineString", "coordinates": [[-97.72937687113881, 30.303294434922478], [-97.72867178544402, 30.304407715565787]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 125049}}, {"id": 29536, "type": "Feature", "source": "jsx-source-0", "geometry": {"type": "LineString", "coordinates": [[-97.72867178544402, 30.304407715565787], [-97.72792797535658, 30.30553675911436]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 129536}}, {"id": 39707, "type": "Feature", "source": "jsx-source-0", "geometry": {"type": "LineString", "coordinates": [[-97.72792797535658, 30.30553675911436], [-97.72720964625478, 30.306666368571754]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 139707}}, {"id": 23598, "type": "Feature", "source": "jsx-source-0", "geometry": {"type": "LineString", "coordinates": [[-97.72720964625478, 30.306666368571754], [-97.72683581337333, 30.307250055327543], [-97.72650389000773, 30.307713615628003]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 123598}}, {"id": 6478, "type": "Feature", "source": "jsx-source-0", "geometry": {"type": "LineString", "coordinates": [[-97.72650389000773, 30.307713615628003], [-97.72520100697875, 30.309708651094596]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 106478}}, {"id": 28790, "type": "Feature", "source": "jsx-source-0", "geometry": {"type": "LineString", "coordinates": [[-97.72464444860816, 30.31059667123114], [-97.72388169541955, 30.311755600662806]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 128790}}, {"id": 27487, "type": "Feature", "source": "jsx-source-0", "geometry": {"type": "LineString", "coordinates": [[-97.72388169541955, 30.311755600662806], [-97.72316671907902, 30.312876889471113]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 127487}}, {"id": 37217, "type": "Feature", "source": "jsx-source-0", "geometry": {"type": "LineString", "coordinates": [[-97.72520100697875, 30.309708651094596], [-97.72464444860816, 30.31059667123114]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 137217}}, {"id": 27815, "type": "Feature", "source": "jsx-source-0", "geometry": {"type": "LineString", "coordinates": [[-97.72316671907902, 30.312876889471113], [-97.72241871803999, 30.31403883100012]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 127815}}, {"id": 34837, "type": "Feature", "source": "jsx-source-0", "geometry": {"type": "LineString", "coordinates": [[-97.72241871803999, 30.31403883100012], [-97.7217498421669, 30.31512261234316]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 134837}}, {"id": 33035, "type": "Feature", "source": "jsx-source-0", "geometry": {"type": "LineString", "coordinates": [[-97.7217498421669, 30.31512261234316], [-97.72102111950517, 30.316191476153534]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 133035}}, {"id": 25270, "type": "Feature", "source": "jsx-source-0", "geometry": {"type": "LineString", "coordinates": [[-97.72102111950517, 30.316191476153534], [-97.72029139101505, 30.317271181739386]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 125270}}, {"id": 25101, "type": "Feature", "source": "jsx-source-0", "geometry": {"type": "LineString", "coordinates": [[-97.72029139101505, 30.317271181739386], [-97.71960692480206, 30.318340890377684]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 125101}}, {"id": 24260, "type": "Feature", "source": "jsx-source-0", "geometry": {"type": "LineString", "coordinates": [[-97.71960692480206, 30.318340890377684], [-97.71889278665185, 30.319423755882283]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 124260}}, {"id": 33003, "type": "Feature", "source": "jsx-source-0", "geometry": {"type": "LineString", "coordinates": [[-97.71889278665185, 30.319423755882283], [-97.7181132696569, 30.32063728036431]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 133003}}]}, "project_description_public": null}, "old": {"added_by": null, "end_date": null, "date_added": "2021-01-26T10:06:41.4938+00:00", "eCapris_id": "5771.072", "is_retired": false, "project_id": 159, "start_date": "2021-03-23", "fiscal_year": "2018", "timeline_id": null, "project_name": "Avenue G Healthy Street", "project_uuid": "f95c4c47-6099-49a2-9513-376c34459cf8", "current_phase": "construction", "project_order": null, "current_status": "active", "project_length": 106, "capitally_funded": true, "project_priority": "Low", "project_importance": null, "project_description": "Installation of semi-permanent traffic barriers based on community demand", "project_extent_geojson": {"type": "FeatureCollection", "features": [{"id": 38528, "type": "Feature", "source": "jsx-source-0", "geometry": {"type": "LineString", "coordinates": [[-97.73157846182585, 30.299585000265452], [-97.73083079606295, 30.300865204565497]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 138528}}, {"id": 2479, "type": "Feature", "source": "jsx-source-0", "geometry": {"type": "LineString", "coordinates": [[-97.73083079606295, 30.300865204565497], [-97.73008245974779, 30.302170141796154]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 102479}}, {"id": 23584, "type": "Feature", "source": "jsx-source-0", "geometry": {"type": "LineString", "coordinates": [[-97.73008245974779, 30.302170141796154], [-97.72937687113881, 30.303294434922478]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 123584}}, {"id": 25049, "type": "Feature", "source": "jsx-source-0", "geometry": {"type": "LineString", "coordinates": [[-97.72937687113881, 30.303294434922478], [-97.72867178544402, 30.304407715565787]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 125049}}, {"id": 29536, "type": "Feature", "source": "jsx-source-0", "geometry": {"type": "LineString", "coordinates": [[-97.72867178544402, 30.304407715565787], [-97.72792797535658, 30.30553675911436]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 129536}}, {"id": 39707, "type": "Feature", "source": "jsx-source-0", "geometry": {"type": "LineString", "coordinates": [[-97.72792797535658, 30.30553675911436], [-97.72720964625478, 30.306666368571754]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 139707}}, {"id": 23598, "type": "Feature", "source": "jsx-source-0", "geometry": {"type": "LineString", "coordinates": [[-97.72720964625478, 30.306666368571754], [-97.72683581337333, 30.307250055327543], [-97.72650389000773, 30.307713615628003]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 123598}}, {"id": 6478, "type": "Feature", "source": "jsx-source-0", "geometry": {"type": "LineString", "coordinates": [[-97.72650389000773, 30.307713615628003], [-97.72520100697875, 30.309708651094596]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 106478}}, {"id": 28790, "type": "Feature", "source": "jsx-source-0", "geometry": {"type": "LineString", "coordinates": [[-97.72464444860816, 30.31059667123114], [-97.72388169541955, 30.311755600662806]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 128790}}, {"id": 27487, "type": "Feature", "source": "jsx-source-0", "geometry": {"type": "LineString", "coordinates": [[-97.72388169541955, 30.311755600662806], [-97.72316671907902, 30.312876889471113]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 127487}}, {"id": 37217, "type": "Feature", "source": "jsx-source-0", "geometry": {"type": "LineString", "coordinates": [[-97.72520100697875, 30.309708651094596], [-97.72464444860816, 30.31059667123114]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 137217}}, {"id": 27815, "type": "Feature", "source": "jsx-source-0", "geometry": {"type": "LineString", "coordinates": [[-97.72316671907902, 30.312876889471113], [-97.72241871803999, 30.31403883100012]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 127815}}, {"id": 34837, "type": "Feature", "source": "jsx-source-0", "geometry": {"type": "LineString", "coordinates": [[-97.72241871803999, 30.31403883100012], [-97.7217498421669, 30.31512261234316]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 134837}}, {"id": 33035, "type": "Feature", "source": "jsx-source-0", "geometry": {"type": "LineString", "coordinates": [[-97.7217498421669, 30.31512261234316], [-97.72102111950517, 30.316191476153534]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 133035}}, {"id": 25270, "type": "Feature", "source": "jsx-source-0", "geometry": {"type": "LineString", "coordinates": [[-97.72102111950517, 30.316191476153534], [-97.72029139101505, 30.317271181739386]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 125270}}, {"id": 25101, "type": "Feature", "source": "jsx-source-0", "geometry": {"type": "LineString", "coordinates": [[-97.72029139101505, 30.317271181739386], [-97.71960692480206, 30.318340890377684]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 125101}}, {"id": 24260, "type": "Feature", "source": "jsx-source-0", "geometry": {"type": "LineString", "coordinates": [[-97.71960692480206, 30.318340890377684], [-97.71889278665185, 30.319423755882283]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 124260}}, {"id": 33003, "type": "Feature", "source": "jsx-source-0", "geometry": {"type": "LineString", "coordinates": [[-97.71889278665185, 30.319423755882283], [-97.7181132696569, 30.32063728036431]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 133003}}]}, "project_description_public": null}}, "trace_context": {"span_id": 17784305494158522556, "trace_id": 578298752847253035}, "session_variables": {"x-hasura-role": "moped-admin", "x-hasura-user-id": "ec609228-4442-41e5-a0dc-2c417af00c6b", "x-hasura-user-db-id": "1", "x-hasura-user-wg-id": "18"}}, "table": {"name": "moped_project", "schema": "public"}, "trigger": {"name": "activity_log_moped_project"}, "created_at": "2021-03-23T16:56:56.885225Z", "delivery_info": {"max_retries": 0, "current_retry": 0}}', '[{"new": "potential", "old": "active", "field": "current_status"}]', '2021-03-23 16:57:08.622478+00', 'ec609228-4442-41e5-a0dc-2c417af00c6b', 159, 'UPDATE'); INSERT INTO public.moped_activity_log (activity_id, record_id, record_type, record_data, description, created_at, updated_by, record_project_id, operation_type) VALUES ('b79b12c5-1dc3-47c7-b962-4bc43f924f30', 159, 'moped_project', '{"id": "9dbc083a-d82c-4bdc-ad0d-3b486d404595", "event": {"op": "UPDATE", "data": {"new": {"added_by": null, "end_date": null, "date_added": "2021-01-26T10:06:41.4938+00:00", "eCapris_id": "5771.072", "is_retired": false, "project_id": 159, "start_date": "2021-03-23", "fiscal_year": "2018", "timeline_id": null, "project_name": "Avenue G Healthy Street", "project_uuid": "f95c4c47-6099-49a2-9513-376c34459cf8", "current_phase": "potential", "project_order": null, "current_status": "potential", "project_length": 106, "capitally_funded": true, "project_priority": "Low", "project_importance": null, "project_description": "Installation of semi-permanent traffic barriers based on community demand", "project_extent_geojson": {"type": "FeatureCollection", "features": [{"id": 38528, "type": "Feature", "source": "jsx-source-0", "geometry": {"type": "LineString", "coordinates": [[-97.73157846182585, 30.299585000265452], [-97.73083079606295, 30.300865204565497]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 138528}}, {"id": 2479, "type": "Feature", "source": "jsx-source-0", "geometry": {"type": "LineString", "coordinates": [[-97.73083079606295, 30.300865204565497], [-97.73008245974779, 30.302170141796154]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 102479}}, {"id": 23584, "type": "Feature", "source": "jsx-source-0", "geometry": {"type": "LineString", "coordinates": [[-97.73008245974779, 30.302170141796154], [-97.72937687113881, 30.303294434922478]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 123584}}, {"id": 25049, "type": "Feature", "source": "jsx-source-0", "geometry": {"type": "LineString", "coordinates": [[-97.72937687113881, 30.303294434922478], [-97.72867178544402, 30.304407715565787]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 125049}}, {"id": 29536, "type": "Feature", "source": "jsx-source-0", "geometry": {"type": "LineString", "coordinates": [[-97.72867178544402, 30.304407715565787], [-97.72792797535658, 30.30553675911436]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 129536}}, {"id": 39707, "type": "Feature", "source": "jsx-source-0", "geometry": {"type": "LineString", "coordinates": [[-97.72792797535658, 30.30553675911436], [-97.72720964625478, 30.306666368571754]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 139707}}, {"id": 23598, "type": "Feature", "source": "jsx-source-0", "geometry": {"type": "LineString", "coordinates": [[-97.72720964625478, 30.306666368571754], [-97.72683581337333, 30.307250055327543], [-97.72650389000773, 30.307713615628003]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 123598}}, {"id": 6478, "type": "Feature", "source": "jsx-source-0", "geometry": {"type": "LineString", "coordinates": [[-97.72650389000773, 30.307713615628003], [-97.72520100697875, 30.309708651094596]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 106478}}, {"id": 28790, "type": "Feature", "source": "jsx-source-0", "geometry": {"type": "LineString", "coordinates": [[-97.72464444860816, 30.31059667123114], [-97.72388169541955, 30.311755600662806]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 128790}}, {"id": 27487, "type": "Feature", "source": "jsx-source-0", "geometry": {"type": "LineString", "coordinates": [[-97.72388169541955, 30.311755600662806], [-97.72316671907902, 30.312876889471113]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 127487}}, {"id": 37217, "type": "Feature", "source": "jsx-source-0", "geometry": {"type": "LineString", "coordinates": [[-97.72520100697875, 30.309708651094596], [-97.72464444860816, 30.31059667123114]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 137217}}, {"id": 27815, "type": "Feature", "source": "jsx-source-0", "geometry": {"type": "LineString", "coordinates": [[-97.72316671907902, 30.312876889471113], [-97.72241871803999, 30.31403883100012]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 127815}}, {"id": 34837, "type": "Feature", "source": "jsx-source-0", "geometry": {"type": "LineString", "coordinates": [[-97.72241871803999, 30.31403883100012], [-97.7217498421669, 30.31512261234316]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 134837}}, {"id": 33035, "type": "Feature", "source": "jsx-source-0", "geometry": {"type": "LineString", "coordinates": [[-97.7217498421669, 30.31512261234316], [-97.72102111950517, 30.316191476153534]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 133035}}, {"id": 25270, "type": "Feature", "source": "jsx-source-0", "geometry": {"type": "LineString", "coordinates": [[-97.72102111950517, 30.316191476153534], [-97.72029139101505, 30.317271181739386]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 125270}}, {"id": 25101, "type": "Feature", "source": "jsx-source-0", "geometry": {"type": "LineString", "coordinates": [[-97.72029139101505, 30.317271181739386], [-97.71960692480206, 30.318340890377684]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 125101}}, {"id": 24260, "type": "Feature", "source": "jsx-source-0", "geometry": {"type": "LineString", "coordinates": [[-97.71960692480206, 30.318340890377684], [-97.71889278665185, 30.319423755882283]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 124260}}, {"id": 33003, "type": "Feature", "source": "jsx-source-0", "geometry": {"type": "LineString", "coordinates": [[-97.71889278665185, 30.319423755882283], [-97.7181132696569, 30.32063728036431]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 133003}}]}, "project_description_public": null}, "old": {"added_by": null, "end_date": null, "date_added": "2021-01-26T10:06:41.4938+00:00", "eCapris_id": "5771.072", "is_retired": false, "project_id": 159, "start_date": "2021-03-23", "fiscal_year": "2018", "timeline_id": null, "project_name": "Avenue G Healthy Street", "project_uuid": "f95c4c47-6099-49a2-9513-376c34459cf8", "current_phase": "construction", "project_order": null, "current_status": "potential", "project_length": 106, "capitally_funded": true, "project_priority": "Low", "project_importance": null, "project_description": "Installation of semi-permanent traffic barriers based on community demand", "project_extent_geojson": {"type": "FeatureCollection", "features": [{"id": 38528, "type": "Feature", "source": "jsx-source-0", "geometry": {"type": "LineString", "coordinates": [[-97.73157846182585, 30.299585000265452], [-97.73083079606295, 30.300865204565497]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 138528}}, {"id": 2479, "type": "Feature", "source": "jsx-source-0", "geometry": {"type": "LineString", "coordinates": [[-97.73083079606295, 30.300865204565497], [-97.73008245974779, 30.302170141796154]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 102479}}, {"id": 23584, "type": "Feature", "source": "jsx-source-0", "geometry": {"type": "LineString", "coordinates": [[-97.73008245974779, 30.302170141796154], [-97.72937687113881, 30.303294434922478]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 123584}}, {"id": 25049, "type": "Feature", "source": "jsx-source-0", "geometry": {"type": "LineString", "coordinates": [[-97.72937687113881, 30.303294434922478], [-97.72867178544402, 30.304407715565787]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 125049}}, {"id": 29536, "type": "Feature", "source": "jsx-source-0", "geometry": {"type": "LineString", "coordinates": [[-97.72867178544402, 30.304407715565787], [-97.72792797535658, 30.30553675911436]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 129536}}, {"id": 39707, "type": "Feature", "source": "jsx-source-0", "geometry": {"type": "LineString", "coordinates": [[-97.72792797535658, 30.30553675911436], [-97.72720964625478, 30.306666368571754]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 139707}}, {"id": 23598, "type": "Feature", "source": "jsx-source-0", "geometry": {"type": "LineString", "coordinates": [[-97.72720964625478, 30.306666368571754], [-97.72683581337333, 30.307250055327543], [-97.72650389000773, 30.307713615628003]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 123598}}, {"id": 6478, "type": "Feature", "source": "jsx-source-0", "geometry": {"type": "LineString", "coordinates": [[-97.72650389000773, 30.307713615628003], [-97.72520100697875, 30.309708651094596]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 106478}}, {"id": 28790, "type": "Feature", "source": "jsx-source-0", "geometry": {"type": "LineString", "coordinates": [[-97.72464444860816, 30.31059667123114], [-97.72388169541955, 30.311755600662806]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 128790}}, {"id": 27487, "type": "Feature", "source": "jsx-source-0", "geometry": {"type": "LineString", "coordinates": [[-97.72388169541955, 30.311755600662806], [-97.72316671907902, 30.312876889471113]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 127487}}, {"id": 37217, "type": "Feature", "source": "jsx-source-0", "geometry": {"type": "LineString", "coordinates": [[-97.72520100697875, 30.309708651094596], [-97.72464444860816, 30.31059667123114]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 137217}}, {"id": 27815, "type": "Feature", "source": "jsx-source-0", "geometry": {"type": "LineString", "coordinates": [[-97.72316671907902, 30.312876889471113], [-97.72241871803999, 30.31403883100012]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 127815}}, {"id": 34837, "type": "Feature", "source": "jsx-source-0", "geometry": {"type": "LineString", "coordinates": [[-97.72241871803999, 30.31403883100012], [-97.7217498421669, 30.31512261234316]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 134837}}, {"id": 33035, "type": "Feature", "source": "jsx-source-0", "geometry": {"type": "LineString", "coordinates": [[-97.7217498421669, 30.31512261234316], [-97.72102111950517, 30.316191476153534]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 133035}}, {"id": 25270, "type": "Feature", "source": "jsx-source-0", "geometry": {"type": "LineString", "coordinates": [[-97.72102111950517, 30.316191476153534], [-97.72029139101505, 30.317271181739386]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 125270}}, {"id": 25101, "type": "Feature", "source": "jsx-source-0", "geometry": {"type": "LineString", "coordinates": [[-97.72029139101505, 30.317271181739386], [-97.71960692480206, 30.318340890377684]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 125101}}, {"id": 24260, "type": "Feature", "source": "jsx-source-0", "geometry": {"type": "LineString", "coordinates": [[-97.71960692480206, 30.318340890377684], [-97.71889278665185, 30.319423755882283]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 124260}}, {"id": 33003, "type": "Feature", "source": "jsx-source-0", "geometry": {"type": "LineString", "coordinates": [[-97.71889278665185, 30.319423755882283], [-97.7181132696569, 30.32063728036431]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 133003}}]}, "project_description_public": null}}, "trace_context": {"span_id": 6607851743559513518, "trace_id": 17961708981458787052}, "session_variables": {"x-hasura-role": "moped-admin", "x-hasura-user-id": "ec609228-4442-41e5-a0dc-2c417af00c6b", "x-hasura-user-db-id": "1", "x-hasura-user-wg-id": "18"}}, "table": {"name": "moped_project", "schema": "public"}, "trigger": {"name": "activity_log_moped_project"}, "created_at": "2021-03-23T16:57:03.698854Z", "delivery_info": {"max_retries": 0, "current_retry": 0}}', '[{"new": "potential", "old": "construction", "field": "current_phase"}]', '2021-03-23 16:57:15.084635+00', 'ec609228-4442-41e5-a0dc-2c417af00c6b', 159, 'UPDATE'); INSERT INTO public.moped_activity_log (activity_id, record_id, record_type, record_data, description, created_at, updated_by, record_project_id, operation_type) VALUES ('14578c20-435f-4e72-a5a4-c33067a22e7d', 188, 'moped_project', '{"id": "49cd6ef0-0737-495f-9f45-36171acb063d", "event": {"op": "UPDATE", "data": {"new": {"added_by": null, "end_date": null, "date_added": "2021-03-23T16:56:35.754826+00:00", "eCapris_id": "", "is_retired": false, "project_id": 188, "start_date": "2021-03-23", "fiscal_year": "2021", "timeline_id": null, "project_name": "Another John Project", "project_uuid": "892a57ab-74d1-4033-8920-4084d6117c41", "current_phase": "complete", "project_order": null, "current_status": "active", "project_length": 0, "capitally_funded": false, "project_priority": "", "project_importance": null, "project_description": "This is gonna be good", "project_extent_geojson": {"type": "FeatureCollection", "features": [{"id": 54325, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.74485321715474, 30.269660368310596], [-97.74449598044157, 30.270580023866273]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 154325}}, {"id": 54442, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.74521112442017, 30.268721592638997], [-97.74485321715474, 30.269660368310596]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 154442}}, {"id": 54443, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.74521112442017, 30.268721592638997], [-97.7462675794959, 30.269028968820365]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 154443}}, {"id": 48417, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.7462675794959, 30.269028968820365], [-97.74594135582447, 30.269968465464004]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 148417}}, {"id": 54312, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.7441355586052, 30.26842203386127], [-97.74378100410104, 30.269352704539784]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 154312}}, {"id": 47473, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.74247946217656, 30.26897163447613], [-97.74378100410104, 30.269352704539784]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 147473}}, {"id": 53749, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.74282043799758, 30.26807093069874], [-97.7441355586052, 30.26842203386127]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 153749}}, {"id": 53748, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.74282043799758, 30.26807093069874], [-97.74247946217656, 30.26897163447613]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 153748}}, {"id": 52382, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.74111723527312, 30.268608516185054], [-97.74078816175461, 30.269537013352178]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 152382}}, {"id": 54322, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.74146189913154, 30.267688697374666], [-97.74111723527312, 30.268608516185054]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 154322}}, {"id": 47852, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.74111723527312, 30.268608516185054], [-97.74004502221942, 30.268300849117793]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 147852}}, {"id": 48531, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.7403829805553, 30.267399994400208], [-97.74004502221942, 30.268300849117793]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 148531}}, {"id": 51717, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.73934295400977, 30.267073646083887], [-97.73895654827356, 30.26801200315832]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 151717}}, {"id": 47863, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.73895654827356, 30.26801200315832], [-97.7379254065454, 30.2677050581497]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 147863}}, {"id": 6518, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.73825431242585, 30.26678754746615], [-97.7379254065454, 30.2677050581497]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 106518}}, {"id": 47866, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.74343013763428, 30.270261214776838], [-97.74450302124023, 30.270594791564676]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 147866}}, {"id": 48693, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.74449598044157, 30.270580023866273], [-97.74560004472733, 30.27087740434517]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 148693}}]}, "project_description_public": null}, "old": {"added_by": null, "end_date": null, "date_added": "2021-03-23T16:56:35.754826+00:00", "eCapris_id": "", "is_retired": false, "project_id": 188, "start_date": "2021-03-23", "fiscal_year": "2021", "timeline_id": null, "project_name": "Another John Project", "project_uuid": "892a57ab-74d1-4033-8920-4084d6117c41", "current_phase": "complete", "project_order": null, "current_status": "active", "project_length": 0, "capitally_funded": false, "project_priority": "", "project_importance": null, "project_description": "This is gonna be good", "project_extent_geojson": {"type": "FeatureCollection", "features": [{"id": 54325, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.74485321715474, 30.269660368310596], [-97.74449598044157, 30.270580023866273]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 154325}}, {"id": 54442, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.74521112442017, 30.268721592638997], [-97.74485321715474, 30.269660368310596]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 154442}}, {"id": 54443, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.74521112442017, 30.268721592638997], [-97.7462675794959, 30.269028968820365]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 154443}}, {"id": 48417, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.7462675794959, 30.269028968820365], [-97.74594135582447, 30.269968465464004]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 148417}}, {"id": 54312, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.7441355586052, 30.26842203386127], [-97.74378100410104, 30.269352704539784]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 154312}}, {"id": 47473, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.74247946217656, 30.26897163447613], [-97.74378100410104, 30.269352704539784]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 147473}}, {"id": 53749, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.74282043799758, 30.26807093069874], [-97.7441355586052, 30.26842203386127]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 153749}}, {"id": 53748, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.74282043799758, 30.26807093069874], [-97.74247946217656, 30.26897163447613]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 153748}}, {"id": 52382, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.74111723527312, 30.268608516185054], [-97.74078816175461, 30.269537013352178]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 152382}}, {"id": 54322, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.74146189913154, 30.267688697374666], [-97.74111723527312, 30.268608516185054]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 154322}}, {"id": 47852, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.74111723527312, 30.268608516185054], [-97.74004502221942, 30.268300849117793]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 147852}}, {"id": 48531, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.7403829805553, 30.267399994400208], [-97.74004502221942, 30.268300849117793]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 148531}}, {"id": 51717, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.73934295400977, 30.267073646083887], [-97.73895654827356, 30.26801200315832]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 151717}}, {"id": 47863, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.73895654827356, 30.26801200315832], [-97.7379254065454, 30.2677050581497]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 147863}}, {"id": 6518, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.73825431242585, 30.26678754746615], [-97.7379254065454, 30.2677050581497]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 106518}}, {"id": 47866, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.74343013763428, 30.270261214776838], [-97.74450302124023, 30.270594791564676]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 147866}}]}, "project_description_public": null}}, "trace_context": {"span_id": 7314644711510233905, "trace_id": 14481523999612599550}, "session_variables": {"x-hasura-role": "moped-admin", "x-hasura-user-id": "40422ee4-4aca-43b3-898c-ed2ad2f88f6d", "x-hasura-user-db-id": "10", "x-hasura-user-wg-id": "3"}}, "table": {"name": "moped_project", "schema": "public"}, "trigger": {"name": "activity_log_moped_project"}, "created_at": "2021-03-23T16:57:37.740995Z", "delivery_info": {"max_retries": 0, "current_retry": 0}}', '[{"new": {"CTN": [154325, 154442, 154443, 148417, 154312, 147473, 153749, 153748, 152382, 154322, 147852, 148531, 151717, 147863, 106518, 148693, 147866]}, "old": {"CTN": [154325, 154442, 154443, 148417, 154312, 147473, 153749, 153748, 152382, 154322, 147852, 148531, 151717, 147863, 106518]}, "field": "project_extent_ids"}, {"new": {"type": "FeatureCollection", "features": [{"id": 54325, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.74485321715474, 30.269660368310596], [-97.74449598044157, 30.270580023866273]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 154325}}, {"id": 54442, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.74521112442017, 30.268721592638997], [-97.74485321715474, 30.269660368310596]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 154442}}, {"id": 54443, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.74521112442017, 30.268721592638997], [-97.7462675794959, 30.269028968820365]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 154443}}, {"id": 48417, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.7462675794959, 30.269028968820365], [-97.74594135582447, 30.269968465464004]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 148417}}, {"id": 54312, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.7441355586052, 30.26842203386127], [-97.74378100410104, 30.269352704539784]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 154312}}, {"id": 47473, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.74247946217656, 30.26897163447613], [-97.74378100410104, 30.269352704539784]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 147473}}, {"id": 53749, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.74282043799758, 30.26807093069874], [-97.7441355586052, 30.26842203386127]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 153749}}, {"id": 53748, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.74282043799758, 30.26807093069874], [-97.74247946217656, 30.26897163447613]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 153748}}, {"id": 52382, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.74111723527312, 30.268608516185054], [-97.74078816175461, 30.269537013352178]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 152382}}, {"id": 54322, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.74146189913154, 30.267688697374666], [-97.74111723527312, 30.268608516185054]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 154322}}, {"id": 47852, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.74111723527312, 30.268608516185054], [-97.74004502221942, 30.268300849117793]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 147852}}, {"id": 48531, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.7403829805553, 30.267399994400208], [-97.74004502221942, 30.268300849117793]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 148531}}, {"id": 51717, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.73934295400977, 30.267073646083887], [-97.73895654827356, 30.26801200315832]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 151717}}, {"id": 47863, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.73895654827356, 30.26801200315832], [-97.7379254065454, 30.2677050581497]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 147863}}, {"id": 6518, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.73825431242585, 30.26678754746615], [-97.7379254065454, 30.2677050581497]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 106518}}, {"id": 47866, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.74343013763428, 30.270261214776838], [-97.74450302124023, 30.270594791564676]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 147866}}, {"id": 48693, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.74449598044157, 30.270580023866273], [-97.74560004472733, 30.27087740434517]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 148693}}]}, "old": {"type": "FeatureCollection", "features": [{"id": 54325, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.74485321715474, 30.269660368310596], [-97.74449598044157, 30.270580023866273]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 154325}}, {"id": 54442, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.74521112442017, 30.268721592638997], [-97.74485321715474, 30.269660368310596]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 154442}}, {"id": 54443, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.74521112442017, 30.268721592638997], [-97.7462675794959, 30.269028968820365]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 154443}}, {"id": 48417, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.7462675794959, 30.269028968820365], [-97.74594135582447, 30.269968465464004]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 148417}}, {"id": 54312, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.7441355586052, 30.26842203386127], [-97.74378100410104, 30.269352704539784]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 154312}}, {"id": 47473, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.74247946217656, 30.26897163447613], [-97.74378100410104, 30.269352704539784]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 147473}}, {"id": 53749, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.74282043799758, 30.26807093069874], [-97.7441355586052, 30.26842203386127]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 153749}}, {"id": 53748, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.74282043799758, 30.26807093069874], [-97.74247946217656, 30.26897163447613]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 153748}}, {"id": 52382, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.74111723527312, 30.268608516185054], [-97.74078816175461, 30.269537013352178]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 152382}}, {"id": 54322, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.74146189913154, 30.267688697374666], [-97.74111723527312, 30.268608516185054]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 154322}}, {"id": 47852, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.74111723527312, 30.268608516185054], [-97.74004502221942, 30.268300849117793]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 147852}}, {"id": 48531, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.7403829805553, 30.267399994400208], [-97.74004502221942, 30.268300849117793]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 148531}}, {"id": 51717, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.73934295400977, 30.267073646083887], [-97.73895654827356, 30.26801200315832]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 151717}}, {"id": 47863, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.73895654827356, 30.26801200315832], [-97.7379254065454, 30.2677050581497]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 147863}}, {"id": 6518, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.73825431242585, 30.26678754746615], [-97.7379254065454, 30.2677050581497]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 106518}}, {"id": 47866, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.74343013763428, 30.270261214776838], [-97.74450302124023, 30.270594791564676]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 147866}}]}, "field": "project_extent_geojson"}]', '2021-03-23 16:57:49.426031+00', '40422ee4-4aca-43b3-898c-ed2ad2f88f6d', 188, 'UPDATE'); INSERT INTO public.moped_activity_log (activity_id, record_id, record_type, record_data, description, created_at, updated_by, record_project_id, operation_type) VALUES ('9ad6d931-732a-4104-830b-d6204831c725', 188, 'moped_project', '{"id": "bec8969f-a8c8-4cf0-b46d-212d28f54ec0", "event": {"op": "UPDATE", "data": {"new": {"added_by": null, "end_date": null, "date_added": "2021-03-23T16:56:35.754826+00:00", "eCapris_id": "", "is_retired": false, "project_id": 188, "start_date": "2021-03-23", "fiscal_year": "2021", "timeline_id": null, "project_name": "Another John Project", "project_uuid": "892a57ab-74d1-4033-8920-4084d6117c41", "current_phase": "complete", "project_order": null, "current_status": "active", "project_length": 0, "capitally_funded": false, "project_priority": "", "project_importance": null, "project_description": "This is gonna be good", "project_extent_geojson": {"type": "FeatureCollection", "features": [{"id": 54325, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.74485321715474, 30.269660368310596], [-97.74449598044157, 30.270580023866273]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 154325}}, {"id": 54442, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.74521112442017, 30.268721592638997], [-97.74485321715474, 30.269660368310596]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 154442}}, {"id": 54443, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.74521112442017, 30.268721592638997], [-97.7462675794959, 30.269028968820365]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 154443}}, {"id": 48417, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.7462675794959, 30.269028968820365], [-97.74594135582447, 30.269968465464004]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 148417}}, {"id": 54312, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.7441355586052, 30.26842203386127], [-97.74378100410104, 30.269352704539784]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 154312}}, {"id": 47473, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.74247946217656, 30.26897163447613], [-97.74378100410104, 30.269352704539784]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 147473}}, {"id": 53749, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.74282043799758, 30.26807093069874], [-97.7441355586052, 30.26842203386127]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 153749}}, {"id": 53748, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.74282043799758, 30.26807093069874], [-97.74247946217656, 30.26897163447613]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 153748}}, {"id": 52382, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.74111723527312, 30.268608516185054], [-97.74078816175461, 30.269537013352178]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 152382}}, {"id": 54322, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.74146189913154, 30.267688697374666], [-97.74111723527312, 30.268608516185054]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 154322}}, {"id": 47852, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.74111723527312, 30.268608516185054], [-97.74004502221942, 30.268300849117793]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 147852}}, {"id": 48531, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.7403829805553, 30.267399994400208], [-97.74004502221942, 30.268300849117793]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 148531}}, {"id": 51717, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.73934295400977, 30.267073646083887], [-97.73895654827356, 30.26801200315832]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 151717}}, {"id": 47863, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.73895654827356, 30.26801200315832], [-97.7379254065454, 30.2677050581497]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 147863}}, {"id": 6518, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.73825431242585, 30.26678754746615], [-97.7379254065454, 30.2677050581497]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 106518}}, {"id": 47866, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.74343013763428, 30.270261214776838], [-97.74450302124023, 30.270594791564676]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 147866}}]}, "project_description_public": null}, "old": {"added_by": null, "end_date": null, "date_added": "2021-03-23T16:56:35.754826+00:00", "eCapris_id": "", "is_retired": false, "project_id": 188, "start_date": "2021-03-23", "fiscal_year": "2021", "timeline_id": null, "project_name": "Another John Project", "project_uuid": "892a57ab-74d1-4033-8920-4084d6117c41", "current_phase": "complete", "project_order": null, "current_status": "active", "project_length": 0, "capitally_funded": false, "project_priority": "", "project_importance": null, "project_description": "This is gonna be good", "project_extent_geojson": {"type": "FeatureCollection", "features": [{"id": 54325, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.74485321715474, 30.269660368310596], [-97.74449598044157, 30.270580023866273]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 154325}}, {"id": 54442, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.74521112442017, 30.268721592638997], [-97.74485321715474, 30.269660368310596]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 154442}}, {"id": 54443, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.74521112442017, 30.268721592638997], [-97.7462675794959, 30.269028968820365]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 154443}}, {"id": 48417, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.7462675794959, 30.269028968820365], [-97.74594135582447, 30.269968465464004]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 148417}}, {"id": 54312, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.7441355586052, 30.26842203386127], [-97.74378100410104, 30.269352704539784]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 154312}}, {"id": 47473, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.74247946217656, 30.26897163447613], [-97.74378100410104, 30.269352704539784]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 147473}}, {"id": 53749, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.74282043799758, 30.26807093069874], [-97.7441355586052, 30.26842203386127]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 153749}}, {"id": 53748, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.74282043799758, 30.26807093069874], [-97.74247946217656, 30.26897163447613]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 153748}}, {"id": 52382, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.74111723527312, 30.268608516185054], [-97.74078816175461, 30.269537013352178]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 152382}}, {"id": 54322, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.74146189913154, 30.267688697374666], [-97.74111723527312, 30.268608516185054]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 154322}}, {"id": 47852, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.74111723527312, 30.268608516185054], [-97.74004502221942, 30.268300849117793]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 147852}}, {"id": 48531, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.7403829805553, 30.267399994400208], [-97.74004502221942, 30.268300849117793]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 148531}}, {"id": 51717, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.73934295400977, 30.267073646083887], [-97.73895654827356, 30.26801200315832]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 151717}}, {"id": 47863, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.73895654827356, 30.26801200315832], [-97.7379254065454, 30.2677050581497]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 147863}}, {"id": 6518, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.73825431242585, 30.26678754746615], [-97.7379254065454, 30.2677050581497]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 106518}}, {"id": 47866, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.74343013763428, 30.270261214776838], [-97.74450302124023, 30.270594791564676]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 147866}}, {"id": 48693, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.74449598044157, 30.270580023866273], [-97.74560004472733, 30.27087740434517]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 148693}}]}, "project_description_public": null}}, "trace_context": {"span_id": 3679271474502845354, "trace_id": 18371608663279385474}, "session_variables": {"x-hasura-role": "moped-admin", "x-hasura-user-id": "40422ee4-4aca-43b3-898c-ed2ad2f88f6d", "x-hasura-user-db-id": "10", "x-hasura-user-wg-id": "3"}}, "table": {"name": "moped_project", "schema": "public"}, "trigger": {"name": "activity_log_moped_project"}, "created_at": "2021-03-23T16:57:42.810925Z", "delivery_info": {"max_retries": 0, "current_retry": 0}}', '[{"new": {"CTN": [154325, 154442, 154443, 148417, 154312, 147473, 153749, 153748, 152382, 154322, 147852, 148531, 151717, 147863, 106518]}, "old": {"CTN": [154325, 154442, 154443, 148417, 154312, 147473, 153749, 153748, 152382, 154322, 147852, 148531, 151717, 147863, 106518, 148693, 147866]}, "field": "project_extent_ids"}, {"new": {"type": "FeatureCollection", "features": [{"id": 54325, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.74485321715474, 30.269660368310596], [-97.74449598044157, 30.270580023866273]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 154325}}, {"id": 54442, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.74521112442017, 30.268721592638997], [-97.74485321715474, 30.269660368310596]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 154442}}, {"id": 54443, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.74521112442017, 30.268721592638997], [-97.7462675794959, 30.269028968820365]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 154443}}, {"id": 48417, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.7462675794959, 30.269028968820365], [-97.74594135582447, 30.269968465464004]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 148417}}, {"id": 54312, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.7441355586052, 30.26842203386127], [-97.74378100410104, 30.269352704539784]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 154312}}, {"id": 47473, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.74247946217656, 30.26897163447613], [-97.74378100410104, 30.269352704539784]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 147473}}, {"id": 53749, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.74282043799758, 30.26807093069874], [-97.7441355586052, 30.26842203386127]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 153749}}, {"id": 53748, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.74282043799758, 30.26807093069874], [-97.74247946217656, 30.26897163447613]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 153748}}, {"id": 52382, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.74111723527312, 30.268608516185054], [-97.74078816175461, 30.269537013352178]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 152382}}, {"id": 54322, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.74146189913154, 30.267688697374666], [-97.74111723527312, 30.268608516185054]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 154322}}, {"id": 47852, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.74111723527312, 30.268608516185054], [-97.74004502221942, 30.268300849117793]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 147852}}, {"id": 48531, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.7403829805553, 30.267399994400208], [-97.74004502221942, 30.268300849117793]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 148531}}, {"id": 51717, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.73934295400977, 30.267073646083887], [-97.73895654827356, 30.26801200315832]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 151717}}, {"id": 47863, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.73895654827356, 30.26801200315832], [-97.7379254065454, 30.2677050581497]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 147863}}, {"id": 6518, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.73825431242585, 30.26678754746615], [-97.7379254065454, 30.2677050581497]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 106518}}, {"id": 47866, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.74343013763428, 30.270261214776838], [-97.74450302124023, 30.270594791564676]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 147866}}]}, "old": {"type": "FeatureCollection", "features": [{"id": 54325, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.74485321715474, 30.269660368310596], [-97.74449598044157, 30.270580023866273]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 154325}}, {"id": 54442, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.74521112442017, 30.268721592638997], [-97.74485321715474, 30.269660368310596]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 154442}}, {"id": 54443, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.74521112442017, 30.268721592638997], [-97.7462675794959, 30.269028968820365]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 154443}}, {"id": 48417, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.7462675794959, 30.269028968820365], [-97.74594135582447, 30.269968465464004]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 148417}}, {"id": 54312, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.7441355586052, 30.26842203386127], [-97.74378100410104, 30.269352704539784]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 154312}}, {"id": 47473, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.74247946217656, 30.26897163447613], [-97.74378100410104, 30.269352704539784]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 147473}}, {"id": 53749, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.74282043799758, 30.26807093069874], [-97.7441355586052, 30.26842203386127]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 153749}}, {"id": 53748, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.74282043799758, 30.26807093069874], [-97.74247946217656, 30.26897163447613]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 153748}}, {"id": 52382, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.74111723527312, 30.268608516185054], [-97.74078816175461, 30.269537013352178]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 152382}}, {"id": 54322, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.74146189913154, 30.267688697374666], [-97.74111723527312, 30.268608516185054]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 154322}}, {"id": 47852, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.74111723527312, 30.268608516185054], [-97.74004502221942, 30.268300849117793]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 147852}}, {"id": 48531, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.7403829805553, 30.267399994400208], [-97.74004502221942, 30.268300849117793]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 148531}}, {"id": 51717, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.73934295400977, 30.267073646083887], [-97.73895654827356, 30.26801200315832]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 151717}}, {"id": 47863, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.73895654827356, 30.26801200315832], [-97.7379254065454, 30.2677050581497]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 147863}}, {"id": 6518, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.73825431242585, 30.26678754746615], [-97.7379254065454, 30.2677050581497]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 106518}}, {"id": 47866, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.74343013763428, 30.270261214776838], [-97.74450302124023, 30.270594791564676]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 147866}}, {"id": 48693, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.74449598044157, 30.270580023866273], [-97.74560004472733, 30.27087740434517]]}, "properties": {"sourceLayer": "CTN", "PROJECT_EXTENT_ID": 148693}}]}, "field": "project_extent_geojson"}]', '2021-03-23 16:57:54.283067+00', '40422ee4-4aca-43b3-898c-ed2ad2f88f6d', 188, 'UPDATE'); @@ -1424,3 +1424,53 @@ SELECT pg_catalog.setval('public.moped_workgroup_workgroup_id_seq', 1, true); -- PostgreSQL database dump complete -- +/** + INSERTS DEMO FEATURES WE NEED +**/ +INSERT INTO public.moped_proj_features (feature_id, project_id, location, status_id) VALUES (1, 159, '{"id": "70a64fa6-4773-4e85-8de5-2b1b6c43e2ec", "type": "Feature", "geometry": {"type": "Point", "coordinates": [-97.74280552637893, 30.26807489857954]}, "properties": {"renderType": "Point", "sourceLayer": "drawnByUser", "PROJECT_EXTENT_ID": "70a64fa6-4773-4e85-8de5-2b1b6c43e2ec"}}', 0); +INSERT INTO public.moped_proj_features (feature_id, project_id, location, status_id) VALUES (2, 159, '{"id": 53748, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.74282043799758, 30.26807093069874], [-97.74247946217656, 30.26897163447613]]}, "properties": {"_symbol": 0, "LINE_TYPE": "On-Street", "sourceLayer": "CTN", "TO_ADDRESS_MAX": 623, "FROM_ADDRESS_MIN": 600, "FULL_STREET_NAME": "CONGRESS AVE", "PROJECT_EXTENT_ID": 153748}}', 1); +INSERT INTO public.moped_proj_features (feature_id, project_id, location, status_id) VALUES (3, 159, '{"id": 49354, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.74247946217656, 30.26897163447613], [-97.74111723527312, 30.268608516185054]]}, "properties": {"_symbol": 0, "LINE_TYPE": "On-Street", "sourceLayer": "CTN", "TO_ADDRESS_MAX": 121, "FROM_ADDRESS_MIN": 100, "FULL_STREET_NAME": "E 7TH ST", "PROJECT_EXTENT_ID": 149354}}', 1); +INSERT INTO public.moped_proj_features (feature_id, project_id, location, status_id) VALUES (4, 159, '{"id": 50656, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.74282043799758, 30.26807093069874], [-97.74146189913154, 30.267688697374666]]}, "properties": {"_symbol": 0, "LINE_TYPE": "On-Street", "sourceLayer": "CTN", "TO_ADDRESS_MAX": 121, "FROM_ADDRESS_MIN": 100, "FULL_STREET_NAME": "E 6TH ST", "PROJECT_EXTENT_ID": 150656}}', 1); +INSERT INTO public.moped_proj_features (feature_id, project_id, location, status_id) VALUES (5, 159, '{"id": 54322, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.74146189913154, 30.267688697374666], [-97.74111723527312, 30.268608516185054]]}, "properties": {"_symbol": 0, "LINE_TYPE": "On-Street", "sourceLayer": "CTN", "TO_ADDRESS_MAX": 617, "FROM_ADDRESS_MIN": 600, "FULL_STREET_NAME": "BRAZOS ST", "PROJECT_EXTENT_ID": 154322}}', 1); +INSERT INTO public.moped_proj_features (feature_id, project_id, location, status_id) VALUES (6, 159, '{"id": 94918, "type": "Feature", "geometry": {"type": "Point", "coordinates": [-97.74247946217656, 30.26897163447613]}, "properties": {"sourceLayer": "Project_Component_Points_prototype", "PROJECT_EXTENT_ID": 694918}}', 1); +INSERT INTO public.moped_proj_features (feature_id, project_id, location, status_id) VALUES (7, 159, '{"id": 101277, "type": "Feature", "geometry": {"type": "Point", "coordinates": [-97.74282043799758, 30.26807093069874]}, "properties": {"sourceLayer": "Project_Component_Points_prototype", "PROJECT_EXTENT_ID": 701277}}', 1); +INSERT INTO public.moped_proj_features (feature_id, project_id, location, status_id) VALUES (8, 159, '{"id": 101278, "type": "Feature", "geometry": {"type": "Point", "coordinates": [-97.74146189913154, 30.267688697374666]}, "properties": {"sourceLayer": "Project_Component_Points_prototype", "PROJECT_EXTENT_ID": 701278}}', 1); +INSERT INTO public.moped_proj_features (feature_id, project_id, location, status_id) VALUES (9, 159, '{"id": 95673, "type": "Feature", "geometry": {"type": "Point", "coordinates": [-97.74111723527312, 30.268608516185054]}, "properties": {"sourceLayer": "Project_Component_Points_prototype", "PROJECT_EXTENT_ID": 695673}}', 1); +INSERT INTO public.moped_proj_features (feature_id, project_id, location, status_id) VALUES (10, 159, '{"id": 47852, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.74111723527312, 30.268608516185054], [-97.74004502221942, 30.268300849117793]]}, "properties": {"_symbol": 0, "LINE_TYPE": "On-Street", "sourceLayer": "CTN", "TO_ADDRESS_MAX": 217, "FROM_ADDRESS_MIN": 200, "FULL_STREET_NAME": "E 7TH ST", "PROJECT_EXTENT_ID": 147852}}', 1); +INSERT INTO public.moped_proj_features (feature_id, project_id, location, status_id) VALUES (11, 159, '{"id": 51525, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.74146189913154, 30.267688697374666], [-97.7403829805553, 30.267399994400208]]}, "properties": {"_symbol": 0, "LINE_TYPE": "On-Street", "sourceLayer": "CTN", "TO_ADDRESS_MAX": 223, "FROM_ADDRESS_MIN": 200, "FULL_STREET_NAME": "E 6TH ST", "PROJECT_EXTENT_ID": 151525}}', 1); +INSERT INTO public.moped_proj_features (feature_id, project_id, location, status_id) VALUES (12, 159, '{"id": 97029, "type": "Feature", "geometry": {"type": "Point", "coordinates": [-97.7403829805553, 30.267399994400208]}, "properties": {"sourceLayer": "Project_Component_Points_prototype", "PROJECT_EXTENT_ID": 697029}}', 1); +INSERT INTO public.moped_proj_features (feature_id, project_id, location, status_id) VALUES (13, 159, '{"id": 48531, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.7403829805553, 30.267399994400208], [-97.74004502221942, 30.268300849117793]]}, "properties": {"_symbol": 0, "LINE_TYPE": "On-Street", "sourceLayer": "CTN", "TO_ADDRESS_MAX": 617, "FROM_ADDRESS_MIN": 600, "FULL_STREET_NAME": "SAN JACINTO BLVD", "PROJECT_EXTENT_ID": 148531}}', 1); +INSERT INTO public.moped_proj_features (feature_id, project_id, location, status_id) VALUES (14, 159, '{"id": 94927, "type": "Feature", "geometry": {"type": "Point", "coordinates": [-97.74004502221942, 30.268300849117793]}, "properties": {"sourceLayer": "Project_Component_Points_prototype", "PROJECT_EXTENT_ID": 694927}}', 1); + +/* MOPED PROJECT COMPONENTS */ +INSERT INTO public.moped_proj_components (project_component_id, project_id, component_id, name, description) VALUES (1, 159, 1, 'Component A', null); +INSERT INTO public.moped_proj_components (project_component_id, project_id, component_id, name, description) VALUES (2, 159, 2, 'Component B', null); +INSERT INTO public.moped_proj_components (project_component_id, project_id, component_id, name, description) VALUES (3, 159, 3, 'Component C', null); +INSERT INTO public.moped_proj_components (project_component_id, project_id, component_id, name, description) VALUES (4, 159, 4, 'Component D', null); +INSERT INTO public.moped_proj_components (project_component_id, project_id, component_id, name, description) VALUES (5, 159, 5, 'Component E', null); +INSERT INTO public.moped_proj_components (project_component_id, project_id, component_id, name, description) VALUES (6, 159, 6, 'Component D', null); + +/* MOPED PROJECT COMPONENT SUBCOMPONENTS */ +INSERT INTO public.moped_proj_components_subcomponents (component_subcomponent_id, project_component_id, subcomponent_id) VALUES (1, 1, 1); +INSERT INTO public.moped_proj_components_subcomponents (component_subcomponent_id, project_component_id, subcomponent_id) VALUES (2, 1, 2); +INSERT INTO public.moped_proj_components_subcomponents (component_subcomponent_id, project_component_id, subcomponent_id) VALUES (3, 2, 3); +INSERT INTO public.moped_proj_components_subcomponents (component_subcomponent_id, project_component_id, subcomponent_id) VALUES (5, 3, 1); +INSERT INTO public.moped_proj_components_subcomponents (component_subcomponent_id, project_component_id, subcomponent_id) VALUES (6, 3, 3); +INSERT INTO public.moped_proj_components_subcomponents (component_subcomponent_id, project_component_id, subcomponent_id) VALUES (4, 2, 4); + +/* FEATURE COMPONENTS */ +INSERT INTO public.moped_proj_features_components (project_features_components_id, moped_proj_features_id, moped_proj_component_id, name, description, create_date, status_id) VALUES (1, 1, 1, 'The component a feature one', null, '2021-06-04 18:00:42.105875', 0); +INSERT INTO public.moped_proj_features_components (project_features_components_id, moped_proj_features_id, moped_proj_component_id, name, description, create_date, status_id) VALUES (2, 2, 2, 'The component a feature two', null, '2021-06-04 18:01:56.267785', 0); +INSERT INTO public.moped_proj_features_components (project_features_components_id, moped_proj_features_id, moped_proj_component_id, name, description, create_date, status_id) VALUES (3, 3, 3, 'The component a feature two', null, '2021-06-04 18:01:56.267785', 0); +INSERT INTO public.moped_proj_features_components (project_features_components_id, moped_proj_features_id, moped_proj_component_id, name, description, create_date, status_id) VALUES (4, 4, 4, 'The component a feature two', null, '2021-06-04 18:01:56.267785', 0); +INSERT INTO public.moped_proj_features_components (project_features_components_id, moped_proj_features_id, moped_proj_component_id, name, description, create_date, status_id) VALUES (5, 5, 5, 'The component a feature two', null, '2021-06-04 18:01:56.267785', 0); +INSERT INTO public.moped_proj_features_components (project_features_components_id, moped_proj_features_id, moped_proj_component_id, name, description, create_date, status_id) VALUES (6, 6, 6, 'The component a feature two', null, '2021-06-04 18:01:56.267785', 0); +INSERT INTO public.moped_proj_features_components (project_features_components_id, moped_proj_features_id, moped_proj_component_id, name, description, create_date, status_id) VALUES (7, 7, 1, 'The component a feature two', null, '2021-06-04 18:01:56.267785', 0); +INSERT INTO public.moped_proj_features_components (project_features_components_id, moped_proj_features_id, moped_proj_component_id, name, description, create_date, status_id) VALUES (8, 8, 2, 'The component a feature two', null, '2021-06-04 18:01:56.267785', 0); +INSERT INTO public.moped_proj_features_components (project_features_components_id, moped_proj_features_id, moped_proj_component_id, name, description, create_date, status_id) VALUES (9, 9, 3, 'The component a feature two', null, '2021-06-04 18:01:56.267785', 0); +INSERT INTO public.moped_proj_features_components (project_features_components_id, moped_proj_features_id, moped_proj_component_id, name, description, create_date, status_id) VALUES (10, 10, 4, 'The component a feature two', null, '2021-06-04 18:01:56.267785', 0); +INSERT INTO public.moped_proj_features_components (project_features_components_id, moped_proj_features_id, moped_proj_component_id, name, description, create_date, status_id) VALUES (11, 11, 5, 'The component a feature two', null, '2021-06-04 18:01:56.267785', 0); +INSERT INTO public.moped_proj_features_components (project_features_components_id, moped_proj_features_id, moped_proj_component_id, name, description, create_date, status_id) VALUES (12, 12, 6, 'The component a feature two', null, '2021-06-04 18:01:56.267785', 0); +INSERT INTO public.moped_proj_features_components (project_features_components_id, moped_proj_features_id, moped_proj_component_id, name, description, create_date, status_id) VALUES (13, 13, 1, 'The component a feature two', null, '2021-06-04 18:01:56.267785', 0); +INSERT INTO public.moped_proj_features_components (project_features_components_id, moped_proj_features_id, moped_proj_component_id, name, description, create_date, status_id) VALUES (14, 14, 2, 'The component a feature two', null, '2021-06-04 18:01:56.267785', 0); + From 243674a4bc2f07809eaaa5c6d17e3aa1793ba4d0 Mon Sep 17 00:00:00 2001 From: Sergio Garcia Date: Fri, 4 Jun 2021 13:53:50 -0500 Subject: [PATCH 014/130] Add moped_proj_components_subcomponents to query --- moped-editor/src/queries/project.js | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/moped-editor/src/queries/project.js b/moped-editor/src/queries/project.js index 7b2e4029f8..3e065c4b2f 100644 --- a/moped-editor/src/queries/project.js +++ b/moped-editor/src/queries/project.js @@ -492,9 +492,7 @@ export const PROJECT_CLEAR_MAP_DATA_TEMPLATE = `mutation ClearProjectMapData($pr export const COMPONENTS_QUERY = gql` query getComponents($projectId: Int) { - moped_proj_components( - where: { project_id: { _eq: $projectId } } - ) { + moped_proj_components(where: { project_id: { _eq: $projectId } }) { project_component_id project_id component_id @@ -504,6 +502,12 @@ export const COMPONENTS_QUERY = gql` component_type: component_name component_subtype } + moped_proj_components_subcomponents { + moped_subcomponent { + subcomponent_id + subcomponent_name + } + } moped_proj_features_components { name moped_proj_feature { From 1a4f9cd164e950ca1862cf44a17852d1df79ed52 Mon Sep 17 00:00:00 2001 From: Sergio Garcia Date: Fri, 4 Jun 2021 13:54:00 -0500 Subject: [PATCH 015/130] Refactor subcomponents --- .../projects/projectView/ProjectComponents.js | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/moped-editor/src/views/projects/projectView/ProjectComponents.js b/moped-editor/src/views/projects/projectView/ProjectComponents.js index e69eb7c2f5..a64ecfec66 100644 --- a/moped-editor/src/views/projects/projectView/ProjectComponents.js +++ b/moped-editor/src/views/projects/projectView/ProjectComponents.js @@ -66,6 +66,8 @@ const ProjectComponents = () => { // Return loading if not in progress if (loading) return ; + if (error) return
{error}
; + /** * Retrieve and flatten a nested list of features: * moped_proj_components -> moped_proj_features_components -> moped_proj_feature @@ -93,12 +95,10 @@ const ProjectComponents = () => { ); /** - * Handles logic whenever a component is clicked + * Handles logic whenever a component is clicked, refreshes whatever is in memory and re-renders * @param componentId - The Database id of the component in question */ - const handleComponentClick = componentId => { - setSelectedComp(componentId); - }; + const handleComponentClick = componentId => setSelectedComp(componentId); /** * Resets the color of a selected component back to white @@ -149,11 +149,15 @@ const ProjectComponents = () => { {[ ...new Set( - component.moped_proj_features_components.map( - subcomponent => subcomponent.name + component.moped_proj_components_subcomponents.map( + mpcs => + mpcs.moped_subcomponent + .subcomponent_name ) ), - ].join(", ")} + ] + .sort() + .join(", ")} From f325170f45887b09c0eb31aba33e12c89b461c08 Mon Sep 17 00:00:00 2001 From: Sergio Garcia Date: Fri, 4 Jun 2021 14:50:06 -0500 Subject: [PATCH 016/130] Implements COMPONENT_DETAILS_QUERY --- moped-editor/src/queries/project.js | 35 +++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/moped-editor/src/queries/project.js b/moped-editor/src/queries/project.js index 3e065c4b2f..2c8cdfc4a0 100644 --- a/moped-editor/src/queries/project.js +++ b/moped-editor/src/queries/project.js @@ -517,3 +517,38 @@ export const COMPONENTS_QUERY = gql` } } `; + +export const COMPONENT_DETAILS_QUERY = gql` + query GetComponentDetails($componentId: Int!) { + moped_proj_components(where: { component_id: { _eq: $componentId } }) { + component_id + description + name + project_component_id + project_id + moped_components { + component_name + component_id + component_subtype + } + moped_proj_features_components { + moped_proj_feature { + location + feature_id + status_id + project_id + } + } + } + moped_subcomponents { + subcomponent_name + subcomponent_id + component_id + } + moped_components { + component_name + component_subtype + component_id + } + } +`; From 35e293917a27d70291bb021d7497bac5a00d91dc Mon Sep 17 00:00:00 2001 From: Sergio Garcia Date: Fri, 4 Jun 2021 14:50:20 -0500 Subject: [PATCH 017/130] Creates ProjectComponentEdit --- .../projectView/ProjectComponentEdit.js | 119 ++++++++++++++++++ 1 file changed, 119 insertions(+) create mode 100644 moped-editor/src/views/projects/projectView/ProjectComponentEdit.js diff --git a/moped-editor/src/views/projects/projectView/ProjectComponentEdit.js b/moped-editor/src/views/projects/projectView/ProjectComponentEdit.js new file mode 100644 index 0000000000..9bde036935 --- /dev/null +++ b/moped-editor/src/views/projects/projectView/ProjectComponentEdit.js @@ -0,0 +1,119 @@ +import React, { useEffect, useState } from "react"; +import { useQuery } from "@apollo/client"; +import { + Button, + CircularProgress, + FormControl, + Grid, + InputLabel, + MenuItem, + Select, +} from "@material-ui/core"; +import makeStyles from "@material-ui/core/styles/makeStyles"; +import { COMPONENT_DETAILS_QUERY } from "../../../queries/project"; + +const useStyles = makeStyles(theme => ({ + selectEmpty: { + marginTop: theme.spacing(2), + }, + formSelect: { + width: "60%", + }, + formButton: { + margin: theme.spacing(1), + }, +})); + +const ProjectComponentEdit = ({ componentId, cancelEdit }) => { + const classes = useStyles(); + + const [selectedComponentId, setSelectedComponentId] = useState(0); + + const [selectedComponentType, setSelectedComponentType] = useState(null); + const [selectedComponentSubType, setSelectedComponentSubtype] = useState( + null + ); + const [availableSubtypes, setAvailableSubtypes] = useState([]); + + const { loading, data, error, refetch } = useQuery(COMPONENT_DETAILS_QUERY, { + variables: { + componentId: componentId, + }, + }); + + /** + * On select, it changes the available items for that specific type + * @param {Object} e - The Object Type + */ + const handleComponentTypeSelect = e => { + const selectedType = e.target.value; + + // Set The selected component type + setSelectedComponentType(selectedType); + }; + + useEffect(() => { + console.log("Component Type Changed", selectedComponentType); + }, [selectedComponentType]); + + if (loading) return ; + if (error) return
Error: {error}
; + + return ( + + +
Editing Component ID: {componentId}
+
+ + + Type + + + + + + + +
+ ); +}; + +export default ProjectComponentEdit; From eaaed407f8092a4fed3b25f8f48cc6b6be675b0c Mon Sep 17 00:00:00 2001 From: Sergio Garcia Date: Fri, 4 Jun 2021 14:50:43 -0500 Subject: [PATCH 018/130] Imports ProjectComponentEdit and refactors --- .../projects/projectView/ProjectComponents.js | 149 +++++++++++------- 1 file changed, 88 insertions(+), 61 deletions(-) diff --git a/moped-editor/src/views/projects/projectView/ProjectComponents.js b/moped-editor/src/views/projects/projectView/ProjectComponents.js index a64ecfec66..53a89b9202 100644 --- a/moped-editor/src/views/projects/projectView/ProjectComponents.js +++ b/moped-editor/src/views/projects/projectView/ProjectComponents.js @@ -23,6 +23,7 @@ import ApolloErrorHandler from "../../../components/ApolloErrorHandler"; import ProjectComponentsMap from "./ProjectComponentsMap"; import { createFeatureCollectionFromProjectFeatures } from "../../../utils/mapHelpers"; import ProjectSummaryMapFallback from "./ProjectSummaryMapFallback"; +import ProjectComponentEdit from "./ProjectComponentEdit"; const useStyles = makeStyles(theme => ({ root: { @@ -56,6 +57,7 @@ const ProjectComponents = () => { const [selectedComp, setSelectedComp] = useState(0); const [mapError, setMapError] = useState(false); + const [componentEditMode, setComponentEditMode] = useState(false); const { error, loading, data, refetch } = useQuery(COMPONENTS_QUERY, { variables: { @@ -105,72 +107,97 @@ const ProjectComponents = () => { */ const handleComponentClickAway = () => setSelectedComp(0); + const handleComponentDetailsClick = () => { + setComponentEditMode(true); + }; + + const handleCancelEdit = () => { + setComponentEditMode(false); + setSelectedComp(0); + }; + return ( - - - - - - - Component - Type - Subtype - Sub-Components - Details - - - - {data.moped_proj_components.map( - (component, compIndex) => { - const componentId = component.project_component_id; - return ( - handleComponentClick(componentId)} - className={ - componentId === selectedComp - ? classes.componentItemBlue - : classes.componentItem - } - > - {component?.name} - - {component?.moped_components?.component_type} - - - {component?.moped_components?.component_subtype} - - - {[ - ...new Set( - component.moped_proj_components_subcomponents.map( - mpcs => - mpcs.moped_subcomponent - .subcomponent_name - ) - ), - ] - .sort() - .join(", ")} - - - - - - ); - } - )} - -
-
-
-
+ {!componentEditMode ? ( + + + + + + + Component + Type + Subtype + Sub-Components + Details + + + + {data.moped_proj_components.map( + (component, compIndex) => { + const componentId = component.project_component_id; + return ( + + handleComponentClick(componentId) + } + className={ + componentId === selectedComp + ? classes.componentItemBlue + : classes.componentItem + } + > + {component?.name} + + {component?.moped_components?.component_type} + + + { + component?.moped_components + ?.component_subtype + } + + + {[ + ...new Set( + component.moped_proj_components_subcomponents.map( + mpcs => + mpcs.moped_subcomponent + .subcomponent_name + ) + ), + ] + .sort() + .join(", ")} + + + + handleComponentDetailsClick(componentId) + } + /> + + + ); + } + )} + +
+
+
+
+ ) : ( + + )}
Date: Fri, 4 Jun 2021 17:58:09 -0500 Subject: [PATCH 019/130] Commentary & Subtype menu --- .../projectView/ProjectComponentEdit.js | 141 ++++++++++++++++-- 1 file changed, 128 insertions(+), 13 deletions(-) diff --git a/moped-editor/src/views/projects/projectView/ProjectComponentEdit.js b/moped-editor/src/views/projects/projectView/ProjectComponentEdit.js index 9bde036935..6a4be3e194 100644 --- a/moped-editor/src/views/projects/projectView/ProjectComponentEdit.js +++ b/moped-editor/src/views/projects/projectView/ProjectComponentEdit.js @@ -1,4 +1,4 @@ -import React, { useEffect, useState } from "react"; +import React, { useState } from "react"; import { useQuery } from "@apollo/client"; import { Button, @@ -24,46 +24,136 @@ const useStyles = makeStyles(theme => ({ }, })); +/** + * The project component editor + * @param {Number} componentId - The moped_proj_component id being edited + * @param {function} cancelEdit - The function to call if we need to cancel editing + * @return {JSX.Element} + * @constructor + */ const ProjectComponentEdit = ({ componentId, cancelEdit }) => { const classes = useStyles(); - const [selectedComponentId, setSelectedComponentId] = useState(0); - + /** + * The State + * @type {String} selectedComponentType - A string containing the name of the selected type in lowercase + * @type {String} selectedComponentSubtype - A string containing the name of the selected subtype in lowercase + * @type {String[]} selectedComponentSubtype - A string containing all available subtypes for type + * @constant + */ const [selectedComponentType, setSelectedComponentType] = useState(null); - const [selectedComponentSubType, setSelectedComponentSubtype] = useState( + const [selectedComponentSubtype, setSelectedComponentSubtype] = useState( null ); const [availableSubtypes, setAvailableSubtypes] = useState([]); + /** + * Apollo hook functions + */ const { loading, data, error, refetch } = useQuery(COMPONENT_DETAILS_QUERY, { variables: { componentId: componentId, }, }); + /** + * Generates an initial list of component types, subtypes and counts + */ + const initialTypeCounts = data + ? data.moped_components.reduce((accumulator, component, index) => { + const componentId = component?.component_id ?? null; + const componentName = (component?.component_name ?? "").toLowerCase(); + const componentSubtype = ( + component?.component_subtype ?? "" + ).toLowerCase(); + // Get the total count + const currentCount = accumulator[componentName]?.count ?? 0; + + return { + ...accumulator, + [componentName]: { + count: currentCount + 1, + component_id: currentCount > 1 ? 0 : componentId, + index: index, + subtypes: { + ...(accumulator[componentName]?.subtypes ?? {}), + [componentSubtype]: { + component_id: componentId, + component_name: component?.component_name ?? null, + component_subtype: component?.component_subtype ?? null, + }, + }, + }, + }; + }, {}) + : {}; + + /** + * Generates a list of available subtypes for a fiven type name + * @param {String} type - The type name + * @return {String[]} - A string array with the available subtypes + */ + const getAvailableSubtypes = type => + Object.entries(initialTypeCounts[type].subtypes) + .map(([_, component]) => component.component_subtype.trim()) + .filter(item => item.length > 0); + /** * On select, it changes the available items for that specific type * @param {Object} e - The Object Type */ const handleComponentTypeSelect = e => { - const selectedType = e.target.value; + const selectedType = (e.target.value ?? "").toLowerCase(); + + // Generates a list of available component subtypes given a component type + const availableSubTypes = getAvailableSubtypes(selectedType); // Set The selected component type setSelectedComponentType(selectedType); + setAvailableSubtypes(availableSubTypes); }; - useEffect(() => { - console.log("Component Type Changed", selectedComponentType); - }, [selectedComponentType]); + /** + * On select, it changes the value of selectedSubtype state + * @param {Object} e - The event object + */ + const handleComponentSubtypeSelect = e => + setSelectedComponentSubtype(e.target.value.toLowerCase()); + // Handle loading and error events if (loading) return ; if (error) return
Error: {error}
; + /** + * Pre-populates the type and subtype for the existing data from DB + */ + if (data && initialTypeCounts && selectedComponentType === null) { + // Get the component_id from the moped_proj_component table + const databaseComponent = data.moped_components.filter( + componentItem => + componentItem.component_id === + data.moped_proj_components[0].project_component_id + )[0]; + + // Determine component type and available subtypes + const componentTypeDB = databaseComponent.component_name.toLowerCase(); + const availableSubTypes = getAvailableSubtypes(componentTypeDB); + + // Update state with new values + setSelectedComponentType(componentTypeDB); + setAvailableSubtypes(availableSubTypes); + + // If the component type has subtypes, then fetch those and update state + if (initialTypeCounts[componentTypeDB].count > 1) { + const subtypeDB = databaseComponent.component_subtype + .trim() + .toLowerCase(); + setSelectedComponentSubtype(subtypeDB); + } + } + return ( - -
Editing Component ID: {componentId}
-
Type @@ -71,7 +161,7 @@ const ProjectComponentEdit = ({ componentId, cancelEdit }) => { className={classes.formSelect} labelId="mopedComponentType" id="mopedComponentTypeSelect" - value={selectedComponentType} + value={(selectedComponentType ?? "").toLowerCase()} onChange={handleComponentTypeSelect} > {[ @@ -86,7 +176,7 @@ const ProjectComponentEdit = ({ componentId, cancelEdit }) => { return ( {moped_component} @@ -95,6 +185,31 @@ const ProjectComponentEdit = ({ componentId, cancelEdit }) => { + + {availableSubtypes.length > 0 && ( + + Subtype + + + )} + - - ( - + ( + + )} + onReset={() => setMapError(false)} + resetKeys={[mapError]} + > + - )} - onReset={() => setMapError(false)} - resetKeys={[mapError]} - > - - - +
+
+ )}
)}
From e0ba4de41f02f690b61d29f79deb8a6364e6d4f3 Mon Sep 17 00:00:00 2001 From: Sergio Garcia Date: Mon, 14 Jun 2021 15:10:30 -0400 Subject: [PATCH 089/130] Remove refetch --- .../src/views/projects/projectView/ProjectComponentEdit.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/moped-editor/src/views/projects/projectView/ProjectComponentEdit.js b/moped-editor/src/views/projects/projectView/ProjectComponentEdit.js index 46121bf62c..f08032a0cb 100644 --- a/moped-editor/src/views/projects/projectView/ProjectComponentEdit.js +++ b/moped-editor/src/views/projects/projectView/ProjectComponentEdit.js @@ -102,7 +102,7 @@ const ProjectComponentEdit = ({ /** * Apollo hook functions */ - const { loading, data, error, refetch } = useQuery(COMPONENT_DETAILS_QUERY, { + const { loading, data, error } = useQuery(COMPONENT_DETAILS_QUERY, { variables: { componentId: componentId, }, From 75c1a366dbec54ccd864be919ee45ddd5c6ebc1a Mon Sep 17 00:00:00 2001 From: Sergio Garcia Date: Mon, 14 Jun 2021 16:47:28 -0400 Subject: [PATCH 090/130] Insert project id whenever a feature is created --- .../src/views/projects/projectView/ProjectComponentEdit.js | 1 + 1 file changed, 1 insertion(+) diff --git a/moped-editor/src/views/projects/projectView/ProjectComponentEdit.js b/moped-editor/src/views/projects/projectView/ProjectComponentEdit.js index f08032a0cb..7a1ed4deef 100644 --- a/moped-editor/src/views/projects/projectView/ProjectComponentEdit.js +++ b/moped-editor/src/views/projects/projectView/ProjectComponentEdit.js @@ -350,6 +350,7 @@ const ProjectComponentEdit = ({ update_columns: ["location", "status_id"], }, data: { + project_id: projectId, location: feature.location, status_id: feature.status_id, }, From 1bec5aacc87ff1e300658c3ca99505ccc2bd3a62 Mon Sep 17 00:00:00 2001 From: Sergio Garcia Date: Mon, 14 Jun 2021 16:47:41 -0400 Subject: [PATCH 091/130] Make components accessible from project --- moped-database/metadata/tables.yaml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/moped-database/metadata/tables.yaml b/moped-database/metadata/tables.yaml index a63b8f9c00..67ee5eec5d 100644 --- a/moped-database/metadata/tables.yaml +++ b/moped-database/metadata/tables.yaml @@ -3712,6 +3712,13 @@ schema: public name: moped_project array_relationships: + - name: moped_proj_components + using: + foreign_key_constraint_on: + column: project_id + table: + schema: public + name: moped_proj_components - name: moped_proj_features using: foreign_key_constraint_on: From 5e4938c12d792e93e460262aca7a27cfcb443c56 Mon Sep 17 00:00:00 2001 From: Sergio Garcia Date: Tue, 15 Jun 2021 12:13:22 -0400 Subject: [PATCH 092/130] Enforce no cache, use new variable method --- .../projectView/ProjectComponentEdit.js | 31 +++++++++++++++---- 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/moped-editor/src/views/projects/projectView/ProjectComponentEdit.js b/moped-editor/src/views/projects/projectView/ProjectComponentEdit.js index 7a1ed4deef..90afbc10ed 100644 --- a/moped-editor/src/views/projects/projectView/ProjectComponentEdit.js +++ b/moped-editor/src/views/projects/projectView/ProjectComponentEdit.js @@ -106,6 +106,7 @@ const ProjectComponentEdit = ({ variables: { componentId: componentId, }, + fetchPolicy: "no-cache", }); const [updateProjectComponents] = useMutation(UPDATE_MOPED_COMPONENT); @@ -179,6 +180,13 @@ const ProjectComponentEdit = ({ .map(([_, component]) => (component?.component_subtype ?? "").trim()) .filter(item => item.length > 0); + /** + * Returns the current project componetn id + * @return {number|null} + */ + const getProjectComponentId = () => + data ? data.moped_proj_components[0].project_component_id : null; + /** * Handles the delete button click */ @@ -363,18 +371,29 @@ const ProjectComponentEdit = ({ // First update the map features: create, retire, // Associate the map features to the current component: upsert moped_proj_features_components + // const oldVariablePayload = { + // project_id: Number.parseInt(projectId), + // component_id: selectedComponentId, + // subcomponents: subcomponentChanges, + // description: componentDescription, + // features: features, + // featureUpdates: featureUpdates, + // }; + const variablePayload = { + name: "", project_id: Number.parseInt(projectId), + status_id: 1, component_id: selectedComponentId, - subcomponents: subcomponentChanges, description: componentDescription, - features: features, - featureUpdates: featureUpdates, + project_component_id: getProjectComponentId(), }; - updateProjectComponents({ variables: variablePayload }).then(() => - exitAndReload() - ); + updateProjectComponents({ + variables: { + objects: variablePayload, + }, + }).then(() => exitAndReload()); }; /** From af77369a0cf6d5c925d26f64748fd99e2c759096 Mon Sep 17 00:00:00 2001 From: Sergio Garcia Date: Tue, 15 Jun 2021 12:13:59 -0400 Subject: [PATCH 093/130] Reduce query --- moped-editor/src/queries/project.js | 53 +------------------ .../projects/projectView/ProjectSummary.js | 2 +- 2 files changed, 3 insertions(+), 52 deletions(-) diff --git a/moped-editor/src/queries/project.js b/moped-editor/src/queries/project.js index 76d729eb2b..9353404aa3 100644 --- a/moped-editor/src/queries/project.js +++ b/moped-editor/src/queries/project.js @@ -573,57 +573,8 @@ export const COMPONENT_DETAILS_QUERY = gql` `; export const UPDATE_MOPED_COMPONENT = gql` - mutation UpdateMopedComponent( - $project_id: Int! - $component_id: Int! - $description: String = null - $status_id: Int = 1 - $subcomponents: [moped_proj_components_subcomponents_insert_input!]! - $features: [moped_proj_features_components_insert_input!]! - $featureUpdates: [moped_proj_features_insert_input!]! - ) { - insert_moped_proj_components( - objects: { - component_id: $component_id - description: $description - project_id: $project_id - status_id: $status_id - name: "" - moped_proj_components_subcomponents: { - data: $subcomponents - on_conflict: { - constraint: moped_proj_components_subcomponents_pkey - update_columns: [project_component_id, subcomponent_id, status_id] - } - } - moped_proj_features_components: { - data: $features - on_conflict: { - constraint: moped_proj_features_components_pkey - update_columns: [ - moped_proj_features_id - moped_proj_component_id - name - description - status_id - ] - } - } - } - on_conflict: { - constraint: moped_proj_components_pkey - update_columns: [component_id, description, status_id] - } - ) { - affected_rows - } - insert_moped_proj_features( - objects: $featureUpdates - on_conflict: { - constraint: moped_proj_features_pkey - update_columns: status_id - } - ) { + mutation UpdateMopedComponent($objects: [moped_proj_components_insert_input!]!) { + insert_moped_proj_components(objects: $objects, on_conflict: {constraint: moped_proj_components_pkey, update_columns: [component_id, description, status_id]}) { affected_rows } } diff --git a/moped-editor/src/views/projects/projectView/ProjectSummary.js b/moped-editor/src/views/projects/projectView/ProjectSummary.js index 021331c5be..5b2b3dddca 100644 --- a/moped-editor/src/views/projects/projectView/ProjectSummary.js +++ b/moped-editor/src/views/projects/projectView/ProjectSummary.js @@ -44,7 +44,7 @@ const ProjectSummary = ({ loading, error, data, refetch }) => { {projectFeatureCollection && ( ( + FallbackComponent={({ error, resetErrorBoundary }) => ( Date: Tue, 15 Jun 2021 14:58:09 -0400 Subject: [PATCH 094/130] Implements subcomponent insertion & fixes updates --- .../projectView/ProjectComponentEdit.js | 42 ++++++++++++++----- 1 file changed, 32 insertions(+), 10 deletions(-) diff --git a/moped-editor/src/views/projects/projectView/ProjectComponentEdit.js b/moped-editor/src/views/projects/projectView/ProjectComponentEdit.js index 90afbc10ed..4c90183654 100644 --- a/moped-editor/src/views/projects/projectView/ProjectComponentEdit.js +++ b/moped-editor/src/views/projects/projectView/ProjectComponentEdit.js @@ -123,6 +123,11 @@ const ProjectComponentEdit = ({ const componentSubtype = ( component?.component_subtype ?? "" ).toLowerCase(); + + const componentSubcomponents = data.moped_subcomponents.filter( + subcomponent => subcomponent.component_id === componentId + ); + // Get the total count const currentCount = accumulator[componentName]?.count ?? 0; @@ -140,6 +145,7 @@ const ProjectComponentEdit = ({ component_subtype: component?.component_subtype ?? null, }, }, + subcomponents: componentSubcomponents, }, }; }, {}) @@ -180,6 +186,14 @@ const ProjectComponentEdit = ({ .map(([_, component]) => (component?.component_subtype ?? "").trim()) .filter(item => item.length > 0); + /** + * Returns any available subcomponent objects for a specific type + * @param {String} type - Lower case of the name of the type + * @return {Object[]} + */ + const getAvailableSubcomponents = () => + initialTypeCounts[selectedComponentType].subcomponents.length; + /** * Returns the current project componetn id * @return {number|null} @@ -295,11 +309,15 @@ const ProjectComponentEdit = ({ * @return {Object[]} */ const generateSubcomponentUpserts = () => { + // If there are no subcomponents, then remove them all if present. + const removeAllSubcomponents = getAvailableSubcomponents().length === 0; + // Generate a list of subcomponents to be removed const removalList = subcomponentsDB.filter( // Check every old subcomponent oldSubcomponent => // If not found, mark it as true so it's part of the selectedSubcomponents list + removeAllSubcomponents || !selectedSubcomponents.find( newSubcomponent => // Return true if we have found the old subcomponent in this list @@ -310,6 +328,7 @@ const ProjectComponentEdit = ({ // Remove existing subcomponents, keep only those that need inserting const insertionList = selectedSubcomponents.filter( // If the subcomponent does not have component_subcomponent_id, then keep + // Otherwise, it means it already exists in the database subcomponent => isNaN(subcomponent?.component_subcomponent_id) ); @@ -349,7 +368,6 @@ const ProjectComponentEdit = ({ */ const handleSaveButtonClick = () => { // 1. Generate feature upserts - const featureUpdates = []; const features = generateMapUpserts().map(feature => ({ status_id: feature.status_id, moped_proj_feature_object: { @@ -365,21 +383,14 @@ const ProjectComponentEdit = ({ }, })); + console.log(features); + // 2. Generate a list of subcomponent upserts const subcomponentChanges = generateSubcomponentUpserts(); // First update the map features: create, retire, // Associate the map features to the current component: upsert moped_proj_features_components - // const oldVariablePayload = { - // project_id: Number.parseInt(projectId), - // component_id: selectedComponentId, - // subcomponents: subcomponentChanges, - // description: componentDescription, - // features: features, - // featureUpdates: featureUpdates, - // }; - const variablePayload = { name: "", project_id: Number.parseInt(projectId), @@ -387,6 +398,17 @@ const ProjectComponentEdit = ({ component_id: selectedComponentId, description: componentDescription, project_component_id: getProjectComponentId(), + moped_proj_components_subcomponents: { + data: subcomponentChanges, + on_conflict: { + constraint: "moped_proj_components_subcomponents_pkey", + update_columns: [ + "project_component_id", + "subcomponent_id", + "status_id", + ], + }, + }, }; updateProjectComponents({ From 0b8de31c15e12440c12932b395a24b1a464ab152 Mon Sep 17 00:00:00 2001 From: Sergio Garcia Date: Tue, 15 Jun 2021 14:58:26 -0400 Subject: [PATCH 095/130] Clean up UPDATE_MOPED_COMPONENT query --- moped-editor/src/queries/project.js | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/moped-editor/src/queries/project.js b/moped-editor/src/queries/project.js index 9353404aa3..8552c4e4d6 100644 --- a/moped-editor/src/queries/project.js +++ b/moped-editor/src/queries/project.js @@ -491,7 +491,7 @@ export const PROJECT_CLEAR_MAP_DATA_TEMPLATE = `mutation ClearProjectMapData($pr `; export const COMPONENTS_QUERY = gql` - query getComponents($projectId: Int) { + query GetComponents($projectId: Int) { moped_proj_components( where: { project_id: { _eq: $projectId }, status_id: { _eq: 1 } } ) { @@ -504,18 +504,21 @@ export const COMPONENTS_QUERY = gql` component_type: component_name component_subtype } - moped_proj_components_subcomponents { + moped_proj_components_subcomponents(where: { status_id: { _eq: 1 } }) { + status_id moped_subcomponent { subcomponent_id subcomponent_name } } - moped_proj_features_components { - name + moped_proj_features_components(where: { status_id: { _eq: 1 } }) { moped_proj_component_id + name + status_id moped_proj_feature { location feature_id + status_id } } } @@ -573,8 +576,16 @@ export const COMPONENT_DETAILS_QUERY = gql` `; export const UPDATE_MOPED_COMPONENT = gql` - mutation UpdateMopedComponent($objects: [moped_proj_components_insert_input!]!) { - insert_moped_proj_components(objects: $objects, on_conflict: {constraint: moped_proj_components_pkey, update_columns: [component_id, description, status_id]}) { + mutation UpdateMopedComponent( + $objects: [moped_proj_components_insert_input!]! + ) { + insert_moped_proj_components( + objects: $objects + on_conflict: { + constraint: moped_proj_components_pkey + update_columns: [component_id, description, status_id] + } + ) { affected_rows } } From 71659b88c34bc031a27dae3c70bc39921118cc26 Mon Sep 17 00:00:00 2001 From: Sergio Garcia Date: Tue, 15 Jun 2021 15:03:47 -0400 Subject: [PATCH 096/130] Fixes getAvailableSubcomponents --- .../src/views/projects/projectView/ProjectComponentEdit.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/moped-editor/src/views/projects/projectView/ProjectComponentEdit.js b/moped-editor/src/views/projects/projectView/ProjectComponentEdit.js index 4c90183654..6b26bf38b1 100644 --- a/moped-editor/src/views/projects/projectView/ProjectComponentEdit.js +++ b/moped-editor/src/views/projects/projectView/ProjectComponentEdit.js @@ -192,7 +192,7 @@ const ProjectComponentEdit = ({ * @return {Object[]} */ const getAvailableSubcomponents = () => - initialTypeCounts[selectedComponentType].subcomponents.length; + initialTypeCounts[selectedComponentType].subcomponents; /** * Returns the current project componetn id @@ -331,6 +331,7 @@ const ProjectComponentEdit = ({ // Otherwise, it means it already exists in the database subcomponent => isNaN(subcomponent?.component_subcomponent_id) ); + debugger; // Generate output, clean up & return return [...insertionList, ...removalList] From d84ee429d853f9c20c6edfb47897b14e954dc9b8 Mon Sep 17 00:00:00 2001 From: Sergio Garcia Date: Tue, 15 Jun 2021 15:22:46 -0400 Subject: [PATCH 097/130] Fixes getProjectComponentId --- .../projects/projectView/ProjectComponentEdit.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/moped-editor/src/views/projects/projectView/ProjectComponentEdit.js b/moped-editor/src/views/projects/projectView/ProjectComponentEdit.js index 6b26bf38b1..e57e3d82bc 100644 --- a/moped-editor/src/views/projects/projectView/ProjectComponentEdit.js +++ b/moped-editor/src/views/projects/projectView/ProjectComponentEdit.js @@ -199,7 +199,7 @@ const ProjectComponentEdit = ({ * @return {number|null} */ const getProjectComponentId = () => - data ? data.moped_proj_components[0].project_component_id : null; + data?.moped_proj_components[0]?.project_component_id ?? null; /** * Handles the delete button click @@ -331,7 +331,6 @@ const ProjectComponentEdit = ({ // Otherwise, it means it already exists in the database subcomponent => isNaN(subcomponent?.component_subcomponent_id) ); - debugger; // Generate output, clean up & return return [...insertionList, ...removalList] @@ -368,7 +367,10 @@ const ProjectComponentEdit = ({ * Persists the changes to the database */ const handleSaveButtonClick = () => { - // 1. Generate feature upserts + // Retrieve current project component id + const projComponentId = getProjectComponentId(); + + // Generate feature upserts const features = generateMapUpserts().map(feature => ({ status_id: feature.status_id, moped_proj_feature_object: { @@ -384,8 +386,6 @@ const ProjectComponentEdit = ({ }, })); - console.log(features); - // 2. Generate a list of subcomponent upserts const subcomponentChanges = generateSubcomponentUpserts(); @@ -398,7 +398,7 @@ const ProjectComponentEdit = ({ status_id: 1, component_id: selectedComponentId, description: componentDescription, - project_component_id: getProjectComponentId(), + ...(!!projComponentId ? { project_component_id: projComponentId } : {}), moped_proj_components_subcomponents: { data: subcomponentChanges, on_conflict: { From df7fc28ca246f668cac8326d7712b88ddd61f817 Mon Sep 17 00:00:00 2001 From: Sergio Garcia Date: Tue, 15 Jun 2021 15:23:18 -0400 Subject: [PATCH 098/130] Incorporate features to query --- .../projects/projectView/ProjectComponentEdit.js | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/moped-editor/src/views/projects/projectView/ProjectComponentEdit.js b/moped-editor/src/views/projects/projectView/ProjectComponentEdit.js index e57e3d82bc..9026fefaf0 100644 --- a/moped-editor/src/views/projects/projectView/ProjectComponentEdit.js +++ b/moped-editor/src/views/projects/projectView/ProjectComponentEdit.js @@ -369,7 +369,7 @@ const ProjectComponentEdit = ({ const handleSaveButtonClick = () => { // Retrieve current project component id const projComponentId = getProjectComponentId(); - + // Generate feature upserts const features = generateMapUpserts().map(feature => ({ status_id: feature.status_id, @@ -410,6 +410,19 @@ const ProjectComponentEdit = ({ ], }, }, + moped_proj_features_components: { + data: features, + on_conflict: { + constraint: "moped_proj_features_components_pkey", + update_columns: [ + "moped_proj_features_id", + "moped_proj_component_id", + "name", + "description", + "status_id", + ], + }, + }, }; updateProjectComponents({ From 575c7f3a3414b4bea043f32aa526a68cb0d8d562 Mon Sep 17 00:00:00 2001 From: Sergio Garcia Date: Tue, 15 Jun 2021 16:14:07 -0400 Subject: [PATCH 099/130] Change feature relationship from array to object --- moped-database/metadata/tables.yaml | 7 +++---- .../views/projects/projectView/ProjectComponentEdit.js | 10 +++++++--- .../views/projects/projectView/ProjectComponents.js | 2 +- 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/moped-database/metadata/tables.yaml b/moped-database/metadata/tables.yaml index 67ee5eec5d..50770f7ae7 100644 --- a/moped-database/metadata/tables.yaml +++ b/moped-database/metadata/tables.yaml @@ -1523,10 +1523,6 @@ - name: moped_proj_component using: foreign_key_constraint_on: moped_proj_component_id - - name: moped_proj_feature_object - using: - foreign_key_constraint_on: moped_proj_features_id - array_relationships: - name: moped_proj_feature using: manual_configuration: @@ -1535,6 +1531,9 @@ name: moped_proj_features column_mapping: moped_proj_features_id: feature_id + - name: moped_proj_feature_object + using: + foreign_key_constraint_on: moped_proj_features_id insert_permissions: - role: moped-admin permission: diff --git a/moped-editor/src/views/projects/projectView/ProjectComponentEdit.js b/moped-editor/src/views/projects/projectView/ProjectComponentEdit.js index 9026fefaf0..6b44a9762c 100644 --- a/moped-editor/src/views/projects/projectView/ProjectComponentEdit.js +++ b/moped-editor/src/views/projects/projectView/ProjectComponentEdit.js @@ -268,7 +268,7 @@ const ProjectComponentEdit = ({ const editedFeatures = editFeatureCollection.features; // Find new records that need to be inserted and create a feature record from them - const newRecordsToInsert = editedFeatures + const newFeaturesToInsert = editedFeatures .filter( feature => !projectFeatureRecords.find( @@ -283,7 +283,7 @@ const ProjectComponentEdit = ({ })); // Find existing records that need to be soft deleted, clean them, and set status to inactive - const existingRecordsToUpdate = + const existingFeaturesToDelete = componentId !== 0 ? projectFeatureRecords .map(record => filterObjectByKeys(record, ["__typename"])) @@ -301,7 +301,7 @@ const ProjectComponentEdit = ({ })) : []; // if this is a new component, there are no old records to update - return [...newRecordsToInsert, ...existingRecordsToUpdate]; + return [...newFeaturesToInsert, ...existingFeaturesToDelete]; }; /** @@ -425,6 +425,10 @@ const ProjectComponentEdit = ({ }, }; + debugger; + + console.log(variablePayload); + updateProjectComponents({ variables: { objects: variablePayload, diff --git a/moped-editor/src/views/projects/projectView/ProjectComponents.js b/moped-editor/src/views/projects/projectView/ProjectComponents.js index 22f5852ddb..845fc6e7a9 100644 --- a/moped-editor/src/views/projects/projectView/ProjectComponents.js +++ b/moped-editor/src/views/projects/projectView/ProjectComponents.js @@ -86,7 +86,7 @@ const ProjectComponents = () => { // Append if current component is selected, or none are selected (0) ...(selectedComp === component.project_component_id || selectedComp === 0 ? component.moped_proj_features_components.map( - feature_comp => feature_comp.moped_proj_feature[0] + feature_comp => feature_comp.moped_proj_feature ) : []), ], From e2c38083c7128c54514e59b67e43a4de64602eeb Mon Sep 17 00:00:00 2001 From: Sergio Garcia Date: Tue, 15 Jun 2021 16:17:07 -0400 Subject: [PATCH 100/130] Update SUMMARY_QUERY --- moped-editor/src/queries/project.js | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/moped-editor/src/queries/project.js b/moped-editor/src/queries/project.js index 8552c4e4d6..97fb2e825c 100644 --- a/moped-editor/src/queries/project.js +++ b/moped-editor/src/queries/project.js @@ -30,10 +30,21 @@ export const SUMMARY_QUERY = gql` ecapris_subproject_id fiscal_year project_priority + moped_proj_components(where: { status_id: { _eq: 1 } }) { + moped_proj_features_components(where: { status_id: { _eq: 1 } }) { + moped_proj_feature { + feature_id + project_id + location + status_id + } + } + } moped_proj_features(where: { status_id: { _eq: 1 } }) { feature_id project_id location + status_id } } moped_phases { @@ -542,10 +553,11 @@ export const COMPONENT_DETAILS_QUERY = gql` component_subtype } moped_proj_features_components(where: { status_id: { _eq: 1 } }) { + project_features_components_id status_id moped_proj_feature { - location feature_id + location status_id project_id } From b6af719b324c8c7b0162c893dbb51764b416cd87 Mon Sep 17 00:00:00 2001 From: Sergio Garcia Date: Tue, 15 Jun 2021 19:17:09 -0400 Subject: [PATCH 101/130] The great alternative --- .../projectView/ProjectComponentEdit.js | 70 +++++++++++++------ .../projects/projectView/ProjectComponents.js | 8 ++- 2 files changed, 53 insertions(+), 25 deletions(-) diff --git a/moped-editor/src/views/projects/projectView/ProjectComponentEdit.js b/moped-editor/src/views/projects/projectView/ProjectComponentEdit.js index 6b44a9762c..062002aae8 100644 --- a/moped-editor/src/views/projects/projectView/ProjectComponentEdit.js +++ b/moped-editor/src/views/projects/projectView/ProjectComponentEdit.js @@ -67,12 +67,11 @@ const ProjectComponentEdit = ({ componentId, handleCancelEdit, projectFeatureRecords, - projectFeatureCollection, projectRefetchFeatures, }) => { const { projectId } = useParams(); const classes = useStyles(); - const emptyCollection = { + const emptyFeatureCollection = { type: "FeatureCollection", features: [], }; @@ -91,8 +90,9 @@ const ProjectComponentEdit = ({ ); const [selectedSubcomponents, setSelectedSubcomponents] = useState([]); const [availableSubtypes, setAvailableSubtypes] = useState([]); + const [editFeatureComponents, setEditFeatureComponents] = useState([]); const [editFeatureCollection, setEditFeatureCollection] = useState( - componentId === 0 ? emptyCollection : projectFeatureCollection + emptyFeatureCollection ); const [componentDescription, setComponentDescription] = useState(null); @@ -266,26 +266,26 @@ const ProjectComponentEdit = ({ */ const generateMapUpserts = () => { const editedFeatures = editFeatureCollection.features; - + debugger; // Find new records that need to be inserted and create a feature record from them const newFeaturesToInsert = editedFeatures .filter( - feature => - !projectFeatureRecords.find( - record => - feature.properties.PROJECT_EXTENT_ID === - record.location.properties.PROJECT_EXTENT_ID + newFeature => + !editFeatureComponents.find( + existingRecord => + newFeature?.properties?.PROJECT_EXTENT_ID === + existingRecord.location.properties.PROJECT_EXTENT_ID ) ) .map(feature => ({ location: feature, status_id: 1, })); - + debugger; // Find existing records that need to be soft deleted, clean them, and set status to inactive const existingFeaturesToDelete = componentId !== 0 - ? projectFeatureRecords + ? editFeatureComponents .map(record => filterObjectByKeys(record, ["__typename"])) .filter( record => @@ -300,7 +300,7 @@ const ProjectComponentEdit = ({ status_id: 0, })) : []; // if this is a new component, there are no old records to update - + debugger; return [...newFeaturesToInsert, ...existingFeaturesToDelete]; }; @@ -370,8 +370,10 @@ const ProjectComponentEdit = ({ // Retrieve current project component id const projComponentId = getProjectComponentId(); + const mapUpserts = generateMapUpserts(); + // Generate feature upserts - const features = generateMapUpserts().map(feature => ({ + const features = mapUpserts.map(feature => ({ status_id: feature.status_id, moped_proj_feature_object: { on_conflict: { @@ -425,15 +427,11 @@ const ProjectComponentEdit = ({ }, }; - debugger; - - console.log(variablePayload); - - updateProjectComponents({ - variables: { - objects: variablePayload, - }, - }).then(() => exitAndReload()); + // updateProjectComponents({ + // variables: { + // objects: variablePayload, + // }, + // }).then(() => exitAndReload()); }; /** @@ -549,6 +547,34 @@ const ProjectComponentEdit = ({ setComponentDescription(data?.moped_proj_components[0]?.description); } + /** + * We need to populate the features we will need in order to build the collection + */ + if (data && editFeatureComponents.length === 0) { + const featuresFromComponents = ( + data?.moped_proj_components[0]?.moped_proj_features_components ?? [] + ).map(featureComponent => { + // Retrieve the feature component's primary key + const featureCompId = featureComponent.project_features_components_id; + // Clone the geojson data from the feature component + const newGeoJson = { + ...featureComponent.moped_proj_feature.location, + }; + // Now go ahead and patch the primary key into the GeoJson properties + newGeoJson.properties.project_features_components_id = featureCompId; + + return newGeoJson; + }); + + const featureCollectionFromComponents = { + ...emptyFeatureCollection, + features: featuresFromComponents, + }; + + setEditFeatureComponents(featuresFromComponents); + setEditFeatureCollection(featureCollectionFromComponents); + } + return ( diff --git a/moped-editor/src/views/projects/projectView/ProjectComponents.js b/moped-editor/src/views/projects/projectView/ProjectComponents.js index 845fc6e7a9..c70d539a6c 100644 --- a/moped-editor/src/views/projects/projectView/ProjectComponents.js +++ b/moped-editor/src/views/projects/projectView/ProjectComponents.js @@ -85,9 +85,11 @@ const ProjectComponents = () => { ...accumulator, // Append if current component is selected, or none are selected (0) ...(selectedComp === component.project_component_id || selectedComp === 0 - ? component.moped_proj_features_components.map( - feature_comp => feature_comp.moped_proj_feature - ) + ? component.moped_proj_features_components.map(featureComponent => ({ + ...featureComponent.moped_proj_feature, + project_features_components_id: + featureComponent.project_features_components_id, + })) : []), ], [] From 45ef36a511dfda722029cf264fd60ab5a0506d24 Mon Sep 17 00:00:00 2001 From: Sergio Garcia Date: Tue, 15 Jun 2021 20:46:20 -0400 Subject: [PATCH 102/130] Restore SUMMARY_QUERY --- moped-editor/src/queries/project.js | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/moped-editor/src/queries/project.js b/moped-editor/src/queries/project.js index 97fb2e825c..060deeaaf5 100644 --- a/moped-editor/src/queries/project.js +++ b/moped-editor/src/queries/project.js @@ -30,21 +30,10 @@ export const SUMMARY_QUERY = gql` ecapris_subproject_id fiscal_year project_priority - moped_proj_components(where: { status_id: { _eq: 1 } }) { - moped_proj_features_components(where: { status_id: { _eq: 1 } }) { - moped_proj_feature { - feature_id - project_id - location - status_id - } - } - } moped_proj_features(where: { status_id: { _eq: 1 } }) { feature_id project_id location - status_id } } moped_phases { @@ -523,8 +512,8 @@ export const COMPONENTS_QUERY = gql` } } moped_proj_features_components(where: { status_id: { _eq: 1 } }) { - moped_proj_component_id name + moped_proj_component_id status_id moped_proj_feature { location @@ -556,8 +545,8 @@ export const COMPONENT_DETAILS_QUERY = gql` project_features_components_id status_id moped_proj_feature { - feature_id location + feature_id status_id project_id } From de023ed3e61bbd71d42a66c1cbc033a440d91fb0 Mon Sep 17 00:00:00 2001 From: Sergio Garcia Date: Tue, 15 Jun 2021 20:46:20 -0400 Subject: [PATCH 103/130] Restore SUMMARY_QUERY --- moped-editor/src/queries/project.js | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/moped-editor/src/queries/project.js b/moped-editor/src/queries/project.js index 97fb2e825c..060deeaaf5 100644 --- a/moped-editor/src/queries/project.js +++ b/moped-editor/src/queries/project.js @@ -30,21 +30,10 @@ export const SUMMARY_QUERY = gql` ecapris_subproject_id fiscal_year project_priority - moped_proj_components(where: { status_id: { _eq: 1 } }) { - moped_proj_features_components(where: { status_id: { _eq: 1 } }) { - moped_proj_feature { - feature_id - project_id - location - status_id - } - } - } moped_proj_features(where: { status_id: { _eq: 1 } }) { feature_id project_id location - status_id } } moped_phases { @@ -523,8 +512,8 @@ export const COMPONENTS_QUERY = gql` } } moped_proj_features_components(where: { status_id: { _eq: 1 } }) { - moped_proj_component_id name + moped_proj_component_id status_id moped_proj_feature { location @@ -556,8 +545,8 @@ export const COMPONENT_DETAILS_QUERY = gql` project_features_components_id status_id moped_proj_feature { - feature_id location + feature_id status_id project_id } From 04bee8a815cce45e3a0eea9784bdd514780ee038 Mon Sep 17 00:00:00 2001 From: Sergio Garcia Date: Tue, 15 Jun 2021 21:20:09 -0400 Subject: [PATCH 104/130] Implement remaining functionality with features --- .../projectView/ProjectComponentEdit.js | 48 ++++++++++++------- 1 file changed, 30 insertions(+), 18 deletions(-) diff --git a/moped-editor/src/views/projects/projectView/ProjectComponentEdit.js b/moped-editor/src/views/projects/projectView/ProjectComponentEdit.js index 062002aae8..4f9fd0e49a 100644 --- a/moped-editor/src/views/projects/projectView/ProjectComponentEdit.js +++ b/moped-editor/src/views/projects/projectView/ProjectComponentEdit.js @@ -266,7 +266,6 @@ const ProjectComponentEdit = ({ */ const generateMapUpserts = () => { const editedFeatures = editFeatureCollection.features; - debugger; // Find new records that need to be inserted and create a feature record from them const newFeaturesToInsert = editedFeatures .filter( @@ -274,14 +273,14 @@ const ProjectComponentEdit = ({ !editFeatureComponents.find( existingRecord => newFeature?.properties?.PROJECT_EXTENT_ID === - existingRecord.location.properties.PROJECT_EXTENT_ID + existingRecord.properties.PROJECT_EXTENT_ID ) ) - .map(feature => ({ - location: feature, + .map(newFeature => ({ + ...newFeature, status_id: 1, })); - debugger; + // Find existing records that need to be soft deleted, clean them, and set status to inactive const existingFeaturesToDelete = componentId !== 0 @@ -292,7 +291,7 @@ const ProjectComponentEdit = ({ !editedFeatures.find( feature => feature.properties.PROJECT_EXTENT_ID === - record.location.properties.PROJECT_EXTENT_ID + record.properties.PROJECT_EXTENT_ID ) ) .map(record => ({ @@ -300,7 +299,7 @@ const ProjectComponentEdit = ({ status_id: 0, })) : []; // if this is a new component, there are no old records to update - debugger; + return [...newFeaturesToInsert, ...existingFeaturesToDelete]; }; @@ -370,19 +369,32 @@ const ProjectComponentEdit = ({ // Retrieve current project component id const projComponentId = getProjectComponentId(); - const mapUpserts = generateMapUpserts(); + // First, we need a list of map changes only + const mapListOfChanges = generateMapUpserts(); - // Generate feature upserts - const features = mapUpserts.map(feature => ({ + // For each change, we generate a list of feature component objects + const featureComponents = mapListOfChanges.map(feature => ({ + // Each feature component shares the status of it's child feature status_id: feature.status_id, + // Now we must determine if the feature has a nested `project_features_components_id` field + ...(feature?.properties?.project_features_components_id ?? null + ? // If so, then add it to the object, so that it can be upserted + { + project_features_components_id: + feature.properties.project_features_components_id, + } + : // If not, ignore it so that we can insert a new one + {}), + // Create the moped_proj_feature_object key with conflict rules and data moped_proj_feature_object: { on_conflict: { constraint: "moped_proj_features_pkey", update_columns: ["location", "status_id"], }, + // This inserts into moped_proj_features, and assumes relationship with moped_proj_features_components data: { - project_id: projectId, - location: feature.location, + project_id: Number.parseInt(projectId), + location: { ...feature }, status_id: feature.status_id, }, }, @@ -413,7 +425,7 @@ const ProjectComponentEdit = ({ }, }, moped_proj_features_components: { - data: features, + data: featureComponents, on_conflict: { constraint: "moped_proj_features_components_pkey", update_columns: [ @@ -427,11 +439,11 @@ const ProjectComponentEdit = ({ }, }; - // updateProjectComponents({ - // variables: { - // objects: variablePayload, - // }, - // }).then(() => exitAndReload()); + updateProjectComponents({ + variables: { + objects: variablePayload, + }, + }).then(() => exitAndReload()); }; /** From 6effa73e8ce558741fab319a6e7a2d9d25d28f9c Mon Sep 17 00:00:00 2001 From: Sergio Garcia Date: Tue, 15 Jun 2021 21:25:57 -0400 Subject: [PATCH 105/130] Add commentary --- .../projectView/ProjectComponentEdit.js | 26 ++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/moped-editor/src/views/projects/projectView/ProjectComponentEdit.js b/moped-editor/src/views/projects/projectView/ProjectComponentEdit.js index 4f9fd0e49a..83770a7bd2 100644 --- a/moped-editor/src/views/projects/projectView/ProjectComponentEdit.js +++ b/moped-editor/src/views/projects/projectView/ProjectComponentEdit.js @@ -403,16 +403,31 @@ const ProjectComponentEdit = ({ // 2. Generate a list of subcomponent upserts const subcomponentChanges = generateSubcomponentUpserts(); - // First update the map features: create, retire, - // Associate the map features to the current component: upsert moped_proj_features_components - + /** + * This document represents all the variables Hasura needs + * to create a moped_proj_component in Hasura. It uses Hasura's + * nested insertion to establish relationships when creating + * new objects, and it uses primary keys when upserting. + * @type {moped_proj_component} + */ const variablePayload = { + /* + First we need a component's common fields: name, status, etc. + */ name: "", project_id: Number.parseInt(projectId), status_id: 1, component_id: selectedComponentId, description: componentDescription, + /* + To update a component, we need it's primary key. + If the project component is new, it will not have a projComponentId, then it's safe to ignore. + */ ...(!!projComponentId ? { project_component_id: projComponentId } : {}), + + /* + Now we need to insert the subcomponents previously generated. + */ moped_proj_components_subcomponents: { data: subcomponentChanges, on_conflict: { @@ -424,6 +439,10 @@ const ProjectComponentEdit = ({ ], }, }, + /* + Finally we inject the features components & geojson features + as previously generated. + */ moped_proj_features_components: { data: featureComponents, on_conflict: { @@ -439,6 +458,7 @@ const ProjectComponentEdit = ({ }, }; + // Finally we must run the graphql query and refetch updateProjectComponents({ variables: { objects: variablePayload, From 50e2e865308f6578c4ccf48ebb816aedd19eff9c Mon Sep 17 00:00:00 2001 From: Sergio Garcia Date: Tue, 15 Jun 2021 21:40:12 -0400 Subject: [PATCH 106/130] Remove unnecessary fields --- .../src/views/projects/projectView/ProjectComponents.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/moped-editor/src/views/projects/projectView/ProjectComponents.js b/moped-editor/src/views/projects/projectView/ProjectComponents.js index c70d539a6c..05602bdccb 100644 --- a/moped-editor/src/views/projects/projectView/ProjectComponents.js +++ b/moped-editor/src/views/projects/projectView/ProjectComponents.js @@ -152,8 +152,6 @@ const ProjectComponents = () => { )} From 7d13ec29486e5c22372852a225cb70b45f732102 Mon Sep 17 00:00:00 2001 From: Sergio Garcia Date: Tue, 15 Jun 2021 21:40:38 -0400 Subject: [PATCH 107/130] Fix state infinite loop error --- .../projectView/ProjectComponentEdit.js | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/moped-editor/src/views/projects/projectView/ProjectComponentEdit.js b/moped-editor/src/views/projects/projectView/ProjectComponentEdit.js index 83770a7bd2..a0e182d206 100644 --- a/moped-editor/src/views/projects/projectView/ProjectComponentEdit.js +++ b/moped-editor/src/views/projects/projectView/ProjectComponentEdit.js @@ -57,8 +57,6 @@ const useStyles = makeStyles(theme => ({ * The project component editor * @param {Number} componentId - The moped_proj_component id being edited * @param {function} handleCancelEdit - The function to call if we need to cancel editing - * @param {Object} projectFeatureRecords - The a list of feature records - * @param {Object} projectFeatureCollection - The feature collection GeoJSON * @param {function} projectRefetchFeatures - Reload parent component's features * @return {JSX.Element} * @constructor @@ -66,7 +64,6 @@ const useStyles = makeStyles(theme => ({ const ProjectComponentEdit = ({ componentId, handleCancelEdit, - projectFeatureRecords, projectRefetchFeatures, }) => { const { projectId } = useParams(); @@ -580,9 +577,11 @@ const ProjectComponentEdit = ({ } /** - * We need to populate the features we will need in order to build the collection + * We need to populate the features we will need in order to build the + * geojson collection that we can feed it to the map. */ if (data && editFeatureComponents.length === 0) { + // First, we will need a list of all moped_proj_features_components and make it geojson const featuresFromComponents = ( data?.moped_proj_components[0]?.moped_proj_features_components ?? [] ).map(featureComponent => { @@ -598,13 +597,19 @@ const ProjectComponentEdit = ({ return newGeoJson; }); + /** + * Secondly, use emptyFeatureCollection as a template, then inject our previously rendered features + */ const featureCollectionFromComponents = { ...emptyFeatureCollection, features: featuresFromComponents, }; - setEditFeatureComponents(featuresFromComponents); - setEditFeatureCollection(featureCollectionFromComponents); + // Unless we have features to work with, then leave it alone + if (featuresFromComponents.length > 0) { + setEditFeatureComponents(featuresFromComponents); + setEditFeatureCollection(featureCollectionFromComponents); + } } return ( From 85ebec67953b527a5e5e8327f8f89f75e52f1986 Mon Sep 17 00:00:00 2001 From: Sergio Garcia Date: Tue, 15 Jun 2021 22:07:07 -0400 Subject: [PATCH 108/130] Update map fallback dialog --- .../projectView/ProjectSummaryMapFallback.js | 61 +++++-------------- 1 file changed, 15 insertions(+), 46 deletions(-) diff --git a/moped-editor/src/views/projects/projectView/ProjectSummaryMapFallback.js b/moped-editor/src/views/projects/projectView/ProjectSummaryMapFallback.js index 3ef3c2ca69..d709f52905 100644 --- a/moped-editor/src/views/projects/projectView/ProjectSummaryMapFallback.js +++ b/moped-editor/src/views/projects/projectView/ProjectSummaryMapFallback.js @@ -1,9 +1,8 @@ import React from "react"; import { Box, Button, Card, Icon, makeStyles } from "@material-ui/core"; -import { gql, useMutation } from "@apollo/client"; -import { PROJECT_CLEAR_MAP_DATA_TEMPLATE } from "../../../queries/project"; -import { v4 as uuid } from "uuid"; + +import { Link } from "react-router-dom"; const useStyles = makeStyles(theme => ({ root: { @@ -35,50 +34,19 @@ const useStyles = makeStyles(theme => ({ * Renders a fallback component that shows the user whenever there is a map error. * @param {object} error - provided by ErrorBoundary component, contains error details. * @param {function} resetErrorBoundary - A function that forces ErrorBoundary to re-render it's children components - * @param {integer} projectId - The project id of the map - * @param {function} refetchProjectDetails - A refetch function to run after the data is cleared - * @param {function} setIsEditing - A function to enable editing * @param {object} mapData - The map data with errors to show in the console for debugging * @return {JSX.Element} * @constructor */ -const ProjectSummaryMapFallback = ({ - error, - resetErrorBoundary, - projectId, - refetchProjectDetails, - setIsEditing, - mapData, -}) => { +const ProjectSummaryMapFallback = ({ error, mapData }) => { const classes = useStyles(); - const [clearProjectMapData] = useMutation( - gql(PROJECT_CLEAR_MAP_DATA_TEMPLATE.replaceAll("RANDOM_FEATURE_ID", uuid())), - { - variables: { - projectId: projectId, - }, - } - ); - /** * Log whatever error there may be */ console.error("MapDataError: ", error); console.error("MapData: ", mapData); - /** - * Clears the json data in the project and opens the editor - */ - const clearAndEdit = () => { - clearProjectMapData().then(() => { - refetchProjectDetails().then(() => { - setIsEditing(true); - resetErrorBoundary(); - }); - }); - }; - return ( @@ -90,8 +58,8 @@ const ProjectSummaryMapFallback = ({

No map available

- The map for this project is either missing or outdated. Create a new - map or{" "} + This project does not have components or is outdated. Create new + components or{" "}

- + + +
); From 3e3ba849af528f2986cc5bc37a63540667f7ac8e Mon Sep 17 00:00:00 2001 From: Sergio Garcia Date: Tue, 15 Jun 2021 22:50:01 -0400 Subject: [PATCH 109/130] Update DELETE_MOPED_COMPONENT --- moped-editor/src/queries/project.js | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/moped-editor/src/queries/project.js b/moped-editor/src/queries/project.js index 060deeaaf5..6f7a8eb7ce 100644 --- a/moped-editor/src/queries/project.js +++ b/moped-editor/src/queries/project.js @@ -600,5 +600,33 @@ export const DELETE_MOPED_COMPONENT = gql` ) { affected_rows } + update_moped_proj_components_subcomponents( + where: { project_component_id: { _eq: $projComponentId } } + _set: { status_id: 0 } + ) { + affected_rows + } + update_moped_proj_features_components( + where: { + moped_proj_component: { + project_component_id: { _eq: $projComponentId } + } + } + _set: { status_id: 0 } + ) { + affected_rows + } + update_moped_proj_features( + where: { + moped_project: { + moped_proj_components: { + project_component_id: { _eq: $projComponentId } + } + } + } + _set: { status_id: 0 } + ) { + affected_rows + } } `; From e62162ad2d260f97d1c2832ee64ac68a3c0274c2 Mon Sep 17 00:00:00 2001 From: Sergio Garcia Date: Tue, 15 Jun 2021 23:12:16 -0400 Subject: [PATCH 110/130] Refactor relationship and updates --- moped-database/metadata/tables.yaml | 8 ++++++++ moped-editor/src/queries/project.js | 6 ++---- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/moped-database/metadata/tables.yaml b/moped-database/metadata/tables.yaml index 50770f7ae7..1331531e0f 100644 --- a/moped-database/metadata/tables.yaml +++ b/moped-database/metadata/tables.yaml @@ -1453,6 +1453,14 @@ - name: moped_project using: foreign_key_constraint_on: project_id + array_relationships: + - name: moped_proj_features_components + using: + foreign_key_constraint_on: + column: moped_proj_features_id + table: + schema: public + name: moped_proj_features_components insert_permissions: - role: moped-admin permission: diff --git a/moped-editor/src/queries/project.js b/moped-editor/src/queries/project.js index 6f7a8eb7ce..a085e48384 100644 --- a/moped-editor/src/queries/project.js +++ b/moped-editor/src/queries/project.js @@ -618,10 +618,8 @@ export const DELETE_MOPED_COMPONENT = gql` } update_moped_proj_features( where: { - moped_project: { - moped_proj_components: { - project_component_id: { _eq: $projComponentId } - } + moped_proj_features_components: { + moped_proj_component_id: { _eq: $projComponentId } } } _set: { status_id: 0 } From 5520cc7f65e640f4e17e31db1c5bf39e182def7c Mon Sep 17 00:00:00 2001 From: Sergio Garcia Date: Tue, 15 Jun 2021 23:12:36 -0400 Subject: [PATCH 111/130] Refetch made-sure --- .../src/views/projects/projectView/ProjectSummary.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/moped-editor/src/views/projects/projectView/ProjectSummary.js b/moped-editor/src/views/projects/projectView/ProjectSummary.js index 5b2b3dddca..ce52fb433c 100644 --- a/moped-editor/src/views/projects/projectView/ProjectSummary.js +++ b/moped-editor/src/views/projects/projectView/ProjectSummary.js @@ -18,6 +18,7 @@ import { ErrorBoundary } from "react-error-boundary"; const ProjectSummary = ({ loading, error, data, refetch }) => { const { projectId } = useParams(); + const [makeSureRefresh, setMakeSureRefresh] = useState(false); const [isEditing, setIsEditing] = useState(false); const [mapError, setMapError] = useState(false); @@ -29,6 +30,10 @@ const ProjectSummary = ({ loading, error, data, refetch }) => { projectFeatureRecords ); + refetch(); + if (projectFeatureRecords.length === 0 && !makeSureRefresh) + setMakeSureRefresh(true); + return ( From 7acd0527850096ff91dc2f45364ad018c5a900b6 Mon Sep 17 00:00:00 2001 From: Sergio Garcia Date: Tue, 15 Jun 2021 23:12:44 -0400 Subject: [PATCH 112/130] No cache policy --- moped-editor/src/views/projects/projectView/ProjectView.js | 1 + 1 file changed, 1 insertion(+) diff --git a/moped-editor/src/views/projects/projectView/ProjectView.js b/moped-editor/src/views/projects/projectView/ProjectView.js index ff6a89be44..c467b56aaa 100644 --- a/moped-editor/src/views/projects/projectView/ProjectView.js +++ b/moped-editor/src/views/projects/projectView/ProjectView.js @@ -156,6 +156,7 @@ const ProjectView = () => { */ const { loading, error, data, refetch } = useQuery(SUMMARY_QUERY, { variables: { projectId }, + fetchPolicy: "no-cache", }); /** From 142eb634a58ed37e7add28ad17b17dc52de37caa Mon Sep 17 00:00:00 2001 From: Sergio Garcia Date: Tue, 15 Jun 2021 23:30:30 -0400 Subject: [PATCH 113/130] Clear demo features --- .../1602292389297_initial_seed_staging.sql | 53 ------------------- 1 file changed, 53 deletions(-) diff --git a/moped-database/seeds/1602292389297_initial_seed_staging.sql b/moped-database/seeds/1602292389297_initial_seed_staging.sql index cebfc9b538..d7881be750 100644 --- a/moped-database/seeds/1602292389297_initial_seed_staging.sql +++ b/moped-database/seeds/1602292389297_initial_seed_staging.sql @@ -1423,56 +1423,3 @@ SELECT pg_catalog.setval('public.moped_workgroup_workgroup_id_seq', 1, true); -- -- PostgreSQL database dump complete -- - -/** - INSERTS DEMO FEATURES WE NEED -**/ -INSERT INTO public.moped_proj_features (feature_id, project_id, location, status_id) VALUES (1, 159, '{"id": "70a64fa6-4773-4e85-8de5-2b1b6c43e2ec", "type": "Feature", "geometry": {"type": "Point", "coordinates": [-97.74280552637893, 30.26807489857954]}, "properties": {"renderType": "Point", "sourceLayer": "drawnByUser", "PROJECT_EXTENT_ID": "70a64fa6-4773-4e85-8de5-2b1b6c43e2ec"}}', 0); -INSERT INTO public.moped_proj_features (feature_id, project_id, location, status_id) VALUES (2, 159, '{"id": 53748, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.74282043799758, 30.26807093069874], [-97.74247946217656, 30.26897163447613]]}, "properties": {"_symbol": 0, "LINE_TYPE": "On-Street", "sourceLayer": "CTN", "TO_ADDRESS_MAX": 623, "FROM_ADDRESS_MIN": 600, "FULL_STREET_NAME": "CONGRESS AVE", "PROJECT_EXTENT_ID": 153748}}', 1); -INSERT INTO public.moped_proj_features (feature_id, project_id, location, status_id) VALUES (3, 159, '{"id": 49354, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.74247946217656, 30.26897163447613], [-97.74111723527312, 30.268608516185054]]}, "properties": {"_symbol": 0, "LINE_TYPE": "On-Street", "sourceLayer": "CTN", "TO_ADDRESS_MAX": 121, "FROM_ADDRESS_MIN": 100, "FULL_STREET_NAME": "E 7TH ST", "PROJECT_EXTENT_ID": 149354}}', 1); -INSERT INTO public.moped_proj_features (feature_id, project_id, location, status_id) VALUES (4, 159, '{"id": 50656, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.74282043799758, 30.26807093069874], [-97.74146189913154, 30.267688697374666]]}, "properties": {"_symbol": 0, "LINE_TYPE": "On-Street", "sourceLayer": "CTN", "TO_ADDRESS_MAX": 121, "FROM_ADDRESS_MIN": 100, "FULL_STREET_NAME": "E 6TH ST", "PROJECT_EXTENT_ID": 150656}}', 1); -INSERT INTO public.moped_proj_features (feature_id, project_id, location, status_id) VALUES (5, 159, '{"id": 54322, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.74146189913154, 30.267688697374666], [-97.74111723527312, 30.268608516185054]]}, "properties": {"_symbol": 0, "LINE_TYPE": "On-Street", "sourceLayer": "CTN", "TO_ADDRESS_MAX": 617, "FROM_ADDRESS_MIN": 600, "FULL_STREET_NAME": "BRAZOS ST", "PROJECT_EXTENT_ID": 154322}}', 1); -INSERT INTO public.moped_proj_features (feature_id, project_id, location, status_id) VALUES (6, 159, '{"id": 94918, "type": "Feature", "geometry": {"type": "Point", "coordinates": [-97.74247946217656, 30.26897163447613]}, "properties": {"sourceLayer": "Project_Component_Points_prototype", "PROJECT_EXTENT_ID": 694918}}', 1); -INSERT INTO public.moped_proj_features (feature_id, project_id, location, status_id) VALUES (7, 159, '{"id": 101277, "type": "Feature", "geometry": {"type": "Point", "coordinates": [-97.74282043799758, 30.26807093069874]}, "properties": {"sourceLayer": "Project_Component_Points_prototype", "PROJECT_EXTENT_ID": 701277}}', 1); -INSERT INTO public.moped_proj_features (feature_id, project_id, location, status_id) VALUES (8, 159, '{"id": 101278, "type": "Feature", "geometry": {"type": "Point", "coordinates": [-97.74146189913154, 30.267688697374666]}, "properties": {"sourceLayer": "Project_Component_Points_prototype", "PROJECT_EXTENT_ID": 701278}}', 1); -INSERT INTO public.moped_proj_features (feature_id, project_id, location, status_id) VALUES (9, 159, '{"id": 95673, "type": "Feature", "geometry": {"type": "Point", "coordinates": [-97.74111723527312, 30.268608516185054]}, "properties": {"sourceLayer": "Project_Component_Points_prototype", "PROJECT_EXTENT_ID": 695673}}', 1); -INSERT INTO public.moped_proj_features (feature_id, project_id, location, status_id) VALUES (10, 159, '{"id": 47852, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.74111723527312, 30.268608516185054], [-97.74004502221942, 30.268300849117793]]}, "properties": {"_symbol": 0, "LINE_TYPE": "On-Street", "sourceLayer": "CTN", "TO_ADDRESS_MAX": 217, "FROM_ADDRESS_MIN": 200, "FULL_STREET_NAME": "E 7TH ST", "PROJECT_EXTENT_ID": 147852}}', 1); -INSERT INTO public.moped_proj_features (feature_id, project_id, location, status_id) VALUES (11, 159, '{"id": 51525, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.74146189913154, 30.267688697374666], [-97.7403829805553, 30.267399994400208]]}, "properties": {"_symbol": 0, "LINE_TYPE": "On-Street", "sourceLayer": "CTN", "TO_ADDRESS_MAX": 223, "FROM_ADDRESS_MIN": 200, "FULL_STREET_NAME": "E 6TH ST", "PROJECT_EXTENT_ID": 151525}}', 1); -INSERT INTO public.moped_proj_features (feature_id, project_id, location, status_id) VALUES (12, 159, '{"id": 97029, "type": "Feature", "geometry": {"type": "Point", "coordinates": [-97.7403829805553, 30.267399994400208]}, "properties": {"sourceLayer": "Project_Component_Points_prototype", "PROJECT_EXTENT_ID": 697029}}', 1); -INSERT INTO public.moped_proj_features (feature_id, project_id, location, status_id) VALUES (13, 159, '{"id": 48531, "type": "Feature", "geometry": {"type": "LineString", "coordinates": [[-97.7403829805553, 30.267399994400208], [-97.74004502221942, 30.268300849117793]]}, "properties": {"_symbol": 0, "LINE_TYPE": "On-Street", "sourceLayer": "CTN", "TO_ADDRESS_MAX": 617, "FROM_ADDRESS_MIN": 600, "FULL_STREET_NAME": "SAN JACINTO BLVD", "PROJECT_EXTENT_ID": 148531}}', 1); -INSERT INTO public.moped_proj_features (feature_id, project_id, location, status_id) VALUES (14, 159, '{"id": 94927, "type": "Feature", "geometry": {"type": "Point", "coordinates": [-97.74004502221942, 30.268300849117793]}, "properties": {"sourceLayer": "Project_Component_Points_prototype", "PROJECT_EXTENT_ID": 694927}}', 1); - -/* MOPED PROJECT COMPONENTS */ -INSERT INTO public.moped_proj_components (project_component_id, project_id, component_id, name, description) VALUES (1, 159, 1, 'Component A', 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer pellentesque eget mauris mollis pellentesque. Praesent at arcu id turpis ultrices posuere vel ut purus.'); -INSERT INTO public.moped_proj_components (project_component_id, project_id, component_id, name, description) VALUES (2, 159, 2, 'Component B', 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer pellentesque eget mauris mollis pellentesque. Praesent at arcu id turpis ultrices posuere vel ut purus.'); -INSERT INTO public.moped_proj_components (project_component_id, project_id, component_id, name, description) VALUES (3, 159, 3, 'Component C', 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer pellentesque eget mauris mollis pellentesque. Praesent at arcu id turpis ultrices posuere vel ut purus.'); -INSERT INTO public.moped_proj_components (project_component_id, project_id, component_id, name, description) VALUES (4, 159, 4, 'Component D', 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer pellentesque eget mauris mollis pellentesque. Praesent at arcu id turpis ultrices posuere vel ut purus.'); -INSERT INTO public.moped_proj_components (project_component_id, project_id, component_id, name, description) VALUES (5, 159, 5, 'Component E', 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer pellentesque eget mauris mollis pellentesque. Praesent at arcu id turpis ultrices posuere vel ut purus.'); -INSERT INTO public.moped_proj_components (project_component_id, project_id, component_id, name, description) VALUES (6, 159, 6, 'Component D', 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer pellentesque eget mauris mollis pellentesque. Praesent at arcu id turpis ultrices posuere vel ut purus.'); - -/* MOPED PROJECT COMPONENT SUBCOMPONENTS */ -INSERT INTO public.moped_proj_components_subcomponents (component_subcomponent_id, project_component_id, subcomponent_id) VALUES (1, 1, 1); -INSERT INTO public.moped_proj_components_subcomponents (component_subcomponent_id, project_component_id, subcomponent_id) VALUES (2, 1, 2); -INSERT INTO public.moped_proj_components_subcomponents (component_subcomponent_id, project_component_id, subcomponent_id) VALUES (3, 2, 3); -INSERT INTO public.moped_proj_components_subcomponents (component_subcomponent_id, project_component_id, subcomponent_id) VALUES (5, 3, 1); -INSERT INTO public.moped_proj_components_subcomponents (component_subcomponent_id, project_component_id, subcomponent_id) VALUES (6, 3, 3); -INSERT INTO public.moped_proj_components_subcomponents (component_subcomponent_id, project_component_id, subcomponent_id) VALUES (4, 2, 4); - -/* FEATURE COMPONENTS */ -INSERT INTO public.moped_proj_features_components (project_features_components_id, moped_proj_features_id, moped_proj_component_id, name, description, create_date, status_id) VALUES (1, 1, 1, 'The component a feature one', null, '2021-06-04 18:00:42.105875', 0); -INSERT INTO public.moped_proj_features_components (project_features_components_id, moped_proj_features_id, moped_proj_component_id, name, description, create_date, status_id) VALUES (2, 2, 2, 'The component a feature two', null, '2021-06-04 18:01:56.267785', 0); -INSERT INTO public.moped_proj_features_components (project_features_components_id, moped_proj_features_id, moped_proj_component_id, name, description, create_date, status_id) VALUES (3, 3, 3, 'The component a feature two', null, '2021-06-04 18:01:56.267785', 0); -INSERT INTO public.moped_proj_features_components (project_features_components_id, moped_proj_features_id, moped_proj_component_id, name, description, create_date, status_id) VALUES (4, 4, 4, 'The component a feature two', null, '2021-06-04 18:01:56.267785', 0); -INSERT INTO public.moped_proj_features_components (project_features_components_id, moped_proj_features_id, moped_proj_component_id, name, description, create_date, status_id) VALUES (5, 5, 5, 'The component a feature two', null, '2021-06-04 18:01:56.267785', 0); -INSERT INTO public.moped_proj_features_components (project_features_components_id, moped_proj_features_id, moped_proj_component_id, name, description, create_date, status_id) VALUES (6, 6, 6, 'The component a feature two', null, '2021-06-04 18:01:56.267785', 0); -INSERT INTO public.moped_proj_features_components (project_features_components_id, moped_proj_features_id, moped_proj_component_id, name, description, create_date, status_id) VALUES (7, 7, 1, 'The component a feature two', null, '2021-06-04 18:01:56.267785', 0); -INSERT INTO public.moped_proj_features_components (project_features_components_id, moped_proj_features_id, moped_proj_component_id, name, description, create_date, status_id) VALUES (8, 8, 2, 'The component a feature two', null, '2021-06-04 18:01:56.267785', 0); -INSERT INTO public.moped_proj_features_components (project_features_components_id, moped_proj_features_id, moped_proj_component_id, name, description, create_date, status_id) VALUES (9, 9, 3, 'The component a feature two', null, '2021-06-04 18:01:56.267785', 0); -INSERT INTO public.moped_proj_features_components (project_features_components_id, moped_proj_features_id, moped_proj_component_id, name, description, create_date, status_id) VALUES (10, 10, 4, 'The component a feature two', null, '2021-06-04 18:01:56.267785', 0); -INSERT INTO public.moped_proj_features_components (project_features_components_id, moped_proj_features_id, moped_proj_component_id, name, description, create_date, status_id) VALUES (11, 11, 5, 'The component a feature two', null, '2021-06-04 18:01:56.267785', 0); -INSERT INTO public.moped_proj_features_components (project_features_components_id, moped_proj_features_id, moped_proj_component_id, name, description, create_date, status_id) VALUES (12, 12, 6, 'The component a feature two', null, '2021-06-04 18:01:56.267785', 0); -INSERT INTO public.moped_proj_features_components (project_features_components_id, moped_proj_features_id, moped_proj_component_id, name, description, create_date, status_id) VALUES (13, 13, 1, 'The component a feature two', null, '2021-06-04 18:01:56.267785', 0); -INSERT INTO public.moped_proj_features_components (project_features_components_id, moped_proj_features_id, moped_proj_component_id, name, description, create_date, status_id) VALUES (14, 14, 2, 'The component a feature two', null, '2021-06-04 18:01:56.267785', 0); --- Reset the features sequence -SELECT setval('moped_proj_features_feature_id_seq', COALESCE((SELECT MAX(feature_id)+1 FROM moped_proj_features), 1), false); --- Done seeding components From 4f8fc82e6ed30acf49f06986f383ef043622abd3 Mon Sep 17 00:00:00 2001 From: Sergio Garcia Date: Thu, 24 Jun 2021 10:32:40 -0400 Subject: [PATCH 114/130] Adds missing commentary --- .../views/projects/projectView/ProjectComponentEdit.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/moped-editor/src/views/projects/projectView/ProjectComponentEdit.js b/moped-editor/src/views/projects/projectView/ProjectComponentEdit.js index a0e182d206..fc97862419 100644 --- a/moped-editor/src/views/projects/projectView/ProjectComponentEdit.js +++ b/moped-editor/src/views/projects/projectView/ProjectComponentEdit.js @@ -77,7 +77,13 @@ const ProjectComponentEdit = ({ * The State * @type {String} selectedComponentType - A string containing the name of the selected type in lowercase * @type {String} selectedComponentSubtype - A string containing the name of the selected subtype in lowercase - * @type {String[]} selectedComponentSubtype - A string containing all available subtypes for type + * @type {String[]} selectedComponentSubtype - A string list containing all available subtypes for type + * @type {Number[]} selectedSubcomponents - A number array containing the id of the selected subcomponents + * @type {String[]} availableSubtypes - An string list containing all available subtypes for the selected component + * @type {Object[]} editFeatureComponents - An object list containing the features for this component + * @type {Object} editFeatureCollection - The final GeoJson generated for all the the features in this component + * @type {String} componentDescription - The description of this component + * @type {boolean} deleteDialogOpen - If true, it displays the delete dialog, or hides it if false. * @constant */ const [selectedComponentId, setSelectedComponentId] = useState(null); From aba360f19c5b30653c146b08879ebd5226c7477b Mon Sep 17 00:00:00 2001 From: Sergio Garcia Date: Thu, 24 Jun 2021 10:32:40 -0400 Subject: [PATCH 115/130] Adds missing commentary --- .../views/projects/projectView/ProjectComponentEdit.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/moped-editor/src/views/projects/projectView/ProjectComponentEdit.js b/moped-editor/src/views/projects/projectView/ProjectComponentEdit.js index a0e182d206..fc97862419 100644 --- a/moped-editor/src/views/projects/projectView/ProjectComponentEdit.js +++ b/moped-editor/src/views/projects/projectView/ProjectComponentEdit.js @@ -77,7 +77,13 @@ const ProjectComponentEdit = ({ * The State * @type {String} selectedComponentType - A string containing the name of the selected type in lowercase * @type {String} selectedComponentSubtype - A string containing the name of the selected subtype in lowercase - * @type {String[]} selectedComponentSubtype - A string containing all available subtypes for type + * @type {String[]} selectedComponentSubtype - A string list containing all available subtypes for type + * @type {Number[]} selectedSubcomponents - A number array containing the id of the selected subcomponents + * @type {String[]} availableSubtypes - An string list containing all available subtypes for the selected component + * @type {Object[]} editFeatureComponents - An object list containing the features for this component + * @type {Object} editFeatureCollection - The final GeoJson generated for all the the features in this component + * @type {String} componentDescription - The description of this component + * @type {boolean} deleteDialogOpen - If true, it displays the delete dialog, or hides it if false. * @constant */ const [selectedComponentId, setSelectedComponentId] = useState(null); From 0d16d8d7b0585158a22204ae604d4ac73e8d000a Mon Sep 17 00:00:00 2001 From: Sergio Garcia Date: Thu, 24 Jun 2021 11:09:47 -0400 Subject: [PATCH 116/130] Add missing commentary --- .../projects/newProjectView/NewProjectView.js | 55 +++++++++++++++++-- 1 file changed, 50 insertions(+), 5 deletions(-) diff --git a/moped-editor/src/views/projects/newProjectView/NewProjectView.js b/moped-editor/src/views/projects/newProjectView/NewProjectView.js index 190309a9a0..bf4df19bd7 100644 --- a/moped-editor/src/views/projects/newProjectView/NewProjectView.js +++ b/moped-editor/src/views/projects/newProjectView/NewProjectView.js @@ -1,4 +1,4 @@ -import React, { useEffect, useState } from "react"; +import React, {useEffect, useRef, useState} from "react"; import { useNavigate } from "react-router-dom"; import { Button, @@ -76,6 +76,16 @@ const NewProjectView = () => { } }, [success, newProjectId, navigate]); + /** + * Form State + * @type {Number} activeStep - The current step being rendered + * @type {Object} projectDetails - The current state of project details + * @type {boolean} nameError - When true, it denotes an error in the name + * @type {boolean} descriptionError - When true, it denotes an error in the project description + * @type {Object[]} personnel - An array of objects containing the personnel data + * @type {Object} featureCollection - The final GeoJSON to be inserted into a component + * @type {boolean} areNoFeaturesSelected - True when no features are selected + */ const [activeStep, setActiveStep] = useState(0); const [projectDetails, setProjectDetails] = useState({ fiscal_year: "", @@ -89,13 +99,11 @@ const NewProjectView = () => { }); const [nameError, setNameError] = useState(false); const [descriptionError, setDescriptionError] = useState(false); - const [personnel, setPersonnel] = useState([]); const [featureCollection, setFeatureCollection] = useState({ type: "FeatureCollection", features: [], }); - const [areNoFeaturesSelected, setAreNoFeaturesSelected] = useState(false); // Reset areNoFeaturesSelected once a feature is selected to remove error message @@ -107,6 +115,11 @@ const NewProjectView = () => { } }, [featureCollection]); + + /**\ + * Generates an object with labels for the steps + * @return {[{label: string}, {label: string}, {isError: boolean, label: string, error: string}]} + */ const getSteps = () => { return [ { label: "Define project" }, @@ -119,6 +132,11 @@ const NewProjectView = () => { ]; }; + /** + * Returns a component for a specific step number + * @param {Number} step + * @return {JSX.Element|string} + */ const getStepContent = step => { switch (step) { case 0: @@ -145,8 +163,18 @@ const NewProjectView = () => { return "Unknown step"; } }; + + /** + * A constant object with all the steps generated by getSteps + * @constant + * @type {Object} + */ const steps = getSteps(); + /** + * Handles the logic for the "Next" button + * @return {string} + */ const handleNext = () => { let nameError = projectDetails.project_name.length === 0; let descriptionError = projectDetails.project_description.length === 0; @@ -175,6 +203,10 @@ const NewProjectView = () => { setDescriptionError(descriptionError); }; + /** + * Handles the back step button logic + * @return {string} + */ const handleBack = () => { if (activeStep > 0) { setActiveStep(prevActiveStep => prevActiveStep - 1); @@ -189,15 +221,25 @@ const NewProjectView = () => { } }; + /** + * Handles the reset button logic + */ const handleReset = () => { setActiveStep(0); }; + /** + * Add Project Apollo Mutation + */ const [addProject] = useMutation(ADD_PROJECT); - const timer = React.useRef(); + /** + * Timer Reference Object + * @type {React.MutableRefObject} + */ + const timer = useRef(); - React.useEffect(() => { + useEffect(() => { const currentTimer = timer.current; return () => { @@ -205,6 +247,9 @@ const NewProjectView = () => { }; }, []); + /** + * Persists a new project into the database + */ const handleSubmit = () => { if (countFeatures(featureCollection) < mapConfig.minimumFeaturesInProject) { setAreNoFeaturesSelected(true); From 121d3297400523c2b43c1cdc0382e06d78c8afdf Mon Sep 17 00:00:00 2001 From: Sergio Garcia Date: Thu, 24 Jun 2021 11:16:10 -0400 Subject: [PATCH 117/130] More cleanup --- .../src/views/projects/newProjectView/NewProjectView.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/moped-editor/src/views/projects/newProjectView/NewProjectView.js b/moped-editor/src/views/projects/newProjectView/NewProjectView.js index bf4df19bd7..7cd7db7870 100644 --- a/moped-editor/src/views/projects/newProjectView/NewProjectView.js +++ b/moped-editor/src/views/projects/newProjectView/NewProjectView.js @@ -116,9 +116,9 @@ const NewProjectView = () => { }, [featureCollection]); - /**\ + /** * Generates an object with labels for the steps - * @return {[{label: string}, {label: string}, {isError: boolean, label: string, error: string}]} + * @return {Object[]} */ const getSteps = () => { return [ @@ -134,7 +134,7 @@ const NewProjectView = () => { /** * Returns a component for a specific step number - * @param {Number} step + * @param {Number} step - The step number component to render * @return {JSX.Element|string} */ const getStepContent = step => { From df9e272e338b25af2a0744da169cf045b62ad4be Mon Sep 17 00:00:00 2001 From: Sergio Garcia Date: Thu, 24 Jun 2021 13:07:30 -0400 Subject: [PATCH 118/130] Parse the project id into an integer --- .../src/views/projects/projectView/ProjectComponents.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/moped-editor/src/views/projects/projectView/ProjectComponents.js b/moped-editor/src/views/projects/projectView/ProjectComponents.js index 05602bdccb..62286ae076 100644 --- a/moped-editor/src/views/projects/projectView/ProjectComponents.js +++ b/moped-editor/src/views/projects/projectView/ProjectComponents.js @@ -67,7 +67,7 @@ const ProjectComponents = () => { const { error, loading, data, refetch } = useQuery(COMPONENTS_QUERY, { variables: { - projectId, + projectId: Number.parseInt(projectId), }, }); From 5182e2344f060ccd9c655f5c2088529283526603 Mon Sep 17 00:00:00 2001 From: Sergio Garcia Date: Thu, 24 Jun 2021 13:08:10 -0400 Subject: [PATCH 119/130] Implement variablePayload --- .../projects/newProjectView/NewProjectView.js | 52 ++++++++++++++----- 1 file changed, 39 insertions(+), 13 deletions(-) diff --git a/moped-editor/src/views/projects/newProjectView/NewProjectView.js b/moped-editor/src/views/projects/newProjectView/NewProjectView.js index 7cd7db7870..e7a6645741 100644 --- a/moped-editor/src/views/projects/newProjectView/NewProjectView.js +++ b/moped-editor/src/views/projects/newProjectView/NewProjectView.js @@ -1,4 +1,4 @@ -import React, {useEffect, useRef, useState} from "react"; +import React, { useEffect, useRef, useState } from "react"; import { useNavigate } from "react-router-dom"; import { Button, @@ -115,7 +115,6 @@ const NewProjectView = () => { } }, [featureCollection]); - /** * Generates an object with labels for the steps * @return {Object[]} @@ -283,19 +282,46 @@ const NewProjectView = () => { ...filterObjectByKeys(row, ["tableData"]), })); - const projectFeatures = featureCollection.features.map(feature => ({ - location: feature, - status_id: 1, - })); - - addProject({ - variables: { - object: { - ...projectDetails, - moped_proj_features: { data: projectFeatures }, - moped_proj_personnel: { data: cleanedPersonnel }, + /** + * We now must generate the payload with variables for our GraphQL query. + * @type {Object} + */ + const variablePayload = { + object: { + // First we need to copy the project details + ...projectDetails, + // Next we generate the project extent component + moped_proj_components: { + data: [ + { + name: "Extent", + description: "Project full extent", + component_id: 1, + status_id: 1, + moped_proj_features_components: { + data: { + name: "Feature Extent Component", + description: "New Project Feature Extent", + status_id: 1, + moped_proj_feature_object: { + // Here we must copy the entire feature collection + data: { + status_id: 1, + location: featureCollection, + }, + }, + }, + }, + }, + ], }, + // Finally we provide the project personnel + moped_proj_personnel: { data: cleanedPersonnel }, }, + }; + + addProject({ + variables: variablePayload, }) .then(response => { const { project_id } = response.data.insert_moped_project_one; From 78328ba4a1d79e3ea65c3aca916719a29b691de4 Mon Sep 17 00:00:00 2001 From: Sergio Garcia Date: Thu, 24 Jun 2021 13:08:17 -0400 Subject: [PATCH 120/130] Update ADD_PROJECT --- moped-editor/src/queries/project.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/moped-editor/src/queries/project.js b/moped-editor/src/queries/project.js index a085e48384..e3fb72ad29 100644 --- a/moped-editor/src/queries/project.js +++ b/moped-editor/src/queries/project.js @@ -13,6 +13,13 @@ export const ADD_PROJECT = gql` fiscal_year capitally_funded start_date + moped_proj_components{ + moped_proj_features_components { + moped_proj_feature { + feature_id + } + } + } } } `; From ce889e2f86a799eb14155c79c4d6ad78adbb5bbb Mon Sep 17 00:00:00 2001 From: Sergio Garcia Date: Thu, 24 Jun 2021 14:21:14 -0400 Subject: [PATCH 121/130] Refactor variablePayload --- .../src/views/projects/newProjectView/NewProjectView.js | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/moped-editor/src/views/projects/newProjectView/NewProjectView.js b/moped-editor/src/views/projects/newProjectView/NewProjectView.js index e7a6645741..a8b84b1c12 100644 --- a/moped-editor/src/views/projects/newProjectView/NewProjectView.js +++ b/moped-editor/src/views/projects/newProjectView/NewProjectView.js @@ -299,18 +299,17 @@ const NewProjectView = () => { component_id: 1, status_id: 1, moped_proj_features_components: { - data: { + data: featureCollection.features.map(feature => ({ name: "Feature Extent Component", description: "New Project Feature Extent", status_id: 1, moped_proj_feature_object: { - // Here we must copy the entire feature collection data: { status_id: 1, - location: featureCollection, + location: feature, }, }, - }, + })), }, }, ], From 591e716cf1138bd6cb63565aca618847c1293cf5 Mon Sep 17 00:00:00 2001 From: Sergio Garcia Date: Thu, 24 Jun 2021 14:21:40 -0400 Subject: [PATCH 122/130] Add UPDATE_NEW_PROJ_FEATURES --- moped-editor/src/queries/project.js | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/moped-editor/src/queries/project.js b/moped-editor/src/queries/project.js index e3fb72ad29..a722dc69a6 100644 --- a/moped-editor/src/queries/project.js +++ b/moped-editor/src/queries/project.js @@ -13,7 +13,7 @@ export const ADD_PROJECT = gql` fiscal_year capitally_funded start_date - moped_proj_components{ + moped_proj_components { moped_proj_features_components { moped_proj_feature { feature_id @@ -635,3 +635,14 @@ export const DELETE_MOPED_COMPONENT = gql` } } `; + +export const UPDATE_NEW_PROJ_FEATURES = gql` + mutation UpdateNewProjectFeatures($featureList: [Int!]!, $projectId: Int!) { + update_moped_proj_features( + where: { feature_id: { _in: $featureList } } + _set: { project_id: $projectId } + ) { + affected_rows + } + } +`; From 47d0876c92e0e6a74e7533def58c37f63dee7578 Mon Sep 17 00:00:00 2001 From: Sergio Garcia Date: Thu, 24 Jun 2021 14:22:00 -0400 Subject: [PATCH 123/130] Upgrade createFeatureCollectionFromProjectFeatures --- moped-editor/src/utils/mapHelpers.js | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/moped-editor/src/utils/mapHelpers.js b/moped-editor/src/utils/mapHelpers.js index ee978a2283..8f5d7036bd 100644 --- a/moped-editor/src/utils/mapHelpers.js +++ b/moped-editor/src/utils/mapHelpers.js @@ -345,9 +345,23 @@ export const getLayerSource = e => */ export const createFeatureCollectionFromProjectFeatures = projectFeatureRecords => ({ type: "FeatureCollection", - features: projectFeatureRecords - ? projectFeatureRecords.map(feature => feature.location) - : [], + features: projectFeatureRecords // Do we have a records object? + ? // We do, then unpack features + projectFeatureRecords.reduce( + (accumulator, feature) => [ + // First copy the current state of the accumulator + ...accumulator, + // Then we must copy any individual feature (or features) + ...(feature.location.type === "FeatureCollection" + ? // We must unpack the features + feature.location.features + : // Provide the regular feature + [feature.location]), + ], + [] // Initial accumulator state + ) + : // We don't, return empty array + [], }); /** From 2a4b44b11fdd5dd61aa9bb226ecc0ccd957eb35b Mon Sep 17 00:00:00 2001 From: Sergio Garcia Date: Thu, 24 Jun 2021 14:32:30 -0400 Subject: [PATCH 124/130] Implement update features --- .../projects/newProjectView/NewProjectView.js | 36 +++++++++++++++++-- 1 file changed, 33 insertions(+), 3 deletions(-) diff --git a/moped-editor/src/views/projects/newProjectView/NewProjectView.js b/moped-editor/src/views/projects/newProjectView/NewProjectView.js index a8b84b1c12..78dd103a86 100644 --- a/moped-editor/src/views/projects/newProjectView/NewProjectView.js +++ b/moped-editor/src/views/projects/newProjectView/NewProjectView.js @@ -20,7 +20,10 @@ import NewProjectTeam from "./NewProjectTeam"; import NewProjectMap from "./NewProjectMap"; import Page from "src/components/Page"; import { useMutation } from "@apollo/client"; -import { ADD_PROJECT } from "../../../queries/project"; +import { + ADD_PROJECT, + UPDATE_NEW_PROJ_FEATURES, +} from "../../../queries/project"; import { filterObjectByKeys } from "../../../utils/materialTableHelpers"; import { countFeatures, mapErrors, mapConfig } from "../../../utils/mapHelpers"; @@ -231,6 +234,7 @@ const NewProjectView = () => { * Add Project Apollo Mutation */ const [addProject] = useMutation(ADD_PROJECT); + const [updateFeatures] = useMutation(UPDATE_NEW_PROJ_FEATURES); /** * Timer Reference Object @@ -319,13 +323,39 @@ const NewProjectView = () => { }, }; + /** + * Persist the new project to database + */ addProject({ variables: variablePayload, }) + // On success .then(response => { - const { project_id } = response.data.insert_moped_project_one; - setNewProjectId(project_id); + // Destructure the data we need from the response + const { + project_id, + moped_proj_components, + } = response.data.insert_moped_project_one; + + // Retrieve the feature_ids that need to be updated + const featuresToUpdate = moped_proj_components[0].moped_proj_features_components.map( + featureComponent => featureComponent.moped_proj_feature.feature_id + ); + + // Persist the feature updates, we must. + updateFeatures({ + variables: { + featureList: featuresToUpdate, + projectId: project_id, + }, + }) + .then(() => setNewProjectId(project_id)) + .catch(err => { + alert(err); + setNewProjectId(project_id); + }); }) + // If there is an error, we must show it... .catch(err => { alert(err); setLoading(false); From fee2bff9d272649fae213e9fea55d858e57cf8e7 Mon Sep 17 00:00:00 2001 From: Sergio Garcia Date: Thu, 24 Jun 2021 15:08:47 -0400 Subject: [PATCH 125/130] Update COMPONENT_DETAILS_QUERY --- moped-editor/src/queries/project.js | 1 + 1 file changed, 1 insertion(+) diff --git a/moped-editor/src/queries/project.js b/moped-editor/src/queries/project.js index a722dc69a6..7e038c4485 100644 --- a/moped-editor/src/queries/project.js +++ b/moped-editor/src/queries/project.js @@ -550,6 +550,7 @@ export const COMPONENT_DETAILS_QUERY = gql` } moped_proj_features_components(where: { status_id: { _eq: 1 } }) { project_features_components_id + moped_proj_features_id status_id moped_proj_feature { location From 07fb81a42f380b97412710642436765c4cd480ec Mon Sep 17 00:00:00 2001 From: Sergio Garcia Date: Thu, 24 Jun 2021 15:09:11 -0400 Subject: [PATCH 126/130] Incorporate feature_id in feature upserts --- .../projects/projectView/ProjectComponentEdit.js | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/moped-editor/src/views/projects/projectView/ProjectComponentEdit.js b/moped-editor/src/views/projects/projectView/ProjectComponentEdit.js index fc97862419..2e32bc81c6 100644 --- a/moped-editor/src/views/projects/projectView/ProjectComponentEdit.js +++ b/moped-editor/src/views/projects/projectView/ProjectComponentEdit.js @@ -299,6 +299,7 @@ const ProjectComponentEdit = ({ ) .map(record => ({ ...record, + feature_id: record.properties.moped_proj_feature_id, status_id: 0, })) : []; // if this is a new component, there are no old records to update @@ -396,6 +397,9 @@ const ProjectComponentEdit = ({ }, // This inserts into moped_proj_features, and assumes relationship with moped_proj_features_components data: { + ...(feature.hasOwnProperty("feature_id") + ? { feature_id: feature.feature_id } + : {}), project_id: Number.parseInt(projectId), location: { ...feature }, status_id: feature.status_id, @@ -592,13 +596,17 @@ const ProjectComponentEdit = ({ data?.moped_proj_components[0]?.moped_proj_features_components ?? [] ).map(featureComponent => { // Retrieve the feature component's primary key - const featureCompId = featureComponent.project_features_components_id; + const { + moped_proj_features_id, + project_features_components_id, + } = featureComponent; // Clone the geojson data from the feature component const newGeoJson = { ...featureComponent.moped_proj_feature.location, }; // Now go ahead and patch the primary key into the GeoJson properties - newGeoJson.properties.project_features_components_id = featureCompId; + newGeoJson.properties.project_features_components_id = project_features_components_id; + newGeoJson.properties.moped_proj_feature_id = moped_proj_features_id; return newGeoJson; }); From 6ff5a3eb4460c1b3b8858b2ed56e21f015eaa1f5 Mon Sep 17 00:00:00 2001 From: Sergio Garcia Date: Thu, 24 Jun 2021 16:23:45 -0400 Subject: [PATCH 127/130] Create Project Extent Component --- .../down.sql | 2 ++ .../up.sql | 4 ++++ 2 files changed, 6 insertions(+) create mode 100644 moped-database/migrations/1624565634524_update_table_moped_components_add_generic_component/down.sql create mode 100644 moped-database/migrations/1624565634524_update_table_moped_components_add_generic_component/up.sql diff --git a/moped-database/migrations/1624565634524_update_table_moped_components_add_generic_component/down.sql b/moped-database/migrations/1624565634524_update_table_moped_components_add_generic_component/down.sql new file mode 100644 index 0000000000..2e3793e741 --- /dev/null +++ b/moped-database/migrations/1624565634524_update_table_moped_components_add_generic_component/down.sql @@ -0,0 +1,2 @@ +/* Delete extent project component */ +DELETE FROM public.moped_components WHERE component_id = 0; diff --git a/moped-database/migrations/1624565634524_update_table_moped_components_add_generic_component/up.sql b/moped-database/migrations/1624565634524_update_table_moped_components_add_generic_component/up.sql new file mode 100644 index 0000000000..cf0d9777b0 --- /dev/null +++ b/moped-database/migrations/1624565634524_update_table_moped_components_add_generic_component/up.sql @@ -0,0 +1,4 @@ +/* Adds the project extent component or generic type */ +INSERT INTO + public.moped_components (component_id, component_name, status_id, component_subtype, line_representation) + VALUES (0, 'Project Extent - Generic', 1, null, false); From 70e6921cf014c517237003ef797762751bfc35bb Mon Sep 17 00:00:00 2001 From: Sergio Garcia Date: Thu, 24 Jun 2021 16:23:53 -0400 Subject: [PATCH 128/130] Use project extent category --- .../src/views/projects/newProjectView/NewProjectView.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/moped-editor/src/views/projects/newProjectView/NewProjectView.js b/moped-editor/src/views/projects/newProjectView/NewProjectView.js index 78dd103a86..8d4a771597 100644 --- a/moped-editor/src/views/projects/newProjectView/NewProjectView.js +++ b/moped-editor/src/views/projects/newProjectView/NewProjectView.js @@ -300,7 +300,7 @@ const NewProjectView = () => { { name: "Extent", description: "Project full extent", - component_id: 1, + component_id: 0, status_id: 1, moped_proj_features_components: { data: featureCollection.features.map(feature => ({ From a8ca4178c1f02af508d05f72162e8e0c442dd39a Mon Sep 17 00:00:00 2001 From: Sergio Garcia Date: Fri, 25 Jun 2021 15:39:25 -0400 Subject: [PATCH 129/130] Added more commentary where missing --- .../projectView/ProjectComponentEdit.js | 85 +++++++++++++------ 1 file changed, 61 insertions(+), 24 deletions(-) diff --git a/moped-editor/src/views/projects/projectView/ProjectComponentEdit.js b/moped-editor/src/views/projects/projectView/ProjectComponentEdit.js index 2e32bc81c6..5ae6481d6b 100644 --- a/moped-editor/src/views/projects/projectView/ProjectComponentEdit.js +++ b/moped-editor/src/views/projects/projectView/ProjectComponentEdit.js @@ -119,29 +119,51 @@ const ProjectComponentEdit = ({ /** * Generates an initial list of component types, subtypes and counts */ - const initialTypeCounts = data - ? data.moped_components.reduce((accumulator, component, index) => { + const initialTypeCounts = data // Do we have data? + ? // Yes, let's get the counts by using reduce + data.moped_components.reduce((accumulator, component, index) => { + // Retrieve the current component's values, in lower case const componentId = component?.component_id ?? null; const componentName = (component?.component_name ?? "").toLowerCase(); const componentSubtype = ( component?.component_subtype ?? "" ).toLowerCase(); + // Then, retrieve the subcomponents associated to this component_id by filtering const componentSubcomponents = data.moped_subcomponents.filter( subcomponent => subcomponent.component_id === componentId ); - // Get the total count + // Get the total count for this component name const currentCount = accumulator[componentName]?.count ?? 0; + // Send back to the accumulator a copy of itself plus new data: return { + // Here is the copy of the current state of the output: ...accumulator, + // And for new data, create (or overwrite) a new key with the component name [componentName]: { - count: currentCount + 1, + count: currentCount + 1, // Assign count to currentCount + 1 + /** + * If currentCount is zero, it means this is the first iteration of reduce + * for this componentName, which means this should be considered a single item + * and we need to give it its component_id. + * + * Otherwise, this is another iteration (n+1) for this componentName, which means + * componentName is a group. Let's give it an id of zero as a lazy way to categorize + * and differentiate groups from single items. + */ component_id: currentCount > 1 ? 0 : componentId, + // Provide Index for context index: index, + // Initialize a subtypes key with an object containing componentSubtype information. subtypes: { + // Copy the current state of the accumulator's subtypes ...(accumulator[componentName]?.subtypes ?? {}), + /** + * Create (or overwrite) a new subtype by the name of componentSubtype, + * containing all the data of this component iteration. + */ [componentSubtype]: { component_id: componentId, component_name: component?.component_name ?? null, @@ -156,17 +178,24 @@ const ProjectComponentEdit = ({ // Now check if we have any subcomponents in the DB const subcomponentsDB = + /** + * Get moped_proj_components or assume empty array, if the array is empty it means + * the user has not selected a component; which should never be the case. Do we have + * a selected component? (is the count greater than zero?) + */ (data?.moped_proj_components ?? []).length > 0 - ? data.moped_proj_components[0].moped_proj_components_subcomponents.map( + ? // Yes, we have project a component, now gather a list of subcomponents for that component + data.moped_proj_components[0].moped_proj_components_subcomponents.map( subcomponent => ({ ...subcomponent.moped_subcomponent, component_subcomponent_id: subcomponent.component_subcomponent_id, }) ) - : []; + : // Nothing to do here, no valid component is selected. + []; /** - * This is a constant list containing the names of available types + * This is a unique sorted list containing the names of available components * @type {String[]} */ const availableTypes = data @@ -185,9 +214,11 @@ const ProjectComponentEdit = ({ * @return {String[]} - A string array with the available subtypes */ const getAvailableSubtypes = type => + // For every subtype found in initialTypeCounts[type] Object.entries(initialTypeCounts[type]?.subtypes ?? {}) + // Destructure the key and value (_ & component, respectively) and gather the name .map(([_, component]) => (component?.component_subtype ?? "").trim()) - .filter(item => item.length > 0); + .filter(item => item.length > 0); // Keep only if the name is not empty /** * Returns any available subcomponent objects for a specific type @@ -246,14 +277,16 @@ const ProjectComponentEdit = ({ ); /** - * Retrieves the component_id based no the type and subtype names + * Retrieves the component_id based on the type and subtype names * @param {string} type - The type name * @param {string} subtype - The subtype name */ const getSelectedComponentId = (type, subtype) => - initialTypeCounts[type].count > 1 - ? initialTypeCounts[type].subtypes[subtype ?? ""]?.component_id ?? null - : initialTypeCounts[type]?.component_id ?? null; + initialTypeCounts[type].count > 1 // Is it a group? + ? // Yes, we need to look for the subtype's component_id + initialTypeCounts[type].subtypes[subtype ?? ""]?.component_id ?? null + : // No, then it's safe to get the component_id from the parent + initialTypeCounts[type]?.component_id ?? null; /** * Returns true if the given type needs a subtype @@ -336,18 +369,22 @@ const ProjectComponentEdit = ({ ); // Generate output, clean up & return - return [...insertionList, ...removalList] - .map(subcomponent => ({ - ...subcomponent, - status_id: isNaN(subcomponent?.component_subcomponent_id) ? 1 : 0, - })) - .map(record => - filterObjectByKeys(record, [ - "__typename", - "component_id", - "subcomponent_name", - ]) - ); + return ( + [...insertionList, ...removalList] // Mix both insertion and removal list + // For each subcomponent, mark for deletion (status_id = 0) if component_subcomponent_id has a number + .map(subcomponent => ({ + ...subcomponent, + status_id: isNaN(subcomponent?.component_subcomponent_id) ? 1 : 0, + })) + // Then remove certain objects by their key names from the output + .map(record => + filterObjectByKeys(record, [ + "__typename", + "component_id", + "subcomponent_name", + ]) + ) + ); }; /** From 70a7dd1909f4788b806d70b156bbd244cb61eea5 Mon Sep 17 00:00:00 2001 From: Sergio Garcia Date: Fri, 25 Jun 2021 16:13:12 -0400 Subject: [PATCH 130/130] Update migration to add more components --- .../down.sql | 4 ++ .../up.sql | 44 ++++++++++++++++++- 2 files changed, 47 insertions(+), 1 deletion(-) diff --git a/moped-database/migrations/1624565634524_update_table_moped_components_add_generic_component/down.sql b/moped-database/migrations/1624565634524_update_table_moped_components_add_generic_component/down.sql index 2e3793e741..a60962038d 100644 --- a/moped-database/migrations/1624565634524_update_table_moped_components_add_generic_component/down.sql +++ b/moped-database/migrations/1624565634524_update_table_moped_components_add_generic_component/down.sql @@ -1,2 +1,6 @@ /* Delete extent project component */ DELETE FROM public.moped_components WHERE component_id = 0; + +/* Then delete the rest of the components in the migration */ +DELETE FROM public.moped_components + WHERE component_id >= 19 AND component_id <= 59; diff --git a/moped-database/migrations/1624565634524_update_table_moped_components_add_generic_component/up.sql b/moped-database/migrations/1624565634524_update_table_moped_components_add_generic_component/up.sql index cf0d9777b0..9d4e6c9709 100644 --- a/moped-database/migrations/1624565634524_update_table_moped_components_add_generic_component/up.sql +++ b/moped-database/migrations/1624565634524_update_table_moped_components_add_generic_component/up.sql @@ -1,4 +1,46 @@ /* Adds the project extent component or generic type */ INSERT INTO public.moped_components (component_id, component_name, status_id, component_subtype, line_representation) - VALUES (0, 'Project Extent - Generic', 1, null, false); + VALUES + (19, 'Bike Parking', 1, null, false), + (20, 'Bike Parking', 1, 'Corral', false), + (21, 'Bike Lane', 1, 'Turn Lane', true), + (22, 'Bike Lane', 1, 'Wide Curb Lane', true), + (23, 'Pavement Marking', 1, 'Crossbike', false), + (24, 'Access Control', 1, 'Driveway Gate', false), + (25, 'Dynamic Speed Display Device', 1, null, false), + (26, 'Guardrail', 1, null, true), + (27, 'Highway', 1, 'Access Ramp', false), + (28, 'Highway', 1, 'Added Capacity / Lanes', true), + (29, 'Highway', 1, 'Collector Distributor', true), + (30, 'Highway', 1, 'Flyover', true), + (31, 'Highway', 1, 'Intersection Grade Separation', true), + (32, 'Highway', 1, 'Managed Lane', true), + (33, 'Highway', 1, 'Toll Road', true), + (34, 'Landscaping', 1, null, true), + (35, 'Placemaking', 1, null, true), + (36, 'Refuge Island', 1, 'Bike', false), + (37, 'Refuge Island', 1, 'Ped', false), + (38, 'Refuge Island', 1, 'Bike/Ped', false), + (39, 'Signal', 1, 'School Zone Beacon', false), + (40, 'Pavement Marking', 1, 'School Zone', false), + (41, 'Sidewalk', 1, null, true), + (42, 'Sidewalk', 1, 'In Street', true), + (43, 'Sidewalk', 1, 'Wide', true), + (44, 'Sidewalk', 1, 'With Curb and Gutter', true), + (45, 'Sidewalk', 1, 'Rams', true), + (46, 'Speed Management', 1, 'Chicane', false), + (47, 'Speed Management', 1, 'Nbhd Traffic Circle', false), + (48, 'Speed Management', 1, 'Speed Cushions (Asphalt)', false), + (49, 'Speed Management', 1, 'Speed Cushions (Rubber)', false), + (50, 'Speed Management', 1, 'Speed Humps', false), + (51, 'Pavement Marking', 1, 'Stop Bar', false), + (52, 'Transit', 1, 'Lane', true), + (53, 'Transit', 1, 'Managed Lane Access Point', true), + (54, 'Transit', 1, 'Transit Queue Jump', true), + (55, 'Transit', 1, 'Transit/Bike Lane', true), + (56, 'Pavement Marking', 1, 'Two-stage Bike Turn Queue', false), + (57, 'Pavement Marking', 1, 'Sharrows', false), + (58, 'Pavement Marking', 1, 'Sharrows (Wide Curb Lane)', false), + (59, 'Signage', 1, null, false), + (0, 'Project Extent - Generic', 1, null, false);