lodash#findLastIndex TypeScript Examples

The following examples show how to use lodash#findLastIndex. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: history.ts    From am-editor with MIT License 6 votes vote down vote up
getUndoOp(): Operation | undefined {
		const prevIndex = this.currentActionIndex - 1;
		if (this.actionOps[prevIndex]) {
			let prevOp = cloneDeep(this.actionOps[prevIndex]);
			let opIndex = findLastIndex(
				this.actionOps,
				(op) => op.id == prevOp.id,
			);
			if (opIndex !== -1) prevOp = this.actionOps[opIndex];
			else opIndex = prevIndex;
			const invertOps = OTJSON.type.invert(prevOp.ops || []);
			invertOps.forEach((op, index) => {
				const pOp = (prevOp.ops || [])[invertOps.length - index - 1];
				op['id'] = pOp.id;
				op['bi'] = pOp.bi;
			});

			try {
				return {
					self: true,
					ops: invertOps,
					id: prevOp.id,
					type: 'undo',
					rangePath: prevOp.rangePath,
					startRangePath: prevOp.startRangePath,
				};
			} catch (error: any) {
				this.engine.messageError('history-undo-op', error);
			}
		}
		return;
	}
Example #2
Source File: Router.ts    From next-core with GNU General Public License v3.0 4 votes vote down vote up
private async render(location: PluginLocation): Promise<void> {
    this.state = "initial";
    this.renderId = uniqueId("render-id-");

    resetAllInjected();
    clearPollTimeout();

    if (this.locationContext) {
      this.locationContext.resolver.resetRefreshQueue();
    }

    const history = getHistory();
    history.unblock();

    // Create the page tracker before page load.
    // And the API Analyzer maybe disabled.
    const pageTracker = apiAnalyzer.getInstance()?.pageTracker();

    const locationContext = (this.locationContext = new LocationContext(
      this.kernel,
      location
    ));

    const storyboard = locationContext.matchStoryboard(
      this.kernel.bootstrapData.storyboards
    );

    if (storyboard) {
      await this.kernel.fulfilStoryboard(storyboard);

      // 将动态解析后的模板还原,以便重新动态解析。
      restoreDynamicTemplates(storyboard);

      // 预加载权限信息
      if (isLoggedIn() && !getAuth().isAdmin) {
        await preCheckPermissions(storyboard);
      }

      // 如果找到匹配的 storyboard,那么根据路由匹配得到的 sub-storyboard 加载它的依赖库。
      const subStoryboard =
        this.locationContext.getSubStoryboardByRoute(storyboard);
      await this.kernel.loadDepsOfStoryboard(subStoryboard);

      // 注册 Storyboard 中定义的自定义模板和函数。
      this.kernel.registerCustomTemplatesInStoryboard(storyboard);
      registerStoryboardFunctions(storyboard.meta?.functions, storyboard.app);

      registerMock(storyboard.meta?.mocks);

      collectContract(storyboard.meta?.contracts);
    }

    const { mountPoints, currentApp: previousApp } = this.kernel;
    const currentApp = storyboard ? storyboard.app : undefined;
    // Storyboard maybe re-assigned, e.g. when open launchpad.
    const appChanged =
      previousApp && currentApp
        ? previousApp.id !== currentApp.id
        : previousApp !== currentApp;
    const legacy = currentApp ? currentApp.legacy : undefined;
    this.kernel.nextApp = currentApp;
    const layoutType: LayoutType = currentApp?.layoutType || "console";

    setTheme(
      getLocalAppsTheme()?.[currentApp?.id] || currentApp?.theme || "light"
    );
    setMode("default");

    devtoolsHookEmit("rendering");

    unmountTree(mountPoints.bg as MountableElement);

    const redirectToLogin = (): void => {
      history.replace(
        this.featureFlags["sso-enabled"] ? "/sso-auth/login" : "/auth/login",
        {
          from: location,
        }
      );
    };

    if (storyboard) {
      if (appChanged && currentApp.id && isLoggedIn()) {
        const usedCustomApis: CustomApiInfo[] = mapCustomApisToNameAndNamespace(
          scanCustomApisInStoryboard(storyboard)
        );
        if (usedCustomApis?.length) {
          await this.kernel.loadMicroAppApiOrchestrationAsync(usedCustomApis);
        }
      }

      const mountRoutesResult: MountRoutesResult = {
        main: [],
        menuInBg: [],
        menuBar: {},
        portal: [],
        appBar: {
          breadcrumb: [],
          documentId: null,
          noCurrentApp: currentApp.breadcrumb?.noCurrentApp ?? false,
        },
        flags: {
          redirect: undefined,
          hybrid: false,
          failed: false,
        },
      };
      try {
        const specificTemplatePreviewIndex = findLastIndex(
          storyboard.routes,
          (route) =>
            route.path.startsWith(
              "${APP.homepage}/_dev_only_/template-preview/"
            )
        );

        const specificSnippetPreviewIndex = findLastIndex(
          storyboard.routes,
          (route) =>
            route.path.startsWith("${APP.homepage}/_dev_only_/snippet-preview/")
        );
        const mergedRoutes = [
          ...storyboard.routes.slice(0, specificTemplatePreviewIndex + 1),
          ...storyboard.routes.slice(0, specificSnippetPreviewIndex + 1),
          {
            path: "${APP.homepage}/_dev_only_/template-preview/:templateId",
            bricks: [{ brick: "span" }],
            menu: false,
            exact: true,
          } as RouteConf,
          {
            path: "${APP.homepage}/_dev_only_/snippet-preview/:snippetId",
            bricks: [{ brick: "span" }],
            menu: false,
            exact: true,
          } as RouteConf,
          ...storyboard.routes.slice(specificTemplatePreviewIndex + 1),
        ];
        await locationContext.mountRoutes(
          mergedRoutes,
          undefined,
          mountRoutesResult
        );
      } catch (error) {
        // eslint-disable-next-line no-console
        console.error(error);

        // Redirect to login page if not logged in.
        if (isUnauthenticatedError(error) && !window.NO_AUTH_GUARD) {
          mountRoutesResult.flags.unauthenticated = true;
        } else {
          await this.kernel.layoutBootstrap(layoutType);
          const brickPageError = this.kernel.presetBricks.pageError;
          await this.kernel.loadDynamicBricks([brickPageError]);

          mountRoutesResult.flags.failed = true;
          mountRoutesResult.main = [
            {
              type: brickPageError,
              properties: {
                error: httpErrorToString(error),
                code:
                  error instanceof HttpResponseError
                    ? error.response.status
                    : null,
              },
              events: {},
            },
          ];
          mountRoutesResult.portal = [];
        }
      }

      const {
        main,
        menuInBg,
        menuBar,
        appBar,
        flags,
        portal,
        route,
        analyticsData,
      } = mountRoutesResult;

      const { unauthenticated, redirect, barsHidden, hybrid, failed } = flags;

      if (unauthenticated) {
        redirectToLogin();
        return;
      }

      if (redirect) {
        history.replace(redirect.path, redirect.state);
        return;
      }

      if (appChanged) {
        this.kernel.currentApp = currentApp;
        this.kernel.previousApp = previousApp;
      }
      this.kernel.currentUrl = createPath(location);
      this.kernel.currentRoute = route;
      await Promise.all([
        ...(window.STANDALONE_MICRO_APPS
          ? []
          : [this.kernel.updateWorkspaceStack()]),
        this.kernel.layoutBootstrap(layoutType),
      ]);

      this.state = "ready-to-mount";

      // Unmount main tree to avoid app change fired before new routes mounted.
      unmountTree(mountPoints.main as MountableElement);
      unmountTree(mountPoints.portal as MountableElement);

      const actualLegacy =
        (legacy === "iframe" && !hybrid) || (legacy !== "iframe" && hybrid)
          ? "iframe"
          : undefined;
      this.kernel.unsetBars({ appChanged, legacy: actualLegacy });

      if (this.mediaEventTargetHandler) {
        mediaEventTarget.removeEventListener(
          "change",
          this.mediaEventTargetHandler as EventListener
        );
        this.mediaEventTargetHandler = undefined;
      }

      // There is a window to set theme and mode by `lifeCycle.onBeforePageLoad`.
      this.locationContext.handleBeforePageLoad();
      applyTheme();
      applyMode();

      if (appChanged) {
        window.dispatchEvent(
          new CustomEvent<RecentApps>("app.change", {
            detail: this.kernel.getRecentApps(),
          })
        );
      }

      let misc: RuntimeMisc;
      if (
        barsHidden ||
        ((misc = getRuntimeMisc()),
        misc.isInIframeOfSameSite && !misc.isInIframeOfVisualBuilder)
      ) {
        this.kernel.toggleBars(false);
      } else {
        await constructMenu(
          menuBar,
          this.locationContext.getCurrentContext(),
          this.kernel
        );
        if (this.kernel.currentLayout === "console") {
          if (
            shouldBeDefaultCollapsed(
              menuBar.menu?.defaultCollapsed,
              menuBar.menu?.defaultCollapsedBreakpoint
            )
          ) {
            this.kernel.menuBar.collapse(true);
            this.defaultCollapsed = true;
          } else {
            if (this.defaultCollapsed) {
              this.kernel.menuBar.collapse(false);
            }
            this.defaultCollapsed = false;
          }
          if (actualLegacy === "iframe") {
            // Do not modify breadcrumb in iframe mode,
            // it will be *popped* from iframe automatically.
            delete appBar.breadcrumb;
          }
          mountStaticNode(this.kernel.menuBar.element, menuBar);
          mountStaticNode(this.kernel.appBar.element, appBar);
        }
      }

      this.setNavConfig(mountRoutesResult);

      this.kernel.toggleLegacyIframe(actualLegacy === "iframe");

      menuInBg.forEach((brick) => {
        appendBrick(brick, mountPoints.portal as MountableElement);
      });

      if (main.length > 0 || portal.length > 0) {
        main.length > 0 &&
          mountTree(main, mountPoints.main as MountableElement);
        portal.length > 0 &&
          mountTree(portal, mountPoints.portal as MountableElement);

        afterMountTree(mountPoints.main as MountableElement);
        afterMountTree(mountPoints.portal as MountableElement);
        afterMountTree(mountPoints.bg as MountableElement);

        // Scroll to top after each rendering.
        // See https://github.com/ReactTraining/react-router/blob/master/packages/react-router-dom/docs/guides/scroll-restoration.md
        window.scrollTo(0, 0);

        if (!failed) {
          this.locationContext.handleBrickBindObserver();
          this.locationContext.handlePageLoad();
          this.locationContext.handleAnchorLoad();
          this.locationContext.resolver.scheduleRefreshing();
          this.locationContext.handleMessage();
        }

        this.mediaEventTargetHandler = (event) =>
          this.locationContext.handleMediaChange(event.detail);
        mediaEventTarget.addEventListener(
          "change",
          this.mediaEventTargetHandler as EventListener
        );

        pageTracker?.(locationContext.getCurrentMatch().path);

        // analytics page_view event
        userAnalytics.event("page_view", {
          micro_app_id: this.kernel.currentApp.id,
          route_alias: route?.alias,
          ...analyticsData,
        });

        this.state = "mounted";

        devtoolsHookEmit("rendered");

        // Try to prefetch during a browser's idle periods.
        // https://developer.mozilla.org/en-US/docs/Web/API/Window/requestIdleCallback
        if (typeof window.requestIdleCallback === "function") {
          window.requestIdleCallback(() => {
            this.kernel.prefetchDepsOfStoryboard(storyboard);
          });
        } else {
          Promise.resolve().then(() => {
            this.kernel.prefetchDepsOfStoryboard(storyboard);
          });
        }
        return;
      }
    } else if (!window.NO_AUTH_GUARD && !isLoggedIn()) {
      // Todo(steve): refine after api-gateway supports fetching storyboards before logged in.
      // Redirect to login if no storyboard is matched.
      redirectToLogin();
      return;
    }

    await this.kernel.layoutBootstrap(layoutType);
    const brickPageNotFound = this.kernel.presetBricks.pageNotFound;
    await this.kernel.loadDynamicBricks([brickPageNotFound]);

    this.state = "ready-to-mount";

    mountTree(
      [
        {
          type: brickPageNotFound,
          properties: {
            url: history.createHref(location),
          },
          events: {},
        },
      ],
      mountPoints.main as MountableElement
    );
    unmountTree(mountPoints.portal as MountableElement);

    // Scroll to top after each rendering.
    window.scrollTo(0, 0);

    this.state = "mounted";
    devtoolsHookEmit("rendered");
  }