Farmbot-Web-App/frontend/resources/reducer.ts

226 lines
7.4 KiB
TypeScript
Raw Normal View History

import { generateReducer } from "../redux/generate_reducer";
import { RestResources } from "./interfaces";
2018-08-01 07:03:35 -06:00
import {
indexUpsert,
mutateSpecialStatus,
findByUuid,
indexRemove,
initResourceReducer,
afterEach,
beforeEach,
folderIndexer,
2020-02-28 09:35:32 -07:00
reindexFolders,
} from "./reducer_support";
import { TaggedResource, SpecialStatus } from "farmbot";
import { Actions } from "../constants";
import { EditResourceParams } from "../api/interfaces";
import { defensiveClone, equals } from "../util";
import { merge } from "lodash";
import { SyncBodyContents } from "../sync/actions";
import { GeneralizedError } from "./actions";
import { initialState as helpState } from "../help/reducer";
import { initialState as designerState } from "../farm_designer/reducer";
import { farmwareState } from "../farmware/reducer";
import { initialState as regimenState } from "../regimens/reducer";
import { initialState as sequenceState } from "../sequences/reducer";
2019-07-15 13:44:40 -06:00
import { initialState as alertState } from "../messages/reducer";
2019-12-11 15:44:54 -07:00
import { ingest } from "../folders/data_transfer";
import { searchFolderTree } from "../folders/search_folder_tree";
export const emptyState = (): RestResources => {
return {
consumers: {
sequences: sequenceState,
regimens: regimenState,
farm_designer: designerState,
farmware: farmwareState,
help: helpState,
2019-07-15 13:44:40 -06:00
alerts: alertState
},
loaded: [],
index: {
2018-12-01 19:02:02 -07:00
all: {},
byKind: {
2019-08-05 15:45:19 -06:00
Alert: {},
Crop: {},
Device: {},
FarmEvent: {},
2019-08-05 15:45:19 -06:00
FarmwareEnv: {},
FarmwareInstallation: {},
FbosConfig: {},
FirmwareConfig: {},
2019-12-03 16:30:03 -07:00
Folder: {},
Image: {},
Log: {},
Peripheral: {},
2019-08-05 15:45:19 -06:00
PinBinding: {},
Plant: {},
PlantTemplate: {},
Point: {},
2019-08-05 15:45:19 -06:00
PointGroup: {},
Regimen: {},
2019-08-05 15:45:19 -06:00
SavedGarden: {},
Sensor: {},
SensorReading: {},
Sequence: {},
Tool: {},
User: {},
WebAppConfig: {},
2019-08-05 15:45:19 -06:00
WebcamFeed: {},
},
byKindAndId: {},
references: {},
sequenceMetas: {},
2018-11-17 13:36:16 -07:00
inUse: {
"Regimen.FarmEvent": {},
"Sequence.FarmEvent": {},
"Sequence.Regimen": {},
2018-11-17 13:36:16 -07:00
"Sequence.Sequence": {},
2019-12-20 16:48:56 -07:00
"Sequence.PinBinding": {},
2019-09-19 07:37:05 -06:00
"Sequence.FbosConfig": {}
2019-12-04 08:49:55 -07:00
},
sequenceFolders: {
2019-12-05 09:12:14 -07:00
localMetaAttributes: {},
folders: {
folders: [],
noFolder: [],
},
2018-11-17 13:36:16 -07:00
}
}
};
};
2017-06-29 12:54:02 -06:00
/** Responsible for all RESTful resources. */
export const resourceReducer =
generateReducer<RestResources>(emptyState())
.beforeEach(beforeEach)
.afterEach(afterEach)
.add<TaggedResource>(Actions.SAVE_RESOURCE_OK, (s, { payload }) => {
indexUpsert(s.index, [payload], "ongoing");
mutateSpecialStatus(payload.uuid, s.index, SpecialStatus.SAVED);
2017-06-29 12:54:02 -06:00
return s;
})
.add<EditResourceParams>(Actions.EDIT_RESOURCE, (s, { payload }) => {
const { update } = payload;
2018-10-29 07:36:39 -06:00
const target = findByUuid(s.index, payload.uuid);
const before = defensiveClone(target.body);
merge(target, { body: update });
const didChange = !equals(before, target.body);
if (didChange) {
mutateSpecialStatus(target.uuid, s.index, SpecialStatus.DIRTY);
indexUpsert(s.index, [target], "ongoing");
}
return s;
})
.add<EditResourceParams>(Actions.OVERWRITE_RESOURCE, (s, { payload }) => {
const { uuid, update, specialStatus } = payload;
2018-11-06 17:14:38 -07:00
const original = findByUuid(s.index, uuid);
original.body = update;
indexUpsert(s.index, [original], "ongoing");
2018-11-06 17:14:38 -07:00
mutateSpecialStatus(uuid, s.index, specialStatus);
return s;
})
.add<SyncBodyContents<TaggedResource>>(Actions.RESOURCE_READY, (s, { payload }) => {
!s.loaded.includes(payload.kind) && s.loaded.push(payload.kind);
indexUpsert(s.index, payload.body, "initial");
return s;
})
2018-10-29 07:36:39 -06:00
.add<TaggedResource>(Actions.REFRESH_RESOURCE_OK, (s, { payload }) => {
indexUpsert(s.index, [payload], "ongoing");
mutateSpecialStatus(payload.uuid, s.index);
2018-10-29 07:36:39 -06:00
return s;
})
.add<TaggedResource>(Actions.DESTROY_RESOURCE_OK, (s, { payload }) => {
indexRemove(s.index, payload);
folderIndexer(payload, s.index);
return s;
})
.add<GeneralizedError>(Actions._RESOURCE_NO, (s, { payload }) => {
merge(findByUuid(s.index, payload.uuid), payload);
mutateSpecialStatus(payload.uuid, s.index, payload.statusBeforeError);
return s;
})
2018-10-28 14:52:54 -06:00
.add<TaggedResource>(Actions.INIT_RESOURCE, initResourceReducer)
.add<string>(Actions.REFRESH_RESOURCE_START, (s, a) => {
mutateSpecialStatus(a.payload, s.index, SpecialStatus.SAVING);
return s;
})
2018-10-28 15:19:29 -06:00
.add<GeneralizedError>(Actions.REFRESH_RESOURCE_NO, (s, { payload }) => {
mutateSpecialStatus(payload.uuid, s.index);
return s;
})
2018-10-26 14:50:05 -06:00
.add<TaggedResource>(Actions.SAVE_RESOURCE_START, (s, { payload }) => {
mutateSpecialStatus(payload.uuid, s.index, SpecialStatus.SAVING);
return s;
})
.add<TaggedResource[]>(Actions.BATCH_INIT, (s, { payload }) => {
return payload.reduce((state, resource) => {
2018-10-26 14:50:05 -06:00
return initResourceReducer(state, {
type: Actions.INIT_RESOURCE,
payload: resource
});
}, s);
})
.add<{ id: number }>(Actions.FOLDER_TOGGLE, (s, { payload }) => {
const { localMetaAttributes } = s.index.sequenceFolders;
const record = localMetaAttributes[parseInt("" + payload.id)];
2019-12-21 12:47:19 -07:00
record.open = !(record.open ?? true);
reindexFolders(s.index);
return s;
})
2019-12-05 15:40:06 -07:00
.add<boolean>(Actions.FOLDER_TOGGLE_ALL, (s, { payload }) => {
const { localMetaAttributes } = s.index.sequenceFolders;
Object.keys(localMetaAttributes).map((x) => {
localMetaAttributes[parseInt("" + x)].open = payload;
});
reindexFolders(s.index);
return s;
})
.add<{ id: number }>(Actions.FOLDER_TOGGLE_EDIT, (s, { payload }) => {
const { localMetaAttributes } = s.index.sequenceFolders;
const record = localMetaAttributes[parseInt("" + payload.id)];
record.editing = !record.editing;
reindexFolders(s.index);
return s;
})
.add<string | undefined>(Actions.FOLDER_SEARCH, (s, { payload }) => {
s.index.sequenceFolders.searchTerm = payload;
2019-12-11 14:08:07 -07:00
if (payload) {
2019-12-11 15:44:54 -07:00
const folders = searchFolderTree({
references: s.index.references,
input: payload,
root: s.index.sequenceFolders.folders
});
2019-12-10 15:13:16 -07:00
const { localMetaAttributes } = s.index.sequenceFolders;
Object /** Expand all folders when searching. */
.keys(localMetaAttributes)
.map(x => {
s
.index
.sequenceFolders
.localMetaAttributes[x as unknown as number]
.open = true;
});
const nextFolder = ingest({
2019-12-10 15:13:16 -07:00
localMetaAttributes,
folders
});
2019-12-13 14:11:22 -07:00
nextFolder.noFolder = nextFolder.noFolder.filter(uuid => {
const sq = s.index.references[uuid];
if (sq && sq.kind === "Sequence") {
const n = sq.body.name.toLowerCase();
return n.includes(payload);
} else {
return false;
}
});
s.index.sequenceFolders.filteredFolders = nextFolder;
} else {
s.index.sequenceFolders.filteredFolders = undefined;
}
reindexFolders(s.index);
return s;
});