327 lines
12 KiB
TypeScript
327 lines
12 KiB
TypeScript
import { AxiosResponse } from "axios";
|
|
import { useHTTP } from "../http";
|
|
import { Interaction } from "models";
|
|
import { componentIDToString } from "pbHelpers/Component";
|
|
import { pond } from "protobuf-ts/pond";
|
|
import { quack } from "protobuf-ts/quack";
|
|
import { useGlobalState } from "providers/StateContainer";
|
|
import { createContext, PropsWithChildren, useContext } from "react";
|
|
import { has } from "utils/types";
|
|
import { pondURL } from "./pond";
|
|
|
|
export interface IInteractionsAPIContext {
|
|
addInteraction: (device: number, settings: pond.IInteractionSettings, otherTeam?: string) => Promise<AxiosResponse<pond.AddInteractionResponse>>;
|
|
addMultiInteractions: (device: number, settings: pond.MultiInteractionSettings, otherTeam?: string) => Promise<AxiosResponse<pond.AddMultiInteractionsResponse>>;
|
|
addInteractionToComponents: (
|
|
fullComponentLocations: string[],
|
|
settings: pond.IInteractionSettings,
|
|
otherTeam?: string
|
|
) => Promise<AxiosResponse<pond.AddInteractionToComponentsResponse>>;
|
|
updateInteraction: (device: number, settings: pond.IInteractionSettings, otherTeam?: string) => Promise<AxiosResponse<pond.UpdateInteractionResponse>>;
|
|
updateInteractionPondSettings: (
|
|
device: number,
|
|
interaction: string,
|
|
settings: pond.IInteractionPondSettings,
|
|
otherTeam?: string
|
|
) => Promise<AxiosResponse<pond.UpdateInteractionPondSettingsResponse>>;
|
|
removeInteraction: (device: number, interaction: string, otherTeam?: string) => Promise<AxiosResponse<pond.RemoveInteractionResponse>>;
|
|
listInteractionsByDevice: (device: number | string, demo?: boolean, otherTeam?: string) => Promise<Interaction[]>;
|
|
listInteractionsByComponent: (
|
|
device: number,
|
|
component: quack.ComponentID,
|
|
demo?: boolean,
|
|
otherTeam?: string
|
|
) => Promise<Interaction[]>;
|
|
setAlertInteractions: (
|
|
alerts: pond.AlertData[],
|
|
otherTeam?: string
|
|
) => Promise<AxiosResponse<pond.SetAlertInteractionsResponse>>;
|
|
clearInteractions: (device: number, sources?: quack.ComponentID[], otherTeam?: string) => Promise<AxiosResponse<pond.ClearInteractionsResponse>>
|
|
}
|
|
|
|
export const InteractionsAPIContext = createContext<IInteractionsAPIContext>(
|
|
{} as IInteractionsAPIContext
|
|
);
|
|
|
|
interface Props {}
|
|
|
|
//used to validate interaction fields before being sent outbound
|
|
function sanitizeInteraction(interaction: pond.IInteractionSettings): pond.IInteractionSettings {
|
|
let sanitizedInteraction = interaction;
|
|
if (sanitizedInteraction.conditions) {
|
|
sanitizedInteraction.conditions.forEach((condition, i) => {
|
|
if (condition.value && sanitizedInteraction.conditions) {
|
|
sanitizedInteraction.conditions[i].value = Math.round(condition.value);
|
|
}
|
|
});
|
|
}
|
|
return sanitizedInteraction;
|
|
}
|
|
|
|
export default function InteractionProvider(props: PropsWithChildren<Props>) {
|
|
const { children } = props;
|
|
const { get, post, put, del } = useHTTP();
|
|
const [{ as }] = useGlobalState();
|
|
|
|
const addInteraction = (device: number, settings: pond.IInteractionSettings, otherTeam?: string) => {
|
|
const view = otherTeam ? otherTeam : as
|
|
return new Promise<AxiosResponse<pond.AddInteractionResponse>>((resolve, reject) => {
|
|
post<pond.AddInteractionResponse>(
|
|
pondURL("/devices/" + device + "/interactions" + (view ? "?as=" + view : "")),
|
|
sanitizeInteraction(settings)
|
|
).then(resp => {
|
|
resp.data = pond.AddInteractionResponse.fromObject(resp)
|
|
return resolve(resp)
|
|
}).catch(err => {
|
|
return reject(err)
|
|
})
|
|
})
|
|
};
|
|
|
|
/**
|
|
* this function is intended for use to add a single interaction to multiple components by way of an object that they are linked to (bin, gate etc)
|
|
* @param fullComponentLocations the full id of a component including the device ie: [4:9-5-12, 4:9-5-13, 3:9-5-12]
|
|
* @param settings the settings of the interaction to add
|
|
* @returns
|
|
*/
|
|
const addInteractionToComponents = (
|
|
fullComponentLocations: string[],
|
|
settings: pond.IInteractionSettings,
|
|
otherTeam?: string
|
|
) => {
|
|
const view = otherTeam ? otherTeam : as
|
|
let url = pondURL(
|
|
"/interactions/forComponents?componentIds=" +
|
|
fullComponentLocations.toString() +
|
|
(view ? "&as=" + view : "")
|
|
)
|
|
return new Promise<AxiosResponse<pond.AddInteractionToComponentsResponse>>((resolve, reject) => {
|
|
post<pond.AddInteractionToComponentsResponse>(url,sanitizeInteraction(settings)).then(resp => {
|
|
resp.data = pond.AddInteractionToComponentsResponse.fromObject(resp.data)
|
|
return resolve(resp)
|
|
}).catch(err => {
|
|
return reject(err)
|
|
})
|
|
})
|
|
};
|
|
|
|
const addMultiInteractions = (device: number, settings: pond.MultiInteractionSettings, otherTeam?: string) => {
|
|
const view = otherTeam ? otherTeam : as
|
|
let url = pondURL("/devices/" + device + "/interactions/multi" + (view ? "?as=" + view : ""))
|
|
return new Promise<AxiosResponse<pond.AddMultiInteractionsResponse>>((resolve, reject) => {
|
|
post<pond.AddMultiInteractionsResponse>(url,settings).then(resp => {
|
|
resp.data = pond.AddMultiInteractionsResponse.fromObject(resp.data)
|
|
return resolve(resp)
|
|
}).catch(err => {
|
|
return reject(err)
|
|
})
|
|
})
|
|
};
|
|
|
|
const updateInteraction = (device: number, settings: pond.IInteractionSettings, otherTeam?: string) => {
|
|
const view = otherTeam ? otherTeam : as
|
|
let url = pondURL(
|
|
"/devices/" +
|
|
device +
|
|
"/interactions?keys=" +
|
|
[device] +
|
|
"&types=" +
|
|
["device"] +
|
|
(view ? "&as=" + view : "")
|
|
)
|
|
return new Promise<AxiosResponse<pond.UpdateInteractionResponse>>((resolve, reject) => {
|
|
put<pond.UpdateInteractionResponse>(url,sanitizeInteraction(settings)).then(resp => {
|
|
resp.data = pond.UpdateInteractionResponse.fromObject(resp.data)
|
|
return resolve(resp)
|
|
}).catch(err => {
|
|
return reject(err)
|
|
})
|
|
})
|
|
};
|
|
|
|
const updateInteractionPondSettings = (
|
|
device: number,
|
|
interaction: string,
|
|
settings: pond.IInteractionPondSettings,
|
|
otherTeam?: string
|
|
) => {
|
|
const view = otherTeam ? otherTeam : as
|
|
let url = pondURL(
|
|
"/devices/" +
|
|
device +
|
|
"/interactions/" +
|
|
interaction +
|
|
"/interactionPondSettings?keys=" +
|
|
[device] +
|
|
"&types=" +
|
|
["device"] +
|
|
(view ? "&as=" + view : "")
|
|
)
|
|
return new Promise<AxiosResponse<pond.UpdateInteractionPondSettingsResponse>>((resolve, reject) => {
|
|
put<pond.UpdateInteractionPondSettingsResponse>(url, sanitizeInteraction(settings)).then(resp => {
|
|
resp.data = pond.UpdateInteractionPondSettingsResponse.fromObject(resp.data)
|
|
return resolve(resp)
|
|
}).catch(err => {
|
|
return reject(err)
|
|
})
|
|
})
|
|
};
|
|
|
|
const removeInteraction = (device: number, interaction: string, otherTeam?: string) => {
|
|
const view = otherTeam ? otherTeam : as
|
|
let url = pondURL("/devices/" + device + "/interactions/" + interaction + (view ? "?as=" + view : ""))
|
|
return new Promise<AxiosResponse<pond.RemoveInteractionResponse>>((resolve, reject) => {
|
|
del<pond.RemoveInteractionResponse>(url).then(resp => {
|
|
resp.data = pond.RemoveInteractionResponse.fromObject(resp.data)
|
|
return resolve(resp)
|
|
}).catch(err => {
|
|
return reject(err)
|
|
})
|
|
})
|
|
|
|
};
|
|
|
|
const listInteractionsByDevice = (
|
|
device: number | string,
|
|
demo: boolean = false,
|
|
otherTeam?: string
|
|
): Promise<Interaction[]> => {
|
|
const view = otherTeam ? otherTeam : as
|
|
return new Promise((resolve, reject) => {
|
|
get(pondURL("/devices/" + device + "/interactions" + (view ? "?as=" + view : ""), demo))
|
|
.then((response: any) => {
|
|
if (!has(response, "data.interactions")) {
|
|
return resolve([]);
|
|
}
|
|
let interactions: Interaction[] = [];
|
|
response.data.interactions.forEach((interaction: Interaction) => {
|
|
if (
|
|
interaction.settings.nodeOne > interaction.settings.nodeTwo &&
|
|
interaction.settings.nodeTwo !== 0
|
|
) {
|
|
//flip operator and send negative comparitor to save
|
|
interaction.settings.conditions.forEach(condition => {
|
|
//coming back from the backend as a string for some reason
|
|
if (condition.comparison.toString() === "RELATIONAL_OPERATOR_GREATER_THAN") {
|
|
condition.comparison = quack.RelationalOperator.RELATIONAL_OPERATOR_LESS_THAN;
|
|
} else {
|
|
condition.comparison = quack.RelationalOperator.RELATIONAL_OPERATOR_GREATER_THAN;
|
|
}
|
|
condition.value = condition.value * -1;
|
|
});
|
|
}
|
|
interactions.push(Interaction.any(interaction));
|
|
});
|
|
return resolve(interactions);
|
|
})
|
|
.catch((error: any) => {
|
|
return reject(error);
|
|
});
|
|
});
|
|
};
|
|
|
|
const listInteractionsByComponent = (
|
|
device: number,
|
|
component: quack.ComponentID,
|
|
demo: boolean = false,
|
|
otherTeam?: string
|
|
): Promise<Interaction[]> => {
|
|
const view = otherTeam ? otherTeam : as
|
|
return new Promise((resolve, reject) => {
|
|
get(
|
|
pondURL(
|
|
"/devices/" +
|
|
device +
|
|
"/components/" +
|
|
componentIDToString(component) +
|
|
"/interactions" +
|
|
(view ? "?as=" + view : ""),
|
|
demo
|
|
)
|
|
)
|
|
.then((response: any) => {
|
|
if (!has(response, "data.interactions")) {
|
|
return resolve([]);
|
|
}
|
|
let interactions: Interaction[] = [];
|
|
response.data.interactions.forEach((interaction: Interaction) => {
|
|
if (
|
|
interaction.settings.nodeOne > interaction.settings.nodeTwo &&
|
|
interaction.settings.nodeTwo !== 0
|
|
) {
|
|
//flip operator and send negative comparitor to save
|
|
interaction.settings.conditions.forEach(condition => {
|
|
//coming back from the backend as a string for some reason
|
|
if (condition.comparison.toString() === "RELATIONAL_OPERATOR_GREATER_THAN") {
|
|
condition.comparison = quack.RelationalOperator.RELATIONAL_OPERATOR_LESS_THAN;
|
|
} else {
|
|
condition.comparison = quack.RelationalOperator.RELATIONAL_OPERATOR_GREATER_THAN;
|
|
}
|
|
condition.value = condition.value * -1;
|
|
});
|
|
}
|
|
interactions.push(Interaction.any(interaction));
|
|
});
|
|
return resolve(interactions);
|
|
})
|
|
.catch((error: any) => {
|
|
return reject(error);
|
|
});
|
|
});
|
|
};
|
|
|
|
const setAlertInteractions = (
|
|
alerts: pond.AlertData[],
|
|
otherTeam?: string
|
|
): Promise<AxiosResponse<pond.SetAlertInteractionsResponse>> => {
|
|
const view = otherTeam ? otherTeam : as
|
|
let url = pondURL("/interactions/setAlerts" + (view ? "?as=" + view : ""))
|
|
return new Promise<AxiosResponse<pond.SetAlertInteractionsResponse>>((resolve, reject) => {
|
|
post<pond.SetAlertInteractionsResponse>(url, { data: alerts }).then(resp => {
|
|
resp.data = pond.SetAlertInteractionsResponse.fromObject(resp.data)
|
|
return resolve(resp)
|
|
}).catch(err => {
|
|
return reject(err)
|
|
})
|
|
})
|
|
};
|
|
|
|
const clearInteractions = (device: number, sources?: quack.ComponentID[], otherTeam?: string): Promise<AxiosResponse<pond.ClearInteractionsResponse>> => {
|
|
const view = otherTeam ? otherTeam : as
|
|
let sourceArray: string[] = []
|
|
if (sources){
|
|
sources.forEach(source => {
|
|
sourceArray.push(componentIDToString(source))
|
|
})
|
|
}
|
|
let url = pondURL("/devices/"+ device + "/interactions/clear" + (view ? "?as=" + view : "") + (sources ? "&sources=" + sourceArray.toString() : ""))
|
|
return new Promise<AxiosResponse<pond.ClearInteractionsResponse>>((resolve, reject) => {
|
|
post<pond.ClearInteractionsResponse>(url).then(resp => {
|
|
resp.data = pond.ClearInteractionsResponse.fromObject(resp.data)
|
|
return resolve(resp)
|
|
}).catch(err => {
|
|
return reject(err)
|
|
})
|
|
})
|
|
}
|
|
|
|
return (
|
|
<InteractionsAPIContext.Provider
|
|
value={{
|
|
addInteraction,
|
|
addMultiInteractions,
|
|
setAlertInteractions,
|
|
addInteractionToComponents,
|
|
updateInteraction,
|
|
updateInteractionPondSettings,
|
|
removeInteraction,
|
|
listInteractionsByDevice,
|
|
listInteractionsByComponent,
|
|
clearInteractions
|
|
}}>
|
|
{children}
|
|
</InteractionsAPIContext.Provider>
|
|
);
|
|
}
|
|
|
|
export const useInteractionsAPI = () => useContext(InteractionsAPIContext);
|