Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Relocate sync button #2100

Merged
merged 6 commits into from
Jan 22, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading