state event handlers - API
This commit is contained in:
parent
2e6a34c687
commit
3496c13f36
|
@ -2,5 +2,5 @@ Contributors
|
|||
===
|
||||
|
||||
* Michael Shanks - [@mjashanks](https://github.com/mjashanks)
|
||||
* Dan - [@danbudi](https://github.com/danbudi)
|
||||
* Daniel Loudon - [@danbudi](https://github.com/marblekirby)
|
||||
* Joe - [@joebudi](https://github.com/joebudi)
|
|
@ -0,0 +1,61 @@
|
|||
import { ERROR } from "../state/standardState";
|
||||
import {loadRecord} from "./loadRecord";
|
||||
import {listRecords} from "./listRecords";
|
||||
|
||||
export const createApi = ({rootPath, setState, getState}) => {
|
||||
|
||||
const apiCall = (method) => ({url, body, notFound, badRequest, forbidden}) => {
|
||||
fetch(url, {
|
||||
method: method,
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: body && JSON.stringify(body),
|
||||
credentials: "same-origin"
|
||||
}).then(r => {
|
||||
switch (r.status) {
|
||||
case 200:
|
||||
return r.json();
|
||||
case 404:
|
||||
return error(notFound || `${url} Not found`);
|
||||
case 400:
|
||||
return error(badRequest || `${url} Bad Request`);
|
||||
case 403:
|
||||
return error(forbidden || `${url} Forbidden`);
|
||||
default:
|
||||
if(r.status.toString().startsWith("2")
|
||||
|| r.status.toString().startsWith("3"))
|
||||
return r.json()
|
||||
else
|
||||
return error(`${url} - ${r.statusText}`);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
const post = apiCall("POST");
|
||||
const get = apiCall("GET");
|
||||
const patch = apiCall("PATCH");
|
||||
const del = apiCall("DELETE");
|
||||
|
||||
const ERROR_MEMBER = "##error";
|
||||
const error = message => {
|
||||
const e = {};
|
||||
e[ERROR_MEMBER] = message;
|
||||
setState(ERROR, message);
|
||||
return e;
|
||||
}
|
||||
|
||||
const isSuccess = obj => !!obj[ERROR_MEMBER];
|
||||
|
||||
const apiOpts = {
|
||||
rootPath, setState, getState, isSuccess, error,
|
||||
post, get, patch, delete:del
|
||||
};
|
||||
|
||||
return {
|
||||
loadRecord:loadRecord(apiOpts),
|
||||
listRecords: listRecords(api)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
export const listRecords = api => async ({indexKey, statePath}) => {
|
||||
if(!recordKey) {
|
||||
api.error("Load Record: record key not set");
|
||||
return;
|
||||
}
|
||||
|
||||
if(!statePath) {
|
||||
api.error("Load Record: state path not set");
|
||||
return;
|
||||
}
|
||||
|
||||
const records = get({
|
||||
url:`${rootPath}/api/listRecords/${indexKey}`
|
||||
});
|
||||
|
||||
if(api.isSuccess(records))
|
||||
api.setState(statePath, records);
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
|
||||
|
||||
export const loadRecord = (api) => async ({recordKey, statePath}) => {
|
||||
|
||||
if(!recordKey) {
|
||||
api.error("Load Record: record key not set");
|
||||
return;
|
||||
}
|
||||
|
||||
if(!statePath) {
|
||||
api.error("Load Record: state path not set");
|
||||
return;
|
||||
}
|
||||
|
||||
const record = await get({
|
||||
url:`${rootPath}/api/record/${key}`
|
||||
});
|
||||
|
||||
if(api.isSuccess(record))
|
||||
api.setState(statePath, record);
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
|
||||
|
||||
export const saveRecord = (api) => async ({statePath}) => {
|
||||
|
||||
if(!statePath) {
|
||||
api.error("Load Record: state path not set");
|
||||
return;
|
||||
}
|
||||
|
||||
const recordtoSave = api.getState(statePath);
|
||||
|
||||
if(!recordtoSave) {
|
||||
api.error(`there is no record in state: ${statePath}`);
|
||||
return;
|
||||
}
|
||||
|
||||
if(!recordtoSave.key) {
|
||||
api.error(`item in state does not appear to be a record - it has no key (${statePath})`);
|
||||
return;
|
||||
}
|
||||
|
||||
const savedRecord = await post({
|
||||
url:`${rootPath}/api/record/${recordtoSave.key}`,
|
||||
body: recordtoSave
|
||||
});
|
||||
|
||||
if(api.isSuccess(record))
|
||||
api.setState(statePath, savedRecord);
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
|
||||
|
||||
export const createCoreApp = (appDefinition, user) => {
|
||||
const app = {
|
||||
datastore: null,
|
||||
crypto:null,
|
||||
publish: () => {},
|
||||
hierarchy: appDefinition.hierarchy,
|
||||
actions: appDefinition.actions
|
||||
};
|
||||
|
||||
app.asUser(user);
|
||||
|
||||
return app;
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
import { createCoreApp } from "./createCoreApp"
|
||||
import {
|
||||
getNew, getNewChild
|
||||
} from "../../../core/src/recordApi/getNew";
|
||||
|
||||
export const createCoreApi = (appDefinition, user) => {
|
||||
|
||||
const app = createCoreApp(appDefinition, user);
|
||||
|
||||
return {
|
||||
recordApi: {
|
||||
getNew: getNew(app),
|
||||
getNewChild: getNewChild(app)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -5,8 +5,9 @@ import {
|
|||
import {writable} from "svelte/store";
|
||||
import { $ } from "./core/common";
|
||||
import { setupBinding } from "./state/stateBinding";
|
||||
import { createCoreApi } from "./core";
|
||||
|
||||
export const createApp = componentLibraries => {
|
||||
export const createApp = (componentLibraries, appDefinition, user) => {
|
||||
|
||||
const initialiseComponent = (props, htmlElement) => {
|
||||
|
||||
|
@ -14,7 +15,7 @@ export const createApp = componentLibraries => {
|
|||
|
||||
if(!componentName || !libName) return;
|
||||
|
||||
const {initialProps, bind} = setupBinding(store, props);
|
||||
const {initialProps, bind} = setupBinding(store, props, coreApi);
|
||||
|
||||
const component = new (componentLibraries[libName][componentName])({
|
||||
target: htmlElement,
|
||||
|
@ -25,6 +26,7 @@ export const createApp = componentLibraries => {
|
|||
|
||||
}
|
||||
|
||||
const coreApi = createCoreApi(appDefinition, user);
|
||||
const store = writable({});
|
||||
|
||||
const _app = {
|
||||
|
|
|
@ -4,6 +4,12 @@ import { createApp } from "./createApp";
|
|||
export const loadBudibase = async (componentLibraries, props) => {
|
||||
|
||||
const appDefinition = window["##BUDIBASE_APPDEFINITION##"];
|
||||
const user = localStorage.getItem("budibase:user") || {
|
||||
name: "annonymous",
|
||||
permissions : [],
|
||||
isUser:false,
|
||||
temp:false
|
||||
}
|
||||
|
||||
if(!componentLibraries) {
|
||||
|
||||
|
@ -22,7 +28,7 @@ export const loadBudibase = async (componentLibraries, props) => {
|
|||
props = appDefinition.props;
|
||||
}
|
||||
|
||||
const _app = createApp(componentLibraries);
|
||||
const _app = createApp(componentLibraries, user);
|
||||
_app.initialiseComponent(
|
||||
props,
|
||||
document.body);
|
||||
|
|
|
@ -0,0 +1,63 @@
|
|||
import { ERROR } from "./standardState";
|
||||
|
||||
export const getNewChildRecordToState = (store, coreApi) =>
|
||||
({recordKey, collectionName,childRecordType,statePath}) => {
|
||||
const error = errorHandler(setState);
|
||||
try {
|
||||
if(!recordKey) {
|
||||
error("getNewChild > recordKey not set");
|
||||
return;
|
||||
}
|
||||
|
||||
if(!collectionName) {
|
||||
error("getNewChild > collectionName not set");
|
||||
return;
|
||||
}
|
||||
|
||||
if(!childRecordType) {
|
||||
error("getNewChild > childRecordType not set");
|
||||
return;
|
||||
}
|
||||
|
||||
if(!statePath) {
|
||||
error("getNewChild > statePath not set");
|
||||
return;
|
||||
}
|
||||
|
||||
const rec = coreApi.recordApi.getNewChild(recordKey, collectionName, childRecordType);
|
||||
setState(store, statePath, rec);
|
||||
}
|
||||
catch(e) {
|
||||
error(e.message);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export const getNewRecordToState = (store, coreApi) =>
|
||||
({collectionKey,childRecordType,statePath}) => {
|
||||
const error = errorHandler(setState);
|
||||
try {
|
||||
if(!collectionKey) {
|
||||
error("getNewChild > collectionKey not set");
|
||||
return;
|
||||
}
|
||||
|
||||
if(!childRecordType) {
|
||||
error("getNewChild > childRecordType not set");
|
||||
return;
|
||||
}
|
||||
|
||||
if(!statePath) {
|
||||
error("getNewChild > statePath not set");
|
||||
return;
|
||||
}
|
||||
|
||||
const rec = coreApi.recordApi.getNew(collectionKey, childRecordType);
|
||||
setState(store, statePath, rec);
|
||||
}
|
||||
catch(e) {
|
||||
error(e.message);
|
||||
}
|
||||
}
|
||||
|
||||
const errorHandler = setState => message => setState(ERROR, message);
|
|
@ -1,22 +1,43 @@
|
|||
import {
|
||||
setState
|
||||
} from "./setState";
|
||||
import { setState } from "./setState";
|
||||
import { getState } from "./getState";
|
||||
import {
|
||||
isArray, isUndefined
|
||||
} from "lodash/fp";
|
||||
|
||||
import { createApi } from "../api";
|
||||
import {
|
||||
getNewChildRecordToState, getNewRecordToState
|
||||
} from "./coreHandlers";
|
||||
|
||||
export const EVENT_TYPE_MEMBER_NAME = "##eventHandlerType";
|
||||
|
||||
export const eventHandlers = store => {
|
||||
export const eventHandlers = (store,coreApi) => {
|
||||
|
||||
const handler = (parameters, execute) => ({
|
||||
execute, parameters
|
||||
});
|
||||
|
||||
const api = createApi({
|
||||
rootPath:"",
|
||||
setState: (path, value) => setState(store, path, value),
|
||||
getState: (path, fallback) => getState(store, path, fallback)
|
||||
});
|
||||
|
||||
const setStateHandler = ({path, value}) => setState(store, path, value);
|
||||
|
||||
return {
|
||||
"Set State": handler(["path", "value"], setStateHandler)
|
||||
"Set State": handler(["path", "value"], setStateHandler),
|
||||
"Load Record": handler(["recordKey", "statePath"], api.loadRecord),
|
||||
"List Records": handler(["indexKey", "statePath"], api.listRecords),
|
||||
"Save Record": handler(["statePath"], api.saveRecord),
|
||||
|
||||
"Get New Child Record": handler(
|
||||
["recordKey", "collectionName", "childRecordType", "statePath"],
|
||||
getNewChildRecordToState(store, coreApi)),
|
||||
|
||||
"Get New Record": handler(
|
||||
["collectionKey", "childRecordType", "statePath"],
|
||||
getNewRecordToState(store, coreApi)),
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
|
||||
export const ERROR = "##error_message";
|
|
@ -9,7 +9,7 @@ import {
|
|||
export const BB_STATE_BINDINGPATH = "##bbstate";
|
||||
export const BB_STATE_FALLBACK = "##bbstatefallback";
|
||||
const doNothing = () => {};
|
||||
export const setupBinding = (store, props) => {
|
||||
export const setupBinding = (store, props, coreApi) => {
|
||||
|
||||
const initialProps = {...props};
|
||||
const boundProps = [];
|
||||
|
@ -50,7 +50,7 @@ export const setupBinding = (store, props) => {
|
|||
|
||||
if(boundProps.length === 0 && componentEventHandlers.length === 0) return;
|
||||
|
||||
const handlerTypes = eventHandlers(store);
|
||||
const handlerTypes = eventHandlers(store, coreApi);
|
||||
|
||||
const unsubscribe = store.subscribe(s => {
|
||||
const newProps = {};
|
||||
|
|
Loading…
Reference in New Issue