Example #1
0
            exhaustMap((a) => {
                if (!(a.ids || []).length) {
                    return of(
                        {type: shortModelsActionTypes.UPSERT, items: []},
                        {type: `${a.type}_OK`}
                    );
                }
                return this.ConfigureState.state$.pipe(
                    this.ConfigSelectors.selectShortModels(),
                    take(1),
                    switchMap((items) => {
                        if (!items.pristine && a.ids && a.ids.every((_id) => items.value.has(_id)))
                            return of({type: `${a.type}_OK`});

                        return from(this.Clusters.getClusterModels(a.clusterID)).pipe(
                            switchMap(({data}) => of(
                                {type: shortModelsActionTypes.UPSERT, items: data},
                                {type: `${a.type}_OK`}
                            ))
                        );
                    }),
                    catchError((error) => of({
                        type: `${a.type}_ERR`,
                        error: {
                            message: `Failed to load domain models: ${error.data}.`
                        },
                        action: a
                    }))
                );
            })
Example #2
0
            switchMap(([action, edit]) => {
                const changedItems = _applyChangedIDs(edit, {cluster: action.cluster});
                const actions = [{
                    type: cachesActionTypes.UPSERT,
                    items: changedItems.caches
                },
                {
                    type: shortCachesActionTypes.UPSERT,
                    items: changedItems.caches
                },
                {
                    type: clustersActionTypes.UPSERT,
                    items: [changedItems.cluster]
                },
                {
                    type: shortClustersActionTypes.UPSERT,
                    items: [this.Clusters.toShortCluster(changedItems.cluster)]
                }
                ].filter((a) => a.items.length);

                return merge(
                    of(...actions),
                    from(this.Clusters.saveBasic(changedItems)).pipe(
                        switchMap((res) => of(
                            {type: 'EDIT_CLUSTER', cluster: changedItems.cluster},
                            basicSaveOK(changedItems)
                        )),
                        catchError((res) => of(
                            basicSaveErr(changedItems, res),
                            {type: 'UNDO_ACTIONS', actions}
                        ))
                    )
                );
            })
Example #3
0
                    switchMap((cache) => {
                        if (cache)
                            return of({type: `${a.type}_OK`, cache});

                        return from(this.Caches.getCache(a.cacheID)).pipe(
                            switchMap(({data}) => of(
                                {type: 'CACHE', cache: data},
                                {type: `${a.type}_OK`, cache: data}
                            ))
                        );
                    }),
Example #4
0
                    switchMap((igfs) => {
                        if (igfs)
                            return of({type: `${a.type}_OK`, igfs});

                        return from(this.IGFSs.getIGFS(a.igfsID)).pipe(
                            switchMap(({data}) => of(
                                {type: 'IGFS', igfs: data},
                                {type: `${a.type}_OK`, igfs: data}
                            ))
                        );
                    }),
Example #5
0
                    switchMap((model) => {
                        if (model)
                            return of({type: `${a.type}_OK`, model});

                        return from(this.Models.getModel(a.modelID)).pipe(
                            switchMap(({data}) => of(
                                {type: 'MODEL', model: data},
                                {type: `${a.type}_OK`, model: data}
                            ))
                        );
                    }),
Example #6
0
                    switchMap((items) => {
                        if (!items.pristine && a.ids && a.ids.every((_id) => items.value.has(_id)))
                            return of({type: `${a.type}_OK`});

                        return from(this.Clusters.getClusterModels(a.clusterID)).pipe(
                            switchMap(({data}) => of(
                                {type: shortModelsActionTypes.UPSERT, items: data},
                                {type: `${a.type}_OK`}
                            ))
                        );
                    }),
Example #7
0
 exhaustMap((action) => {
     return from(this.Clusters.getConfiguration(action.clusterID)).pipe(
         switchMap(({data}) => of(
             completeConfiguration(data),
             {type: 'LOAD_COMPLETE_CONFIGURATION_OK', data}
         )),
         catchError((error) => of({
             type: 'LOAD_COMPLETE_CONFIGURATION_ERR',
             error: {
                 message: `Failed to load cluster configuration: ${error.data}.`
             },
             action
         })));
 })
Example #8
0
 exhaustMap((a) => {
     return from(this.Clusters.getClustersOverview()).pipe(
         switchMap(({data}) => of(
             {type: shortClustersActionTypes.SET, items: data},
             {type: `${a.type}_OK`}
         )),
         catchError((error) => of({
             type: `${a.type}_ERR`,
             error: {
                 message: `Failed to load clusters: ${error.data}`
             },
             action: a
         }))
     );
 })
Example #9
0
  componentFromStream(props$ => {
    const id$ = props$.pipe(
      map(props => props.params.id),
      distinctUntilChanged()
    );
    const job$ = id$.pipe(
      switchMap(id => getGraphQL(id)),
      map(({ data: { job } }) => job)
    );

    return combineLatest([
      job$,
      props$,
      jobActionDialog$,
      disabledDialog$
    ]).pipe(
      map(([job, { router, ...props }, jobActionDialog, disabledDialog]) => {
        function onJobDeleteSuccess() {
          router.push("/jobs");
          closeDialog();
        }

        return (
          <JobDetailPage
            {...props}
            job={job}
            jobActionDialog={jobActionDialog}
            disabledDialog={disabledDialog}
            errorMsg={null}
            handleDestroyButtonClick={handleDestroyButtonClick}
            handleEditButtonClick={handleEditButtonClick}
            onJobDeleteSuccess={onJobDeleteSuccess}
            closeDialog={closeDialog}
            disableDialog={disableDialog}
          />
        );
      }),
      catchError(() => of(<ErrorScreen />)),
      startWith(<LoadingScreen />)
    );
  })
Example #10
0
 switchMap((cluster) => {
     if (cluster) {
         return of(
             {type: 'EDIT_CLUSTER', cluster},
             {type: 'LOAD_AND_EDIT_CLUSTER_OK'}
         );
     }
     return from(this.Clusters.getCluster(a.clusterID)).pipe(
         switchMap(({data}) => of(
             {type: clustersActionTypes.UPSERT, items: [data]},
             {type: 'EDIT_CLUSTER', cluster: data},
             {type: 'LOAD_AND_EDIT_CLUSTER_OK'}
         )),
         catchError((error) => of({
             type: 'LOAD_AND_EDIT_CLUSTER_ERR',
             error: {
                 message: `Failed to load cluster: ${error.data}.`
             }
         }))
     );
 })
Example #11
0
 exhaustMap(([a, shortClusters]) => {
     if (a.clusterID === 'new') {
         return of(
             {
                 type: 'EDIT_CLUSTER',
                 cluster: {
                     ...this.Clusters.getBlankCluster(),
                     name: uniqueName(defaultNames.cluster, shortClusters)
                 }
             },
             {type: 'LOAD_AND_EDIT_CLUSTER_OK'}
         );
     }
     return this.ConfigureState.state$.pipe(
         this.ConfigSelectors.selectCluster(a.clusterID),
         take(1),
         switchMap((cluster) => {
             if (cluster) {
                 return of(
                     {type: 'EDIT_CLUSTER', cluster},
                     {type: 'LOAD_AND_EDIT_CLUSTER_OK'}
                 );
             }
             return from(this.Clusters.getCluster(a.clusterID)).pipe(
                 switchMap(({data}) => of(
                     {type: clustersActionTypes.UPSERT, items: [data]},
                     {type: 'EDIT_CLUSTER', cluster: data},
                     {type: 'LOAD_AND_EDIT_CLUSTER_OK'}
                 )),
                 catchError((error) => of({
                     type: 'LOAD_AND_EDIT_CLUSTER_ERR',
                     error: {
                         message: `Failed to load cluster: ${error.data}.`
                     }
                 }))
             );
         })
     );
 })
Example #12
0
            exhaustMap((a) => {
                return this.ConfigureState.state$.pipe(
                    this.ConfigSelectors.selectIGFS(a.igfsID),
                    take(1),
                    switchMap((igfs) => {
                        if (igfs)
                            return of({type: `${a.type}_OK`, igfs});

                        return from(this.IGFSs.getIGFS(a.igfsID)).pipe(
                            switchMap(({data}) => of(
                                {type: 'IGFS', igfs: data},
                                {type: `${a.type}_OK`, igfs: data}
                            ))
                        );
                    }),
                    catchError((error) => of({
                        type: `${a.type}_ERR`,
                        error: {
                            message: `Failed to load IGFS: ${error.data}.`
                        }
                    }))
                );
            })
Example #13
0
            exhaustMap((a) => {
                return this.ConfigureState.state$.pipe(
                    this.ConfigSelectors.selectModel(a.modelID),
                    take(1),
                    switchMap((model) => {
                        if (model)
                            return of({type: `${a.type}_OK`, model});

                        return from(this.Models.getModel(a.modelID)).pipe(
                            switchMap(({data}) => of(
                                {type: 'MODEL', model: data},
                                {type: `${a.type}_OK`, model: data}
                            ))
                        );
                    }),
                    catchError((error) => of({
                        type: `${a.type}_ERR`,
                        error: {
                            message: `Failed to load domain model: ${error.data}.`
                        }
                    }))
                );
            })
Example #14
0
            exhaustMap((a) => {
                return this.ConfigureState.state$.pipe(
                    this.ConfigSelectors.selectCache(a.cacheID),
                    take(1),
                    switchMap((cache) => {
                        if (cache)
                            return of({type: `${a.type}_OK`, cache});

                        return from(this.Caches.getCache(a.cacheID)).pipe(
                            switchMap(({data}) => of(
                                {type: 'CACHE', cache: data},
                                {type: `${a.type}_OK`, cache: data}
                            ))
                        );
                    }),
                    catchError((error) => of({
                        type: `${a.type}_ERR`,
                        error: {
                            message: `Failed to load cache: ${error.data}.`
                        }
                    }))
                );
            })
Example #15
0
const removePackageRepositoryGraphql = (name, uri) =>
  dataLayer.query(removePackageRepository, {
    name,
    uri
  });

const deleteEvent$ = new Subject();
const deleteRepository$ = deleteEvent$.pipe(
  switchMap(repository => {
    return removePackageRepositoryGraphql(repository.name, repository.url).pipe(
      startWith({ pendingRequest: true }),
      map(result => {
        return {
          result,
          pendingRequest: false
        };
      }),
      tap(() => {
        repository.complete();
      })
    );
  }),
  startWith({ pendingRequest: false }),
  catchError(error => {
    return deleteRepository$.pipe(
      startWith({
        error: getErrorMessage(error.response),
        pendingRequest: false
      })
    );
  })
Example #16
0
  componentDidMount(): void {
    const { editorFocused, kernelStatus, focusAbove, focusBelow } = this.props;

    require("codemirror/addon/hint/show-hint");
    require("codemirror/addon/hint/anyword-hint");

    require("codemirror/addon/edit/matchbrackets");
    require("codemirror/addon/edit/closebrackets");

    require("codemirror/addon/comment/comment.js");

    require("codemirror/mode/python/python");
    require("codemirror/mode/ruby/ruby");
    require("codemirror/mode/javascript/javascript");
    require("codemirror/mode/css/css");
    require("codemirror/mode/julia/julia");
    require("codemirror/mode/r/r");
    require("codemirror/mode/clike/clike");
    require("codemirror/mode/shell/shell");
    require("codemirror/mode/sql/sql");
    require("codemirror/mode/markdown/markdown");
    require("codemirror/mode/gfm/gfm");

    require("./mode/ipython");

    this.cm = require("codemirror").fromTextArea(
      this.textarea,
      this.defaultOptions
    );

    this.cm.setValue(this.props.defaultValue || this.props.value || "");

    // On first load, if focused, set codemirror to focus
    if (editorFocused) {
      this.cm.focus();
    }

    this.cm.on("topBoundary", focusAbove);
    this.cm.on("bottomBoundary", focusBelow);

    this.cm.on("focus", this.focusChanged.bind(this, true));
    this.cm.on("blur", this.focusChanged.bind(this, false));
    this.cm.on("change", this.codemirrorValueChanged.bind(this));

    const keyupEvents = fromEvent(this.cm, "keyup", (editor, ev) => ({
      editor,
      ev
    }));

    this.keyupEventsSubscriber = keyupEvents
      .pipe(switchMap(i => of(i)))
      .subscribe(({ editor, ev }) => {
        const cursor = editor.getDoc().getCursor();
        const token = editor.getTokenAt(cursor);

        if (
          !editor.state.completionActive &&
          !excludedIntelliSenseTriggerKeys[
            (ev.keyCode || ev.which).toString()
          ] &&
          (token.type === "tag" ||
            token.type === "variable" ||
            token.string === " " ||
            token.string === "<" ||
            token.string === "/") &&
          kernelStatus === "idle"
        ) {
          editor.execCommand("autocomplete", { completeSingle: false });
        }
      });
  }
 switchMap(() => {
   const frameReady = new Subject();
   const consoleProxy = new Subject();
   const frameTests = createTestFramer(
     document,
     state$,
     frameReady,
     consoleProxy
   );
   const challengeResults = frameReady.pipe(
     // Delay for jQuery ready code, in jQuery challenges
     delay(250),
     pluck('checkChallengePayload'),
     map(checkChallengePayload => ({
       checkChallengePayload,
       tests: challengeTestsSelector(state$.value)
     })),
     switchMap(({ checkChallengePayload, tests }) => {
       const postTests = of(
         updateConsole('// tests completed'),
         logsToConsole('// console output'),
         checkChallenge(checkChallengePayload)
       ).pipe(delay(250));
       return runTestsInTestFrame(document, tests).pipe(
         switchMap(tests => {
           return from(tests).pipe(
             map(({ message }) => message),
             filter(overEvery(isString, Boolean)),
             map(updateConsole),
             concat(of(updateTests(tests)))
           );
         }),
         concat(postTests)
       );
     })
   );
   const buildAndFrameChallenge = action$.pipe(
     ofType(types.executeChallenge),
     filter(() => {
       const { challengeType } = challengeMetaSelector(state$.value);
       return (
         challengeType !== challengeTypes.js &&
         challengeType !== challengeTypes.bonfire
       );
     }),
     debounceTime(executeDebounceTimeout),
     filter(() => isJSEnabledSelector(state$.value)),
     switchMap(() => {
       const state = state$.value;
       const { challengeType } = challengeMetaSelector(state);
       const build =
         challengeType === challengeTypes.backend
           ? buildBackendChallenge
           : buildFromFiles;
       return build(state).pipe(
         tap(frameTests),
         ignoreElements(),
         startWith(initLogs()),
         startWith(initConsole('// running tests')),
         catchError(err => {
           console.error(err);
           return of(disableJSOnError(err));
         })
       );
     })
   );
   const proxyConsole = consoleProxy.pipe(map(updateLogs));
   return merge(buildAndFrameChallenge, challengeResults, proxyConsole);
 })
 const handler = (argument, context) => {
     return rxjs_1.from(loader())
         .pipe(operators_1.switchMap(fn => fn(argument, context)));
 };
Example #19
0
            switchMap((action) => {
                const actions = [
                    {
                        type: modelsActionTypes.UPSERT,
                        items: action.changedItems.models
                    },
                    {
                        type: shortModelsActionTypes.UPSERT,
                        items: action.changedItems.models.map((m) => this.Models.toShortModel(m))
                    },
                    {
                        type: igfssActionTypes.UPSERT,
                        items: action.changedItems.igfss
                    },
                    {
                        type: shortIGFSsActionTypes.UPSERT,
                        items: action.changedItems.igfss
                    },
                    {
                        type: cachesActionTypes.UPSERT,
                        items: action.changedItems.caches
                    },
                    {
                        type: shortCachesActionTypes.UPSERT,
                        items: action.changedItems.caches.map(Caches.toShortCache)
                    },
                    {
                        type: clustersActionTypes.UPSERT,
                        items: [action.changedItems.cluster]
                    },
                    {
                        type: shortClustersActionTypes.UPSERT,
                        items: [Clusters.toShortCluster(action.changedItems.cluster)]
                    }
                ].filter((a) => a.items.length);

                return merge(
                    of(...actions),
                    from(Clusters.saveAdvanced(action.changedItems)).pipe(
                        switchMap((res) => {
                            return of(
                                {type: 'EDIT_CLUSTER', cluster: action.changedItems.cluster},
                                {type: 'ADVANCED_SAVE_COMPLETE_CONFIGURATION_OK', changedItems: action.changedItems}
                            );
                        }),
                        catchError((res) => {
                            return of({
                                type: 'ADVANCED_SAVE_COMPLETE_CONFIGURATION_ERR',
                                changedItems: action.changedItems,
                                action,
                                error: {
                                    message: `Failed to save cluster "${action.changedItems.cluster.name}": ${res.data}.`
                                }
                            }, {
                                type: 'UNDO_ACTIONS',
                                actions
                            });
                        })
                    )
                );
            })
Example #20
0
export const launchKernelEpic = (
  action$: ActionsObservable<redux$Action>,
  state$: StateObservable<AppState>
): Observable<redux$Action> =>
  action$.pipe(
    ofType(actions.LAUNCH_KERNEL),
    // We must kill the previous kernel now
    // Then launch the next one
    switchMap((action: actions.LaunchKernelAction) => {
      if (
        !action.payload ||
        !action.payload.kernelSpec ||
        !action.payload.kernelRef
      ) {
        return of(
          actions.launchKernelFailed({
            error: new Error("launchKernel needs a kernelSpec and a kernelRef"),
            kernelRef: action.payload && action.payload.kernelRef,
            contentRef: action.payload.contentRef
          })
        );
      }

      // TODO: Do the async version of `ipc.send`, potentially coordinate with main process
      ipc.send("nteract:ping:kernel", action.payload.kernelSpec);

      const oldKernelRef = selectors.currentKernelRef(state$.value);

      // Kill the old kernel by emitting the action to kill it if it exists
      let cleanupOldKernel$ = empty();
      if (oldKernelRef && oldKernelRef !== action.payload.kernelRef) {
        cleanupOldKernel$ = of(
          actions.killKernel({ restarting: false, kernelRef: oldKernelRef })
        );
      }

      return merge(
        launchKernelObservable(
          action.payload.kernelSpec,
          action.payload.cwd,
          action.payload.kernelRef,
          action.payload.contentRef
        ),
        // Was there a kernel before (?) -- kill it if so, otherwise nothing else
        cleanupOldKernel$
      ).pipe(
        catchError((error: Error) =>
          of(
            actions.launchKernelFailed({
              error,
              kernelRef: action.payload.kernelRef,
              contentRef: action.payload.contentRef
            })
          )
        )
      );
    }),
    // TODO: ask @jayphelps about `merge(of(errorAction), source)` replaying the
    // original action
    catchError((error: Error) => {
      return of({ type: "ERROR", payload: error, error: true });
    })
  );
Example #21
0
    /**
     * @param {ConfigureState} ConfigureState
     * @param {Caches} Caches
     * @param {IGFSs} IGFSs
     * @param {Models} Models
     * @param {ConfigSelectors} ConfigSelectors
     * @param {Clusters} Clusters
     * @param {object} $state
     * @param {object} IgniteMessages
     * @param {object} IgniteConfirm
     * @param {Confirm} Confirm
     * @param {ConfigurationDownload} ConfigurationDownload
     */
    constructor(ConfigureState, Caches, IGFSs, Models, ConfigSelectors, Clusters, $state, IgniteMessages, IgniteConfirm, Confirm, ConfigurationDownload) {
        this.ConfigureState = ConfigureState;
        this.ConfigSelectors = ConfigSelectors;
        this.IGFSs = IGFSs;
        this.Models = Models;
        this.Caches = Caches;
        this.Clusters = Clusters;
        this.$state = $state;
        this.IgniteMessages = IgniteMessages;
        this.IgniteConfirm = IgniteConfirm;
        this.Confirm = Confirm;
        this.configurationDownload = ConfigurationDownload;

        this.loadConfigurationEffect$ = this.ConfigureState.actions$.pipe(
            ofType('LOAD_COMPLETE_CONFIGURATION'),
            exhaustMap((action) => {
                return from(this.Clusters.getConfiguration(action.clusterID)).pipe(
                    switchMap(({data}) => of(
                        completeConfiguration(data),
                        {type: 'LOAD_COMPLETE_CONFIGURATION_OK', data}
                    )),
                    catchError((error) => of({
                        type: 'LOAD_COMPLETE_CONFIGURATION_ERR',
                        error: {
                            message: `Failed to load cluster configuration: ${error.data}.`
                        },
                        action
                    })));
            })
        );

        this.storeConfigurationEffect$ = this.ConfigureState.actions$.pipe(
            ofType(COMPLETE_CONFIGURATION),
            exhaustMap(({configuration: {cluster, caches, models, igfss}}) => of(...[
                cluster && {type: clustersActionTypes.UPSERT, items: [cluster]},
                caches && caches.length && {type: cachesActionTypes.UPSERT, items: caches},
                models && models.length && {type: modelsActionTypes.UPSERT, items: models},
                igfss && igfss.length && {type: igfssActionTypes.UPSERT, items: igfss}
            ].filter((v) => v)))
        );

        this.saveCompleteConfigurationEffect$ = this.ConfigureState.actions$.pipe(
            ofType(ADVANCED_SAVE_COMPLETE_CONFIGURATION),
            switchMap((action) => {
                const actions = [
                    {
                        type: modelsActionTypes.UPSERT,
                        items: action.changedItems.models
                    },
                    {
                        type: shortModelsActionTypes.UPSERT,
                        items: action.changedItems.models.map((m) => this.Models.toShortModel(m))
                    },
                    {
                        type: igfssActionTypes.UPSERT,
                        items: action.changedItems.igfss
                    },
                    {
                        type: shortIGFSsActionTypes.UPSERT,
                        items: action.changedItems.igfss
                    },
                    {
                        type: cachesActionTypes.UPSERT,
                        items: action.changedItems.caches
                    },
                    {
                        type: shortCachesActionTypes.UPSERT,
                        items: action.changedItems.caches.map(Caches.toShortCache)
                    },
                    {
                        type: clustersActionTypes.UPSERT,
                        items: [action.changedItems.cluster]
                    },
                    {
                        type: shortClustersActionTypes.UPSERT,
                        items: [Clusters.toShortCluster(action.changedItems.cluster)]
                    }
                ].filter((a) => a.items.length);

                return merge(
                    of(...actions),
                    from(Clusters.saveAdvanced(action.changedItems)).pipe(
                        switchMap((res) => {
                            return of(
                                {type: 'EDIT_CLUSTER', cluster: action.changedItems.cluster},
                                {type: 'ADVANCED_SAVE_COMPLETE_CONFIGURATION_OK', changedItems: action.changedItems}
                            );
                        }),
                        catchError((res) => {
                            return of({
                                type: 'ADVANCED_SAVE_COMPLETE_CONFIGURATION_ERR',
                                changedItems: action.changedItems,
                                action,
                                error: {
                                    message: `Failed to save cluster "${action.changedItems.cluster.name}": ${res.data}.`
                                }
                            }, {
                                type: 'UNDO_ACTIONS',
                                actions
                            });
                        })
                    )
                );
            })
        );

        this.addCacheToEditEffect$ = this.ConfigureState.actions$.pipe(
            ofType('ADD_CACHE_TO_EDIT'),
            switchMap(() => this.ConfigureState.state$.pipe(this.ConfigSelectors.selectCacheToEdit('new'), take(1))),
            map((cache) => ({type: 'UPSERT_CLUSTER_ITEM', itemType: 'caches', item: cache}))
        );

        this.errorNotificationsEffect$ = this.ConfigureState.actions$.pipe(
            filter((a) => a.error),
            tap((action) => this.IgniteMessages.showError(action.error)),
            ignoreElements()
        );

        this.loadUserClustersEffect$ = this.ConfigureState.actions$.pipe(
            ofType('LOAD_USER_CLUSTERS'),
            exhaustMap((a) => {
                return from(this.Clusters.getClustersOverview()).pipe(
                    switchMap(({data}) => of(
                        {type: shortClustersActionTypes.SET, items: data},
                        {type: `${a.type}_OK`}
                    )),
                    catchError((error) => of({
                        type: `${a.type}_ERR`,
                        error: {
                            message: `Failed to load clusters: ${error.data}`
                        },
                        action: a
                    }))
                );
            })
        );

        this.loadAndEditClusterEffect$ = ConfigureState.actions$.pipe(
            ofType('LOAD_AND_EDIT_CLUSTER'),
            withLatestFrom(this.ConfigureState.state$.pipe(this.ConfigSelectors.selectShortClustersValue())),
            exhaustMap(([a, shortClusters]) => {
                if (a.clusterID === 'new') {
                    return of(
                        {
                            type: 'EDIT_CLUSTER',
                            cluster: {
                                ...this.Clusters.getBlankCluster(),
                                name: uniqueName(defaultNames.cluster, shortClusters)
                            }
                        },
                        {type: 'LOAD_AND_EDIT_CLUSTER_OK'}
                    );
                }
                return this.ConfigureState.state$.pipe(
                    this.ConfigSelectors.selectCluster(a.clusterID),
                    take(1),
                    switchMap((cluster) => {
                        if (cluster) {
                            return of(
                                {type: 'EDIT_CLUSTER', cluster},
                                {type: 'LOAD_AND_EDIT_CLUSTER_OK'}
                            );
                        }
                        return from(this.Clusters.getCluster(a.clusterID)).pipe(
                            switchMap(({data}) => of(
                                {type: clustersActionTypes.UPSERT, items: [data]},
                                {type: 'EDIT_CLUSTER', cluster: data},
                                {type: 'LOAD_AND_EDIT_CLUSTER_OK'}
                            )),
                            catchError((error) => of({
                                type: 'LOAD_AND_EDIT_CLUSTER_ERR',
                                error: {
                                    message: `Failed to load cluster: ${error.data}.`
                                }
                            }))
                        );
                    })
                );
            })
        );

        this.loadCacheEffect$ = this.ConfigureState.actions$.pipe(
            ofType('LOAD_CACHE'),
            exhaustMap((a) => {
                return this.ConfigureState.state$.pipe(
                    this.ConfigSelectors.selectCache(a.cacheID),
                    take(1),
                    switchMap((cache) => {
                        if (cache)
                            return of({type: `${a.type}_OK`, cache});

                        return from(this.Caches.getCache(a.cacheID)).pipe(
                            switchMap(({data}) => of(
                                {type: 'CACHE', cache: data},
                                {type: `${a.type}_OK`, cache: data}
                            ))
                        );
                    }),
                    catchError((error) => of({
                        type: `${a.type}_ERR`,
                        error: {
                            message: `Failed to load cache: ${error.data}.`
                        }
                    }))
                );
            })
        );

        this.storeCacheEffect$ = this.ConfigureState.actions$.pipe(
            ofType('CACHE'),
            map((a) => ({type: cachesActionTypes.UPSERT, items: [a.cache]}))
        );

        this.loadShortCachesEffect$ = ConfigureState.actions$.pipe(
            ofType('LOAD_SHORT_CACHES'),
            exhaustMap((a) => {
                if (!(a.ids || []).length)
                    return of({type: `${a.type}_OK`});

                return this.ConfigureState.state$.pipe(
                    this.ConfigSelectors.selectShortCaches(),
                    take(1),
                    switchMap((items) => {
                        if (!items.pristine && a.ids && a.ids.every((_id) => items.value.has(_id)))
                            return of({type: `${a.type}_OK`});

                        return from(this.Clusters.getClusterCaches(a.clusterID)).pipe(
                            switchMap(({data}) => of(
                                {type: shortCachesActionTypes.UPSERT, items: data},
                                {type: `${a.type}_OK`}
                            ))
                        );
                    }),
                    catchError((error) => of({
                        type: `${a.type}_ERR`,
                        error: {
                            message: `Failed to load caches: ${error.data}.`
                        },
                        action: a
                    }))
                );
            })
        );

        this.loadIgfsEffect$ = this.ConfigureState.actions$.pipe(
            ofType('LOAD_IGFS'),
            exhaustMap((a) => {
                return this.ConfigureState.state$.pipe(
                    this.ConfigSelectors.selectIGFS(a.igfsID),
                    take(1),
                    switchMap((igfs) => {
                        if (igfs)
                            return of({type: `${a.type}_OK`, igfs});

                        return from(this.IGFSs.getIGFS(a.igfsID)).pipe(
                            switchMap(({data}) => of(
                                {type: 'IGFS', igfs: data},
                                {type: `${a.type}_OK`, igfs: data}
                            ))
                        );
                    }),
                    catchError((error) => of({
                        type: `${a.type}_ERR`,
                        error: {
                            message: `Failed to load IGFS: ${error.data}.`
                        }
                    }))
                );
            })
        );

        this.storeIgfsEffect$ = this.ConfigureState.actions$.pipe(
            ofType('IGFS'),
            map((a) => ({type: igfssActionTypes.UPSERT, items: [a.igfs]}))
        );

        this.loadShortIgfssEffect$ = ConfigureState.actions$.pipe(
            ofType('LOAD_SHORT_IGFSS'),
            exhaustMap((a) => {
                if (!(a.ids || []).length) {
                    return of(
                        {type: shortIGFSsActionTypes.UPSERT, items: []},
                        {type: `${a.type}_OK`}
                    );
                }
                return this.ConfigureState.state$.pipe(
                    this.ConfigSelectors.selectShortIGFSs(),
                    take(1),
                    switchMap((items) => {
                        if (!items.pristine && a.ids && a.ids.every((_id) => items.value.has(_id)))
                            return of({type: `${a.type}_OK`});

                        return from(this.Clusters.getClusterIGFSs(a.clusterID)).pipe(
                            switchMap(({data}) => of(
                                {type: shortIGFSsActionTypes.UPSERT, items: data},
                                {type: `${a.type}_OK`}
                            ))
                        );
                    }),
                    catchError((error) => of({
                        type: `${a.type}_ERR`,
                        error: {
                            message: `Failed to load IGFSs: ${error.data}.`
                        },
                        action: a
                    }))
                );
            })
        );

        this.loadModelEffect$ = this.ConfigureState.actions$.pipe(
            ofType('LOAD_MODEL'),
            exhaustMap((a) => {
                return this.ConfigureState.state$.pipe(
                    this.ConfigSelectors.selectModel(a.modelID),
                    take(1),
                    switchMap((model) => {
                        if (model)
                            return of({type: `${a.type}_OK`, model});

                        return from(this.Models.getModel(a.modelID)).pipe(
                            switchMap(({data}) => of(
                                {type: 'MODEL', model: data},
                                {type: `${a.type}_OK`, model: data}
                            ))
                        );
                    }),
                    catchError((error) => of({
                        type: `${a.type}_ERR`,
                        error: {
                            message: `Failed to load domain model: ${error.data}.`
                        }
                    }))
                );
            })
        );

        this.storeModelEffect$ = this.ConfigureState.actions$.pipe(
            ofType('MODEL'),
            map((a) => ({type: modelsActionTypes.UPSERT, items: [a.model]}))
        );

        this.loadShortModelsEffect$ = this.ConfigureState.actions$.pipe(
            ofType('LOAD_SHORT_MODELS'),
            exhaustMap((a) => {
                if (!(a.ids || []).length) {
                    return of(
                        {type: shortModelsActionTypes.UPSERT, items: []},
                        {type: `${a.type}_OK`}
                    );
                }
                return this.ConfigureState.state$.pipe(
                    this.ConfigSelectors.selectShortModels(),
                    take(1),
                    switchMap((items) => {
                        if (!items.pristine && a.ids && a.ids.every((_id) => items.value.has(_id)))
                            return of({type: `${a.type}_OK`});

                        return from(this.Clusters.getClusterModels(a.clusterID)).pipe(
                            switchMap(({data}) => of(
                                {type: shortModelsActionTypes.UPSERT, items: data},
                                {type: `${a.type}_OK`}
                            ))
                        );
                    }),
                    catchError((error) => of({
                        type: `${a.type}_ERR`,
                        error: {
                            message: `Failed to load domain models: ${error.data}.`
                        },
                        action: a
                    }))
                );
            })
        );

        this.basicSaveRedirectEffect$ = this.ConfigureState.actions$.pipe(
            ofType(BASIC_SAVE_OK),
            tap((a) => this.$state.go('base.configuration.edit.basic', {clusterID: a.changedItems.cluster._id}, {location: 'replace', custom: {justIDUpdate: true}})),
            ignoreElements()
        );

        this.basicDownloadAfterSaveEffect$ = this.ConfigureState.actions$.pipe(
            ofType(BASIC_SAVE_AND_DOWNLOAD),
            zip(this.ConfigureState.actions$.pipe(ofType(BASIC_SAVE_OK))),
            pluck('1'),
            tap((a) => this.configurationDownload.downloadClusterConfiguration(a.changedItems.cluster)),
            ignoreElements()
        );

        this.advancedDownloadAfterSaveEffect$ = merge(
            this.ConfigureState.actions$.pipe(ofType(ADVANCED_SAVE_CLUSTER)),
            this.ConfigureState.actions$.pipe(ofType(ADVANCED_SAVE_CACHE)),
            this.ConfigureState.actions$.pipe(ofType(ADVANCED_SAVE_IGFS)),
            this.ConfigureState.actions$.pipe(ofType(ADVANCED_SAVE_MODEL)),
        ).pipe(
            filter((a) => a.download),
            zip(this.ConfigureState.actions$.pipe(ofType('ADVANCED_SAVE_COMPLETE_CONFIGURATION_OK'))),
            pluck('1'),
            tap((a) => this.configurationDownload.downloadClusterConfiguration(a.changedItems.cluster)),
            ignoreElements()
        );

        this.advancedSaveRedirectEffect$ = this.ConfigureState.actions$.pipe(
            ofType('ADVANCED_SAVE_COMPLETE_CONFIGURATION_OK'),
            withLatestFrom(this.ConfigureState.actions$.pipe(ofType(ADVANCED_SAVE_COMPLETE_CONFIGURATION))),
            pluck('1', 'changedItems'),
            map((req) => {
                const firstChangedItem = Object.keys(req).filter((k) => k !== 'cluster')
                    .map((k) => Array.isArray(req[k]) ? [k, req[k][0]] : [k, req[k]])
                    .filter((v) => v[1])
                    .pop();
                return firstChangedItem ? [...firstChangedItem, req.cluster] : ['cluster', req.cluster, req.cluster];
            }),
            tap(([type, value, cluster]) => {
                const go = (state, params = {}) => this.$state.go(
                    state, {...params, clusterID: cluster._id}, {location: 'replace', custom: {justIDUpdate: true}}
                );

                switch (type) {
                    case 'models': {
                        const state = 'base.configuration.edit.advanced.models.model';
                        this.IgniteMessages.showInfo(`Model "${value.valueType}" saved`);

                        if (this.$state.is(state) && this.$state.params.modelID !== value._id)
                            return go(state, {modelID: value._id});

                        break;
                    }

                    case 'caches': {
                        const state = 'base.configuration.edit.advanced.caches.cache';
                        this.IgniteMessages.showInfo(`Cache "${value.name}" saved`);

                        if (this.$state.is(state) && this.$state.params.cacheID !== value._id)
                            return go(state, {cacheID: value._id});

                        break;
                    }

                    case 'igfss': {
                        const state = 'base.configuration.edit.advanced.igfs.igfs';
                        this.IgniteMessages.showInfo(`IGFS "${value.name}" saved`);

                        if (this.$state.is(state) && this.$state.params.igfsID !== value._id)
                            return go(state, {igfsID: value._id});

                        break;
                    }

                    case 'cluster': {
                        const state = 'base.configuration.edit.advanced.cluster';
                        this.IgniteMessages.showInfo(`Cluster "${value.name}" saved`);

                        if (this.$state.is(state) && this.$state.params.clusterID !== value._id)
                            return go(state);

                        break;
                    }

                    default: break;
                }
            }),
            ignoreElements()
        );

        this.removeClusterItemsEffect$ = this.ConfigureState.actions$.pipe(
            ofType(REMOVE_CLUSTER_ITEMS),
            exhaustMap((a) => {
                return a.confirm
                    // TODO: list items to remove in confirmation
                    ? from(this.Confirm.confirm('Are you sure you want to remove these items?')).pipe(
                        mapTo(a),
                        catchError(() => empty())
                    )
                    : of(a);
            }),
            map((a) => removeClusterItemsConfirmed(a.clusterID, a.itemType, a.itemIDs))
        );

        this.persistRemovedClusterItemsEffect$ = this.ConfigureState.actions$.pipe(
            ofType(REMOVE_CLUSTER_ITEMS_CONFIRMED),
            withLatestFrom(this.ConfigureState.actions$.pipe(ofType(REMOVE_CLUSTER_ITEMS))),
            filter(([a, b]) => {
                return a.itemType === b.itemType
                    && b.save
                    && JSON.stringify(a.itemIDs) === JSON.stringify(b.itemIDs);
            }),
            pluck('0'),
            withLatestFrom(this.ConfigureState.state$.pipe(pluck('edit'))),
            map(([action, edit]) => advancedSaveCompleteConfiguration(edit))
        );

        this.confirmClustersRemovalEffect$ = this.ConfigureState.actions$.pipe(
            ofType(CONFIRM_CLUSTERS_REMOVAL),
            pluck('clusterIDs'),
            switchMap((ids) => this.ConfigureState.state$.pipe(
                this.ConfigSelectors.selectClusterNames(ids),
                take(1)
            )),
            exhaustMap((names) => {
                return from(this.Confirm.confirm(`
                    <p>Are you sure you want to remove these clusters?</p>
                    <ul>${names.map((name) => `<li>${name}</li>`).join('')}</ul>
                `)).pipe(
                    map(confirmClustersRemovalOK),
                    catchError(() => empty())
                );
            })
        );

        this.persistRemovedClustersLocallyEffect$ = this.ConfigureState.actions$.pipe(
            ofType(CONFIRM_CLUSTERS_REMOVAL_OK),
            withLatestFrom(this.ConfigureState.actions$.pipe(ofType(CONFIRM_CLUSTERS_REMOVAL))),
            switchMap(([, {clusterIDs}]) => of(
                {type: shortClustersActionTypes.REMOVE, ids: clusterIDs},
                {type: clustersActionTypes.REMOVE, ids: clusterIDs}
            ))
        );

        this.persistRemovedClustersRemotelyEffect$ = this.ConfigureState.actions$.pipe(
            ofType(CONFIRM_CLUSTERS_REMOVAL_OK),
            withLatestFrom(
                this.ConfigureState.actions$.pipe(ofType(CONFIRM_CLUSTERS_REMOVAL)),
                this.ConfigureState.actions$.pipe(ofType(shortClustersActionTypes.REMOVE)),
                this.ConfigureState.actions$.pipe(ofType(clustersActionTypes.REMOVE))
            ),
            switchMap(([, {clusterIDs}, ...backup]) => this.Clusters.removeCluster$(clusterIDs).pipe(
                mapTo({
                    type: 'REMOVE_CLUSTERS_OK'
                }),
                catchError((e) => of(
                    {
                        type: 'REMOVE_CLUSTERS_ERR',
                        error: {
                            message: `Failed to remove clusters: ${e.data}`
                        }
                    },
                    {
                        type: 'UNDO_ACTIONS',
                        actions: backup
                    }
                ))
            ))
        );

        this.notifyRemoteClustersRemoveSuccessEffect$ = this.ConfigureState.actions$.pipe(
            ofType('REMOVE_CLUSTERS_OK'),
            withLatestFrom(this.ConfigureState.actions$.pipe(ofType(CONFIRM_CLUSTERS_REMOVAL))),
            tap(([, {clusterIDs}]) => this.IgniteMessages.showInfo(`Cluster(s) removed: ${clusterIDs.length}`)),
            ignoreElements()
        );

        const _applyChangedIDs = (edit, {cache, igfs, model, cluster} = {}) => ({
            cluster: {
                ...edit.changes.cluster,
                ...(cluster ? cluster : {}),
                caches: cache ? uniq([...edit.changes.caches.ids, cache._id]) : edit.changes.caches.ids,
                igfss: igfs ? uniq([...edit.changes.igfss.ids, igfs._id]) : edit.changes.igfss.ids,
                models: model ? uniq([...edit.changes.models.ids, model._id]) : edit.changes.models.ids
            },
            caches: cache ? uniq([...edit.changes.caches.changedItems, cache]) : edit.changes.caches.changedItems,
            igfss: igfs ? uniq([...edit.changes.igfss.changedItems, igfs]) : edit.changes.igfss.changedItems,
            models: model ? uniq([...edit.changes.models.changedItems, model]) : edit.changes.models.changedItems
        });

        this.advancedSaveCacheEffect$ = merge(
            this.ConfigureState.actions$.pipe(ofType(ADVANCED_SAVE_CLUSTER)),
            this.ConfigureState.actions$.pipe(ofType(ADVANCED_SAVE_CACHE)),
            this.ConfigureState.actions$.pipe(ofType(ADVANCED_SAVE_IGFS)),
            this.ConfigureState.actions$.pipe(ofType(ADVANCED_SAVE_MODEL)),
        ).pipe(
            withLatestFrom(this.ConfigureState.state$.pipe(pluck('edit'))),
            map(([action, edit]) => ({
                type: ADVANCED_SAVE_COMPLETE_CONFIGURATION,
                changedItems: _applyChangedIDs(edit, action)
            }))
        );

        this.basicSaveEffect$ = merge(
            this.ConfigureState.actions$.pipe(ofType(BASIC_SAVE)),
            this.ConfigureState.actions$.pipe(ofType(BASIC_SAVE_AND_DOWNLOAD))
        ).pipe(
            withLatestFrom(this.ConfigureState.state$.pipe(pluck('edit'))),
            switchMap(([action, edit]) => {
                const changedItems = _applyChangedIDs(edit, {cluster: action.cluster});
                const actions = [{
                    type: cachesActionTypes.UPSERT,
                    items: changedItems.caches
                },
                {
                    type: shortCachesActionTypes.UPSERT,
                    items: changedItems.caches
                },
                {
                    type: clustersActionTypes.UPSERT,
                    items: [changedItems.cluster]
                },
                {
                    type: shortClustersActionTypes.UPSERT,
                    items: [this.Clusters.toShortCluster(changedItems.cluster)]
                }
                ].filter((a) => a.items.length);

                return merge(
                    of(...actions),
                    from(this.Clusters.saveBasic(changedItems)).pipe(
                        switchMap((res) => of(
                            {type: 'EDIT_CLUSTER', cluster: changedItems.cluster},
                            basicSaveOK(changedItems)
                        )),
                        catchError((res) => of(
                            basicSaveErr(changedItems, res),
                            {type: 'UNDO_ACTIONS', actions}
                        ))
                    )
                );
            })
        );

        this.basicSaveOKMessagesEffect$ = this.ConfigureState.actions$.pipe(
            ofType(BASIC_SAVE_OK),
            tap((action) => this.IgniteMessages.showInfo(`Cluster "${action.changedItems.cluster.name}" saved.`)),
            ignoreElements()
        );
    }
const subscribeWhen = p$ => source => {
  if (process.env.DEBUG && !p$) throw Error();
  return p$.pipe(switchMap(p => (p ? source : NEVER)));
};
Example #23
0
export const commListenEpic = (action$: ActionsObservable<*>) =>
  action$.pipe(
    ofType(LAUNCH_KERNEL_SUCCESSFUL),
    switchMap(commActionObservable)
  ); // We have a new channel