added some more device actions including interactions stuff
This commit is contained in:
parent
e4cc9b3554
commit
59d9bf2e6b
10 changed files with 381 additions and 34 deletions
|
|
@ -210,12 +210,11 @@ export default function BinYard(props: Props) {
|
|||
const [leaving, setLeaving] = useState<boolean>(false);
|
||||
const [yardPermissions, setYardPermissions] = useState<Dictionary<pond.Permission[]>>({});
|
||||
const [searchSelected, setSearchSelected] = useState(false);
|
||||
const [{ user, as }] = useGlobalState();
|
||||
const [{ user }] = useGlobalState();
|
||||
const [addingYard, setAddingYard] = useState(false)
|
||||
|
||||
useEffect(() => {
|
||||
if (props.yards && props.yardPerms) {
|
||||
console.log(props.yards)
|
||||
setBinYards(props.yards);
|
||||
setYardPermissions(props.yardPerms);
|
||||
return;
|
||||
|
|
@ -249,7 +248,6 @@ export default function BinYard(props: Props) {
|
|||
setBinYards(newYards)
|
||||
setShowAddYard(false);
|
||||
newBinYard.key = resp.data.yard
|
||||
console.log(resp.data.yard)
|
||||
|
||||
let newYardPermissions: Dictionary<pond.Permission[]> = { ...yardPermissions };
|
||||
newYardPermissions[newBinYard.key] = [
|
||||
|
|
|
|||
|
|
@ -75,14 +75,9 @@ export default function DraggableTabs(props: DraggableTabsProps) {
|
|||
|
||||
// save tab order to cache when it changes
|
||||
useEffect(() => {
|
||||
console.log(tabOrder)
|
||||
localStorage.setItem(cacheKey, JSON.stringify(sanitize(tabOrder)));
|
||||
}, [tabOrder]);
|
||||
|
||||
// useEffect(() => {
|
||||
// console.log(initialChildren.length)
|
||||
// }, [initialChildren])
|
||||
|
||||
const getKey = (node: ReactNode): string => {
|
||||
return (React.isValidElement(node) && 'key' in node && typeof node.key === 'string') ? node.key : "";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ import SyncDevice from "device/SyncDevice";
|
|||
// import InteractionSettings from "interactions/InteractionSettings";
|
||||
import { cloneDeep } from "lodash";
|
||||
// import { Component, Device, deviceScope, Interaction } from "models";
|
||||
import { Component, Device, deviceScope } from "models";
|
||||
import { Component, Device, deviceScope, Interaction } from "models";
|
||||
// import { MatchParams } from "navigation/Routes";
|
||||
// import { isShareableLink } from "pbHelpers/Device";
|
||||
import { pond } from "protobuf-ts/pond";
|
||||
|
|
@ -65,6 +65,8 @@ import DeviceSettings from "device/DeviceSettings";
|
|||
import ObjectTeams from "teams/ObjectTeams";
|
||||
import ComponentSettings from "component/ComponentSettings";
|
||||
import LoadDeviceProfile from "./LoadDeviceProfile";
|
||||
import InteractionSettings from "interactions/InteractionSettings";
|
||||
import SaveDeviceProfile from "./SaveDeviceProfile";
|
||||
|
||||
const useStyles = makeStyles((_theme: Theme) => {
|
||||
// const isMobile = useMobile()
|
||||
|
|
@ -97,7 +99,7 @@ interface Props {
|
|||
device: Device;
|
||||
isPaused: boolean;
|
||||
components: Component[];
|
||||
// interactions: Interaction[];
|
||||
interactions: Interaction[];
|
||||
refreshCallback: () => void;
|
||||
availablePositions: DeviceAvailabilityMap;
|
||||
availableOffsets: OffsetAvailabilityMap;
|
||||
|
|
@ -130,7 +132,7 @@ export default function DeviceActions(props: Props) {
|
|||
device,
|
||||
isPaused,
|
||||
components,
|
||||
// interactions,
|
||||
interactions,
|
||||
refreshCallback,
|
||||
availablePositions,
|
||||
availableOffsets,
|
||||
|
|
@ -409,7 +411,7 @@ export default function DeviceActions(props: Props) {
|
|||
isDialogOpen={or(isShareObjectDialogOpen, false)}
|
||||
closeDialogCallback={() => closeDialog("isShareObjectDialogOpen")}
|
||||
/>
|
||||
{/* <InteractionSettings
|
||||
<InteractionSettings
|
||||
device={device}
|
||||
components={cloneDeep(components)}
|
||||
mode="add"
|
||||
|
|
@ -417,7 +419,7 @@ export default function DeviceActions(props: Props) {
|
|||
closeDialogCallback={() => closeDialog("isInteractionSettingsOpen")}
|
||||
refreshCallback={refreshCallback}
|
||||
canEdit={canWrite}
|
||||
/> */}
|
||||
/>
|
||||
<ObjectUsers
|
||||
scope={deviceScope(device.id().toString())}
|
||||
label={deviceName}
|
||||
|
|
@ -440,7 +442,7 @@ export default function DeviceActions(props: Props) {
|
|||
isDialogOpen={isRemoveSelfDialogOpen}
|
||||
closeDialogCallback={() => closeDialog("isRemoveSelfDialogOpen")}
|
||||
/>
|
||||
{/* <SaveDeviceProfile
|
||||
<SaveDeviceProfile
|
||||
isDialogOpen={isSaveDeviceProfileOpen}
|
||||
closeDialogCallback={() => closeDialog("isSaveDeviceProfileOpen")}
|
||||
device={device}
|
||||
|
|
@ -448,7 +450,7 @@ export default function DeviceActions(props: Props) {
|
|||
interactions={interactions}
|
||||
tagIds={device.status.tagKeys}
|
||||
refreshCallback={refreshCallback}
|
||||
/> */}
|
||||
/>
|
||||
<LoadDeviceProfile
|
||||
isDialogOpen={isLoadDeviceProfileOpen}
|
||||
closeDialogCallback={() => closeDialog("isLoadDeviceProfileOpen")}
|
||||
|
|
|
|||
297
src/device/SaveDeviceProfile.tsx
Normal file
297
src/device/SaveDeviceProfile.tsx
Normal file
|
|
@ -0,0 +1,297 @@
|
|||
import {
|
||||
Button,
|
||||
DialogActions,
|
||||
DialogContent,
|
||||
DialogTitle,
|
||||
Grid2 as Grid,
|
||||
MenuItem,
|
||||
TextField,
|
||||
Theme,
|
||||
Typography
|
||||
} from "@mui/material";
|
||||
import { makeStyles } from "@mui/styles";
|
||||
import DeleteButton from "common/DeleteButton";
|
||||
import ResponsiveDialog from "common/ResponsiveDialog";
|
||||
import SearchSelect, { Option } from "common/SearchSelect";
|
||||
import { usePreferenceAPI, usePrevious, useSnackbar } from "hooks";
|
||||
import { cloneDeep } from "lodash";
|
||||
import { Backpack, Component, Device, Interaction } from "models";
|
||||
import { backpackOptions } from "pbHelpers/Backpack";
|
||||
import { DeviceComponentKey } from "pbHelpers/Component";
|
||||
import { ListDeviceProductDescribers } from "products/DeviceProduct";
|
||||
import { pond } from "protobuf-ts/pond";
|
||||
import { useBackpackAPI } from "providers/pond/backpackAPI";
|
||||
import React, { useCallback, useEffect, useState } from "react";
|
||||
|
||||
const useStyles = makeStyles((theme: Theme) => {
|
||||
return ({
|
||||
contentSpacing: {
|
||||
marginTop: theme.spacing(1),
|
||||
marginBottom: theme.spacing(1)
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
interface Props {
|
||||
isDialogOpen: boolean;
|
||||
closeDialogCallback: Function;
|
||||
refreshCallback: Function;
|
||||
device: Device;
|
||||
components: Component[];
|
||||
interactions: Interaction[];
|
||||
tagIds: string[];
|
||||
}
|
||||
|
||||
export default function SaveDeviceProfile(props: Props) {
|
||||
const backpackAPI = useBackpackAPI();
|
||||
const preferenceAPI = usePreferenceAPI();
|
||||
const classes = useStyles();
|
||||
const {
|
||||
isDialogOpen,
|
||||
closeDialogCallback,
|
||||
refreshCallback,
|
||||
device,
|
||||
components,
|
||||
interactions,
|
||||
tagIds
|
||||
} = props;
|
||||
const { success, error } = useSnackbar();
|
||||
const prevOpen = usePrevious(isDialogOpen);
|
||||
const [backpacks, setBackpacks] = useState<Backpack[]>([]);
|
||||
const [backpackName, setBackpackName] = useState<string>();
|
||||
const [loading, setLoading] = useState<boolean>(false);
|
||||
const [isNew, setIsNew] = useState<boolean>(false);
|
||||
const [targetBackpackID, setTargetBackpackID] = useState<number>(0);
|
||||
const [product, setProduct] = useState<pond.DeviceProduct>(0);
|
||||
|
||||
const defaultState = () => {
|
||||
setBackpacks([]);
|
||||
setBackpackName("");
|
||||
setIsNew(false);
|
||||
setTargetBackpackID(0);
|
||||
};
|
||||
|
||||
const close = () => {
|
||||
closeDialogCallback();
|
||||
defaultState();
|
||||
};
|
||||
|
||||
const loadBackpacks = useCallback(() => {
|
||||
const { listBackpacks } = backpackAPI;
|
||||
setLoading(true);
|
||||
listBackpacks()
|
||||
.then((response: any) => {
|
||||
const rawBackpacks = response.data.backpacks;
|
||||
const backpacks: Backpack[] = [];
|
||||
|
||||
if (rawBackpacks && rawBackpacks.length > 0) {
|
||||
rawBackpacks.forEach((b: any) => {
|
||||
backpacks.push(Backpack.create(pond.Backpack.fromObject(b)));
|
||||
});
|
||||
}
|
||||
|
||||
setBackpacks(backpacks.sort((b1, b2) => (b1.name() > b2.name() ? 1 : -1)));
|
||||
})
|
||||
.catch((err: any) => {
|
||||
setBackpacks([]);
|
||||
error(err ? err : "Error occured while loading device profiles");
|
||||
})
|
||||
.finally(() => setLoading(false));
|
||||
}, [backpackAPI, error]);
|
||||
|
||||
useEffect(() => {
|
||||
if (isDialogOpen === true && isDialogOpen !== prevOpen) {
|
||||
loadBackpacks();
|
||||
}
|
||||
}, [isDialogOpen, prevOpen, loadBackpacks]);
|
||||
|
||||
const assembleBackpack = (): Promise<pond.BackpackSettings> => {
|
||||
const { getPreferences } = preferenceAPI;
|
||||
return new Promise((resolve, reject) => {
|
||||
let getDevicePreference = getPreferences("device", [device.id().toString()]);
|
||||
let getComponentPreferences = getPreferences(
|
||||
"component",
|
||||
components.map(c => DeviceComponentKey(device, c))
|
||||
);
|
||||
let promises = [getDevicePreference, getComponentPreferences];
|
||||
Promise.all(promises)
|
||||
.then(responses => {
|
||||
let rDevicePreferences = responses[0];
|
||||
let rComponentPreferences = responses[1];
|
||||
let componentPreferences = {} as {
|
||||
[k: string]: pond.UserPreferences;
|
||||
};
|
||||
rComponentPreferences.forEach(pref => {
|
||||
let match = components.find(c => DeviceComponentKey(device, c) === pref.key);
|
||||
if (match && pref.preferences) {
|
||||
componentPreferences[match.locationString()] = pref.preferences;
|
||||
}
|
||||
});
|
||||
let deviceCopy = cloneDeep(device.settings);
|
||||
deviceCopy.deviceId = 0;
|
||||
deviceCopy.platform = pond.DevicePlatform.DEVICE_PLATFORM_INVALID;
|
||||
if (rDevicePreferences.length < 1) {
|
||||
rDevicePreferences.push(pond.ModelPreferences.create());
|
||||
}
|
||||
let backpack = pond.BackpackSettings.create({
|
||||
backpackId: targetBackpackID,
|
||||
product: product,
|
||||
name: backpackName,
|
||||
device: deviceCopy,
|
||||
components: components.map(c => {
|
||||
let component = cloneDeep(c.settings);
|
||||
component.key = "";
|
||||
return component;
|
||||
}),
|
||||
interactions: interactions.map(i => {
|
||||
let interaction = cloneDeep(i.settings);
|
||||
interaction.key = "";
|
||||
return interaction;
|
||||
}),
|
||||
tagKeys: tagIds,
|
||||
devicePreferences: rDevicePreferences[0].preferences,
|
||||
componentPreferences: componentPreferences
|
||||
});
|
||||
resolve(backpack);
|
||||
})
|
||||
.catch(() => {
|
||||
let reason = "Failed loading user preferences";
|
||||
error(reason);
|
||||
reject(reason);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
const submit = () => {
|
||||
const { addBackpack, updateBackpack } = backpackAPI;
|
||||
assembleBackpack().then((backpack: pond.BackpackSettings) => {
|
||||
if (isNew) {
|
||||
addBackpack(backpack)
|
||||
.then((response: any) => {
|
||||
success("Successfully created " + backpackName + " using " + device.name() + "!");
|
||||
refreshCallback();
|
||||
})
|
||||
.catch((err: any) => {
|
||||
error(err ? err : "Error occured while creating " + backpackName + ".");
|
||||
})
|
||||
.finally(() => close());
|
||||
} else {
|
||||
updateBackpack(targetBackpackID, backpack)
|
||||
.then((response: any) => {
|
||||
success("Successfully updated " + backpackName + " using " + device.name() + "!");
|
||||
refreshCallback();
|
||||
})
|
||||
.catch((err: any) => {
|
||||
error(err ? err : "Error occured while updating " + backpackName + ".");
|
||||
})
|
||||
.finally(() => close());
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const removeSelectedProfile = () => {
|
||||
const { removeBackpack } = backpackAPI;
|
||||
|
||||
const backpackID = targetBackpackID;
|
||||
const backpack = backpacks.find(b => b.id() === backpackID);
|
||||
if (targetBackpackID && backpack) {
|
||||
let backpackName = backpack.name();
|
||||
removeBackpack(backpackID)
|
||||
.then(() => {
|
||||
success("Successfully removed " + backpackName);
|
||||
let updatedBackpacks = cloneDeep(backpacks);
|
||||
defaultState();
|
||||
setBackpacks(updatedBackpacks.filter(b => b.id() !== backpackID));
|
||||
})
|
||||
.catch(err => error(err ? err : "Error occured while removing " + backpackName));
|
||||
}
|
||||
};
|
||||
|
||||
const changeTargetBackpack = (option: Option | null) => {
|
||||
let isNew = option && option.new === true ? true : false;
|
||||
setIsNew(isNew);
|
||||
setTargetBackpackID(isNew || !(option && option.value) ? 0 : Number(option.value));
|
||||
setBackpackName(option && option.label ? option.label : backpackName);
|
||||
};
|
||||
|
||||
const isFormValid = (): boolean => {
|
||||
const isValidBackpackName = isNew ? backpackName !== "" : true;
|
||||
const isValidTargetBackpack = isNew ? true : targetBackpackID > 0;
|
||||
return isValidBackpackName && isValidTargetBackpack;
|
||||
};
|
||||
|
||||
// UI Begins
|
||||
|
||||
const content = () => {
|
||||
const options = backpackOptions(backpacks);
|
||||
let selected: Option | undefined = options.find(
|
||||
option => (option.value as number) === targetBackpackID
|
||||
);
|
||||
|
||||
return (
|
||||
<React.Fragment>
|
||||
<SearchSelect
|
||||
label={"Save to an existing or new profile"}
|
||||
selected={selected}
|
||||
options={options}
|
||||
changeSelection={(option: Option | null) => changeTargetBackpack(option)}
|
||||
loading={loading}
|
||||
creatable
|
||||
/>
|
||||
<TextField
|
||||
id="deviceProduct"
|
||||
label="Device Product"
|
||||
select
|
||||
value={product}
|
||||
onChange={e => setProduct(+e.target.value)}
|
||||
margin="normal"
|
||||
fullWidth
|
||||
variant="outlined">
|
||||
{ListDeviceProductDescribers().map(describer => (
|
||||
<MenuItem key={describer.product} value={describer.product}>
|
||||
{describer.label}
|
||||
</MenuItem>
|
||||
))}
|
||||
</TextField>
|
||||
</React.Fragment>
|
||||
);
|
||||
};
|
||||
|
||||
const actions = () => {
|
||||
return (
|
||||
<Grid container justifyContent="space-between" direction="row">
|
||||
<Grid size={{ xs: 5 }}>
|
||||
<DeleteButton disabled={!isFormValid()} onClick={() => removeSelectedProfile()}>
|
||||
Delete
|
||||
</DeleteButton>
|
||||
</Grid>
|
||||
<Grid size={{ xs: 7 }} container justifyItems="flex-end">
|
||||
<Button size="small" color="primary" onClick={close}>
|
||||
Cancel
|
||||
</Button>
|
||||
<Button size="small" disabled={!isFormValid()} color="primary" onClick={submit}>
|
||||
{isNew ? "Create" : "Update"}
|
||||
</Button>
|
||||
</Grid>
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<ResponsiveDialog
|
||||
open={isDialogOpen}
|
||||
onClose={close}
|
||||
aria-labelledby="save-device-profile"
|
||||
maxWidth="sm"
|
||||
fullWidth>
|
||||
<DialogTitle id="save-device-profile-title">
|
||||
Save Device Profile
|
||||
<Typography variant="body2" color="textSecondary">
|
||||
{device.name()}
|
||||
</Typography>
|
||||
</DialogTitle>
|
||||
<DialogContent className={classes.contentSpacing}>{content()}</DialogContent>
|
||||
<DialogActions>{actions()}</DialogActions>
|
||||
</ResponsiveDialog>
|
||||
);
|
||||
}
|
||||
|
|
@ -16,7 +16,7 @@ export {
|
|||
// useMetricAPI,
|
||||
useMineAPI,
|
||||
usePermissionAPI,
|
||||
// usePreferenceAPI,
|
||||
usePreferenceAPI,
|
||||
// useSecurity,
|
||||
useSnackbar,
|
||||
// useTagAPI,
|
||||
|
|
|
|||
|
|
@ -1564,17 +1564,17 @@ export default function InteractionSettings(props: Props) {
|
|||
</Grid>
|
||||
<Grid size={{ xs: 7 }} container justifyContent="flex-end">
|
||||
<CancelSubmit onSubmit={submit} onCancel={close} submitDisabled={!canEdit || !isInteractionValid(interaction) || invalidConditionValues()}/>
|
||||
<Button onClick={close} color="primary">
|
||||
Cancel
|
||||
{/* <Button onClick={close} color="primary">
|
||||
Cancel
|
||||
</Button>
|
||||
{canEdit && (
|
||||
<Button
|
||||
onClick={submit}
|
||||
color="primary"
|
||||
disabled={!isInteractionValid(interaction) || invalidConditionValues()}>
|
||||
Submit
|
||||
</Button>
|
||||
{canEdit && (
|
||||
<Button
|
||||
onClick={submit}
|
||||
color="primary"
|
||||
disabled={!isInteractionValid(interaction) || invalidConditionValues()}>
|
||||
Submit
|
||||
</Button>
|
||||
)}
|
||||
)} */}
|
||||
</Grid>
|
||||
</Grid>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ export default function DevicePage() {
|
|||
const [addComponentManualDialogOpen, setAddComponentManualDialogOpen] = useState(false)
|
||||
|
||||
const loadDevice = () => {
|
||||
console.log("load device page data")
|
||||
// console.log("load device page data")
|
||||
if (loading) return
|
||||
setLoading(true)
|
||||
deviceAPI.getPageData(deviceID, getContextKeys(), getContextTypes()).then(resp => {
|
||||
|
|
@ -120,7 +120,7 @@ export default function DevicePage() {
|
|||
}).catch(err => {
|
||||
setDevice(Device.create());
|
||||
// setComponents(new Map());
|
||||
// setInteractions([]);
|
||||
setInteractions([]);
|
||||
setAvailablePositions(new Map());
|
||||
setPermissions([]);
|
||||
setPreferences(pond.UserPreferences.create());
|
||||
|
|
@ -436,9 +436,11 @@ export default function DevicePage() {
|
|||
permissions={permissions}
|
||||
preferences={preferences}
|
||||
toggleNotificationPreference={toggleNotificationPreference}
|
||||
refreshCallback={loadDevice}
|
||||
availablePositions={availablePositions}
|
||||
availableOffsets={availableOffsets}
|
||||
refreshCallback={loadDevice}
|
||||
availablePositions={availablePositions}
|
||||
availableOffsets={availableOffsets}
|
||||
components={[...components.values()]}
|
||||
interactions={interactions}
|
||||
/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ export {
|
|||
// useMeasurementsWebsocket,
|
||||
// useMetricAPI,
|
||||
usePermissionAPI,
|
||||
// usePreferenceAPI,
|
||||
usePreferenceAPI,
|
||||
useSiteAPI, //TODO: update api with resolve, reject
|
||||
useTagAPI,
|
||||
useTeamAPI,
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ import HomeMarkerProvider, {useHomeMarkerAPI} from "./homeMarkerAPI";
|
|||
import HarvestPlanProvider, {useHarvestPlanAPI} from "./harvestPlanAPI";
|
||||
import TerminalProvider, {useTerminalAPI} from "./terminalAPI"
|
||||
import SiteProvider, {useSiteAPI} from "./siteAPI";
|
||||
import PreferenceProvider, {usePreferenceAPI} from "./preferenceAPI";
|
||||
// import NoteProvider from "providers/noteAPI";
|
||||
|
||||
export const pondURL = (partial: string, demo: boolean = false): string => {
|
||||
|
|
@ -68,7 +69,9 @@ export default function PondProvider(props: PropsWithChildren<any>) {
|
|||
<HarvestPlanProvider>
|
||||
<TerminalProvider>
|
||||
<SiteProvider>
|
||||
{children}
|
||||
<PreferenceProvider>
|
||||
{children}
|
||||
</PreferenceProvider>
|
||||
</SiteProvider>
|
||||
</TerminalProvider>
|
||||
</HarvestPlanProvider>
|
||||
|
|
@ -123,5 +126,6 @@ export {
|
|||
useHomeMarkerAPI,
|
||||
useHarvestPlanAPI,
|
||||
useTerminalAPI,
|
||||
useSiteAPI
|
||||
useSiteAPI,
|
||||
usePreferenceAPI
|
||||
};
|
||||
|
|
|
|||
49
src/providers/pond/preferenceAPI.tsx
Normal file
49
src/providers/pond/preferenceAPI.tsx
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
import { useHTTP } from "hooks";
|
||||
import { pond } from "protobuf-ts/pond";
|
||||
import { createContext, PropsWithChildren, useContext } from "react";
|
||||
import { pondURL } from "./pond";
|
||||
|
||||
export interface IPreferenceAPIContext {
|
||||
getPreferences: (kind: string, keys: string[]) => Promise<pond.ModelPreferences[]>;
|
||||
}
|
||||
|
||||
export const PreferenceAPIContext = createContext<IPreferenceAPIContext>(
|
||||
{} as IPreferenceAPIContext
|
||||
);
|
||||
|
||||
interface Props {}
|
||||
|
||||
export default function PreferenceProvider(props: PropsWithChildren<Props>) {
|
||||
const { children } = props;
|
||||
const { get } = useHTTP();
|
||||
|
||||
const getPreferences = (kind: string, keys: string[]): Promise<pond.ModelPreferences[]> => {
|
||||
if (keys.length <= 0) {
|
||||
return Promise.resolve([]);
|
||||
}
|
||||
return new Promise((resolve, reject) => {
|
||||
get(pondURL("/preferences/?kind=" + kind + "&keys=" + keys.join(",")))
|
||||
.then((res: any) => {
|
||||
let prefs: pond.ModelPreferences[] = [];
|
||||
if (res && res.data && res.data.preferences) {
|
||||
res.data.preferences.forEach((raw: any) => {
|
||||
prefs.push(pond.ModelPreferences.create(raw));
|
||||
});
|
||||
}
|
||||
resolve(prefs);
|
||||
})
|
||||
.catch((err: any) => reject(err));
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<PreferenceAPIContext.Provider
|
||||
value={{
|
||||
getPreferences
|
||||
}}>
|
||||
{children}
|
||||
</PreferenceAPIContext.Provider>
|
||||
);
|
||||
}
|
||||
|
||||
export const usePreferenceAPI = () => useContext(PreferenceAPIContext);
|
||||
Loading…
Add table
Add a link
Reference in a new issue