From b4c18f41e7532ae61d91f8b27b2cc937ce8d9ff7 Mon Sep 17 00:00:00 2001 From: kanishkrawatt Date: Fri, 10 Jul 2026 20:34:57 +0530 Subject: [PATCH] [RQ-4283] chore: remove API Client from legacy onboarding & workspace creation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The API Client is now a separate standalone product, but the Interceptor app still surfaced it in onboarding and workspace creation, funneling users into creating local workspaces (which only ever held API Client files). Per epic RQ-4191, remove all API Client touchpoints from these flows so onboarding offers only Interceptor: - DesktopOnboardingModal / WelcomeCard: remove the "Start using API Client" welcome card (expandable local-workspace create/open options) and the FOLDER_SELECTION local-workspace-creation step it fed into; drop the now-unused WorkspaceCreationProvider wrapper and the hooks (useCreateDefaultLocalWorkspace / useOpenLocalWorkspace / LocalWorkspaceCreateOptions / redirectToApiClient). "Skip" now simply completes onboarding instead of creating a local API Client workspace and redirecting to the API Client. Drop FOLDER_SELECTION from the OnboardingStep enum. - CreateWorkspaceModalOld: remove the entire "Local workspace" option ("only API client files are supported") and its dead local-workspace creation code — the modal now creates team workspaces only. - personaRecommendationData: remove the dead "Test API endpoints -> API Client" recommendation entry. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../CreateWorkspaceModalOld.tsx | 104 ++---------- .../personaRecommendationData.tsx | 8 - .../DesktopOnboardingModal.tsx | 65 +++----- .../components/WelcomeCard/WelcomeCard.tsx | 152 ++---------------- .../DesktopOnboardingModal/types.ts | 1 - 5 files changed, 46 insertions(+), 284 deletions(-) diff --git a/app/src/componentsV2/modals/CreateWorkspaceModalOld/CreateWorkspaceModalOld.tsx b/app/src/componentsV2/modals/CreateWorkspaceModalOld/CreateWorkspaceModalOld.tsx index c2ec8a5be2..795e2afed7 100644 --- a/app/src/componentsV2/modals/CreateWorkspaceModalOld/CreateWorkspaceModalOld.tsx +++ b/app/src/componentsV2/modals/CreateWorkspaceModalOld/CreateWorkspaceModalOld.tsx @@ -1,14 +1,11 @@ import React, { useCallback, useState } from "react"; -import { Checkbox, Input, Modal, Radio, Tag } from "antd"; +import { Checkbox, Input, Modal, Radio } from "antd"; import { useDispatch, useSelector } from "react-redux"; import * as Sentry from "@sentry/react"; import { getAppMode } from "store/selectors"; import { RQButton } from "lib/design-system-v2/components"; -import { CreateTeamParams, LocalWorkspaceConfig, SharedOrPrivateWorkspaceConfig } from "types"; -import { displayFolderSelector } from "components/mode-specific/desktop/misc/FileDialogButton"; -import { CONSTANTS as GLOBAL_CONSTANTS } from "@requestly/requestly-core"; -import { IoMdClose } from "@react-icons/all-files/io/IoMdClose"; +import { CreateTeamParams, SharedOrPrivateWorkspaceConfig } from "types"; import { getFunctions, httpsCallable } from "firebase/functions"; import { trackAddTeamMemberSuccess, @@ -24,10 +21,8 @@ import { switchWorkspace } from "actions/TeamWorkspaceActions"; import { redirectToTeam } from "utils/RedirectionUtils"; import { useNavigate } from "react-router-dom"; import { getAvailableBillingTeams } from "store/features/billing/selectors"; -import { createWorkspaceFolder } from "services/fsManagerServiceAdapter"; import { isActiveWorkspaceShared } from "store/slices/workspaces/selectors"; -import { workspaceActions } from "store/slices/workspaces/slice"; -import { Workspace, WorkspaceMemberRole, WorkspaceType } from "features/workspaces/types"; +import { WorkspaceType } from "features/workspaces/types"; import "./createOldWorkspaceModal.scss"; interface Props { @@ -45,17 +40,10 @@ export const CreateWorkspaceModalOld: React.FC = ({ isOpen, defaultWorksp const isSharedWorkspaceMode = useSelector(isActiveWorkspaceShared); const billingTeams = useSelector(getAvailableBillingTeams); const [workspaceName, setWorkspaceName] = useState(""); - const [workspaceType, setWorkspaceType] = useState( - defaultWorkspaceType || (user.loggedIn ? WorkspaceType.SHARED : WorkspaceType.LOCAL) - ); - const [folderPath, setFolderPath] = useState(""); + const [workspaceType, setWorkspaceType] = useState(defaultWorkspaceType || WorkspaceType.SHARED); const [isLoading, setIsLoading] = useState(false); const [isNotifyAllSelected, setIsNotifyAllSelected] = useState(false); - const folderSelectCallback = (path: string) => { - setFolderPath(path); - }; - const handlePostTeamCreationStep = useCallback( (teamId: string, newTeamName: string, hasMembersInSameDomain: boolean) => { switchWorkspace( @@ -138,43 +126,15 @@ export const CreateWorkspaceModalOld: React.FC = ({ isOpen, defaultWorksp const createOrgTeamInvite = httpsCallable(functions, "invites-createOrganizationTeamInvite"); const upsertTeamCommonInvite = httpsCallable(functions, "invites-upsertTeamCommonInvite"); - const config = - workspaceType === WorkspaceType.LOCAL - ? ({ type: WorkspaceType.LOCAL, rootPath: folderPath } as LocalWorkspaceConfig) - : ({ type: WorkspaceType.SHARED } as SharedOrPrivateWorkspaceConfig); + const config = { type: WorkspaceType.SHARED } as SharedOrPrivateWorkspaceConfig; try { const teamId = await (async () => { - if (config.type === WorkspaceType.LOCAL) { - const workspaceCreationResult = await createWorkspaceFolder(workspaceName, config.rootPath); - if (workspaceCreationResult.type === "error") { - throw new Error(workspaceCreationResult.error.message); - } - const partialWorkspace = workspaceCreationResult.content; - const localWorkspace: Workspace = { - id: partialWorkspace.id, - name: partialWorkspace.name, - owner: user?.details?.profile?.uid, - accessCount: 1, - adminCount: 1, - members: { - [user?.details?.profile?.uid]: { - role: WorkspaceMemberRole.admin, - }, - }, - appsumo: null, - workspaceType: WorkspaceType.LOCAL, - rootPath: partialWorkspace.path, - }; - dispatch(workspaceActions.upsertWorkspace(localWorkspace)); - return partialWorkspace.id; - } else { - const response: any = await createTeam({ - teamName: workspaceName, - config, - }); - return response.data.teamId; - } + const response: any = await createTeam({ + teamName: workspaceName, + config, + }); + return response.data.teamId; })(); trackNewTeamCreateSuccess(teamId, workspaceName, "create_workspace_modal", workspaceType); @@ -216,7 +176,6 @@ export const CreateWorkspaceModalOld: React.FC = ({ isOpen, defaultWorksp }, [ billingTeams, callback, - dispatch, isNotifyAllSelected, toggleModal, user?.details?.profile?.email, @@ -224,8 +183,6 @@ export const CreateWorkspaceModalOld: React.FC = ({ isOpen, defaultWorksp handlePostTeamCreationStep, handleDomainInvitesCreation, workspaceType, - folderPath, - user?.details?.profile?.uid, ]); return ( @@ -245,7 +202,7 @@ export const CreateWorkspaceModalOld: React.FC = ({ isOpen, defaultWorksp Cancel @@ -300,45 +257,6 @@ export const CreateWorkspaceModalOld: React.FC = ({ isOpen, defaultWorksp ), }, - { - value: WorkspaceType.LOCAL, - disabled: appMode !== GLOBAL_CONSTANTS.APP_MODES.DESKTOP, - label: ( -
-
- Local workspace BETA -
-
- In a Local Workspace, your files are stored on your device. Currently, only API client files are - supported. -
- {workspaceType === WorkspaceType.LOCAL ? ( -
- {folderPath.length ? ( -
-
- SELECTED LOCATION setFolderPath("")} /> -
-
{folderPath}
-
- ) : ( - <> - displayFolderSelector(folderSelectCallback)} - > - Select a folder - -
A location to store your workspace data.
- - )} -
- ) : null} -
- ), - }, ]} > diff --git a/app/src/features/onboarding/components/recommendations/components/recommendations/personaRecommendationData.tsx b/app/src/features/onboarding/components/recommendations/components/recommendations/personaRecommendationData.tsx index 20dd8fa6ad..eb6cd7cb14 100644 --- a/app/src/features/onboarding/components/recommendations/components/recommendations/personaRecommendationData.tsx +++ b/app/src/features/onboarding/components/recommendations/components/recommendations/personaRecommendationData.tsx @@ -5,7 +5,6 @@ import { FeatureSection, FeatureReleaseTag } from "./types"; import { CONSTANTS as GLOBAL_CONSTANTS } from "@requestly/requestly-core"; import { FiVideo } from "@react-icons/all-files/fi/FiVideo"; import { IoDocumentTextOutline } from "@react-icons/all-files/io5/IoDocumentTextOutline"; -import { ApiOutlined } from "@ant-design/icons"; const { RULE_TYPES } = GLOBAL_CONSTANTS; const { RULE_TYPES_CONFIG } = APP_CONSTANTS; @@ -76,13 +75,6 @@ export const personaRecommendationData: FeatureSection[] = [ subTitle: "Create mocks for your APIs", link: PATHS.MOCK_SERVER_V2.ABSOLUTE, }, - { - id: "test_api_endpoints", - title: "Test API endpoints", - icon: () => , - subTitle: "Test responses quickly using API Client", - link: PATHS.API_CLIENT.ABSOLUTE, - }, ], }, ]; diff --git a/app/src/features/onboarding/componentsV2/DesktopOnboardingModal/DesktopOnboardingModal.tsx b/app/src/features/onboarding/componentsV2/DesktopOnboardingModal/DesktopOnboardingModal.tsx index a1e59e013b..956554f5b6 100644 --- a/app/src/features/onboarding/componentsV2/DesktopOnboardingModal/DesktopOnboardingModal.tsx +++ b/app/src/features/onboarding/componentsV2/DesktopOnboardingModal/DesktopOnboardingModal.tsx @@ -1,19 +1,13 @@ import React, { useEffect, useState } from "react"; import { Button, Modal } from "antd"; -import { useNavigate } from "react-router-dom"; -import { WorkspaceCreationView } from "componentsV2/modals/CreateWorkspaceModal/components/WorkspaceCreationView"; import { AuthCard } from "./components/AuthCard/AuthCard"; import { WelcomeCard } from "./components/WelcomeCard/WelcomeCard"; import { useDispatch, useSelector } from "react-redux"; import { globalActions } from "store/slices/global/slice"; import { getUserAuthDetails } from "store/slices/global/user/selectors"; -// import { IoMdArrowBack } from "@react-icons/all-files/io/IoMdArrowBack"; -import { redirectToApiClient } from "utils/RedirectionUtils"; import "./desktopOnboardingModal.scss"; import { trackDesktopOnboardingStepSkipped, trackDesktopOnboardingViewed } from "./analytics"; import { OnboardingStep } from "./types"; -import { WorkspaceType } from "features/workspaces/types"; -import { WorkspaceCreationProvider } from "componentsV2/modals/CreateWorkspaceModal/context"; export const DesktopOnboardingCard = ({ children, className }: { children: React.ReactNode; className?: string }) => { return
{children}
; @@ -21,7 +15,6 @@ export const DesktopOnboardingCard = ({ children, className }: { children: React export const DesktopOnboardingModal = () => { const dispatch = useDispatch(); - const navigate = useNavigate(); const user = useSelector(getUserAuthDetails); const [onboardingStep, setOnboardingStep] = useState(OnboardingStep.FEATURE_SELECTION); @@ -42,43 +35,29 @@ export const DesktopOnboardingModal = () => { wrapClassName="rq-desktop-onboarding-modal-wrapper" className="rq-desktop-onboarding-modal" > - -
- {onboardingStep === OnboardingStep.FEATURE_SELECTION ? ( - - setOnboardingStep(step)} /> +
+ {onboardingStep === OnboardingStep.FEATURE_SELECTION ? ( + + setOnboardingStep(step)} /> + + ) : onboardingStep === OnboardingStep.AUTH ? ( + <> + + setOnboardingStep(OnboardingStep.FEATURE_SELECTION)} /> - ) : onboardingStep === OnboardingStep.FOLDER_SELECTION ? ( - - setOnboardingStep(OnboardingStep.FEATURE_SELECTION)} - callback={() => { - dispatch(globalActions.updateIsOnboardingCompleted(true)); - redirectToApiClient(navigate); - }} - analyticEventSource="desktop_onboarding_modal" - /> - - ) : onboardingStep === OnboardingStep.AUTH ? ( - <> - - setOnboardingStep(OnboardingStep.FEATURE_SELECTION)} /> - - - - ) : null} -
- + + + ) : null} +
); }; diff --git a/app/src/features/onboarding/componentsV2/DesktopOnboardingModal/components/WelcomeCard/WelcomeCard.tsx b/app/src/features/onboarding/componentsV2/DesktopOnboardingModal/components/WelcomeCard/WelcomeCard.tsx index ea8b6671ca..c2e94de95c 100644 --- a/app/src/features/onboarding/componentsV2/DesktopOnboardingModal/components/WelcomeCard/WelcomeCard.tsx +++ b/app/src/features/onboarding/componentsV2/DesktopOnboardingModal/components/WelcomeCard/WelcomeCard.tsx @@ -1,4 +1,4 @@ -import React, { useEffect, useRef, useState } from "react"; +import React from "react"; import { Button } from "antd"; import RQOnlyLogo from "/assets/media/common/RQ-only-logo.svg"; import { useDispatch } from "react-redux"; @@ -6,20 +6,8 @@ import { globalActions } from "store/slices/global/slice"; import { trackDesktopOnboardingFeatureSelected, trackDesktopOnboardingStepSkipped } from "../../analytics"; import { OnboardingStep } from "../../types"; import { WelcomeCardHeader } from "./components/WelcomeCardHeader/WelcomeCardHeader"; -import { AnimatePresence, m } from "framer-motion"; -import { collapseExpandTransition } from "utils/animations"; -import { MdOutlineKeyboardArrowUp } from "@react-icons/all-files/md/MdOutlineKeyboardArrowUp"; -import { MdOutlineKeyboardArrowDown } from "@react-icons/all-files/md/MdOutlineKeyboardArrowDown"; -import { LocalWorkspaceCreateOptions } from "componentsV2/modals/CreateWorkspaceModal"; -import clsx from "clsx"; -import { useCreateDefaultLocalWorkspace } from "features/workspaces/hooks/useCreateDefaultLocalWorkspace"; -import { FileSystemError } from "features/apiClient/helpers/modules/sync/local/services/types"; -import { OpenWorkspaceErrorView } from "componentsV2/modals/CreateWorkspaceModal/components/LocalWorkspaceCreationView/components/OpenWorkspaceErrorView"; -import { useOpenLocalWorkspace } from "features/workspaces/hooks/useOpenLocalWorkspace"; import { MdOutlineKeyboardArrowRight } from "@react-icons/all-files/md/MdOutlineKeyboardArrowRight"; import "./welcomeCard.scss"; -import { useNavigate } from "react-router-dom"; -import { redirectToApiClient } from "utils/RedirectionUtils"; interface Props { onFeatureClick: (step: OnboardingStep) => void; @@ -27,140 +15,19 @@ interface Props { export const WelcomeCard: React.FC = ({ onFeatureClick }) => { const dispatch = useDispatch(); - const navigate = useNavigate(); - const [isApiClientCardExpanded, setIsApiClientCardExpanded] = useState(false); - const [openWorkspaceError, setOpenWorkspaceError] = useState(null); - const apiClientCardRef = useRef(null); - - const { createWorkspace, isLoading } = useCreateDefaultLocalWorkspace({ - analyticEventSource: "desktop_onboarding_modal", - onCreateWorkspaceCallback: () => { - trackDesktopOnboardingStepSkipped(OnboardingStep.FEATURE_SELECTION); - dispatch(globalActions.updateIsOnboardingCompleted(true)); - redirectToApiClient(navigate); - }, - }); - - const { openWorkspace, isLoading: isOpeningWorkspaceLoading } = useOpenLocalWorkspace({ - analyticEventSource: "desktop_onboarding_modal", - onOpenWorkspaceCallback: () => { - dispatch(globalActions.updateIsOnboardingCompleted(true)); - redirectToApiClient(navigate); - }, - onError: (error: FileSystemError) => { - setOpenWorkspaceError(error); - }, - }); - - useEffect(() => { - if (!isApiClientCardExpanded) { - return; - } - - const handleClickOutside = (event: MouseEvent) => { - if (apiClientCardRef.current && !apiClientCardRef.current.contains(event.target as Node)) { - setIsApiClientCardExpanded(false); - } - }; - - document.addEventListener("mousedown", handleClickOutside); - - return () => { - document.removeEventListener("mousedown", handleClickOutside); - }; - }, [isApiClientCardExpanded]); - - const handleApiClientCardExpandToggle = () => { - if (!isApiClientCardExpanded) { - trackDesktopOnboardingFeatureSelected("api_client"); - } - setIsApiClientCardExpanded((prev) => !prev); - }; - - if (openWorkspaceError) { - return ( -
- onFeatureClick(OnboardingStep.FOLDER_SELECTION)} - openWorkspace={openWorkspace} - isOpeningWorkspaceLoading={isOpeningWorkspaceLoading} - analyticEventSource="desktop_onboarding_modal" - /> -
- ); - } return (
- RQ Only Logo -
+ RQ Only Logo +
Welcome to Requestly
-
+
Intercept, Mock, Build & Test APIs faster
- -
-
- - {isApiClientCardExpanded ? ( - - ) : ( - - )} -
- - {isApiClientCardExpanded && ( - -
- onFeatureClick(OnboardingStep.FOLDER_SELECTION)} - onCreationCallback={() => { - dispatch(globalActions.updateIsOnboardingCompleted(true)); - redirectToApiClient(navigate); - }} - openWorkspace={openWorkspace} - isOpeningWorkspaceLoading={isOpeningWorkspaceLoading} - /> -
-
- )} -
-
-
{ trackDesktopOnboardingFeatureSelected("rules"); onFeatureClick(OnboardingStep.AUTH); @@ -175,7 +42,14 @@ export const WelcomeCard: React.FC = ({ onFeatureClick }) => {
- {" "} this screen and quick start diff --git a/app/src/features/onboarding/componentsV2/DesktopOnboardingModal/types.ts b/app/src/features/onboarding/componentsV2/DesktopOnboardingModal/types.ts index 271a41f8d8..a0ca630dbc 100644 --- a/app/src/features/onboarding/componentsV2/DesktopOnboardingModal/types.ts +++ b/app/src/features/onboarding/componentsV2/DesktopOnboardingModal/types.ts @@ -1,5 +1,4 @@ export enum OnboardingStep { FEATURE_SELECTION = "feature_selection", - FOLDER_SELECTION = "folder_selection", AUTH = "auth", }