* Updated Typescript types. * Typefixes after merge with release. * chore: GenericApiResponse Removed alltogether. * chore: resolved ApiResponse unknown errors removed PageListPayload. * Added shouldBeDefined. * fix: Resolved type errors. * fix: Typescript upgrade to 4.5 and type fixes. * feat: upgrade to cra 5 * feat: uncomment service worker registeration * force secure websocket protocol * jest test fixes * fix: react function lint rule removed * fix: klona test case. * fix: typescirpt issues resolved * fix: timeout for colorpicker test and change env. * feat: update client-build.yml file * fix: remove brotliplugin use compression plugin * fix: build config fixed * fix: upgrade webpack plugin * fix: add branchbutton test to todo. * fix: remove branch button test. * fix: Add tailwind theme values, fix cypress tests * fix: Typescript type fixes. * feat: run jest tests in silent mode * fix: cypress rgb values add branchbutton jest test * fix: review comments, fixes for error.message * fix: increase cache size for the workbox * fix: remove OrgApi.ts file * fix: cypress.json file remove credentials * fix: downgrade react and react-dom packages Co-authored-by: rahulramesha <rahul@appsmith.com>
196 lines
5.0 KiB
TypeScript
196 lines
5.0 KiB
TypeScript
import {
|
|
GetCurrentLocationDescription,
|
|
WatchCurrentLocationDescription,
|
|
} from "entities/DataTree/actionTriggers";
|
|
import { EventType } from "constants/AppsmithActionConstants/ActionConstants";
|
|
import {
|
|
executeAppAction,
|
|
TriggerMeta,
|
|
} from "sagas/ActionExecution/ActionExecutionSagas";
|
|
import { call, put, spawn, take } from "redux-saga/effects";
|
|
import {
|
|
logActionExecutionError,
|
|
TriggerFailureError,
|
|
} from "sagas/ActionExecution/errorUtils";
|
|
import { setUserCurrentGeoLocation } from "actions/browserRequestActions";
|
|
import { Channel, channel } from "redux-saga";
|
|
|
|
// Making the getCurrentPosition call in a promise fashion
|
|
const getUserLocation = (options?: PositionOptions) =>
|
|
new Promise((resolve, reject) => {
|
|
navigator.geolocation.getCurrentPosition(
|
|
(location) => resolve(location),
|
|
(error) => reject(error),
|
|
options,
|
|
);
|
|
});
|
|
|
|
/**
|
|
* We need to extract and set certain properties only because the
|
|
* return value is a "class" with functions as well and
|
|
* that cant be stored in the data tree
|
|
**/
|
|
const extractGeoLocation = (
|
|
location: GeolocationPosition,
|
|
): GeolocationPosition => {
|
|
const {
|
|
coords: {
|
|
accuracy,
|
|
altitude,
|
|
altitudeAccuracy,
|
|
heading,
|
|
latitude,
|
|
longitude,
|
|
speed,
|
|
},
|
|
} = location;
|
|
const coords: GeolocationCoordinates = {
|
|
altitude,
|
|
altitudeAccuracy,
|
|
heading,
|
|
latitude,
|
|
longitude,
|
|
accuracy,
|
|
speed,
|
|
};
|
|
return {
|
|
coords,
|
|
timestamp: location.timestamp,
|
|
};
|
|
};
|
|
|
|
let successChannel: Channel<any> | undefined;
|
|
let errorChannel: Channel<any> | undefined;
|
|
|
|
function* successCallbackHandler() {
|
|
if (successChannel) {
|
|
while (true) {
|
|
const payload: unknown = yield take(successChannel);
|
|
// @ts-expect-error: payload is unknown
|
|
const { callback, eventType, location, triggerMeta } = payload;
|
|
const currentLocation = extractGeoLocation(location);
|
|
yield put(setUserCurrentGeoLocation(currentLocation));
|
|
if (callback) {
|
|
yield call(executeAppAction, {
|
|
dynamicString: callback,
|
|
callbackData: [currentLocation],
|
|
event: { type: eventType },
|
|
triggerPropertyName: triggerMeta.triggerPropertyName,
|
|
source: triggerMeta.source,
|
|
});
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
function* errorCallbackHandler() {
|
|
if (errorChannel) {
|
|
while (true) {
|
|
const payload: unknown = yield take(errorChannel);
|
|
// @ts-expect-error: payload is unknown
|
|
const { callback, error, eventType, triggerMeta } = payload;
|
|
if (callback) {
|
|
yield call(executeAppAction, {
|
|
dynamicString: callback,
|
|
callbackData: [error],
|
|
event: { type: eventType },
|
|
triggerPropertyName: triggerMeta.triggerPropertyName,
|
|
source: triggerMeta.source,
|
|
});
|
|
} else {
|
|
throw new TriggerFailureError(error.message, triggerMeta);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
export function* getCurrentLocationSaga(
|
|
actionPayload: GetCurrentLocationDescription["payload"],
|
|
eventType: EventType,
|
|
triggerMeta: TriggerMeta,
|
|
) {
|
|
try {
|
|
const location: GeolocationPosition = yield call(
|
|
getUserLocation,
|
|
actionPayload.options,
|
|
);
|
|
|
|
const currentLocation = extractGeoLocation(location);
|
|
|
|
yield put(setUserCurrentGeoLocation(currentLocation));
|
|
return [currentLocation];
|
|
} catch (error) {
|
|
logActionExecutionError(
|
|
(error as Error).message,
|
|
triggerMeta.source,
|
|
triggerMeta.triggerPropertyName,
|
|
);
|
|
}
|
|
}
|
|
|
|
let watchId: number | undefined;
|
|
export function* watchCurrentLocation(
|
|
actionPayload: WatchCurrentLocationDescription["payload"],
|
|
eventType: EventType,
|
|
triggerMeta: TriggerMeta,
|
|
) {
|
|
if (watchId) {
|
|
// When a watch is already active, we will not start a new watch.
|
|
// at a given point in time, only one watch is active
|
|
logActionExecutionError(
|
|
"A watchLocation is already active. Clear it before before starting a new one",
|
|
triggerMeta.source,
|
|
triggerMeta.triggerPropertyName,
|
|
);
|
|
}
|
|
successChannel = channel();
|
|
errorChannel = channel();
|
|
yield spawn(successCallbackHandler);
|
|
yield spawn(errorCallbackHandler);
|
|
watchId = navigator.geolocation.watchPosition(
|
|
(location) => {
|
|
if (successChannel) {
|
|
successChannel.put({
|
|
location,
|
|
callback: actionPayload.onSuccess,
|
|
eventType,
|
|
triggerMeta,
|
|
});
|
|
}
|
|
},
|
|
(error) => {
|
|
if (errorChannel) {
|
|
errorChannel.put({
|
|
error,
|
|
callback: actionPayload.onError,
|
|
eventType,
|
|
triggerMeta,
|
|
});
|
|
}
|
|
},
|
|
actionPayload.options,
|
|
);
|
|
}
|
|
|
|
export function* stopWatchCurrentLocation(
|
|
eventType: EventType,
|
|
triggerMeta: TriggerMeta,
|
|
) {
|
|
if (watchId === undefined) {
|
|
logActionExecutionError(
|
|
"No location watch active",
|
|
triggerMeta.source,
|
|
triggerMeta.triggerPropertyName,
|
|
);
|
|
return;
|
|
}
|
|
navigator.geolocation.clearWatch(watchId);
|
|
watchId = undefined;
|
|
if (successChannel) {
|
|
successChannel.close();
|
|
}
|
|
if (errorChannel) {
|
|
errorChannel.close();
|
|
}
|
|
}
|