-
-
Notifications
You must be signed in to change notification settings - Fork 53
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: mark tasks validated + start conflation UI (#1743)
* fix(dialogTaskActions): on lock task for validation, redirect to submission table with filtered taskId * fix(projectTaskStatus): syle, existingData, feature prop optional * fix(projectDetails): reorder updateTaskStatus arguments * fix(submissionTable): btn add to update task as mapped * fix(dialogTaskActions): if validated show merge with OSM btn & redirect to conflation page on click * fix(dataConflation): data conflation component and route setup * feat(taskInfo): conflation task section slicing * feat(conflationMap): map & legend setup * fix(button): outline remove from button * feat(dataConflation): merge OSM modal, taskInfo, conflationMap section add * fix(taskInfo): style fix * feat(dataConflation): submissionConflation component add, UI style fix * feat(submissionConflation): component UI slicing * fix(modal): show dialogTrigger only if dialogOpen prop present * fix(dataConflation): UI fix * feat(mergeAttributes): UI slicing for merge attributes modal * feat(submissionConflation): add mergeAttributes component * fix(customTable): remove hover effect & add row bg distinguishable * feat(dataConflation): skeleton loader add * fix(mergeAttributes): preventDefault and stopPropagation add to onClick event * feat(dataConflation): store, slice add * feat(dataConflation): submissionConflationGeojson service add * feat(dataConflation): submissionConflationGeojson service fetch * fix(dataConflation): UI style fix * feat(conflationMap): display submissionConflation on map * feat(conflationMap): on map feature click dispatch action to set selectedFeatureOSMId * feat(submissionConflation): replace actual data with dummy data * feat(mergeAttributes): replace dummy data with actual data * feat(dataConflation): setSelectedFeatureOSMId action add * fix(dataConflation): UI style fix according to feature click * fix(conflationMap): update accessor key * fix(dataConflation): style fix * fix(submissionConflation): remove commented code * feat(taskInfo): task feature, conflict counts calculation * fix(dataConflation): remove modal * fix(dataConflation): loading state add * fix(mergeAttributes): title add, hover effects add * fix(updateTaskStatus): update prop type * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * fix(submissionsTable): replace empty string with null * fix(dialogTaskActions): hide merge data with OSM button --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
- Loading branch information
1 parent
e6c465c
commit 9729f53
Showing
19 changed files
with
749 additions
and
67 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
import axios from 'axios'; | ||
import { DataConflationActions } from '@/store/slices/DataConflationSlice'; | ||
|
||
export const SubmissionConflationGeojsonService: Function = (url: string) => { | ||
return async (dispatch) => { | ||
const getSubmissionGeojsonConflation = async (url) => { | ||
try { | ||
dispatch(DataConflationActions.SetSubmissionConflationGeojsonLoading(true)); | ||
const getSubmissionConflationGeojsonResponse = await axios.get(url); | ||
dispatch(DataConflationActions.SetSubmissionConflationGeojson(getSubmissionConflationGeojsonResponse.data)); | ||
dispatch(DataConflationActions.SetSubmissionConflationGeojsonLoading(false)); | ||
} catch (error) { | ||
dispatch(DataConflationActions.SetSubmissionConflationGeojsonLoading(false)); | ||
} | ||
}; | ||
|
||
await getSubmissionGeojsonConflation(url); | ||
}; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
52 changes: 52 additions & 0 deletions
52
src/frontend/src/components/DataConflation/ConflationMap/MapLegend.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
import React from 'react'; | ||
import Accordion from '@/components/common/Accordion'; | ||
import useOutsideClick from '@/hooks/useOutsideClick'; | ||
|
||
const legendArray = [ | ||
{ name: 'No conflicts', color: '#40AC8C' }, | ||
{ name: 'Tag conflicts', color: '#DB9D35' }, | ||
{ name: 'Geometry conflicts', color: '#3C4A5E' }, | ||
{ name: 'Both conflicts', color: '#EB8B8B' }, | ||
]; | ||
|
||
const MapLegends = () => { | ||
return ( | ||
<div className="fmtm-flex fmtm-flex-col fmtm-gap-1 fmtm-pb-2"> | ||
{legendArray?.map((legend) => ( | ||
<div className="fmtm-flex fmtm-items-center fmtm-gap-2"> | ||
<div | ||
style={{ backgroundColor: legend.color }} | ||
className={`fmtm-w-[0.875rem] fmtm-h-[0.875rem] fmtm-min-w-[0.875rem] fmtm-min-h-[0.875rem]`} | ||
></div> | ||
<p className="fmtm-text-xs fmtm-text-[#484848]">{legend.name}</p> | ||
</div> | ||
))} | ||
</div> | ||
); | ||
}; | ||
|
||
const MapLegend = () => { | ||
const [legendRef, legendToggle, handleLegendToggle] = useOutsideClick(); | ||
|
||
return ( | ||
<> | ||
<Accordion | ||
hasSeperator={false} | ||
ref={legendRef} | ||
body={<MapLegends />} | ||
header={ | ||
<div className="fmtm-flex fmtm-items-center fmtm-gap-1 sm:fmtm-gap-2"> | ||
<p className="fmtm-text-base fmtm-font-bold">Legend</p> | ||
</div> | ||
} | ||
onToggle={() => { | ||
handleLegendToggle(); | ||
}} | ||
className="fmtm-py-0 !fmtm-pb-0 fmtm-rounded-lg hover:fmtm-bg-gray-50" | ||
collapsed={!legendToggle} | ||
/> | ||
</> | ||
); | ||
}; | ||
|
||
export default MapLegend; |
68 changes: 68 additions & 0 deletions
68
src/frontend/src/components/DataConflation/ConflationMap/index.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
import React from 'react'; | ||
import { MapContainer as MapComponent, useOLMap } from '@/components/MapComponent/OpenLayersComponent'; | ||
import LayerSwitcherControl from '@/components/MapComponent/OpenLayersComponent/LayerSwitcher/index'; | ||
import MapLegend from '@/components/DataConflation/ConflationMap/MapLegend'; | ||
import Button from '@/components/common/Button'; | ||
import { useAppSelector } from '@/types/reduxTypes'; | ||
import { VectorLayer } from '@/components/MapComponent/OpenLayersComponent/Layers'; | ||
import { useDispatch } from 'react-redux'; | ||
import { DataConflationActions } from '@/store/slices/DataConflationSlice'; | ||
|
||
const ConflationMap = () => { | ||
const dispatch = useDispatch(); | ||
|
||
const submissionConflationGeojson = useAppSelector((state) => state.dataconflation.submissionConflationGeojson); | ||
const submissionConflationGeojsonLoading = useAppSelector( | ||
(state) => state.dataconflation.submissionConflationGeojsonLoading, | ||
); | ||
|
||
const { mapRef, map } = useOLMap({ | ||
center: [0, 0], | ||
zoom: 4, | ||
}); | ||
|
||
return ( | ||
<> | ||
<MapComponent | ||
ref={mapRef} | ||
mapInstance={map} | ||
className="map naxatw-relative naxatw-min-h-full !fmtm-h-full fmtm-w-[200px] fmtm-rounded-lg fmtm-overflow-hidden" | ||
> | ||
<VectorLayer | ||
geojson={submissionConflationGeojson} | ||
viewProperties={{ | ||
size: map?.getSize(), | ||
padding: [50, 50, 50, 50], | ||
constrainResolution: true, | ||
duration: 2000, | ||
}} | ||
zoomToLayer | ||
mapOnClick={(properties, feature) => { | ||
dispatch( | ||
DataConflationActions.SetSelectedFeatureOSMId( | ||
feature?.getProperties()?.xid | ||
? feature.getProperties().xid | ||
: feature.getProperties()?.osm_id.toString(), | ||
), | ||
); | ||
}} | ||
/> | ||
<LayerSwitcherControl visible="osm" /> | ||
<div className="fmtm-absolute fmtm-bottom-20 sm:fmtm-bottom-3 fmtm-left-3 fmtm-z-50 fmtm-rounded-lg"> | ||
<MapLegend /> | ||
</div> | ||
<div className="fmtm-absolute fmtm-bottom-20 sm:fmtm-top-3 fmtm-right-3 fmtm-z-50 fmtm-rounded-lg fmtm-h-fit"> | ||
<Button | ||
btnText="Upload to OSM" | ||
type="button" | ||
btnType="primary" | ||
onClick={() => {}} | ||
disabled={submissionConflationGeojsonLoading} | ||
/> | ||
</div> | ||
</MapComponent> | ||
</> | ||
); | ||
}; | ||
|
||
export default ConflationMap; |
145 changes: 145 additions & 0 deletions
145
src/frontend/src/components/DataConflation/SubmissionConflation/MergeAttributes.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,145 @@ | ||
import React, { useState } from 'react'; | ||
import { Modal } from '@/components/common/Modal'; | ||
import Button from '@/components/common/Button'; | ||
import Table, { TableHeader } from '@/components/common/CustomTable'; | ||
|
||
type mergeAttributesPropType = { | ||
selectedConflateMethod: 'submission_feature' | 'osm_feature' | 'merge_attributes' | ''; | ||
setSelectedConflateMethod: (value: '') => void; | ||
submissionTags: Record<string, any>; | ||
osmTags: Record<string, any>; | ||
}; | ||
|
||
const MergeAttributes = ({ | ||
selectedConflateMethod, | ||
setSelectedConflateMethod, | ||
submissionTags, | ||
osmTags, | ||
}: mergeAttributesPropType) => { | ||
const [chosenAttribute, setChosenAttribute] = useState({}); | ||
|
||
const tableData: any = []; | ||
for (const [key, value] of Object.entries(osmTags)) { | ||
if (submissionTags?.[key] && submissionTags?.[key] !== value) { | ||
tableData.push({ name: key, osm: value, submission: submissionTags?.[key] }); | ||
} | ||
} | ||
|
||
return ( | ||
<> | ||
<Modal | ||
title={<p className="fmtm-text-left">Merge Data With OSM</p>} | ||
description={ | ||
<div className="fmtm-mt-1"> | ||
<div> | ||
<Table | ||
flag="primarytable" | ||
style={{ maxHeight: '60vh', width: '100%' }} | ||
data={tableData} | ||
onRowClick={() => {}} | ||
isLoading={false} | ||
> | ||
<TableHeader | ||
dataField="Feature Name" | ||
headerClassName="featureHeader" | ||
rowClassName="featureRow" | ||
dataFormat={(row) => <div title={row?.name}>{row?.name}</div>} | ||
/> | ||
<TableHeader | ||
dataField="OSM Tags" | ||
headerClassName="osmHeader" | ||
rowClassName="osmRow !fmtm-p-0" | ||
dataFormat={(row) => ( | ||
<div | ||
className={`fmtm-flex fmtm-items-center fmtm-justify-between !fmtm-h-full fmtm-absolute fmtm-top-0 fmtm-left-0 fmtm-w-full fmtm-p-3 ${ | ||
chosenAttribute[row?.name] === row?.osm | ||
? 'fmtm-bg-[#9FD5C5]' | ||
: 'hover:fmtm-bg-gray-100 fmtm-duration-200' | ||
}`} | ||
onClick={(e) => { | ||
e.preventDefault(); | ||
e.stopPropagation(); | ||
setChosenAttribute((prev) => ({ ...prev, [row?.name]: row?.osm })); | ||
}} | ||
title={row?.osm} | ||
> | ||
<label | ||
htmlFor={row?.name} | ||
className={`fmtm-text-base ${ | ||
chosenAttribute[row?.name] === row?.osm ? 'fmtm-text-white' : 'fmtm-text-gray-500' | ||
} fmtm-mb-[2px] fmtm-cursor-pointer fmtm-flex fmtm-items-center fmtm-gap-2`} | ||
> | ||
<p>{row?.osm}</p> | ||
</label> | ||
<input | ||
type="radio" | ||
id={row?.name} | ||
name={row?.name} | ||
value={row?.osm} | ||
className={`fmtm-accent-[#5BAD8C] fmtm-cursor-pointer fmtm-bg-white`} | ||
checked={chosenAttribute[row?.name] === row?.osm} | ||
/> | ||
</div> | ||
)} | ||
/> | ||
<TableHeader | ||
dataField="Submission #457" | ||
headerClassName="submissionHeader" | ||
rowClassName="submissionRow !fmtm-p-0" | ||
dataFormat={(row) => ( | ||
<div | ||
className={`fmtm-flex fmtm-items-center fmtm-justify-between !fmtm-h-full fmtm-absolute fmtm-top-0 fmtm-left-0 fmtm-w-full fmtm-p-3 ${ | ||
chosenAttribute[row?.name] === row?.submission | ||
? 'fmtm-bg-[#9FD5C5]' | ||
: 'hover:fmtm-bg-gray-100 fmtm-duration-200' | ||
}`} | ||
onClick={(e) => { | ||
e.preventDefault(); | ||
e.stopPropagation(); | ||
setChosenAttribute((prev) => ({ ...prev, [row?.name]: row?.submission })); | ||
}} | ||
title={row?.submission} | ||
> | ||
<label | ||
htmlFor={row?.name} | ||
className={`fmtm-text-base ${ | ||
chosenAttribute[row?.name] === row?.submission ? 'fmtm-text-white' : 'fmtm-text-gray-500' | ||
} fmtm-mb-[2px] fmtm-cursor-pointer fmtm-flex fmtm-items-center fmtm-gap-2`} | ||
> | ||
<p>{row?.submission}</p> | ||
</label> | ||
<input | ||
type="radio" | ||
id={row?.name} | ||
name={row?.name} | ||
value={row?.submission} | ||
className={`fmtm-accent-[#5BAD8C] fmtm-cursor-pointer`} | ||
checked={chosenAttribute[row?.name] === row?.submission} | ||
/> | ||
</div> | ||
)} | ||
/> | ||
</Table> | ||
</div> | ||
<div className="fmtm-flex fmtm-gap-[0.625rem] fmtm-justify-center fmtm-mt-5"> | ||
<Button | ||
btnText="Save" | ||
btnType="primary" | ||
onClick={() => { | ||
setSelectedConflateMethod(''); | ||
}} | ||
type="button" | ||
className="!fmtm-rounded fmtm-text-sm !fmtm-py-2 fmtm-font-bold" | ||
/> | ||
</div> | ||
</div> | ||
} | ||
open={selectedConflateMethod === 'merge_attributes'} | ||
onOpenChange={() => setSelectedConflateMethod('')} | ||
className="fmtm-max-w-[70rem] fmtm-rounded-xl" | ||
/> | ||
</> | ||
); | ||
}; | ||
|
||
export default MergeAttributes; |
Oops, something went wrong.