1 | import { Subject } from 'rxjs';
|
2 | import { filter, map, takeUntil } from 'rxjs/operators';
|
3 | export function syncFrom(args) {
|
4 | const { target } = args;
|
5 | const parent = (args.parent || '').trim();
|
6 | if (!parent) {
|
7 | const err = `Cannot sync: parent node not specified.`;
|
8 | throw new Error(err);
|
9 | }
|
10 | if (!target.query.exists(parent)) {
|
11 | const err = `Cannot sync: the parent node '${parent}' does not exist in tree '${target.id}'.`;
|
12 | throw new Error(err);
|
13 | }
|
14 | const dispose$ = new Subject();
|
15 | const dispose = () => {
|
16 | dispose$.next();
|
17 | dispose$.complete();
|
18 | };
|
19 | target.dispose$.subscribe(() => dispose());
|
20 | if (args.until$) {
|
21 | args.until$.subscribe(() => dispose());
|
22 | }
|
23 | const source$ = args.source$.pipe(takeUntil(dispose$), filter((e) => e.type === 'TreeState/changed'), map((e) => e.payload));
|
24 | const change = (to) => {
|
25 | target.change((draft, ctx) => {
|
26 | const node = ctx.findById(parent);
|
27 | if (node) {
|
28 | ctx.children(node, (children) => {
|
29 | const index = children.findIndex((child) => child.id === to.id);
|
30 | if (index === -1) {
|
31 | children.push(to);
|
32 | }
|
33 | else {
|
34 | children[index] = to;
|
35 | }
|
36 | });
|
37 | }
|
38 | });
|
39 | };
|
40 | if (args.initial) {
|
41 | change(args.initial);
|
42 | }
|
43 | source$.subscribe((e) => {
|
44 | change(e.to);
|
45 | });
|
46 | const syncer = {
|
47 | parent,
|
48 | dispose$,
|
49 | dispose,
|
50 | };
|
51 | return syncer;
|
52 | }
|