import { useHTTP, usePermissionAPI } from "hooks"; import { createContext, PropsWithChildren, useContext } from "react"; import { pond } from "protobuf-ts/pond"; import { has, or } from "utils/types"; import { User, binScope } from "models"; import { pondURL } from "./pond"; import { AxiosResponse } from "axios"; import { dateRange } from "providers/http"; import { useGlobalState } from "providers"; import { quack } from "protobuf-ts/quack"; export interface IBinAPIContext { addBin: (bin: pond.BinSettings, otherTeam?: string) => Promise>; updateBin: (key: string, bin: pond.BinSettings, otherTeam?: string) => Promise>; bulkBinUpdate: (bins: pond.BinSettings[], otherTeam?: string) => Promise>; updateBinStatus: ( key: string, binStatus: pond.BinStatus, otherTeam?: string ) => Promise>; removeBin: (key: string, otherTeam?: string) => Promise>; getBin: (key: string, otherTeam?: string) => Promise>; addComponent: ( bin: string, device: number, component: string, preferences?: pond.BinComponentPreferences, otherTeam?: string ) => Promise>; removeComponent: ( bin: string, component: string, otherTeam?: string ) => Promise>; removeAllComponents: (bin: string, otherTeam?: string) => Promise>; updateComponentPreferences: ( bin: string, component: string, preferences: pond.BinComponentPreferences, otherTeam?: string ) => Promise>; getBinPageData: (binKey: string, userKey: string, showErrors?: boolean, otherTeam?: string) => Promise>; listBins: ( limit: number, offset: number, order?: "asc" | "desc", orderBy?: string, search?: string, otherTeam?: string, asRoot?: boolean, numerical?: boolean, keys?: string[], types?: string[] ) => Promise>; listBinsAndData: ( limit: number, offset: number, order?: "asc" | "desc", orderBy?: string, search?: string, otherTeam?: string, asRoot?: boolean, keys?: string[], types?: string[] ) => Promise>; listHistory: ( id: string, limit: number, offset: number ) => Promise>; listHistoryBetween: ( id: string, limit: number, start: string, end: string ) => Promise>; listBinStatus: ( key: string, startDate: any, endDate: any, limit: number, offset: number, order?: "asc" | "desc", asRoot?: boolean ) => Promise>; listBinComponents: (key: string) => Promise>; listBinComponentsMeasurements: ( key: string, start: string, end: string, showErrors?: boolean, allNodes?: boolean, otherTeam?: string ) => Promise>; updateBinPermissions: ( key: string, users: User[] ) => Promise>; getBinMetrics: (search?: string, otherTeam?: string) => Promise>; listBinLiters: ( key: string, start: string, end: string, moisture: number, plenum: string, cable: string, pressure: string, fan?: string, // the fan controller is optional so that if they don't have one the fan is assumed on otherTeam?: string ) => Promise>; listBinPrefs: (key: string) => Promise>; updateTopNodes: ( key: string, newTopNodes: pond.NewTopNode[], otherTeam?: string ) => Promise>; listBinMeasurements: ( key: string, startDate: any, endDate: any, limit: number, offset: number, order: string, measurementType?: number | quack.MeasurementType, keys?: string[], types?: string[], showErrors?: boolean, otherTeam?: string ) => Promise>; getBinsTrendData: ( bins: string[], days: number ) => Promise>; } export const BinAPIContext = createContext({} as IBinAPIContext); interface Props {} export default function BinProvider(props: PropsWithChildren) { const { children } = props; const { get, post, put, del } = useHTTP(); const permissionAPI = usePermissionAPI(); const [{ as }] = useGlobalState(); const addBin = (bin: pond.BinSettings, otherTeam?: string) => { const view = otherTeam ? otherTeam : as const url = "/bins" + (view ? "?as=" + view : "") return new Promise>((resolve, reject)=>{ post(pondURL(url), bin).then(resp => { resp.data = pond.AddBinResponse.fromObject(resp.data) return resolve(resp) }).catch(err => { return reject(err) }) }) }; const updateBin = (key: string, bin: pond.BinSettings, otherTeam?: string) => { const view = otherTeam ? otherTeam : as const url = "/bins/" + key + (view ? "?as=" + view : "") return new Promise>((resolve, reject)=>{ put(pondURL(url), bin).then(resp => { resp.data = pond.UpdateBinResponse.fromObject(resp.data) return resolve(resp) }).catch(err => { return reject(err) }) }) }; const bulkBinUpdate = (bins: pond.BinSettings[], otherTeam?: string) => { let url = "/bulkBins/update" const view = otherTeam ? otherTeam : as if (view) url = url + "?as=" + view return new Promise>((resolve, reject)=>{ put(pondURL(url), { bins: bins }).then(resp => { resp.data = pond.BulkBinUpdateResponse.fromObject(resp.data) return resolve(resp) }).catch(err => { return reject(err) }) }) }; const updateBinStatus = (key: string, binStatus: pond.BinStatus, otherTeam?: string) => { let url = "/bins/" + key + "/status" const view = otherTeam ? otherTeam : as if (view) url = url + "?as=" + view return new Promise>((resolve, reject)=>{ put(pondURL(url), binStatus).then(resp=>{ resp.data = pond.UpdateBinStatusResponse.fromObject(resp.data) return resolve(resp) }).catch(err=>{ return reject(err) }) }) }; const removeBin = (key: string, otherTeam?: string) => { let url = "/bins/" + key const view = otherTeam ? otherTeam : as if (view) url = url + "?as=" + view return new Promise>((resolve, reject) => { del(pondURL(url)).then(resp => { resp.data = pond.RemoveBinResponse.fromObject(resp.data) return resolve(resp) }).catch(err => { return reject(err) }) }) }; const getBin = (key: string, otherTeam?: string) => { const view = otherTeam ? otherTeam : as const url = "/bins/" + key + (view ? "?as=" + view : "") return new Promise>((resolve, reject)=>{ get(pondURL(url)) .then(resp => { resp.data = pond.Bin.fromObject(resp.data) resolve(resp) }) .catch(err => { reject(err) }) }) }; const addComponent = ( bin: string, device: number, component: string, preferences?: pond.BinComponentPreferences, otherTeam?: string ) => { const view = otherTeam ? otherTeam : as let url = "/bins/" + bin + "/addComponent/" + device + "/" + component; if (view) { url = url + "?as=" + view + (preferences ? "&binPref=" + preferences.type + "&fillNode=" + preferences.node : ""); } else if (preferences) { url = url + "?binPref=" + preferences.type + "&fillNode=" + preferences.node; } return new Promise>((resolve, reject)=>{ post(pondURL(url)).then(resp => { resp.data = pond.AddBinComponentResponse.fromObject(resp.data) return resolve(resp) }).catch(err => { return reject(err) }) }) }; const removeComponent = (bin: string, component: string, otherTeam?: string) => { const view = otherTeam ? otherTeam : as let url = "/bins/" + bin + "/removeComponent/" + component; if (view) url = url + "?as=" + view; return new Promise>((resolve, reject)=>{ post(pondURL(url)).then(resp => { resp.data = pond.RemoveBinComponentResponse.fromObject(resp.data) return resolve(resp) }).catch(err => { return reject(err) }) }) }; const removeAllComponents = (bin: string, otherTeam?: string) => { const view = otherTeam ? otherTeam : as let url = "/bins/" + bin + "/removeAllComponents"; if (view) url = url + "?as=" + view; return new Promise>((resolve, reject)=>{ post(pondURL(url)).then(resp => { resp.data = pond.RemoveAllBinComponentsResponse.fromObject(resp.data) return resolve(resp) }).catch(err => { return reject(err) }) }) }; const updateComponentPreferences = ( bin: string, component: string, preferences: pond.BinComponentPreferences, otherTeam?: string ) => { const view = otherTeam ? otherTeam : as let url = "/bins/" + bin + "/updateComponent/" + component + "/preferences"; if (view) url = url + "?as=" + view; interface request { preferences: Object; } let body: request = { preferences: pond.BinComponentPreferences.toObject(preferences) }; return new Promise>((resolve,reject)=>{ put(pondURL(url), body).then(resp => { resp.data = pond.UpdateBinComponentPreferencesResponse.fromObject(resp.data) return resolve(resp) }).catch(err => { return reject(err) }) }) }; const getBinPageData = (binKey: string, userKey: string, showErrors = true, otherTeam?: string) => { const view = otherTeam ? otherTeam : as const url = "/bins/" + binKey + "/users/" + userKey + (showErrors ? "?showErrors=true" : "?showErrors=false") + (view ? "&as=" + view : "") return new Promise>((resolve, reject)=>{ get(pondURL(url)) .then(resp => { resp.data = pond.GetBinPageDataResponse.fromObject(resp.data) return resolve(resp) }).catch(err => { return reject(err) }) }) }; const listBins = ( limit: number, offset: number, order?: "asc" | "desc", orderBy?: string, search?: string, otherTeam?: string, asRoot?: boolean, numerical?: boolean, keys?: string[], types?: string[] ) => { return new Promise>((resolve, reject)=>{ const view = otherTeam ? otherTeam : as get( pondURL( "/bins" + "?limit=" + limit + "&offset=" + offset + ("&order=" + or(order, "asc")) + ("&by=" + or(orderBy, "key")) + (numerical ? "&numerical=true" : "") + (view ? "&as=" + view : "") + (asRoot ? "&asRoot=" + asRoot.toString() : "") + (search ? "&search=" + search : "") + (keys ? "&keys=" + keys.join(",") : "") + (types ? "&types=" + types.join(",") : "") ) ).then(resp => { resp.data = pond.ListBinsResponse.fromObject(resp.data); return resolve(resp) }).catch(err => { return reject(err) }) }) }; const listBinsAndData = ( limit: number, offset: number, order?: "asc" | "desc", orderBy?: string, search?: string, otherTeam?: string, asRoot?: boolean, keys?: string[], types?: string[] ) => { const view = otherTeam ? otherTeam : as const url = "/binsAndData" + "?limit=" + limit + "&offset=" + offset + ("&order=" + or(order, "asc")) + ("&by=" + or(orderBy, "key")) + (view ? "&as=" + view : "") + (asRoot ? "&asRoot=" + asRoot.toString() : "") + (search ? "&search=" + search : "") + (keys ? "&keys=" + keys.join(",") : "") + (types ? "&types=" + types.join(",") : "") return new Promise>((resolve, reject)=>{ get(pondURL(url)).then(resp => { resp.data = pond.ListBinsAndDataResponse.fromObject(resp.data) return resolve(resp) }).catch(err => { return reject(err) }) }) }; const listBinStatus = ( key: string, startDate: any, endDate: any, limit: number, offset: number, order?: "asc" | "desc", asRoot?: boolean ) => { const url = "/bins/" + key + "/status" + dateRange(startDate, endDate) + "?limit=" + limit + "&offset=" + offset + ("&order=" + or(order, "asc")) + (asRoot ? "&asRoot=" + asRoot.toString() : "") return new Promise>((resolve, reject)=>{ get( pondURL(url) ).then(resp => { resp.data = pond.ListBinStatusResponse.fromObject(resp.data) return resolve(resp) }).catch(err => { return reject(err) }) }) }; const listBinComponents = (key: string) => { return new Promise>((resolve, reject)=>{ get(pondURL("/bins/" + key + "/components")) .then(resp => { resp.data = pond.ListBinComponentsResponse.fromObject(resp.data) return resolve(resp) }) .catch(err => { return reject(err) }) }) }; const listBinComponentsMeasurements = ( key: string, start: string, end: string, showErrors = false, allNodes = false, otherTeam?: string ) => { const view = otherTeam ? otherTeam : as let url = "/bins/" + key + "/components/measurements?start=" + start + "&end=" + end + (view ? "&as=" + view : "") + (showErrors ? "&showErrors=true" : "&showErrors=false") + (allNodes ? "&allNodes=true" : "&allNodes=false") return new Promise>((resolve, reject) => { get(pondURL(url)) .then(resp => { resp.data = pond.ListBinComponentsMeasurementsResponse.fromObject(resp.data) return resolve(resp) }) .catch(err => { return reject(err) }) } ) }; const listHistory = (id: string, limit: number, offset: number) => { let url = "/bins/" + id + "/history?limit=" + limit + "&offset=" + offset return new Promise>((resolve, reject)=>{ get( pondURL(url) ).then(resp => { resp.data = pond.ListBinHistoryResponse.fromObject(resp.data) return resolve(resp) }).catch(err => { return reject(err) }) }) }; const listHistoryBetween = (id: string, limit: number, start: string, end: string) => { let url = "/bins/" + id + "/historyBetween?limit=" + limit + "&start=" + start + "&end=" + end return new Promise>((resolve, reject)=>{ get( pondURL(url) ).then(resp => { resp.data = pond.ListBinHistoryResponse.fromObject(resp.data) return resolve(resp) }).catch(err => { return reject(err) }) }) }; const updateBinPermissions = (key: string, users: User[]) => { return permissionAPI.updatePermissions(binScope(key.toString()), users); }; const getBinMetrics = (search?: string, otherTeam?: string) => { const view = otherTeam ? otherTeam : as let url = "/metrics/bins" + (search ? "?search=" + search : "") if (view) { if (search){ url = "/metrics/bins/?search=" + search + "&as=" + view } url = "/metrics/bins/?as=" + view; } return new Promise>((resolve, reject)=>{ get(pondURL(url)).then(resp => { resp.data = pond.GetBinMetricsResponse.fromObject(resp.data) return resolve(resp) }).catch(err => { return reject(err) }) }) }; const listBinLiters = ( key: string, start: string, end: string, moisture: number, plenum: string, cable: string, pressure: string, fan?: string, otherTeam?: string ) => { const view = otherTeam ? otherTeam : as const url = "/bins/" + key + "/liters?start=" + start + "&end=" + end + "&moisture=" + moisture + "&plenum=" + plenum + "&cable=" + cable + "&pressure=" + pressure + (fan ? "&fan=" + fan : "") + (view ? "&as=" + view : "") return new Promise>((resolve, reject)=>{ get(pondURL(url)) .then(resp => { resp.data = pond.ListBinLiterResponse.fromObject(resp.data) return resolve(resp) }).catch(err => { return reject(err) }) }) }; const listBinPrefs = (key: string, otherTeam?: string) => { const view = otherTeam ? otherTeam : as const url = "/bins/" + key + "/componentPreferences?as=" + view return new Promise>((resolve, reject)=>{ get(pondURL(url)) .then(resp => { resp.data = pond.ListBinComponentPreferencesResponse.fromObject(resp.data) return resolve(resp) }).catch(err => { return reject(err) }) }) }; const updateTopNodes = (key: string, newTopNodes: pond.NewTopNode[], otherTeam?: string) => { let body: pond.TopNodeList = pond.TopNodeList.create({ newTopNodes: newTopNodes }); const view = otherTeam ? otherTeam : as let url = "/bins/" + key + "/updateTopNodes" + (view ? "?as=" + view : "") return new Promise>((resolve,response) => { post(pondURL(url),body).then(resp => { resp.data = pond.UpdateTopNodesResponse.fromObject(resp.data) return resolve(resp) }).catch(err => { return response(err) }) }) }; const listBinMeasurements = ( key: string, startDate: any, endDate: any, limit: number, offset: number, order: string, measurementType?: number | quack.MeasurementType, keys?: string[], types?: string[], showErrors?: boolean, otherTeam?: string ) => { const view = otherTeam ? otherTeam : as const url = pondURL( "/objects/" + key + "/1/unitMeasurements" + dateRange(startDate, endDate) + "&limit=" + limit + "&offset=" + offset + "&order=" + order + (measurementType ? "&type=" + measurementType : "") + (view ? "&as=" + view : "") + (keys ? "&keys=" + keys : "") + (types ? "&types=" + types : "") + (showErrors ? "&showErrors=true" : "&showErrors=false") ); return new Promise>((resolve, reject) => { get(url) .then(resp => { resp.data = pond.ListObjectMeasurementsResponse.fromObject(resp.data) return resolve(resp) }).catch(err => { return reject(err) }) }) }; const getBinsTrendData = (bins: string[], days: number) => { return get( pondURL("/binTrends?bins=" + bins.toString() + "&days=" + days + (as ? "&as=" + as : "")) ); }; return ( {children} ); } export const useBinAPI = () => useContext(BinAPIContext);