Farmbot-Web-App/frontend/farm_designer/util.ts

64 lines
2.3 KiB
TypeScript
Raw Permalink Normal View History

2018-03-09 22:17:16 -07:00
import axios, { AxiosPromise } from "axios";
2017-06-29 12:54:02 -06:00
import { OpenFarm, CropSearchResult } from "./openfarm";
2017-11-24 07:36:10 -07:00
import { DEFAULT_ICON } from "../open_farm/icons";
2018-04-23 09:52:56 -06:00
import { Actions } from "../constants";
2018-08-02 15:46:58 -06:00
import { ExecutableType } from "farmbot/dist/resources/api_resources";
2019-02-04 07:32:26 -07:00
import { get } from "lodash";
2020-02-15 11:30:23 -07:00
import { ExternalUrl } from "../external_urls";
2017-06-29 12:54:02 -06:00
2020-02-15 11:30:23 -07:00
const url = (q: string) =>
`${ExternalUrl.OpenFarm.cropApi}?include=pictures&filter=${q}`;
2018-03-09 22:17:16 -07:00
const openFarmSearchQuery = (q: string): AxiosPromise<CropSearchResult> =>
axios.get<CropSearchResult>(url(q));
2017-06-29 12:54:02 -06:00
interface IdURL {
id: string;
url: string;
}
const FALLBACK: OpenFarm.Included[] = [];
export const OFSearch = (searchTerm: string) =>
2017-06-29 12:54:02 -06:00
(dispatch: Function) => {
2018-12-03 14:36:43 -07:00
dispatch({ type: Actions.OF_SEARCH_RESULTS_START, payload: undefined });
2017-06-29 12:54:02 -06:00
openFarmSearchQuery(searchTerm)
.then(resp => {
2017-08-28 05:49:13 -06:00
const images: { [key: string]: string } = {};
2019-02-04 07:32:26 -07:00
get(resp, "data.included", FALLBACK)
.map((item: OpenFarm.Included) => {
2017-06-29 12:54:02 -06:00
return { id: item.id, url: item.attributes.thumbnail_url };
})
.map((val: IdURL) => images[val.id] = val.url);
2017-08-28 05:49:13 -06:00
const payload = resp.data.data.map(datum => {
const crop = datum.attributes;
2019-02-04 07:32:26 -07:00
const id = get(datum, "relationships.pictures.data[0].id", "");
2017-06-29 12:54:02 -06:00
return { crop, image: (images[id] || DEFAULT_ICON) };
});
2018-04-23 09:52:56 -06:00
dispatch({ type: Actions.OF_SEARCH_RESULTS_OK, payload });
2018-11-28 15:29:46 -07:00
})
.catch(() =>
2020-02-28 09:35:32 -07:00
dispatch({ type: Actions.OF_SEARCH_RESULTS_NO, payload: undefined }));
2017-06-29 12:54:02 -06:00
};
function isExecutableType(x?: string): x is ExecutableType {
const EXECUTABLES: ExecutableType[] = ["Sequence", "Regimen"];
return !!EXECUTABLES.includes(x as ExecutableType);
}
/** USE CASE: You have a `string?` type that you are *certain*
* is an `ExecutableType`. But the type checker is
* complaining.
*
* PROBLEM: `as ExecutableType` results in less type safety and
* makes bugs harder to pin point in production.
*
* SOLUTION: Run a user defined type guard (`x is ExecutableType`)
* and raise a runtime error with the offending string
*/
export function executableType(input?: string): ExecutableType {
if (isExecutableType(input)) {
return input;
} else {
throw new Error("Assumed string was ExecutableType. Got: " + input);
}
}