Skip to content

Commit

Permalink
feat(ui): Map Editing
Browse files Browse the repository at this point in the history
  • Loading branch information
Hypfer committed Oct 12, 2021
1 parent 51181be commit 35feb65
Show file tree
Hide file tree
Showing 33 changed files with 2,155 additions and 82 deletions.
64 changes: 64 additions & 0 deletions frontend/src/api/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import { RawMapData } from "./RawMapData";
import { PresetSelectionState, RobotAttribute } from "./RawRobotState";
import {
Capability,
CombinedVirtualRestrictionsProperties,
CombinedVirtualRestrictionsUpdateRequestParameters,
ConsumableId,
ConsumableState,
DoNotDisturbConfiguration,
Expand All @@ -14,6 +16,9 @@ import {
ManualControlProperties,
MapSegmentationActionRequestParameters,
MapSegmentationProperties,
MapSegmentEditJoinRequestParameters,
MapSegmentEditSplitRequestParameters,
MapSegmentRenameRequestParameters,
MQTTConfiguration,
MQTTProperties,
NTPClientConfiguration,
Expand Down Expand Up @@ -244,6 +249,46 @@ export const sendCleanSegmentsCommand = async (
);
};

export const sendJoinSegmentsCommand = async (
parameters: MapSegmentEditJoinRequestParameters
): Promise<void> => {
await valetudoAPI.put(
`/robot/capabilities/${Capability.MapSegmentEdit}`,
{
action: "join_segments",
segment_a_id: parameters.segment_a_id,
segment_b_id: parameters.segment_b_id
}
);
};

export const sendSplitSegmentCommand = async (
parameters: MapSegmentEditSplitRequestParameters
): Promise<void> => {
await valetudoAPI.put(
`/robot/capabilities/${Capability.MapSegmentEdit}`,
{
action: "split_segment",
segment_id: parameters.segment_id,
pA: parameters.pA,
pB: parameters.pB
}
);
};

export const sendRenameSegmentCommand = async (
parameters: MapSegmentRenameRequestParameters
): Promise<void> => {
await valetudoAPI.put(
`/robot/capabilities/${Capability.MapSegmentRename}`,
{
action: "rename_segment",
segment_id: parameters.segment_id,
name: parameters.name
}
);
};

export const fetchGoToLocationPresets = async (): Promise<Segment[]> => {
return valetudoAPI
.get<Record<string, GoToLocation>>(
Expand Down Expand Up @@ -713,3 +758,22 @@ export const sendManualControlInteraction = async (interaction: ManualControlInt
}
});
};

export const fetchCombinedVirtualRestrictionsPropertiesProperties = async (): Promise<CombinedVirtualRestrictionsProperties> => {
return valetudoAPI
.get<CombinedVirtualRestrictionsProperties>(
`/robot/capabilities/${Capability.CombinedVirtualRestrictions}/properties`
)
.then(({data}) => {
return data;
});
};

export const sendCombinedVirtualRestrictionsUpdate = async (
parameters: CombinedVirtualRestrictionsUpdateRequestParameters
): Promise<void> => {
await valetudoAPI.put(
`/robot/capabilities/${Capability.CombinedVirtualRestrictions}`,
parameters
);
};
126 changes: 119 additions & 7 deletions frontend/src/api/hooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import {
deleteTimer,
fetchAutoEmptyDockAutoEmptyControlState,
fetchCapabilities,
fetchCarpetModeState,
fetchCarpetModeState, fetchCombinedVirtualRestrictionsPropertiesProperties,
fetchConsumableStateInformation,
fetchDoNotDisturbConfiguration,
fetchGoToLocationPresets,
Expand Down Expand Up @@ -53,22 +53,22 @@ import {
sendCarpetModeEnable,
sendCleanSegmentsCommand,
sendCleanTemporaryZonesCommand,
sendCleanZonePresetCommand,
sendCleanZonePresetCommand, sendCombinedVirtualRestrictionsUpdate,
sendConsumableReset,
sendDoNotDisturbConfiguration,
sendGoToCommand,
sendGoToLocationPresetCommand,
sendHTTPBasicAuthConfiguration,
sendHTTPBasicAuthConfiguration, sendJoinSegmentsCommand,
sendKeyLockEnable,
sendLocateCommand,
sendManualControlInteraction,
sendMapReset,
sendMQTTConfiguration,
sendNTPClientConfiguration,
sendObstacleAvoidanceModeEnable,
sendPersistentDataEnable,
sendPersistentDataEnable, sendRenameSegmentCommand,
sendSpeakerTestCommand,
sendSpeakerVolume,
sendSpeakerVolume, sendSplitSegmentCommand,
sendStartMappingPass,
sendTimerCreation,
sendTimerUpdate,
Expand All @@ -90,11 +90,15 @@ import {
import { isAttribute } from "./utils";
import {
Capability,
CombinedVirtualRestrictionsUpdateRequestParameters,
ConsumableId,
DoNotDisturbConfiguration,
HTTPBasicAuthConfiguration,
ManualControlInteraction,
MapSegmentationActionRequestParameters,
MapSegmentEditJoinRequestParameters,
MapSegmentEditSplitRequestParameters,
MapSegmentRenameRequestParameters,
MQTTConfiguration,
NTPClientConfiguration,
NTPClientState,
Expand Down Expand Up @@ -145,13 +149,23 @@ enum CacheKey {
Wifi = "wifi",
ManualControl = "manual_control",
ManualControlProperties = "manual_control_properties",
CombinedVirtualRestrictionsProperties = "combined_virtual_restrictions_properties"
}

const useOnCommandError = (capability: Capability): ((error: unknown) => void) => {
const {enqueueSnackbar} = useSnackbar();

return React.useCallback((error: unknown) => {
enqueueSnackbar(`An error occurred while sending command to ${capability}: ${error}`, {
return React.useCallback((error: any) => {
let errorMessage = "";
if (typeof error?.toString === "function") {
errorMessage = error.toString();
}

if (typeof error?.response?.data === "string") {
errorMessage = error.response.data;
}

enqueueSnackbar(`An error occurred while sending command to ${capability}:\n${errorMessage}`, {
preventDuplicate: true,
key: capability,
variant: "error",
Expand Down Expand Up @@ -436,6 +450,75 @@ export const useCleanSegmentsMutation = (
);
};

export const useJoinSegmentsMutation = (
options?: UseMutationOptions<RobotAttribute[], unknown, MapSegmentEditJoinRequestParameters>
) => {
const queryClient = useQueryClient();
const onError = useOnCommandError(Capability.MapSegmentEdit);

return useMutation(
(parameters: MapSegmentEditJoinRequestParameters) => {
return sendJoinSegmentsCommand(parameters).then(fetchStateAttributes); //TODO: this should actually refetch the map
},
{
onError,
...options,
async onSuccess(data, ...args) {
queryClient.setQueryData<RobotAttribute[]>(CacheKey.Attributes, data, {
updatedAt: Date.now(),
});
await options?.onSuccess?.(data, ...args);
},
}
);
};

export const useSplitSegmentMutation = (
options?: UseMutationOptions<RobotAttribute[], unknown, MapSegmentEditSplitRequestParameters>
) => {
const queryClient = useQueryClient();
const onError = useOnCommandError(Capability.MapSegmentEdit);

return useMutation(
(parameters: MapSegmentEditSplitRequestParameters) => {
return sendSplitSegmentCommand(parameters).then(fetchStateAttributes); //TODO: this should actually refetch the map
},
{
onError,
...options,
async onSuccess(data, ...args) {
queryClient.setQueryData<RobotAttribute[]>(CacheKey.Attributes, data, {
updatedAt: Date.now(),
});
await options?.onSuccess?.(data, ...args);
},
}
);
};

export const useRenameSegmentMutation = (
options?: UseMutationOptions<RobotAttribute[], unknown, MapSegmentRenameRequestParameters>
) => {
const queryClient = useQueryClient();
const onError = useOnCommandError(Capability.MapSegmentRename);

return useMutation(
(parameters: MapSegmentRenameRequestParameters) => {
return sendRenameSegmentCommand(parameters).then(fetchStateAttributes); //TODO: this should actually refetch the map
},
{
onError,
...options,
async onSuccess(data, ...args) {
queryClient.setQueryData<RobotAttribute[]>(CacheKey.Attributes, data, {
updatedAt: Date.now(),
});
await options?.onSuccess?.(data, ...args);
},
}
);
};

export const useGoToLocationPresetsQuery = () => {
return useQuery(CacheKey.GoToLocationPresets, fetchGoToLocationPresets);
};
Expand Down Expand Up @@ -881,3 +964,32 @@ export const useManualControlInteraction = () => {
}
);
};

export const useCombinedVirtualRestrictionsPropertiesQuery = () => {
return useQuery(CacheKey.CombinedVirtualRestrictionsProperties, fetchCombinedVirtualRestrictionsPropertiesProperties, {
staleTime: Infinity
});
};

export const useCombinedVirtualRestrictionsMutation = (
options?: UseMutationOptions<RobotAttribute[], unknown, CombinedVirtualRestrictionsUpdateRequestParameters>
) => {
const queryClient = useQueryClient();
const onError = useOnCommandError(Capability.CombinedVirtualRestrictions);

return useMutation(
(parameters: CombinedVirtualRestrictionsUpdateRequestParameters) => {
return sendCombinedVirtualRestrictionsUpdate(parameters).then(fetchStateAttributes); //TODO: this should actually refetch the map
},
{
onError,
...options,
async onSuccess(data, ...args) {
queryClient.setQueryData<RobotAttribute[]>(CacheKey.Attributes, data, {
updatedAt: Date.now(),
});
await options?.onSuccess?.(data, ...args);
},
}
);
};
50 changes: 46 additions & 4 deletions frontend/src/api/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,10 +73,7 @@ export interface MapSegmentationProperties {
export interface GoToLocation {
id: string;
name: string;
coordinates: {
x: number;
y: number;
};
coordinates: Point;
}

export interface Segment {
Expand Down Expand Up @@ -144,6 +141,22 @@ export interface MapSegmentationActionRequestParameters {
customOrder?: boolean;
}

export interface MapSegmentEditJoinRequestParameters {
segment_a_id: string;
segment_b_id: string;
}

export interface MapSegmentEditSplitRequestParameters {
segment_id: string;
pA: Point;
pB: Point;
}

export interface MapSegmentRenameRequestParameters {
segment_id: string;
name: string;
}

export interface ConsumableState {
type: string;
subType?: string;
Expand Down Expand Up @@ -347,3 +360,32 @@ export interface ManualControlInteraction {
action: ManualControlAction;
movementCommand?: ManualControlCommand;
}

export enum ValetudoRestrictedZoneType {
Regular = "regular",
Mop = "mop"
}

export interface ValetudoRestrictedZone {
type: ValetudoRestrictedZoneType,
points: {
pA: Point,
pB: Point,
pC: Point,
pD: Point
}
}

export interface CombinedVirtualRestrictionsUpdateRequestParameters {
virtualWalls: Array<{
points: {
pA: Point,
pB: Point
}
}>,
restrictedZones: Array<ValetudoRestrictedZone>
}

export interface CombinedVirtualRestrictionsProperties {
supportedRestrictedZoneTypes: Array<ValetudoRestrictedZoneType>
}
Loading

0 comments on commit 35feb65

Please sign in to comment.