Example #1
0
const createSuspension = () => {
    const tasks = new Subject();
    const finished = new Subject();

    let isExecuting = false;
    let lastTask = null;

    tasks.switchMap(async task => {
        if (isExecuting){
            lastTask = task;
            return;
        }
            
        isExecuting = true;

        let result = await task();
        finished.next(result);

        while (lastTask != null){
            const toRun = lastTask;
            lastTask = null;
            result = await toRun();
            finished.next(result);
        }
    })
    .publish()
    .connect();

    return {
        insertTask: task => tasks.next(task),
        finishedTasks: finished
    }
}
 componentDidMount(): void {
   this._resizeSubscription = this._resizeEvents
     .switchMap(() => nextAnimationFrame)
     .subscribe(() => {
       this._updateContainerSize();
     });
 }
    controller: function (cloudMetricsReader) {

      this.viewState = {
        loadingDimensions: false
      };

      this.fetchDimensionOptions = () => {
        this.viewState.loadingDimensions = true;
        let filters = { namespace: this.alarm.namespace };
        return Observable
          .fromPromise(
          cloudMetricsReader.listMetrics('aws', this.serverGroup.account, this.serverGroup.region, filters)
        );
      };

      let dimensionSubject = new Subject();

      dimensionSubject
        .switchMap(this.fetchDimensionOptions)
        .subscribe((results) => {
          this.viewState.loadingDimensions = false;
          results = results || [];
          results.forEach(r => r.dimensions = r.dimensions || []);
          this.dimensionOptions = _.uniq(_.flatten(results.map(r => r.dimensions.map(d => d.name)))).sort();
        });

      this.updateDimensionOptions = () => {
        dimensionSubject.next();
      };

      this.removeDimension = (index) => {
        this.alarm.dimensions.splice(index, 1);
        this.updateAvailableMetrics();
      };

      this.$onInit = () => {
        this.updateDimensionOptions();
        this.namespaceUpdated.subscribe(() => {
          this.updateDimensionOptions();
        });
      };

    }
Example #4
0
  componentDidMount(): void {
    const el = nullthrows(this._rootNode);

    this._disposables = new UniversalDisposable(
      // Update the column widths when the table is resized.
      new ResizeObservable(el)
        .startWith((null: any))
        .map(() => el.offsetWidth)
        .filter(tableWidth => tableWidth > 0)
        .subscribe(tableWidth => {
          this.setState({tableWidth});
        }),
      this._resizeStarts
        .switchMap(({event: startEvent, resizerLocation}) => {
          const startX = startEvent.pageX;
          return Observable.fromEvent(document, 'mousemove')
            .takeUntil(Observable.fromEvent(document, 'mouseup'))
            .map(event => ({
              deltaPx: event.pageX - startX,
              resizerLocation,
            }))
            .concat(Observable.of(null));
        })
        .subscribe(resizeOffset => {
          if (resizeOffset == null) {
            // Finalize the resize by updating the user's preferred column widths to account for
            // their action. Note that these preferences are only updated when columns are resized
            // (NOT when the table is). This is important so that, if the user resizes the table
            // such that a column is at its minimum width and then resizes the table back to its
            // orignal size, their original column widths are restored.
            const preferredColumnWidths = _calculatePreferredColumnWidths({
              currentWidths: this._calculateColumnWidths(),
              tableWidth: this.state.tableWidth,
              minWidths: getMinWidths(this.props.columns),
            });

            // Update the preferred distributions and end the resize.
            this.setState({preferredColumnWidths, resizeOffset: null});
          } else {
            this.setState({resizeOffset});
          }
        }),
      atom.commands.add(el, {
        'core:move-up': event => {
          this.setState({usingKeyboard: true});
          this._moveSelection(-1, event);
        },
        'core:move-down': event => {
          this.setState({usingKeyboard: true});
          this._moveSelection(1, event);
        },
        'core:confirm': event => {
          this.setState({usingKeyboard: true});
          const {rows, selectedIndex, onConfirm} = this.props;
          if (onConfirm == null || selectedIndex == null) {
            return;
          }
          const selectedRow = rows[selectedIndex];
          const selectedItem = selectedRow && selectedRow.data;
          if (selectedItem != null) {
            onConfirm(selectedItem, selectedIndex);
          }
        },
      }),
      () => {
        if (this._mouseMoveDisposable != null) {
          this._mouseMoveDisposable.dispose();
        }
      },
    );
  }
    return function() {
      var deferred;

      let searchConfig = {
        projects: {
          displayName: 'Projects',
          displayFormatter: function(entry) {
            let applications = entry.config && entry.config.applications ?
            ' (' + entry.config.applications.join(', ') + ')' :
              '';
            let project = entry.name || entry.project;
            return $q.when(project + applications);
          },
          order: 0,
        },
        applications: {
          displayName: 'Applications',
          displayFormatter: simpleField('application'),
          order: 1,
        },
        clusters: {
          displayName: 'Clusters',
          displayFormatter: simpleField('cluster'),
          order: 2,
          hideIfEmpty: true,
        },
        serverGroups: {
          displayName: 'Server Groups',
          displayFormatter: function(entry) {
            return $q.when(entry.serverGroup + ' (' + entry.region + ')');
          },
          order: 3,
          hideIfEmpty: true,
        },
        instances: {
          displayName: 'Instances',
          displayFormatter: function(entry) {
            let serverGroup = entry.serverGroup || 'standalone instance';
            return $q.when(entry.instanceId + ' (' + serverGroup + ' - ' + entry.region + ')');
          },
          order: 4,
          hideIfEmpty: true,
        },
        loadBalancers: {
          displayName: 'Load Balancers',
          displayFormatter: function(entry, fromRoute) {
            let name = fromRoute ? entry.name : entry.loadBalancer;
            return $q.when(name + ' (' + entry.region + ')');
          },
          order: 5,
          hideIfEmpty: true,
        },
        securityGroups: {
          displayName: 'Security Groups',
          displayFormatter: function(entry) {
            return $q.when(entry.name + ' (' + entry.region + ')');
          },
          order: 6,
          hideIfEmpty: true,
        }
      };

      function simpleField(field) {
        return function(entry) {
          return $q.when(entry[field]);
        };
      }

      var querySubject = new Subject();

      let initializeCategories = () => {
        let categories = {};
        Object.keys(searchConfig).forEach((searchType) => {
          categories[searchType] = [];
        });
        return categories;
      };

      let formatResult = (category, entry, fromRoute) => {
        var config = searchConfig[category],
            formatter = config.displayFormatter;

        if (serviceDelegate.hasDelegate(entry.provider, 'search.resultFormatter')) {
          let providerFormatter = serviceDelegate.getDelegate(entry.provider, 'search.resultFormatter');
          if (providerFormatter[category]) {
            formatter = providerFormatter[category];
          }
        }
        return formatter(entry, fromRoute);
      };

      querySubject
        .switchMap(function(query) {
          if (!query || !angular.isDefined(query) || query.length < 1) {
            return Observable.of(searchService.getFallbackResults());
          }

          return Observable.fromPromise(searchService.search({
           q: query,
           type: Object.keys(searchConfig),
          }));
        })
        .subscribe(function(result) {
          var tmp = result.results.reduce(function(categories, entry) {
            formatResult(entry.type, entry).then((name) => entry.displayName = name);
            entry.href = urlBuilderService.buildFromMetadata(entry);
            categories[entry.type].push(entry);
            return categories;
          }, initializeCategories());
          deferred.resolve(Object.keys(tmp).map(function(cat) {
            let config = searchConfig[cat];
            return {
              category: config.displayName,
              order: config.order,
              hideIfEmpty: config.hideIfEmpty,
              results: tmp[cat],
            };
          }));
        });

      return {
        query: function(query) {
          deferred = $q.defer();
          querySubject.next(query);
          return deferred.promise;
        },
        formatRouteResult: function(type, params) {
          return formatResult(type, params, true);
        },
      };
    };
  /**
   * Either retrieves the monitor object for the currently active text editor
   * from the cache, or creates (and caches) the new one
   *
   * The monitor object hides the complexity of maintaining the last selection
   * explicitly made by user and handles the expand/collapse requests
   *
   * The monitor objects are held in the state only as long as an editor's
   * selection is modified by the syntactic selection feature. I.e. should a
   * user change the selection manually, the editor is removed from the cache
   * and any in-flight collapse/expand requests are abandoned (ignored).
   */
  _getTextSelectionMonitor(): ?TextEditorSelectionMonitor {
    const editor = atom.workspace.getActiveTextEditor();
    if (editor == null) {
      return null;
    }

    const cachedMonitor = this._textEditorMonitors.get(editor);
    if (cachedMonitor != null) {
      return cachedMonitor;
    }

    // The collapse-expand works with a single selection only, although
    // this could be extended to handle multiple selections as well
    const selectedRanges = editor.getSelectedBufferRanges();
    if (selectedRanges.length > 1) {
      return null;
    }

    // The anchor cursor position.
    // Applying a selection automatically moves the selection to either back
    // of the front of the selected region, so we're storing the original
    // location of the cursor.
    // This information later helps the language service to zoom in (collapse)
    // onto the proper sub-range of current selection when multiple children
    // exist.
    // For example, consider the line below:
    //    foo(arg1, bar('blah'), 100000)
    // If the expand will be iniated when the cursor is on 'blah', this position
    // will be marked as anchor. Let's assume we've expanded the selection
    // to include the entire line, entire call to foo().
    // It means that currently the cursor is at the end, after the ")"
    // When we issue the collapse call, having the anchor stored lets us deduct
    // that the child which is the second argument "bar('bla')" now needs to
    // be selected.
    const selectionAnchor = selectedRanges[0].end;

    // We will modify the selection in the current document, but we also are
    // subscribed to selection changes. We need to differentiate between
    // the changes made by our code from those made by the user.
    // Prior to making a change we set this variable to later on filter out
    // the notification with matching range
    let expectedSelection = selectedRanges[0];

    // Sometimes Atom may reinterpret the range that is provided by the language
    // service. In this case we have one more opportunity to detecting that
    // the selection change is done by us. That is if it is done synchronously
    // it is definitely ours. Unfortunately this relies on an implementation
    // details, and thus is not future-proof. Still, better then terminating
    // the watch too soon
    let changingNow = false;

    // There are multiple events that cover selection change.
    const selectionChangeSignals = Observable.merge(
      observableFromSubscribeFunction(editor.observeSelections.bind(editor)),
      observableFromSubscribeFunction(
        editor.onDidChangeSelectionRange.bind(editor),
      ),
    );

    // We want to stop listening (managing) an editor instance when it is
    // either closed or if its selection was manually changed by the user
    const stopMonitorSignal = Observable.merge(
      observableFromSubscribeFunction(editor.onDidDestroy.bind(editor)),
      selectionChangeSignals.filter(() => {
        if (changingNow) {
          return false;
        }

        const currentSelectedRanges = editor.getSelectedBufferRanges();
        if (
          currentSelectedRanges.length > 1 ||
          (expectedSelection != null &&
            !currentSelectedRanges[0].isEqual(expectedSelection))
        ) {
          // Stop monitoring
          return true;
        }

        return false;
      }),
    );

    // Helps take care of racing requests
    const runningRangeRequests: Subject<Promise<?atom$Range>> = new Subject();

    const monitor = {
      editor,
      doExpand: () => runningRangeRequests.next(this._expandRange(editor)),
      doCollapse: () =>
        runningRangeRequests.next(this._collapseRange(editor, selectionAnchor)),
    };

    this._textEditorMonitors.set(editor, monitor);

    const subscription = runningRangeRequests
      .switchMap(p => p)
      .takeUntil(stopMonitorSignal)
      .finally(() => {
        // Stop signal received - remove the monitor
        this._textEditorMonitors.delete(editor);
        // And do not leak the subscription object
        this._disposables.remove(subscription);
      })
      .subscribe(
        newExpected => {
          expectedSelection = newExpected;
          if (newExpected != null) {
            changingNow = true;
            editor.setSelectedBufferRange(newExpected);
            changingNow = false;
          }
        },
        err => {
          logger.error('Unexpected error in sytnactic selection handling', err);
        },
      );
    this._disposables.add(subscription);

    return monitor;
  }