Skip to content

Commit

Permalink
refactor(mapper): relocate entity sync button (#2100)
Browse files Browse the repository at this point in the history
* fix(dialog-entities-actions): remove sync status button from dialog

* feat(main): add sync button on bottom right

* fix(legend/layer-switcher): update stylings

* feat(project): SyncTaskState action add

* feat(projectDetailsV2): sync task status on sync button click as well
  • Loading branch information
NSUWAL123 authored Jan 22, 2025
1 parent 2a81bdf commit 3fd3665
Show file tree
Hide file tree
Showing 8 changed files with 97 additions and 28 deletions.
43 changes: 43 additions & 0 deletions src/frontend/src/api/Project.ts
Original file line number Diff line number Diff line change
Expand Up @@ -372,3 +372,46 @@ export const GetGeometryLog = (url: string) => {
await getProjectActivity(url);
};
};

export const SyncTaskState = (
url: string,
params: { project_id: string },
taskBoundaryFeatures: any,
geojsonStyles: any,
) => {
return async (dispatch: AppDispatch) => {
const syncTaskState = async () => {
try {
dispatch(ProjectActions.SyncTaskStateLoading(true));
const response: AxiosResponse = await axios.get(url, { params });

response.data.map((task) => {
const feature = taskBoundaryFeatures?.find((feature) => feature.getId() === task.id);
const previousProperties = feature.getProperties();
feature.setProperties({
...previousProperties,
task_state: task.task_state,
actioned_by_uid: task.actioned_by_uid,
actioned_by_username: task.actioned_by_username,
});

feature.setStyle(geojsonStyles[task.task_state]);

dispatch(
ProjectActions.UpdateProjectTaskBoundries({
projectId: params.project_id,
taskId: task.id,
actioned_by_uid: task.actioned_by_uid,
actioned_by_username: task.actioned_by_username,
task_state: task.task_state,
}),
);
});
} catch (error) {
} finally {
dispatch(ProjectActions.SyncTaskStateLoading(false));
}
};
await syncTaskState();
};
};
4 changes: 4 additions & 0 deletions src/frontend/src/store/slices/ProjectSlice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ const initialState: ProjectStateTypes = {
newGeomFeatureCollection: { type: 'FeatureCollection', features: [] },
badGeomLogList: [],
getGeomLogLoading: false,
syncTaskStateLoading: false,
};

const ProjectSlice = createSlice({
Expand Down Expand Up @@ -170,6 +171,9 @@ const ProjectSlice = createSlice({
SetGeometryLogLoading(state, action: PayloadAction<boolean>) {
state.getGeomLogLoading = action.payload;
},
SyncTaskStateLoading(state, action: PayloadAction<boolean>) {
state.syncTaskStateLoading = action.payload;
},
},
});

Expand Down
1 change: 1 addition & 0 deletions src/frontend/src/store/types/IProject.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ export type ProjectStateTypes = {
newGeomFeatureCollection: FeatureCollectionType;
badGeomLogList: geometryLogResponseType[];
getGeomLogLoading: boolean;
syncTaskStateLoading: boolean;
};

type projectCommentsListTypes = {
Expand Down
32 changes: 28 additions & 4 deletions src/frontend/src/views/ProjectDetailsV2.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import '../../node_modules/ol/ol.css';
import '../styles/home.scss';
import WindowDimension from '@/hooks/WindowDimension';
import ActivitiesPanel from '@/components/ProjectDetailsV2/ActivitiesPanel';
import { ProjectById, GetEntityStatusList, GetGeometryLog } from '@/api/Project';
import { ProjectById, GetEntityStatusList, GetGeometryLog, SyncTaskState } from '@/api/Project';
import { ProjectActions } from '@/store/slices/ProjectSlice';
import CustomizedSnackbar from '@/utilities/CustomizedSnackbar';
import { HomeActions } from '@/store/slices/HomeSlice';
Expand Down Expand Up @@ -36,6 +36,7 @@ import { Geolocation } from '@/utilfunctions/Geolocation';
import Instructions from '@/components/ProjectDetailsV2/Instructions';
import useDocumentTitle from '@/utilfunctions/useDocumentTitle';
import { Style, Stroke } from 'ol/style';
import MapStyles from '@/hooks/MapStyles';

const ProjectDetailsV2 = () => {
useDocumentTitle('Project Details');
Expand All @@ -45,6 +46,8 @@ const ProjectDetailsV2 = () => {
const { windowSize } = WindowDimension();
const [divRef, toggle, handleToggle] = useOutsideClick();

const geojsonStyles = MapStyles();

const [selectedTaskArea, setSelectedTaskArea] = useState<Record<string, any> | null>(null);
const [selectedTaskFeature, setSelectedTaskFeature] = useState();
const [dataExtractUrl, setDataExtractUrl] = useState<string | undefined>();
Expand All @@ -69,6 +72,7 @@ const ProjectDetailsV2 = () => {
const entityOsmMapLoading = useAppSelector((state) => state?.project?.entityOsmMapLoading);
const badGeomFeatureCollection = useAppSelector((state) => state?.project?.badGeomFeatureCollection);
const getGeomLogLoading = useAppSelector((state) => state?.project?.getGeomLogLoading);
const syncTaskStateLoading = useAppSelector((state) => state?.project?.syncTaskStateLoading);

useEffect(() => {
if (state.projectInfo.name) {
Expand Down Expand Up @@ -259,6 +263,24 @@ const ProjectDetailsV2 = () => {
dispatch(GetGeometryLog(`${import.meta.env.VITE_API_URL}/projects/${projectId}/geometry/records`));
};

const syncTaskState = () => {
const taskBoundaryLayer = map
.getLayers()
.getArray()
.find((layer: any) => layer.get('name') == 'project-area');
const taskBoundaryFeatures = taskBoundaryLayer.getSource().getFeatures();

projectId &&
dispatch(
SyncTaskState(
`${import.meta.env.VITE_API_URL}/tasks`,
{ project_id: projectId },
taskBoundaryFeatures,
geojsonStyles,
),
);
};

useEffect(() => {
getEntityStatusList();
getGeometryLog();
Expand Down Expand Up @@ -299,6 +321,7 @@ const ProjectDetailsV2 = () => {
const syncStatus = () => {
getEntityStatusList();
getGeometryLog();
syncTaskState();
};

return (
Expand Down Expand Up @@ -462,7 +485,6 @@ const ProjectDetailsV2 = () => {
size: map?.getSize(),
padding: [50, 50, 50, 50],
constrainResolution: true,
duration: 2000,
}}
layerProperties={{ name: 'project-area' }}
mapOnClick={projectClickOnTaskArea}
Expand Down Expand Up @@ -532,14 +554,16 @@ const ProjectDetailsV2 = () => {
<Button
btnText="SYNC STATUS"
icon={
<AssetModules.SyncIcon className={`!fmtm-text-xl ${entityOsmMapLoading && 'fmtm-animate-spin'}`} />
<AssetModules.SyncIcon
className={`!fmtm-text-xl ${(entityOsmMapLoading || getGeomLogLoading || syncTaskStateLoading) && 'fmtm-animate-spin'}`}
/>
}
onClick={() => {
if (entityOsmMapLoading) return;
syncStatus();
}}
btnType="other"
className={`!fmtm-text-sm !fmtm-pr-2 fmtm-bg-white ${entityOsmMapLoading && 'fmtm-cursor-not-allowed'}`}
className={`!fmtm-text-sm !fmtm-pr-2 fmtm-bg-white ${(entityOsmMapLoading || getGeomLogLoading || syncTaskStateLoading) && 'fmtm-cursor-not-allowed'}`}
/>
</div>
<MapControlComponent
Expand Down
20 changes: 0 additions & 20 deletions src/mapper/src/lib/components/dialog-entities-actions.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -136,26 +136,6 @@
<div class="flex flex-col gap-4">
<div class="flex items-center justify-between">
<p class="text-[#333] text-xl font-semibold">Feature {selectedEntity?.osmid}</p>
<sl-button
onclick={async () => {
await entitiesStore.syncEntityStatus(projectData?.id);
}}
onkeydown={(e: KeyboardEvent) => {
e.key === 'Enter' && {};
}}
role="button"
tabindex="0"
size="small"
class="link w-fit ml-auto"
disabled={entitiesStore.syncEntityStatusLoading}
>
<hot-icon
slot="prefix"
name="arrow-repeat"
class={`!text-[1rem] cursor-pointer duration-200 ${entitiesStore.syncEntityStatusLoading && 'animate-spin'}`}
></hot-icon>
<span class="font-barlow font-medium text-sm uppercase">SYNC STATUS</span>
</sl-button>
</div>
<div class="flex flex-col gap-1">
<p><span class="font-medium">Task Id:</span> {selectedEntity?.task_id}</p>
Expand Down
4 changes: 2 additions & 2 deletions src/mapper/src/lib/components/map/layer-switcher.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -190,13 +190,13 @@ map = new Map({
>
<img
style="border: 1px solid #d73f3f;"
class="w-[2.824rem] h-[2.824rem] rounded-full"
class="w-[2.25rem] h-[2.25rem] rounded-full"
src={selectedStyleUrl}
alt="Basemap Icon"
/>
</div>
<div
class={`absolute bottom-0 right-14 bg-white rounded-md p-4 duration-200 ${isOpen ? 'opacity-100' : 'opacity-0 pointer-events-none'}`}
class={`absolute bottom-0 right-11 bg-white rounded-md p-4 duration-200 ${isOpen ? 'opacity-100' : 'opacity-0 pointer-events-none'}`}
>
<p class="font-semibold text-lg mb-2">Base Maps</p>
<div class="grid grid-cols-2 w-[212px] gap-3">
Expand Down
4 changes: 2 additions & 2 deletions src/mapper/src/lib/components/map/legend.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,11 @@
<hot-icon
style="border: 1px solid #D7D7D7;"
name="legend-toggle"
class={`!text-[1.7rem] text-[#333333] bg-white p-2 rounded-full group-hover:text-red-600 duration-200 ${isOpen && 'text-red-600'}`}
class={`!text-[1.7rem] text-[#333333] bg-white p-1 rounded-full group-hover:text-red-600 duration-200 ${isOpen && 'text-red-600'}`}
></hot-icon>
</div>
<div
class={`absolute bottom-0 right-14 bg-white rounded-md p-4 duration-200 ${isOpen ? 'opacity-100' : 'opacity-0 pointer-events-none'} overflow-hidden flex flex-col gap-2`}
class={`absolute bottom-0 right-11 bg-white rounded-md p-4 duration-200 ${isOpen ? 'opacity-100' : 'opacity-0 pointer-events-none'} overflow-hidden flex flex-col gap-2`}
>
<p class="font-semibold leading-0 text-lg mb-3">Legend</p>
{#each taskStatuses as taskStatus}
Expand Down
17 changes: 17 additions & 0 deletions src/mapper/src/lib/components/map/main.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -355,6 +355,23 @@
</ControlGroup></Control
>
<Control class="flex flex-col gap-y-2" position="bottom-right">
<div
class="rounded-full w-[2.25rem] h-[2.25rem] overflow-hidden flex items-center justify-center border-1 border-solid border-red-600 bg-[#FFEDED]"
>
<sl-icon-button
name="arrow-repeat"
label="Settings"
disabled={entitiesStore.syncEntityStatusLoading}
class={`text-[1.25rem] rotate-90 text-red-600 ${entitiesStore.syncEntityStatusLoading && 'animate-spin'}`}
onclick={async () => await entitiesStore.syncEntityStatus(projectId)}
onkeydown={async (e: KeyboardEvent) => {
e.key === 'Enter' && (await entitiesStore.syncEntityStatus(projectId));
}}
role="button"
tabindex="0"
></sl-icon-button>
</div>

<LayerSwitcher
{map}
styles={allBaseLayers}
Expand Down

0 comments on commit 3fd3665

Please sign in to comment.