Skip to content

Commit f7d5f2c

Browse files
committed
Refactor functions to patternMatching.ts
1 parent ab092f1 commit f7d5f2c

File tree

3 files changed

+107
-66
lines changed

3 files changed

+107
-66
lines changed

dash/dash-renderer/src/actions/callbacks.ts

Lines changed: 12 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
import {
22
concat,
3-
dissoc,
4-
equals,
53
flatten,
64
intersection,
75
keys,
@@ -33,7 +31,8 @@ import {
3331
IPrioritizedCallback,
3432
LongCallbackInfo,
3533
CallbackResponse,
36-
CallbackResponseData
34+
CallbackResponseData,
35+
SideUpdateOutput
3736
} from '../types/callbacks';
3837
import {isMultiValued, stringifyId, isMultiOutputProp} from './dependencies';
3938
import {urlBase} from './utils';
@@ -46,6 +45,8 @@ import {handlePatch, isPatch} from './patch';
4645
import {getPath} from './paths';
4746

4847
import {requestDependencies} from './requestDependencies';
48+
import {parsePMCId} from './patternMatching';
49+
import {replacePMC} from './patternMatching';
4950

5051
export const addBlockedCallbacks = createAction<IBlockedCallback[]>(
5152
CallbackActionType.AddBlocked
@@ -342,19 +343,14 @@ function updateComponent(component_id: any, props: any) {
342343
};
343344
}
344345

345-
function parsePMCId(id: string) {
346-
let componentId, propName;
347-
const index = id.lastIndexOf('}');
348-
if (index + 2 < id.length) {
349-
propName = id.substring(index + 2);
350-
componentId = JSON.parse(id.substring(0, index + 1));
351-
} else {
352-
componentId = JSON.parse(id);
353-
}
354-
return [componentId, propName];
355-
}
356-
357-
function sideUpdate(outputs: any, cb: ICallbackPayload) {
346+
/**
347+
* Update a component props with `running`/`progress`/`set_props` calls.
348+
*
349+
* @param outputs Props to update.
350+
* @param cb The originating callback info.
351+
* @returns
352+
*/
353+
function sideUpdate(outputs: SideUpdateOutput, cb: ICallbackPayload) {
358354
return function (dispatch: any, getState: any) {
359355
toPairs(outputs)
360356
.reduce((acc, [id, value], i) => {
@@ -389,56 +385,6 @@ function sideUpdate(outputs: any, cb: ICallbackPayload) {
389385
};
390386
}
391387

392-
function getAllPMCIds(id: any, state: any, triggerKey: string) {
393-
const keysOfIds = keys(id);
394-
const idKey = keysOfIds.join(',');
395-
return state.paths.objs[idKey]
396-
.map((obj: any) =>
397-
keysOfIds.reduce((acc, key, i) => {
398-
acc[key] = obj.values[i];
399-
return acc;
400-
}, {} as any)
401-
)
402-
.filter((obj: any) =>
403-
equals(dissoc(triggerKey, obj), dissoc(triggerKey, id))
404-
);
405-
}
406-
407-
function replacePMC(
408-
id: any,
409-
cb: ICallbackPayload,
410-
index: number,
411-
getState: any
412-
) {
413-
let extras: any = [];
414-
const replaced: any = {};
415-
toPairs(id).forEach(([key, value]) => {
416-
if (extras.length) {
417-
// All done.
418-
return;
419-
}
420-
if (Array.isArray(value)) {
421-
const triggerValue = (cb.parsedChangedPropsIds[index] ||
422-
cb.parsedChangedPropsIds[0])[key];
423-
if (value.includes('MATCH')) {
424-
replaced[key] = triggerValue;
425-
} else if (value.includes('ALL')) {
426-
extras = getAllPMCIds(id, getState(), key);
427-
} else if (value.includes('ALLSMALLER')) {
428-
extras = getAllPMCIds(id, getState(), key).filter(
429-
(obj: any) => obj[key] < triggerValue
430-
);
431-
}
432-
} else {
433-
replaced[key] = value;
434-
}
435-
});
436-
if (extras.length) {
437-
return extras;
438-
}
439-
return [replaced];
440-
}
441-
442388
function handleServerside(
443389
dispatch: any,
444390
hooks: any,
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
import {keys, equals, dissoc, toPairs} from 'ramda';
2+
import {ICallbackPayload} from '../types/callbacks';
3+
4+
/**
5+
* Deserialize pattern matching ids that come in one of the form:
6+
* - '{"type":"component","index":["MATCH"]}.children'
7+
* - '{"type":"component","index":["MATCH"]}'
8+
*
9+
* @param id The raw object as a string id.
10+
* @returns The id object.
11+
*/
12+
export function parsePMCId(id: string): [any, string | undefined] {
13+
let componentId, propName;
14+
const index = id.lastIndexOf('}');
15+
if (index + 2 < id.length) {
16+
propName = id.substring(index + 2);
17+
componentId = JSON.parse(id.substring(0, index + 1));
18+
} else {
19+
componentId = JSON.parse(id);
20+
}
21+
return [componentId, propName];
22+
}
23+
24+
/**
25+
* Get all the associated ids for an id.
26+
*
27+
* @param id Id to get all the pmc ids from.
28+
* @param state State of the store.
29+
* @param triggerKey Key to remove from the equality comparison.
30+
* @returns
31+
*/
32+
export function getAllPMCIds(id: any, state: any, triggerKey: string) {
33+
const keysOfIds = keys(id);
34+
const idKey = keysOfIds.join(',');
35+
return state.paths.objs[idKey]
36+
.map((obj: any) =>
37+
keysOfIds.reduce((acc, key, i) => {
38+
acc[key] = obj.values[i];
39+
return acc;
40+
}, {} as any)
41+
)
42+
.filter((obj: any) =>
43+
equals(dissoc(triggerKey, obj), dissoc(triggerKey, id))
44+
);
45+
}
46+
47+
/**
48+
* Replace the pattern matching ids with the actual trigger value
49+
* for MATCH, all the ids for ALL and smaller than the trigger value
50+
* for ALLSMALLER.
51+
*
52+
* @param id The parsed id in dictionary format.
53+
* @param cb Original callback info.
54+
* @param index Index of the dependency in case there is more than one changed id.
55+
* @param getState Function to get the state of the redux store.
56+
* @returns List of replaced ids.
57+
*/
58+
export function replacePMC(
59+
id: any,
60+
cb: ICallbackPayload,
61+
index: number,
62+
getState: any
63+
): any[] {
64+
let extras: any = [];
65+
const replaced: any = {};
66+
toPairs(id).forEach(([key, value]) => {
67+
if (extras.length) {
68+
// All done.
69+
return;
70+
}
71+
if (Array.isArray(value)) {
72+
const triggerValue = (cb.parsedChangedPropsIds[index] ||
73+
cb.parsedChangedPropsIds[0])[key];
74+
if (value.includes('MATCH')) {
75+
replaced[key] = triggerValue;
76+
} else if (value.includes('ALL')) {
77+
extras = getAllPMCIds(id, getState(), key);
78+
} else if (value.includes('ALLSMALLER')) {
79+
extras = getAllPMCIds(id, getState(), key).filter(
80+
(obj: any) => obj[key] < triggerValue
81+
);
82+
}
83+
} else {
84+
replaced[key] = value;
85+
}
86+
});
87+
if (extras.length) {
88+
return extras;
89+
}
90+
return [replaced];
91+
}

dash/dash-renderer/src/types/callbacks.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,3 +107,7 @@ export type CallbackResponseData = {
107107
cancel?: ICallbackProperty[];
108108
sideUpdate?: any;
109109
};
110+
111+
export type SideUpdateOutput = {
112+
[key: string]: any;
113+
};

0 commit comments

Comments
 (0)