Project

General

Profile

Hacking Workbench2 » History » Version 8

Ward Vandewege, 12/15/2020 04:23 PM

1 1 Peter Amstutz
h1. Hacking Workbench2
2
3 3 Peter Amstutz
h2. References
4
5
"Redux":https://redux.js.org/api/api-reference
6
"Material UI":https://material-ui.com/getting-started/installation/
7
8
h2. Startup
9
10 1 Peter Amstutz
The application logically begin in @workbench2/src/index.tsx@ with a call to fetchConfig() and then (when the promise is fulfilled) the constructs the major pieces of the application architecture:
11
12 2 Peter Amstutz
h2. Services
13 1 Peter Amstutz
14 2 Peter Amstutz
"services" interact with external resources.  These classes define methods for reading and writing to various types of backend (as far as I can tell, they don't hold any state themselves, but talk to external stateful services).  Services defined include a service for each the API server endpoint that workbench uses, WebDAV server, workbench2 configuration like vocabulary and file viewers, and preferences kept in the browser local store.
15
16
h2. Store
17
18 1 Peter Amstutz
"store" is a "Redux":https://redux.js.org/ state container.  State is divided into a groups.  Each group defines a "reducer".  A reducer is a function that takes (current state, action) and "reduces" it to a new state.  At start, reducers are executed with an undefined state to get the initial starting state.  After that, state is updated by "dispatching" an action to the state container.
19
20 2 Peter Amstutz
h2. App
21
22
The "App" is the root react component.  It is invoked to regenerate the page, producing a "virtual DOM".  ReactDOM merges the virtual DOM changes into the actual browser DOM.
23
24 5 Peter Amstutz
h2. Split implementation
25
26 7 Peter Amstutz
Many program features (for example, the "process" panel for displaying a container request) consist of both actions and/or thunks (and their associated reducers or middleware) in the @store/@ tree as well as React components that live in the @views/@ tree.  For example, @loadProcess@ in @store/workbench/workbench-actions@ is responsible for initializing the state that will be used to create and update the @ProcessPanel@ DOM tree.
27 5 Peter Amstutz
28 2 Peter Amstutz
h2. Interaction loop
29
30
# Render the DOM (based on state from redux store)
31
# User clicks on something
32
# onClick handler dispatches an action
33
# reducer produces a new state based on the action
34
# subscribers are notified that the state has changed
35
36
'react-redux' links the data store to components use those state items.  As part of defining a react component, call @connect@ with a function that extracts only the state required to render the component from the data store.  This returns a function, call this with the actual react component definition.  This optimizes re-rendering by only updating components that are potentially affected by a given state change.
37
38
h2. Defining new state items
39
40
@workbench2/src/store/store.ts@
41
42
@createRootReducer@ defines the reducer groups.  Pick one which is relevant, or define a new one.  A reducer group "xyz" is defined in @workbench2/src/store/xyz/xyz-reducer.ts@
43
44
Add the state item to @interface XyzState@ and @initialState: XyzState@ for the group.
45
46
h2. Defining new actions
47
48
Actions types are declared in @xyzActions@ in @workbench2/src/store/xyz/xyz-actions.ts@.
49
50
Actions are implemented in @xyzReducer@ in @workbench2/src/store/xyz/xyz-reducer.ts@ 
51
52
The reducer for the action reduces (current state, action) to (new state).  The new state must have all the state items.  There is a shorthand syntax for this: @{ ...state, open: false }@ which means "construct a new object with all the items from 'state', except those declared explicitly"
53
54
A common pattern seems to be to define functions that can be called or used as event handlers that implement high level behaviors by calling services and dispatching actions.
55 3 Peter Amstutz
56
h2. Middleware and thunks
57
58
Redux "middleware":https://redux.js.org/api/applymiddleware is a chain of functions that the action is passed through before it gets to the store.
59
60
Middleware enables these three things:
61
62
* Execute code that should happen before an action modifies store
63
* Modify or suppress actions before they get to the store
64
* Execute code in response to an action after it has modified the store
65
66
If you read the redux documentation, you'll notice that it only talks about dispatching actions, not functions.  Workbench2 uses a library called "redux-thunk":https://github.com/reduxjs/redux-thunk .  The redux-thunk middleware intercepts dispatched functions and calls them with (dispatch, getState, services).  They don't go to the store.  You can use a thunk to invoke an asynchronous function that will proceed independently from the caller.
67
68
As a design principal, use a thunk when you need to do some asynchronous action before *putting* data into the store.  For example, making an API call, and then updating the store with the result.
69
70
Middleware should be *acting* on data in the store. For example, synchronizing browser local storage.
71
72 4 Peter Amstutz
h2. DataExplorer
73
74
The DataExplorer uses middleware.  
75
76
# An event callback dispatches to a thunk, such as "loadCollection" or "loadProcess"
77
# The thunk's call tree calls REQUEST_ITEMS
78
# The middleware responds to REQUEST_ITEMS by starting an asynchronous API request. 
79
# When the API response comes back, the handler uses SET_ITEMS to put data into the table.
80 8 Ward Vandewege
81
h2. Running tests
82
83
See [[Running tests#Running-workbench2-tests]]: "Running tests"