Compare commits
1 commit
main
...
react-rout
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
038d8decd5 |
94 changed files with 893 additions and 1056 deletions
|
|
@ -1,5 +1,5 @@
|
|||
import React, { lazy, Suspense } from 'react';
|
||||
import { Switch, Route } from 'react-router-dom';
|
||||
import { Routes, Route } from 'react-router-dom';
|
||||
import { Loader } from 'UI';
|
||||
import withSiteIdUpdater from 'HOCs/withSiteIdUpdater';
|
||||
|
||||
|
|
@ -46,13 +46,13 @@ function IFrameRoutes(props: Props) {
|
|||
<Layout hideHeader={true}>
|
||||
<Loader loading={!!loading} className='flex-1'>
|
||||
<Suspense fallback={<Loader loading={true} className='flex-1' />}>
|
||||
<Switch key='content'>
|
||||
<Routes key='content'>
|
||||
<Route exact strict path={withSiteId(SESSION_PATH, siteIdList)}
|
||||
component={enhancedComponents.Session} />
|
||||
<Route exact strict path={withSiteId(LIVE_SESSION_PATH, siteIdList)}
|
||||
component={enhancedComponents.LiveSession} />
|
||||
<Route path='*' render={NotFoundPage} />
|
||||
</Switch>
|
||||
</Routes>
|
||||
</Suspense>
|
||||
</Loader>
|
||||
</Layout>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import withSiteIdUpdater from 'HOCs/withSiteIdUpdater';
|
||||
import React, { Suspense, lazy } from 'react';
|
||||
import { Redirect, Route, Switch } from 'react-router-dom';
|
||||
import { useNavigate } from 'react-router'
|
||||
import { Navigate, Route, Routes } from 'react-router-dom';
|
||||
import { observer } from 'mobx-react-lite';
|
||||
import { useStore } from './mstore';
|
||||
import { GLOBAL_HAS_NO_RECORDINGS } from 'App/constants/storageKeys';
|
||||
|
|
@ -101,6 +102,7 @@ const HIGHLIGHTS_PATH = routes.highlights();
|
|||
let debounceSearch: any = () => {};
|
||||
|
||||
function PrivateRoutes() {
|
||||
const navigate = useNavigate();
|
||||
const { projectsStore, userStore, integrationsStore, searchStore } = useStore();
|
||||
const onboarding = userStore.onboarding;
|
||||
const scope = userStore.scopeState;
|
||||
|
|
@ -129,34 +131,52 @@ function PrivateRoutes() {
|
|||
debounceSearch();
|
||||
}, [searchStore.instance.filters, searchStore.instance.eventsOrder]);
|
||||
|
||||
React.useEffect(() => {
|
||||
if (redirectToSetup) {
|
||||
navigate(SCOPE_SETUP)
|
||||
}
|
||||
}, [redirectToSetup])
|
||||
React.useEffect(() => {
|
||||
if (redirectToOnboarding) {
|
||||
navigate(withSiteId(ONBOARDING_REDIRECT_PATH, siteId))
|
||||
}
|
||||
}, [redirectToOnboarding]);
|
||||
|
||||
console.log(withSiteId(SESSIONS_PATH, siteIdList))
|
||||
return (
|
||||
<Suspense fallback={<Loader loading={true} className="flex-1" />}>
|
||||
<Switch key="content">
|
||||
<Routes key="content">
|
||||
<Route
|
||||
exact
|
||||
strict
|
||||
path={SCOPE_SETUP}
|
||||
component={enhancedComponents.ScopeSetup}
|
||||
element={enhancedComponents.ScopeSetup}
|
||||
/>
|
||||
{redirectToSetup ? <Redirect to={SCOPE_SETUP} /> : null}
|
||||
<Route path={CLIENT_PATH} component={enhancedComponents.Client} />
|
||||
<Route path={CLIENT_PATH} element={enhancedComponents.Client} />
|
||||
<Route
|
||||
path={withSiteId(ONBOARDING_PATH, siteIdList)}
|
||||
component={enhancedComponents.Onboarding}
|
||||
element={enhancedComponents.Onboarding}
|
||||
/>
|
||||
<Route
|
||||
exact
|
||||
strict
|
||||
path={SPOTS_LIST_PATH}
|
||||
component={enhancedComponents.SpotsList}
|
||||
element={enhancedComponents.SpotsList}
|
||||
/>
|
||||
<Route
|
||||
exact
|
||||
strict
|
||||
path={SPOT_PATH}
|
||||
component={enhancedComponents.Spot}
|
||||
element={enhancedComponents.Spot}
|
||||
/>
|
||||
{scope === 1 ? <Redirect to={SPOTS_LIST_PATH} /> : null}
|
||||
{scope === 1
|
||||
? <Route
|
||||
path="*"
|
||||
>
|
||||
<Redirect to={SPOTS_LIST_PATH} />
|
||||
</Route>
|
||||
: null
|
||||
}
|
||||
<Route
|
||||
path="/integrations/"
|
||||
render={({ location }) => {
|
||||
|
|
@ -175,111 +195,106 @@ function PrivateRoutes() {
|
|||
});
|
||||
break;
|
||||
}
|
||||
return <Redirect to={CLIENT_PATH} />;
|
||||
return <Route
|
||||
path="*"
|
||||
element={<Navigate to={CLIENT_PATH} />}
|
||||
/>
|
||||
}}
|
||||
/>
|
||||
{redirectToOnboarding && (
|
||||
<Redirect to={withSiteId(ONBOARDING_REDIRECT_PATH, siteId)} />
|
||||
)}
|
||||
|
||||
{/* DASHBOARD and Metrics */}
|
||||
<Route
|
||||
exact
|
||||
strict
|
||||
path={[
|
||||
withSiteId(ALERTS_PATH, siteIdList),
|
||||
withSiteId(ALERT_EDIT_PATH, siteIdList),
|
||||
withSiteId(ALERT_CREATE_PATH, siteIdList),
|
||||
withSiteId(METRICS_PATH, siteIdList),
|
||||
withSiteId(METRICS_DETAILS, siteIdList),
|
||||
withSiteId(METRICS_DETAILS_SUB, siteIdList),
|
||||
withSiteId(DASHBOARD_PATH, siteIdList),
|
||||
withSiteId(DASHBOARD_SELECT_PATH, siteIdList),
|
||||
withSiteId(DASHBOARD_METRIC_CREATE_PATH, siteIdList),
|
||||
withSiteId(DASHBOARD_METRIC_DETAILS_PATH, siteIdList)
|
||||
]}
|
||||
component={enhancedComponents.Dashboard}
|
||||
/>
|
||||
{[
|
||||
withSiteId(ALERTS_PATH, siteIdList),
|
||||
withSiteId(ALERT_EDIT_PATH, siteIdList),
|
||||
withSiteId(ALERT_CREATE_PATH, siteIdList),
|
||||
withSiteId(METRICS_PATH, siteIdList),
|
||||
withSiteId(METRICS_DETAILS, siteIdList),
|
||||
withSiteId(METRICS_DETAILS_SUB, siteIdList),
|
||||
withSiteId(DASHBOARD_PATH, siteIdList),
|
||||
withSiteId(DASHBOARD_SELECT_PATH, siteIdList),
|
||||
withSiteId(DASHBOARD_METRIC_CREATE_PATH, siteIdList),
|
||||
withSiteId(DASHBOARD_METRIC_DETAILS_PATH, siteIdList)
|
||||
].map((path) => (
|
||||
<Route
|
||||
path={path}
|
||||
element={enhancedComponents.Dashboard}
|
||||
/>
|
||||
))}
|
||||
|
||||
<Route
|
||||
exact
|
||||
strict
|
||||
path={withSiteId(USABILITY_TESTING_PATH, siteIdList)}
|
||||
component={enhancedComponents.UsabilityTesting}
|
||||
element={enhancedComponents.UsabilityTesting}
|
||||
/>
|
||||
<Route
|
||||
exact
|
||||
strict
|
||||
path={withSiteId(USABILITY_TESTING_EDIT_PATH, siteIdList)}
|
||||
component={enhancedComponents.UsabilityTestEdit}
|
||||
element={enhancedComponents.UsabilityTestEdit}
|
||||
/>
|
||||
<Route
|
||||
exact
|
||||
strict
|
||||
path={withSiteId(USABILITY_TESTING_VIEW_PATH, siteIdList)}
|
||||
component={enhancedComponents.UsabilityTestOverview}
|
||||
element={enhancedComponents.UsabilityTestOverview}
|
||||
/>
|
||||
|
||||
<Route
|
||||
exact
|
||||
path={withSiteId(MULTIVIEW_INDEX_PATH, siteIdList)}
|
||||
component={enhancedComponents.Multiview}
|
||||
element={enhancedComponents.Multiview}
|
||||
/>
|
||||
<Route
|
||||
path={withSiteId(MULTIVIEW_PATH, siteIdList)}
|
||||
component={enhancedComponents.Multiview}
|
||||
element={enhancedComponents.Multiview}
|
||||
/>
|
||||
<Route
|
||||
exact
|
||||
strict
|
||||
path={withSiteId(ASSIST_PATH, siteIdList)}
|
||||
component={enhancedComponents.Assist}
|
||||
element={enhancedComponents.Assist}
|
||||
/>
|
||||
<Route
|
||||
exact
|
||||
strict
|
||||
path={withSiteId(RECORDINGS_PATH, siteIdList)}
|
||||
component={enhancedComponents.Assist}
|
||||
element={enhancedComponents.Assist}
|
||||
/>
|
||||
<Route
|
||||
exact
|
||||
strict
|
||||
path={withSiteId(HIGHLIGHTS_PATH, siteIdList)}
|
||||
component={enhancedComponents.Highlights}
|
||||
/>
|
||||
<Route
|
||||
exact
|
||||
strict
|
||||
path={[
|
||||
withSiteId(SESSIONS_PATH, siteIdList),
|
||||
withSiteId(FFLAGS_PATH, siteIdList),
|
||||
withSiteId(FFLAG_PATH, siteIdList),
|
||||
withSiteId(FFLAG_READ_PATH, siteIdList),
|
||||
withSiteId(FFLAG_CREATE_PATH, siteIdList),
|
||||
withSiteId(NOTES_PATH, siteIdList),
|
||||
withSiteId(BOOKMARKS_PATH, siteIdList)
|
||||
]}
|
||||
component={enhancedComponents.SessionsOverview}
|
||||
element={enhancedComponents.Highlights}
|
||||
/>
|
||||
{[
|
||||
withSiteId(SESSIONS_PATH),
|
||||
withSiteId(FFLAGS_PATH, siteIdList),
|
||||
withSiteId(FFLAG_PATH, siteIdList),
|
||||
withSiteId(FFLAG_READ_PATH, siteIdList),
|
||||
withSiteId(FFLAG_CREATE_PATH, siteIdList),
|
||||
withSiteId(NOTES_PATH, siteIdList),
|
||||
withSiteId(BOOKMARKS_PATH, siteIdList)
|
||||
].map((path) => (
|
||||
<Route
|
||||
path={path}
|
||||
element={<enhancedComponents.SessionsOverview />}
|
||||
/>
|
||||
))}
|
||||
<Route
|
||||
exact
|
||||
strict
|
||||
path={withSiteId(SESSION_PATH, siteIdList)}
|
||||
component={enhancedComponents.Session}
|
||||
element={enhancedComponents.Session}
|
||||
/>
|
||||
<Route
|
||||
exact
|
||||
strict
|
||||
path={withSiteId(LIVE_SESSION_PATH, siteIdList)}
|
||||
component={enhancedComponents.LiveSession}
|
||||
element={enhancedComponents.LiveSession}
|
||||
/>
|
||||
{Object.entries(routes.redirects).map(([fr, to]) => (
|
||||
<Redirect key={fr} exact strict from={fr} to={to} />
|
||||
))}
|
||||
<Route path={'*'}>
|
||||
<Redirect to={withSiteId(routes.sessions(), siteId)} />
|
||||
</Route>
|
||||
</Switch>
|
||||
{/*<Route path={'*'} element={<Navigate to={withSiteId(routes.sessions(), siteId)} />} />*/}
|
||||
</Routes>
|
||||
</Suspense>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import React, { lazy, Suspense, useEffect } from 'react';
|
||||
import { Loader } from 'UI';
|
||||
import { Redirect, Route, Switch } from 'react-router-dom';
|
||||
import { Navigate, Route, Routes } from 'react-router-dom';
|
||||
import Signup from 'Components/Signup/Signup';
|
||||
import SupportCallout from 'Shared/SupportCallout';
|
||||
import { useStore } from 'App/mstore';
|
||||
|
|
@ -35,13 +35,16 @@ function PublicRoutes() {
|
|||
return (
|
||||
<Loader loading={loading} className="flex-1">
|
||||
<Suspense fallback={<Loader loading={true} className="flex-1" />}>
|
||||
<Switch>
|
||||
<Route exact strict path={SPOT_PATH} component={Spot} />
|
||||
<Route exact strict path={FORGOT_PASSWORD} component={ForgotPassword} />
|
||||
<Route exact strict path={LOGIN_PATH} component={Login} />
|
||||
<Route exact strict path={SIGNUP_PATH} component={Signup} />
|
||||
<Redirect to={LOGIN_PATH} />
|
||||
</Switch>
|
||||
<Routes>
|
||||
<Route exact strict path={SPOT_PATH} element={<Spot />} />
|
||||
<Route exact strict path={FORGOT_PASSWORD} element={<ForgotPassword />} />
|
||||
<Route exact strict path={LOGIN_PATH} element={<Login />} />
|
||||
<Route exact strict path={SIGNUP_PATH} element={Signup} />
|
||||
<Route
|
||||
path="*"
|
||||
element={<Navigate to={LOGIN_PATH} replace />}
|
||||
/>
|
||||
</Routes>
|
||||
{!hideSupport && <SupportCallout />}
|
||||
</Suspense>
|
||||
</Loader>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
import React, { useEffect, useRef } from 'react';
|
||||
import { RouteComponentProps, withRouter } from 'react-router-dom';
|
||||
|
||||
import { useLocation, useNavigate } from 'react-router'
|
||||
import IFrameRoutes from 'App/IFrameRoutes';
|
||||
import PrivateRoutes from 'App/PrivateRoutes';
|
||||
import PublicRoutes from 'App/PublicRoutes';
|
||||
|
|
@ -19,19 +18,9 @@ import { Loader } from 'UI';
|
|||
import * as routes from './routes';
|
||||
import { observer } from 'mobx-react-lite'
|
||||
|
||||
interface RouterProps extends RouteComponentProps {
|
||||
match: {
|
||||
params: {
|
||||
siteId: string;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
const Router: React.FC<RouterProps> = (props) => {
|
||||
const {
|
||||
location,
|
||||
history,
|
||||
} = props;
|
||||
const Router = () => {
|
||||
const location = useLocation()
|
||||
const navigate = useNavigate()
|
||||
const mstore = useStore();
|
||||
const { customFieldStore, projectsStore, sessionStore, searchStore, userStore } = mstore;
|
||||
const jwt = userStore.jwt;
|
||||
|
|
@ -113,7 +102,7 @@ const Router: React.FC<RouterProps> = (props) => {
|
|||
) {
|
||||
const url = new URL(destinationPath, window.location.origin);
|
||||
checkParams(url.search);
|
||||
history.push(destinationPath);
|
||||
navigate(destinationPath);
|
||||
localStorage.removeItem(GLOBAL_DESTINATION_PATH);
|
||||
}
|
||||
};
|
||||
|
|
@ -219,4 +208,4 @@ const Router: React.FC<RouterProps> = (props) => {
|
|||
);
|
||||
};
|
||||
|
||||
export default withRouter(observer(Router));
|
||||
export default observer(Router);
|
||||
|
|
|
|||
|
|
@ -1,13 +1,11 @@
|
|||
import React from 'react';
|
||||
import { withRouter } from 'react-router-dom';
|
||||
import { Switch, Route, Redirect } from 'react-router';
|
||||
import { Routes, Route, Navigate } from 'react-router';
|
||||
import { CLIENT_TABS, client as clientRoute } from 'App/routes';
|
||||
|
||||
import ProfileSettings from './ProfileSettings';
|
||||
import Integrations from './Integrations';
|
||||
import UserView from './Users/UsersView';
|
||||
import AuditView from './Audit/AuditView';
|
||||
import Sites from './Sites';
|
||||
import Projects from './Projects';
|
||||
import CustomFields from './CustomFields';
|
||||
import Webhooks from './Webhooks';
|
||||
|
|
@ -16,43 +14,27 @@ import Roles from './Roles';
|
|||
import SessionsListingSettings from 'Components/Client/SessionsListingSettings';
|
||||
import Modules from 'Components/Client/Modules';
|
||||
|
||||
@withRouter
|
||||
export default class Client extends React.PureComponent {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
}
|
||||
|
||||
setTab = (tab) => {
|
||||
this.props.history.push(clientRoute(tab));
|
||||
};
|
||||
|
||||
renderActiveTab = () => (
|
||||
<Switch>
|
||||
<Route exact strict path={clientRoute(CLIENT_TABS.PROFILE)} component={ProfileSettings} />
|
||||
<Route exact strict path={clientRoute(CLIENT_TABS.SESSIONS_LISTING)} component={SessionsListingSettings} />
|
||||
<Route exact strict path={clientRoute(CLIENT_TABS.INTEGRATIONS)} component={Integrations} />
|
||||
<Route exact strict path={clientRoute(CLIENT_TABS.MANAGE_USERS)} component={UserView} />
|
||||
<Route exact strict path={clientRoute(CLIENT_TABS.SITES)} component={Projects} />
|
||||
<Route exact strict path={clientRoute(CLIENT_TABS.CUSTOM_FIELDS)} component={CustomFields} />
|
||||
<Route exact strict path={clientRoute(CLIENT_TABS.WEBHOOKS)} component={Webhooks} />
|
||||
<Route exact strict path={clientRoute(CLIENT_TABS.NOTIFICATIONS)} component={Notifications} />
|
||||
<Route exact strict path={clientRoute(CLIENT_TABS.MANAGE_ROLES)} component={Roles} />
|
||||
<Route exact strict path={clientRoute(CLIENT_TABS.AUDIT)} component={AuditView} />
|
||||
<Route exact strict path={clientRoute(CLIENT_TABS.MODULES)} component={Modules} />
|
||||
<Redirect to={clientRoute(CLIENT_TABS.PROFILE)} />
|
||||
</Switch>
|
||||
);
|
||||
|
||||
render() {
|
||||
const {
|
||||
match: {
|
||||
params: { activeTab }
|
||||
}
|
||||
} = this.props;
|
||||
return (
|
||||
<div className='w-full mx-auto mb-8' style={{ maxWidth: '1360px' }}>
|
||||
{activeTab && this.renderActiveTab()}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
function Client() {
|
||||
return (
|
||||
<div className='w-full mx-auto mb-8' style={{ maxWidth: '1360px' }}>
|
||||
<Routes>
|
||||
<Route exact strict path={clientRoute(CLIENT_TABS.PROFILE)} component={ProfileSettings} />
|
||||
<Route exact strict path={clientRoute(CLIENT_TABS.SESSIONS_LISTING)} component={SessionsListingSettings} />
|
||||
<Route exact strict path={clientRoute(CLIENT_TABS.INTEGRATIONS)} component={Integrations} />
|
||||
<Route exact strict path={clientRoute(CLIENT_TABS.MANAGE_USERS)} component={UserView} />
|
||||
<Route exact strict path={clientRoute(CLIENT_TABS.SITES)} component={Projects} />
|
||||
<Route exact strict path={clientRoute(CLIENT_TABS.CUSTOM_FIELDS)} component={CustomFields} />
|
||||
<Route exact strict path={clientRoute(CLIENT_TABS.WEBHOOKS)} component={Webhooks} />
|
||||
<Route exact strict path={clientRoute(CLIENT_TABS.NOTIFICATIONS)} component={Notifications} />
|
||||
<Route exact strict path={clientRoute(CLIENT_TABS.MANAGE_ROLES)} component={Roles} />
|
||||
<Route exact strict path={clientRoute(CLIENT_TABS.AUDIT)} component={AuditView} />
|
||||
<Route exact strict path={clientRoute(CLIENT_TABS.MODULES)} component={Modules} />
|
||||
<Route path={'*'}>
|
||||
<Navigate to={clientRoute(CLIENT_TABS.PROFILE)} />
|
||||
</Route>
|
||||
</Routes>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default Client;
|
||||
|
|
@ -1,8 +1,8 @@
|
|||
import React from 'react';
|
||||
import { App, Button, Card, Layout, Space, Tooltip, Typography } from 'antd';
|
||||
import { App, Button, Card, Layout, Tooltip, Typography } from 'antd';
|
||||
import ProjectList from 'Components/Client/Projects/ProjectList';
|
||||
import ProjectTabs from 'Components/Client/Projects/ProjectTabs';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
import { useNavigate } from 'react-router';
|
||||
import { useStore } from '@/mstore';
|
||||
import { observer } from 'mobx-react-lite';
|
||||
import {PlusOutlined, KeyOutlined} from '@ant-design/icons'
|
||||
|
|
@ -13,12 +13,12 @@ import Project from '@/mstore/types/project';
|
|||
|
||||
function Projects() {
|
||||
const { projectsStore, customFieldStore } = useStore();
|
||||
const history = useHistory();
|
||||
const navigate = useNavigate();
|
||||
const { project, pid, tab } = projectsStore.config;
|
||||
const { openModal, closeModal } = useModal();
|
||||
|
||||
React.useEffect(() => {
|
||||
const params = new URLSearchParams(history.location.search);
|
||||
const params = new URLSearchParams(location.search);
|
||||
const pid = params.get('pid');
|
||||
const tab = params.get('tab');
|
||||
projectsStore.setConfigProject(pid ? parseInt(pid) : undefined);
|
||||
|
|
@ -30,7 +30,7 @@ function Projects() {
|
|||
}, []);
|
||||
|
||||
React.useEffect(() => {
|
||||
const params = new URLSearchParams(history.location.search);
|
||||
const params = new URLSearchParams(location.search);
|
||||
if (projectsStore.config.pid) {
|
||||
params.set('pid', projectsStore.config.pid + '');
|
||||
}
|
||||
|
|
@ -38,7 +38,8 @@ function Projects() {
|
|||
if (projectsStore.config.tab) {
|
||||
params.set('tab', projectsStore.config.tab);
|
||||
}
|
||||
history.push({ search: params.toString() });
|
||||
const search = params.toString();
|
||||
navigate(location.pathname + '?' + search);
|
||||
}, [pid, tab]);
|
||||
|
||||
const createProject = () => {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { Segmented } from 'antd';
|
||||
import React, { ChangeEvent, FormEvent, useEffect, useState } from 'react';
|
||||
import { RouteComponentProps, withRouter } from 'react-router-dom';
|
||||
import { useLocation } from 'react-router'
|
||||
import { toast } from 'react-toastify';
|
||||
import { useStore } from 'App/mstore';
|
||||
import { confirm, Form, Icon, Input } from 'UI';
|
||||
|
|
@ -13,9 +13,10 @@ type OwnProps = {
|
|||
onClose: (arg: any) => void;
|
||||
};
|
||||
|
||||
type Props = RouteComponentProps & OwnProps;
|
||||
type Props = OwnProps;
|
||||
|
||||
const NewSiteForm = ({ location: { pathname }, onClose }: Props) => {
|
||||
const NewSiteForm = ({ onClose }: Props) => {
|
||||
const { pathname } = useLocation();
|
||||
const mstore = useStore();
|
||||
const { projectsStore } = mstore;
|
||||
const activeSiteId = projectsStore.active?.id;
|
||||
|
|
@ -170,4 +171,4 @@ const NewSiteForm = ({ location: { pathname }, onClose }: Props) => {
|
|||
);
|
||||
};
|
||||
|
||||
export default withRouter(observer(NewSiteForm));
|
||||
export default observer(NewSiteForm);
|
||||
|
|
|
|||
|
|
@ -1,20 +1,15 @@
|
|||
import React, { useEffect } from 'react';
|
||||
import { observer } from 'mobx-react-lite';
|
||||
import { useStore } from 'App/mstore';
|
||||
import { withRouter, RouteComponentProps } from 'react-router-dom';
|
||||
import { useNavigate, useParams } from "react-router";
|
||||
import { Loader } from 'UI';
|
||||
import { withSiteId, dashboard, metrics } from "App/routes";
|
||||
import DashboardRouter from './components/DashboardRouter';
|
||||
import withPermissions from 'HOCs/withPermissions';
|
||||
|
||||
interface RouterProps {
|
||||
siteId: string;
|
||||
dashboardId: string;
|
||||
metricId: string;
|
||||
}
|
||||
|
||||
function NewDashboard(props: RouteComponentProps<RouterProps>) {
|
||||
const { history, match: { params: { siteId, dashboardId } } } = props;
|
||||
function NewDashboard() {
|
||||
const { siteId, dashboardId } = useParams()
|
||||
const navigate = useNavigate();
|
||||
const { dashboardStore } = useStore();
|
||||
const initId = React.useRef(siteId)
|
||||
const loading = dashboardStore.isLoading;
|
||||
|
|
@ -23,10 +18,10 @@ function NewDashboard(props: RouteComponentProps<RouterProps>) {
|
|||
useEffect(() => {
|
||||
if (siteId !== initId.current) {
|
||||
if (isMetricListMetric) {
|
||||
history.push(withSiteId(metrics(), siteId))
|
||||
navigate(withSiteId(metrics(), siteId))
|
||||
}
|
||||
if (isDbMetric) {
|
||||
history.push(withSiteId(dashboard(), siteId))
|
||||
navigate(withSiteId(dashboard(), siteId))
|
||||
}
|
||||
}
|
||||
dashboardStore.fetchList().then((resp) => {
|
||||
|
|
@ -43,4 +38,4 @@ function NewDashboard(props: RouteComponentProps<RouterProps>) {
|
|||
);
|
||||
}
|
||||
|
||||
export default withRouter(withPermissions(['METRICS'])(observer(NewDashboard)));
|
||||
export default withPermissions(['METRICS'])(observer(NewDashboard))
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import React, { useEffect } from "react";
|
||||
import { Pagination, NoContent, Icon } from "UI";
|
||||
import ErrorListItem from "App/components/Dashboard/components/Errors/ErrorListItem";
|
||||
import { withRouter, RouteComponentProps } from "react-router-dom";
|
||||
import { useLocation, useNavigate } from "react-router";
|
||||
import { useModal } from "App/components/Modal";
|
||||
import ErrorDetailsModal from "App/components/Dashboard/components/Errors/ErrorDetailsModal";
|
||||
|
||||
|
|
@ -9,19 +9,18 @@ interface Props {
|
|||
metric: any;
|
||||
data: any;
|
||||
isEdit: any;
|
||||
history: any;
|
||||
location: any;
|
||||
}
|
||||
function CustomMetricTableErrors(props: RouteComponentProps & Props) {
|
||||
function CustomMetricTableErrors(props: Props) {
|
||||
const { metric, data } = props;
|
||||
const errorId = new URLSearchParams(props.location.search).get("errorId");
|
||||
const location = useLocation();
|
||||
const navigate = useNavigate();
|
||||
const errorId = new URLSearchParams(location.search).get("errorId");
|
||||
const { showModal, hideModal } = useModal();
|
||||
|
||||
const onErrorClick = (e: any, error: any) => {
|
||||
e.stopPropagation();
|
||||
props.history.replace({
|
||||
search: new URLSearchParams({ errorId: error.errorId }).toString(),
|
||||
});
|
||||
const search = new URLSearchParams({ errorId: error.errorId }).toString()
|
||||
navigate(location.pathname + "?" + search, { replace: true });
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
|
|
@ -31,8 +30,8 @@ function CustomMetricTableErrors(props: RouteComponentProps & Props) {
|
|||
right: true,
|
||||
width: 1200,
|
||||
onClose: () => {
|
||||
if (props.history.location.pathname.includes("/dashboard") || props.history.location.pathname.includes("/metrics/")) {
|
||||
props.history.replace({ search: "" });
|
||||
if (location.pathname.includes("/dashboard") || location.pathname.includes("/metrics/")) {
|
||||
navigate(location.pathname, { replace: true });
|
||||
}
|
||||
},
|
||||
});
|
||||
|
|
@ -60,7 +59,6 @@ function CustomMetricTableErrors(props: RouteComponentProps & Props) {
|
|||
</div>
|
||||
))}
|
||||
|
||||
{/*{isEdit && (*/}
|
||||
<div className="my-6 flex items-center justify-center">
|
||||
<Pagination
|
||||
page={metric.page}
|
||||
|
|
@ -72,25 +70,9 @@ function CustomMetricTableErrors(props: RouteComponentProps & Props) {
|
|||
debounceRequest={500}
|
||||
/>
|
||||
</div>
|
||||
{/*)}*/}
|
||||
|
||||
{/*{!isEdit && (*/}
|
||||
{/* <ViewMore total={data.total} limit={5} />*/}
|
||||
{/*)}*/}
|
||||
</div>
|
||||
</NoContent>
|
||||
);
|
||||
}
|
||||
|
||||
export default withRouter<Props & RouteComponentProps, React.FunctionComponent>(CustomMetricTableErrors);
|
||||
|
||||
const ViewMore = ({ total, limit }: any) =>
|
||||
total > limit && (
|
||||
<div className="mt-4 flex items-center justify-center cursor-pointer w-fit mx-auto">
|
||||
<div className="text-center">
|
||||
<div className="color-teal text-lg">
|
||||
All <span className="font-medium">{total}</span> errors
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
export default CustomMetricTableErrors;
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ import {
|
|||
USER_PATH,
|
||||
CATEGORIES,
|
||||
} from 'App/constants/card';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
import { useNavigate } from 'react-router';
|
||||
import { dashboardMetricCreate, withSiteId, metricCreate } from 'App/routes';
|
||||
import { FilterKey } from 'Types/filter/filterType';
|
||||
import MetricsLibraryModal from '../MetricsLibraryModal/MetricsLibraryModal';
|
||||
|
|
@ -183,16 +183,16 @@ function CategoryTab({
|
|||
}) {
|
||||
const items = isMobile ? mobileTabItems[tab] : tabItems[tab];
|
||||
const { projectsStore, dashboardStore } = useStore();
|
||||
const history = useHistory();
|
||||
const navigate = useNavigate();
|
||||
|
||||
const handleCardSelection = (card: string) => {
|
||||
if (projectsStore.activeSiteId) {
|
||||
if (inCards) {
|
||||
history.push(
|
||||
navigate(
|
||||
withSiteId(metricCreate(), projectsStore.activeSiteId) + `?mk=${card}`
|
||||
);
|
||||
} else if (dashboardStore.selectedDashboard) {
|
||||
history.push(
|
||||
navigate(
|
||||
withSiteId(
|
||||
dashboardMetricCreate(dashboardStore.selectedDashboard.dashboardId),
|
||||
projectsStore.activeSiteId
|
||||
|
|
|
|||
|
|
@ -6,10 +6,10 @@ import { withSiteId, alertEdit } from 'App/routes';
|
|||
import { numberWithCommas } from 'App/utils';
|
||||
// @ts-ignore
|
||||
import { DateTime } from 'luxon';
|
||||
import { withRouter, RouteComponentProps } from 'react-router-dom';
|
||||
import cn from 'classnames';
|
||||
import Alert from 'Types/alert';
|
||||
import { observer } from 'mobx-react-lite'
|
||||
import { useNavigate } from 'react-router';
|
||||
|
||||
const getThreshold = (threshold: number) => {
|
||||
if (threshold === 15) return '15 Minutes';
|
||||
|
|
@ -84,7 +84,8 @@ interface Props extends RouteComponentProps {
|
|||
}
|
||||
|
||||
function AlertListItem(props: Props) {
|
||||
const { alert, siteId, history, init, demo, webhooks, triggerOptions } = props;
|
||||
const { alert, siteId, init, demo, webhooks, triggerOptions } = props;
|
||||
const navigate = useNavigate();
|
||||
|
||||
if (!alert) {
|
||||
return null;
|
||||
|
|
@ -94,7 +95,7 @@ function AlertListItem(props: Props) {
|
|||
if (demo) return;
|
||||
const path = withSiteId(alertEdit(alert.alertId), siteId);
|
||||
init(alert || {});
|
||||
history.push(path);
|
||||
navigate(path);
|
||||
};
|
||||
|
||||
const formTriggerName = () =>
|
||||
|
|
@ -169,4 +170,4 @@ function AlertListItem(props: Props) {
|
|||
);
|
||||
}
|
||||
|
||||
export default withRouter(observer(AlertListItem));
|
||||
export default observer(AlertListItem);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import React, { useEffect } from 'react';
|
||||
import { PageTitle, Icon, Link } from 'UI';
|
||||
import { PageTitle, Link } from 'UI';
|
||||
import { Button } from 'antd';
|
||||
import { PlusOutlined } from '@ant-design/icons';
|
||||
import withPageTitle from 'HOCs/withPageTitle';
|
||||
|
|
@ -7,7 +7,7 @@ import { withSiteId, alertCreate } from 'App/routes';
|
|||
|
||||
import AlertsList from './AlertsList';
|
||||
import AlertsSearch from './AlertsSearch';
|
||||
import { useHistory } from 'react-router';
|
||||
import { useLocation } from 'react-router';
|
||||
import { useStore } from 'App/mstore';
|
||||
|
||||
interface IAlertsView {
|
||||
|
|
@ -15,18 +15,16 @@ interface IAlertsView {
|
|||
}
|
||||
|
||||
function AlertsView({ siteId }: IAlertsView) {
|
||||
const history = useHistory();
|
||||
const location = useLocation();
|
||||
const { alertsStore } = useStore();
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
const unmount = history.listen((location) => {
|
||||
return () => {
|
||||
if (!location.pathname.includes('/alert')) {
|
||||
alertsStore.updateKey('page', 1);
|
||||
}
|
||||
});
|
||||
return unmount;
|
||||
}, [history]);
|
||||
}
|
||||
}, [location.pathname]);
|
||||
return (
|
||||
<div style={{ maxWidth: '1360px', margin: 'auto'}} className="bg-white rounded-lg shadow-sm py-4 border">
|
||||
<div className="flex items-center mb-4 justify-between px-6">
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ import { toast } from 'react-toastify';
|
|||
import { SLACK, WEBHOOK, TEAMS } from 'App/constants/schedule';
|
||||
import Breadcrumb from 'Shared/Breadcrumb';
|
||||
import { withSiteId, alerts } from 'App/routes';
|
||||
import { withRouter, RouteComponentProps } from 'react-router-dom';
|
||||
import { useStore } from 'App/mstore'
|
||||
import { observer } from 'mobx-react-lite'
|
||||
import Alert from 'Types/alert'
|
||||
|
|
@ -16,6 +15,7 @@ import BottomButtons from './AlertForm/BottomButtons';
|
|||
import NotifyHooks from './AlertForm/NotifyHooks';
|
||||
import AlertListItem from './AlertListItem';
|
||||
import Condition from './AlertForm/Condition';
|
||||
import { useNavigate } from "react-router";
|
||||
|
||||
const Circle = ({ text }: { text: string }) => (
|
||||
<div
|
||||
|
|
@ -52,7 +52,7 @@ interface Select {
|
|||
value: string | number
|
||||
}
|
||||
|
||||
interface IProps extends RouteComponentProps {
|
||||
interface IProps {
|
||||
siteId: string;
|
||||
slackChannels: any[];
|
||||
loading: boolean;
|
||||
|
|
@ -63,7 +63,9 @@ interface IProps extends RouteComponentProps {
|
|||
}
|
||||
|
||||
const NewAlert = (props: IProps) => {
|
||||
const { alertsStore, settingsStore } = useStore();
|
||||
const navigate = useNavigate();
|
||||
const { alertsStore, settingsStore, projectsStore } = useStore();
|
||||
const siteId = projectsStore.activeSiteId
|
||||
const {
|
||||
fetchTriggerOptions,
|
||||
init,
|
||||
|
|
@ -80,9 +82,6 @@ const NewAlert = (props: IProps) => {
|
|||
const deleting = loading
|
||||
const webhooks = settingsStore.webhooks
|
||||
const fetchWebhooks = settingsStore.fetchWebhooks
|
||||
const {
|
||||
siteId,
|
||||
} = props;
|
||||
|
||||
useEffect(() => {
|
||||
init({});
|
||||
|
|
@ -120,7 +119,7 @@ const NewAlert = (props: IProps) => {
|
|||
})
|
||||
) {
|
||||
remove(instance.alertId).then(() => {
|
||||
props.history.push(withSiteId(alerts(), siteId));
|
||||
navigate(withSiteId(alerts(), siteId));
|
||||
toast.success('Alert deleted');
|
||||
}).catch(() => {
|
||||
toast.error('Failed to delete an alert');
|
||||
|
|
@ -133,7 +132,7 @@ const NewAlert = (props: IProps) => {
|
|||
save(instance).then(() => {
|
||||
if (!wasUpdating) {
|
||||
toast.success('New alert saved');
|
||||
props.history.push(withSiteId(alerts(), siteId));
|
||||
navigate(withSiteId(alerts(), siteId));
|
||||
} else {
|
||||
toast.success('Alert updated');
|
||||
}
|
||||
|
|
@ -296,4 +295,4 @@ const NewAlert = (props: IProps) => {
|
|||
);
|
||||
};
|
||||
|
||||
export default withRouter(observer(NewAlert))
|
||||
export default observer(NewAlert)
|
||||
|
|
|
|||
|
|
@ -1,21 +1,19 @@
|
|||
import { useModal } from 'App/components/Modal';
|
||||
import { observer } from 'mobx-react-lite';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { RouteComponentProps, withRouter } from 'react-router';
|
||||
import { Loader, Pagination } from 'UI';
|
||||
import { Button } from 'antd'
|
||||
import SessionsModal from './SessionsModal';
|
||||
import CardUserItem from './CardUserItem';
|
||||
import { useStore } from 'App/mstore';
|
||||
import { useNavigate, useLocation } from 'react-router';
|
||||
|
||||
interface Props {
|
||||
history: any;
|
||||
location: any;
|
||||
}
|
||||
function CardUserList(props: RouteComponentProps<Props>) {
|
||||
function CardUserList() {
|
||||
const navigate = useNavigate();
|
||||
const location = useLocation();
|
||||
const [loading, setLoading] = useState(false);
|
||||
const { showModal } = useModal();
|
||||
const userId = new URLSearchParams(props.location.search).get("userId");
|
||||
const userId = new URLSearchParams(location.search).get("userId");
|
||||
const { metricStore, dashboardStore } = useStore();
|
||||
|
||||
const [data, setData] = useState<any>([
|
||||
|
|
@ -27,7 +25,8 @@ function CardUserList(props: RouteComponentProps<Props>) {
|
|||
const pageSize = data.length;
|
||||
|
||||
const handleClick = (issue: any) => {
|
||||
props.history.replace({search: (new URLSearchParams({userId : '123'})).toString()});
|
||||
const search = (new URLSearchParams({userId : '123'})).toString()
|
||||
navigate(location.pathname + "?" + search, { replace: true });
|
||||
// showModal(<SessionsModal list={[]} />, { right: true, width: 450 })
|
||||
}
|
||||
|
||||
|
|
@ -35,8 +34,8 @@ function CardUserList(props: RouteComponentProps<Props>) {
|
|||
if (!userId) return;
|
||||
|
||||
showModal(<SessionsModal userId={userId} name="test" hash="test" />, { right: true, width: 600, onClose: () => {
|
||||
if (props.history.location.pathname.includes("/metric")) {
|
||||
props.history.replace({search: ""});
|
||||
if (location.pathname.includes("/metric")) {
|
||||
navigate(location.pathname, { replace: true });
|
||||
}
|
||||
}});
|
||||
}, [userId]);
|
||||
|
|
@ -75,4 +74,4 @@ function CardUserList(props: RouteComponentProps<Props>) {
|
|||
);
|
||||
}
|
||||
|
||||
export default withRouter(observer(CardUserList));
|
||||
export default observer(CardUserList);
|
||||
|
|
@ -2,7 +2,7 @@ import React from 'react';
|
|||
import { PlusOutlined } from '@ant-design/icons';
|
||||
import { Button } from 'antd';
|
||||
import { useStore } from 'App/mstore';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
import { useNavigate } from 'react-router';
|
||||
|
||||
interface Props {
|
||||
disabled?: boolean;
|
||||
|
|
@ -12,7 +12,7 @@ function CreateDashboardButton({ disabled }: Props) {
|
|||
const [dashboardCreating, setDashboardCreating] = React.useState(false);
|
||||
const { projectsStore, dashboardStore } = useStore();
|
||||
const siteId = projectsStore.siteId;
|
||||
const history = useHistory();
|
||||
const navigate = useNavigate();
|
||||
|
||||
const createNewDashboard = async () => {
|
||||
setDashboardCreating(true);
|
||||
|
|
@ -21,7 +21,7 @@ function CreateDashboardButton({ disabled }: Props) {
|
|||
.save(dashboardStore.dashboardInstance)
|
||||
.then(async (syncedDashboard) => {
|
||||
dashboardStore.selectDashboardById(syncedDashboard.dashboardId);
|
||||
history.push(`/${siteId}/dashboard/${syncedDashboard.dashboardId}`);
|
||||
navigate(`/${siteId}/dashboard/${syncedDashboard.dashboardId}`);
|
||||
})
|
||||
.finally(() => {
|
||||
setDashboardCreating(false);
|
||||
|
|
|
|||
|
|
@ -2,23 +2,21 @@ import React from 'react';
|
|||
import { useStore } from 'App/mstore';
|
||||
import { SideMenuitem, Icon } from 'UI';
|
||||
import { withSiteId, dashboardSelected } from 'App/routes';
|
||||
import { withRouter } from 'react-router-dom';
|
||||
import { useNavigate } from 'react-router';
|
||||
import { useModal } from 'App/components/Modal';
|
||||
|
||||
interface Props {
|
||||
siteId: string
|
||||
history: any
|
||||
}
|
||||
function DashbaordListModal(props: Props) {
|
||||
const { dashboardStore } = useStore();
|
||||
function DashbaordListModal() {
|
||||
const navigate = useNavigate();
|
||||
const { dashboardStore, projectsStore } = useStore();
|
||||
const siteId = projectsStore.activeSiteId;
|
||||
const { hideModal } = useModal();
|
||||
const dashboards = dashboardStore.dashboards;
|
||||
const activeDashboardId = dashboardStore.selectedDashboard?.dashboardId;
|
||||
|
||||
const onItemClick = (dashboard) => {
|
||||
dashboardStore.selectDashboardById(dashboard.dashboardId);
|
||||
const path = withSiteId(dashboardSelected(dashboard.dashboardId), parseInt(props.siteId));
|
||||
props.history.push(path);
|
||||
const path = withSiteId(dashboardSelected(dashboard.dashboardId), parseInt(siteId));
|
||||
navigate(path);
|
||||
hideModal();
|
||||
};
|
||||
return (
|
||||
|
|
@ -46,4 +44,4 @@ function DashbaordListModal(props: Props) {
|
|||
);
|
||||
}
|
||||
|
||||
export default withRouter(DashbaordListModal);
|
||||
export default DashbaordListModal;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
import React from 'react';
|
||||
import BackButton from 'Shared/Breadcrumb/BackButton';
|
||||
import { withSiteId } from 'App/routes';
|
||||
import { withRouter, RouteComponentProps } from 'react-router-dom';
|
||||
import { PageTitle, confirm } from 'UI';
|
||||
import { Tooltip, Popover, Button } from 'antd';
|
||||
import { PlusOutlined } from '@ant-design/icons';
|
||||
|
|
@ -12,21 +11,23 @@ import withModal from 'App/components/Modal/withModal';
|
|||
import { observer } from 'mobx-react-lite';
|
||||
import DashboardEditModal from '../DashboardEditModal';
|
||||
import AddCardSection from '../AddCardSection/AddCardSection';
|
||||
import { useNavigate } from "react-router";
|
||||
|
||||
interface IProps {
|
||||
siteId: string;
|
||||
renderReport?: any;
|
||||
}
|
||||
|
||||
type Props = IProps & RouteComponentProps;
|
||||
type Props = IProps;
|
||||
|
||||
function DashboardHeader(props: Props) {
|
||||
const { siteId } = props;
|
||||
const navigate = useNavigate();
|
||||
const [popoverOpen, setPopoverOpen] = React.useState(false);
|
||||
const handleOpenChange = (open: boolean) => {
|
||||
setPopoverOpen(open);
|
||||
};
|
||||
const { dashboardStore } = useStore();
|
||||
const { dashboardStore, projectsStore } = useStore();
|
||||
const siteId = projectsStore.activeSiteId
|
||||
const [focusTitle, setFocusedInput] = React.useState(true);
|
||||
const [showEditModal, setShowEditModal] = React.useState(false);
|
||||
const period = dashboardStore.period;
|
||||
|
|
@ -48,7 +49,7 @@ function DashboardHeader(props: Props) {
|
|||
})
|
||||
) {
|
||||
dashboardStore.deleteDashboard(dashboard).then(() => {
|
||||
props.history.push(withSiteId(`/dashboard`, siteId));
|
||||
navigate(withSiteId(`/dashboard`, siteId));
|
||||
});
|
||||
}
|
||||
};
|
||||
|
|
@ -118,4 +119,4 @@ function DashboardHeader(props: Props) {
|
|||
);
|
||||
}
|
||||
|
||||
export default withRouter(withModal(observer(DashboardHeader)));
|
||||
export default withModal(observer(DashboardHeader));
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { observer } from 'mobx-react-lite';
|
||||
import React from 'react';
|
||||
import { useHistory } from 'react-router';
|
||||
import { useNavigate } from 'react-router';
|
||||
import {
|
||||
Empty,
|
||||
Switch,
|
||||
|
|
@ -32,7 +32,7 @@ function DashboardList() {
|
|||
|
||||
const list = dashboardStore.filteredList;
|
||||
const dashboardsSearch = dashboardStore.filter.query;
|
||||
const history = useHistory();
|
||||
const navigate = useNavigate();
|
||||
|
||||
// Define custom width and height for each scenario
|
||||
const searchImageDimensions = { width: 60, height: 'auto' };
|
||||
|
|
@ -250,7 +250,7 @@ function DashboardList() {
|
|||
dashboardSelected(record.dashboardId),
|
||||
siteId
|
||||
);
|
||||
history.push(path);
|
||||
navigate(path);
|
||||
},
|
||||
})}
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import withPageTitle from 'HOCs/withPageTitle';
|
|||
import DashboardList from './DashboardList';
|
||||
import Header from './Header';
|
||||
|
||||
function DashboardsView({history, siteId}: { history: any; siteId: string }) {
|
||||
function DashboardsView() {
|
||||
return (
|
||||
<div style={{maxWidth: '1360px', margin: 'auto'}} className="bg-white rounded-lg py-4 border shadow-sm">
|
||||
<Header />
|
||||
|
|
|
|||
|
|
@ -1,108 +1,96 @@
|
|||
import React from 'react';
|
||||
import {Button, Space} from "antd";
|
||||
import {ArrowLeft, ArrowRight} from "lucide-react";
|
||||
import CardBuilder from "Components/Dashboard/components/WidgetForm/CardBuilder";
|
||||
import {useHistory} from "react-router";
|
||||
import {useStore} from "App/mstore";
|
||||
import { HEATMAP } from "App/constants/card";
|
||||
import {renderClickmapThumbnail} from "Components/Dashboard/components/WidgetForm/renderMap";
|
||||
import WidgetPreview from "Components/Dashboard/components/WidgetPreview/WidgetPreview";
|
||||
import { Button, Space } from 'antd';
|
||||
import { ArrowLeft, ArrowRight } from 'lucide-react';
|
||||
import { useNavigate, useLocation } from 'react-router';
|
||||
import { useStore } from 'App/mstore';
|
||||
import { HEATMAP } from 'App/constants/card';
|
||||
import { renderClickmapThumbnail } from 'Components/Dashboard/components/WidgetForm/renderMap';
|
||||
import WidgetPreview from 'Components/Dashboard/components/WidgetPreview/WidgetPreview';
|
||||
import WidgetFormNew from 'Components/Dashboard/components/WidgetForm/WidgetFormNew';
|
||||
|
||||
const getTitleByType = (type: string) => {
|
||||
switch (type) {
|
||||
case HEATMAP:
|
||||
return 'Heatmap';
|
||||
default:
|
||||
return 'Trend Single';
|
||||
}
|
||||
}
|
||||
|
||||
interface Props {
|
||||
// cardType: string,
|
||||
onBack?: () => void
|
||||
onAdded?: () => void
|
||||
extra?: React.ReactNode
|
||||
onBack?: () => void;
|
||||
onAdded?: () => void;
|
||||
extra?: React.ReactNode;
|
||||
}
|
||||
|
||||
function CreateCard(props: Props) {
|
||||
const history = useHistory();
|
||||
const {metricStore, dashboardStore, aiFiltersStore} = useStore();
|
||||
const metric = metricStore.instance;
|
||||
const siteId: string = history.location.pathname.split('/')[1];
|
||||
const dashboardId: string = history.location.pathname.split('/')[3];
|
||||
const isItDashboard = history.location.pathname.includes('dashboard')
|
||||
// const title = getTitleByType(metric.metricType)
|
||||
const location = useLocation();
|
||||
const navigate = useNavigate();
|
||||
const { metricStore, dashboardStore } = useStore();
|
||||
const metric = metricStore.instance;
|
||||
const dashboardId: string = location.pathname.split('/')[3];
|
||||
const isItDashboard = location.pathname.includes('dashboard');
|
||||
|
||||
const createNewDashboard = async () => {
|
||||
dashboardStore.initDashboard();
|
||||
return await dashboardStore
|
||||
.save(dashboardStore.dashboardInstance)
|
||||
.then(async (syncedDashboard) => {
|
||||
dashboardStore.selectDashboardById(syncedDashboard.dashboardId);
|
||||
return syncedDashboard.dashboardId;
|
||||
});
|
||||
}
|
||||
const createNewDashboard = async () => {
|
||||
dashboardStore.initDashboard();
|
||||
return await dashboardStore
|
||||
.save(dashboardStore.dashboardInstance)
|
||||
.then(async (syncedDashboard) => {
|
||||
dashboardStore.selectDashboardById(syncedDashboard.dashboardId);
|
||||
return syncedDashboard.dashboardId;
|
||||
});
|
||||
};
|
||||
|
||||
const addCardToDashboard = async (dashboardId: string, metricId: string) => {
|
||||
return dashboardStore.addWidgetToDashboard(
|
||||
dashboardStore.getDashboard(parseInt(dashboardId, 10))!, [metricId]
|
||||
);
|
||||
}
|
||||
|
||||
const createCard = async () => {
|
||||
const isClickMap = metric.metricType === HEATMAP;
|
||||
if (isClickMap) {
|
||||
try {
|
||||
metric.thumbnail = await renderClickmapThumbnail();
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
}
|
||||
|
||||
const savedMetric = await metricStore.save(metric);
|
||||
return savedMetric.metricId;
|
||||
}
|
||||
|
||||
const createDashboardAndAddCard = async () => {
|
||||
const cardId = await createCard();
|
||||
|
||||
if (dashboardId) {
|
||||
await addCardToDashboard(dashboardId, cardId);
|
||||
void dashboardStore.fetch(dashboardId);
|
||||
props.onAdded?.();
|
||||
} else if (isItDashboard) {
|
||||
const dashboardId = await createNewDashboard();
|
||||
await addCardToDashboard(dashboardId, cardId);
|
||||
history.replace(`${history.location.pathname}/${dashboardId}`);
|
||||
} else {
|
||||
history.replace(`${history.location.pathname}/${cardId}`);
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="flex gap-4 flex-col">
|
||||
<div className="flex items-center justify-between">
|
||||
<Space>
|
||||
{props.onBack ? <Button type="text" onClick={props.onBack}>
|
||||
<ArrowLeft size={16} />
|
||||
</Button> : null}
|
||||
<div className="text-xl leading-4 font-medium">
|
||||
{metric.name}
|
||||
</div>
|
||||
</Space>
|
||||
<Button type="primary" onClick={createDashboardAndAddCard}>
|
||||
<Space>
|
||||
Create <ArrowRight size={14}/>
|
||||
</Space>
|
||||
</Button>
|
||||
</div>
|
||||
{props.extra}
|
||||
{/*<CardBuilder siteId={siteId}/>*/}
|
||||
<WidgetFormNew/>
|
||||
<WidgetPreview className="" name={metric.name} isEditing={true}/>
|
||||
</div>
|
||||
const addCardToDashboard = async (dashboardId: string, metricId: string) => {
|
||||
return dashboardStore.addWidgetToDashboard(
|
||||
dashboardStore.getDashboard(parseInt(dashboardId, 10))!,
|
||||
[metricId]
|
||||
);
|
||||
};
|
||||
|
||||
const createCard = async () => {
|
||||
const isClickMap = metric.metricType === HEATMAP;
|
||||
if (isClickMap) {
|
||||
try {
|
||||
metric.thumbnail = await renderClickmapThumbnail();
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
}
|
||||
|
||||
const savedMetric = await metricStore.save(metric);
|
||||
return savedMetric.metricId;
|
||||
};
|
||||
|
||||
const createDashboardAndAddCard = async () => {
|
||||
const cardId = await createCard();
|
||||
|
||||
if (dashboardId) {
|
||||
await addCardToDashboard(dashboardId, cardId);
|
||||
void dashboardStore.fetch(dashboardId);
|
||||
props.onAdded?.();
|
||||
} else if (isItDashboard) {
|
||||
const dashboardId = await createNewDashboard();
|
||||
await addCardToDashboard(dashboardId, cardId);
|
||||
navigate(`${location.pathname}/${dashboardId}`, { replace: true });
|
||||
} else {
|
||||
navigate(`${location.pathname}/${cardId}`, { replace: true });
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="flex gap-4 flex-col">
|
||||
<div className="flex items-center justify-between">
|
||||
<Space>
|
||||
{props.onBack ? (
|
||||
<Button type="text" onClick={props.onBack}>
|
||||
<ArrowLeft size={16} />
|
||||
</Button>
|
||||
) : null}
|
||||
<div className="text-xl leading-4 font-medium">{metric.name}</div>
|
||||
</Space>
|
||||
<Button type="primary" onClick={createDashboardAndAddCard}>
|
||||
<Space>
|
||||
Create <ArrowRight size={14} />
|
||||
</Space>
|
||||
</Button>
|
||||
</div>
|
||||
{props.extra}
|
||||
<WidgetFormNew />
|
||||
<WidgetPreview className="" name={metric.name} isEditing={true} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default CreateCard;
|
||||
|
|
|
|||
|
|
@ -1,13 +1,13 @@
|
|||
import React, { useMemo, useState, useEffect } from 'react';
|
||||
import { Button, Input, Segmented, Space } from 'antd';
|
||||
import { RightOutlined } from '@ant-design/icons';
|
||||
import { ArrowRight, Info } from 'lucide-react';
|
||||
import { Info } from 'lucide-react';
|
||||
import { CARD_LIST, CARD_CATEGORIES, CardType } from './ExampleCards';
|
||||
import { useStore } from 'App/mstore';
|
||||
import Option from './Option';
|
||||
import CardsLibrary from 'Components/Dashboard/components/DashboardList/NewDashModal/CardsLibrary';
|
||||
import { FUNNEL } from 'App/constants/card';
|
||||
import { useHistory } from 'react-router';
|
||||
import { useNavigate } from 'react-router';
|
||||
import { FilterKey } from 'Types/filter/filterType';
|
||||
import FilterSeries from '@/mstore/types/filterSeries';
|
||||
|
||||
|
|
@ -32,7 +32,7 @@ const SelectCard: React.FC<SelectCardProps> = (props: SelectCardProps) => {
|
|||
const isCreatingDashboard = !dashboardId && location.pathname.includes('dashboard');
|
||||
const [dashboardCreating, setDashboardCreating] = useState<boolean>(false);
|
||||
const [dashboardUpdating, setDashboardUpdating] = useState<boolean>(false);
|
||||
const history = useHistory();
|
||||
const navigate = useNavigate();
|
||||
|
||||
useEffect(() => {
|
||||
if (dashboardId) {
|
||||
|
|
@ -49,8 +49,7 @@ const SelectCard: React.FC<SelectCardProps> = (props: SelectCardProps) => {
|
|||
.save(dashboardStore.dashboardInstance)
|
||||
.then(async (syncedDashboard) => {
|
||||
dashboardStore.selectDashboardById(syncedDashboard.dashboardId);
|
||||
history.push(`/${siteId}/dashboard/${syncedDashboard.dashboardId}`);
|
||||
//return syncedDashboard.dashboardId;
|
||||
navigate(`/${siteId}/dashboard/${syncedDashboard.dashboardId}`);
|
||||
}).finally(() => {
|
||||
setDashboardCreating(false);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -3,20 +3,20 @@ import { useObserver } from 'mobx-react-lite';
|
|||
import DashboardMetricSelection from '../DashboardMetricSelection';
|
||||
import DashboardForm from '../DashboardForm';
|
||||
import { Button } from 'antd';
|
||||
import { withRouter, RouteComponentProps } from 'react-router-dom';
|
||||
import { useStore } from 'App/mstore';
|
||||
import { useModal } from 'App/components/Modal';
|
||||
import { dashboardMetricCreate, withSiteId } from 'App/routes';
|
||||
import { useNavigate } from "react-router";
|
||||
|
||||
interface Props extends RouteComponentProps {
|
||||
history: any
|
||||
siteId?: string
|
||||
interface Props {
|
||||
dashboardId?: string
|
||||
onMetricAdd?: () => void;
|
||||
}
|
||||
function DashboardModal(props: Props) {
|
||||
const { history, siteId, dashboardId } = props;
|
||||
const { dashboardStore } = useStore();
|
||||
const navigate = useNavigate();
|
||||
const { dashboardId } = props;
|
||||
const { dashboardStore, projectsStore } = useStore();
|
||||
const siteId = projectsStore.activeSiteId
|
||||
const selectedWidgetsCount = useObserver(() => dashboardStore.selectedWidgets.length);
|
||||
const { hideModal } = useModal();
|
||||
const dashboard = useObserver(() => dashboardStore.dashboardInstance);
|
||||
|
|
@ -28,7 +28,7 @@ function DashboardModal(props: Props) {
|
|||
await dashboardStore.fetch(dashboard.dashboardId)
|
||||
}
|
||||
dashboardStore.selectDashboardById(syncedDashboard.dashboardId);
|
||||
history.push(withSiteId(`/dashboard/${syncedDashboard.dashboardId}`, siteId))
|
||||
navigate(withSiteId(`/dashboard/${syncedDashboard.dashboardId}`, siteId))
|
||||
})
|
||||
.then(hideModal)
|
||||
}
|
||||
|
|
@ -36,7 +36,7 @@ function DashboardModal(props: Props) {
|
|||
const handleCreateNew = () => {
|
||||
const path = withSiteId(dashboardMetricCreate(dashboardId), siteId);
|
||||
props.onMetricAdd();
|
||||
history.push(path);
|
||||
navigate(path);
|
||||
hideModal();
|
||||
}
|
||||
const isDashboardExists = dashboard.exists()
|
||||
|
|
@ -81,4 +81,4 @@ function DashboardModal(props: Props) {
|
|||
));
|
||||
}
|
||||
|
||||
export default withRouter(DashboardModal);
|
||||
export default DashboardModal;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
import React from 'react';
|
||||
import { Switch, Route } from 'react-router';
|
||||
import { withRouter, RouteComponentProps } from 'react-router-dom';
|
||||
import { Routes, Route } from 'react-router';
|
||||
|
||||
import {
|
||||
metrics,
|
||||
|
|
@ -22,26 +21,18 @@ import WidgetSubDetailsView from '../WidgetSubDetailsView';
|
|||
import DashboardsView from '../DashboardList';
|
||||
import Alerts from '../Alerts';
|
||||
import CreateAlert from '../Alerts/NewAlert'
|
||||
import { useParams, useNavigate } from "react-router";
|
||||
|
||||
function DashboardViewSelected({ siteId, dashboardId }: { siteId: string; dashboardId: string }) {
|
||||
return <DashboardView siteId={siteId} dashboardId={dashboardId} />;
|
||||
}
|
||||
|
||||
interface Props extends RouteComponentProps {
|
||||
match: any;
|
||||
}
|
||||
|
||||
function DashboardRouter(props: Props) {
|
||||
const {
|
||||
match: {
|
||||
params: { siteId, dashboardId },
|
||||
},
|
||||
history,
|
||||
} = props;
|
||||
function DashboardRouter(props: any) {
|
||||
const { siteId, dashboardId } = useParams();
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Switch>
|
||||
<Routes>
|
||||
<Route exact strict path={withSiteId(metrics(), siteId)}>
|
||||
<MetricsView siteId={siteId} />
|
||||
</Route>
|
||||
|
|
@ -55,7 +46,7 @@ function DashboardRouter(props: Props) {
|
|||
</Route>
|
||||
|
||||
<Route exact path={withSiteId(dashboard(), siteId)}>
|
||||
<DashboardsView siteId={siteId} history={history} />
|
||||
<DashboardsView siteId={siteId} />
|
||||
</Route>
|
||||
|
||||
<Route exact strict path={withSiteId(dashboardMetricDetails(dashboardId), siteId)}>
|
||||
|
|
@ -83,9 +74,9 @@ function DashboardRouter(props: Props) {
|
|||
{/* @ts-ignore */}
|
||||
<CreateAlert siteId={siteId} {...props} />
|
||||
</Route>
|
||||
</Switch>
|
||||
</Routes>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default withRouter(DashboardRouter);
|
||||
export default DashboardRouter;
|
||||
|
|
|
|||
|
|
@ -1,20 +1,21 @@
|
|||
import React from 'react';
|
||||
import { SideMenuitem } from 'UI';
|
||||
import { withRouter, RouteComponentProps } from 'react-router-dom';
|
||||
import { withSiteId, metrics, dashboard, alerts } from 'App/routes';
|
||||
import { useLocation, useNavigate } from "react-router";
|
||||
|
||||
interface Props extends RouteComponentProps {
|
||||
interface Props {
|
||||
siteId: string;
|
||||
history: any;
|
||||
}
|
||||
function DashboardSideMenu(props: Props) {
|
||||
const { history, siteId } = props;
|
||||
const isMetric = history.location.pathname.includes('metrics');
|
||||
const isDashboards = history.location.pathname.includes('dashboard');
|
||||
const isAlerts = history.location.pathname.includes('alerts');
|
||||
const { siteId } = props;
|
||||
const navigate = useNavigate();
|
||||
const location = useLocation();
|
||||
const isMetric = location.pathname.includes('metrics');
|
||||
const isDashboards = location.pathname.includes('dashboard');
|
||||
const isAlerts = location.pathname.includes('alerts');
|
||||
|
||||
const redirect = (path: string) => {
|
||||
history.push(path);
|
||||
navigate(path);
|
||||
};
|
||||
|
||||
return (
|
||||
|
|
@ -53,4 +54,4 @@ function DashboardSideMenu(props: Props) {
|
|||
);
|
||||
}
|
||||
|
||||
export default withRouter(DashboardSideMenu);
|
||||
export default DashboardSideMenu;
|
||||
|
|
|
|||
|
|
@ -5,29 +5,28 @@ import {Loader} from 'UI';
|
|||
import {withSiteId} from 'App/routes';
|
||||
import withModal from 'App/components/Modal/withModal';
|
||||
import DashboardWidgetGrid from '../DashboardWidgetGrid';
|
||||
import {withRouter, RouteComponentProps} from 'react-router-dom';
|
||||
import {useModal} from 'App/components/Modal';
|
||||
import DashboardModal from '../DashboardModal';
|
||||
import AlertFormModal from 'App/components/Alerts/AlertFormModal';
|
||||
import withPageTitle from 'HOCs/withPageTitle';
|
||||
import withReport from 'App/components/hocs/withReport';
|
||||
import DashboardHeader from '../DashboardHeader';
|
||||
import {useHistory} from "react-router";
|
||||
import { useNavigate } from "react-router";
|
||||
import AiQuery from "./AiQuery";
|
||||
|
||||
interface IProps {
|
||||
siteId: string;
|
||||
dashboardId: any;
|
||||
renderReport?: any;
|
||||
}
|
||||
|
||||
type Props = IProps & RouteComponentProps;
|
||||
type Props = IProps;
|
||||
|
||||
function DashboardView(props: Props) {
|
||||
const {siteId, dashboardId} = props;
|
||||
const {dashboardStore} = useStore();
|
||||
const { dashboardId } = props;
|
||||
const { dashboardStore, projectsStore } = useStore();
|
||||
const siteId = projectsStore.activeSiteId;
|
||||
const {showModal, hideModal} = useModal();
|
||||
const history = useHistory();
|
||||
const navigate = useNavigate();
|
||||
|
||||
const showAlertModal = dashboardStore.showAlertModal;
|
||||
const loading = dashboardStore.fetchingDashboard;
|
||||
|
|
@ -38,9 +37,8 @@ function DashboardView(props: Props) {
|
|||
const trimQuery = () => {
|
||||
if (!queryParams.has('modal')) return;
|
||||
queryParams.delete('modal');
|
||||
history.replace({
|
||||
search: queryParams.toString(),
|
||||
});
|
||||
const search = queryParams.toString();
|
||||
navigate(location.pathname + "?" + search, { replace: true });
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
|
|
@ -60,7 +58,7 @@ function DashboardView(props: Props) {
|
|||
}, [showAlertModal])
|
||||
|
||||
const pushQuery = () => {
|
||||
if (!queryParams.has('modal')) history.push('?modal=addMetric');
|
||||
if (!queryParams.has('modal')) navigate('?modal=addMetric');
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
|
|
@ -75,7 +73,7 @@ function DashboardView(props: Props) {
|
|||
useEffect(() => {
|
||||
const isExists = dashboardStore.getDashboardById(dashboardId);
|
||||
if (!isExists) {
|
||||
history.push(withSiteId(`/dashboard`, siteId));
|
||||
navigate(withSiteId(`/dashboard`, siteId));
|
||||
}
|
||||
}, [dashboardId]);
|
||||
|
||||
|
|
|
|||
|
|
@ -6,18 +6,18 @@ import WidgetWrapper from 'App/components/Dashboard/components/WidgetWrapper';
|
|||
import { useStore } from 'App/mstore';
|
||||
import { useModal } from 'App/components/Modal';
|
||||
import { dashboardMetricCreate, withSiteId } from 'App/routes';
|
||||
import { withRouter, RouteComponentProps } from 'react-router-dom';
|
||||
import { useNavigate } from "react-router";
|
||||
|
||||
interface IProps extends RouteComponentProps {
|
||||
siteId: string;
|
||||
interface IProps {
|
||||
title: string;
|
||||
description: string;
|
||||
}
|
||||
|
||||
function AddMetric({ history, siteId, title, description }: IProps) {
|
||||
function AddMetric({ title, description }: IProps) {
|
||||
const [metrics, setMetrics] = React.useState<Record<string, any>[]>([]);
|
||||
|
||||
const { dashboardStore } = useStore();
|
||||
const navigate = useNavigate();
|
||||
const { dashboardStore, projectsStore } = useStore();
|
||||
const siteId = projectsStore.activeSiteId
|
||||
const { hideModal } = useModal();
|
||||
|
||||
React.useEffect(() => {
|
||||
|
|
@ -47,8 +47,8 @@ function AddMetric({ history, siteId, title, description }: IProps) {
|
|||
|
||||
const onCreateNew = () => {
|
||||
const path = withSiteId(dashboardMetricCreate(dashboard.dashboardId), siteId);
|
||||
if (!queryParams.has('modal')) history.push('?modal=addMetric');
|
||||
history.push(path);
|
||||
if (!queryParams.has('modal')) navigate('?modal=addMetric');
|
||||
navigate(path);
|
||||
hideModal();
|
||||
};
|
||||
|
||||
|
|
@ -110,4 +110,4 @@ function AddMetric({ history, siteId, title, description }: IProps) {
|
|||
);
|
||||
}
|
||||
|
||||
export default withRouter(observer(AddMetric));
|
||||
export default observer(AddMetric);
|
||||
|
|
|
|||
|
|
@ -6,18 +6,19 @@ import WidgetWrapper from 'App/components/Dashboard/components/WidgetWrapper';
|
|||
import { useStore } from 'App/mstore';
|
||||
import { useModal } from 'App/components/Modal';
|
||||
import { dashboardMetricCreate, withSiteId } from 'App/routes';
|
||||
import { withRouter, RouteComponentProps } from 'react-router-dom';
|
||||
import { WidgetCategoryItem } from 'App/components/Dashboard/components/DashboardMetricSelection/DashboardMetricSelection';
|
||||
import { useNavigate } from "react-router";
|
||||
|
||||
interface IProps extends RouteComponentProps {
|
||||
siteId: string;
|
||||
interface IProps {
|
||||
title: string;
|
||||
description: string;
|
||||
}
|
||||
|
||||
function AddPredefinedMetric({ history, siteId, title, description }: IProps) {
|
||||
function AddPredefinedMetric({ title, description }: IProps) {
|
||||
const navigate = useNavigate();
|
||||
const [categories, setCategories] = React.useState([]);
|
||||
const { dashboardStore } = useStore();
|
||||
const { dashboardStore, projectsStore } = useStore();
|
||||
const siteId = projectsStore.activeSiteId
|
||||
const { hideModal } = useModal();
|
||||
const [activeCategory, setActiveCategory] = React.useState<Record<string, any>>();
|
||||
|
||||
|
|
@ -62,8 +63,8 @@ function AddPredefinedMetric({ history, siteId, title, description }: IProps) {
|
|||
|
||||
const onCreateNew = () => {
|
||||
const path = withSiteId(dashboardMetricCreate(dashboard.dashboardId), siteId);
|
||||
if (!queryParams.has('modal')) history.push('?modal=addMetric');
|
||||
history.push(path);
|
||||
if (!queryParams.has('modal')) navigate('?modal=addMetric');
|
||||
navigate(path);
|
||||
hideModal();
|
||||
};
|
||||
|
||||
|
|
@ -155,4 +156,4 @@ function AddPredefinedMetric({ history, siteId, title, description }: IProps) {
|
|||
);
|
||||
}
|
||||
|
||||
export default withRouter(observer(AddPredefinedMetric));
|
||||
export default observer(AddPredefinedMetric);
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@ import { Table, Typography } from 'antd';
|
|||
import type { TableProps } from 'antd';
|
||||
import { useObserver } from 'mobx-react-lite';
|
||||
import React, { useEffect } from 'react';
|
||||
import { RouteComponentProps, withRouter } from 'react-router-dom';
|
||||
|
||||
import { useModal } from 'App/components/Modal';
|
||||
import { useStore } from 'App/mstore';
|
||||
|
|
@ -10,8 +9,8 @@ import { NoContent } from 'UI';
|
|||
import { InfoCircleOutlined } from '@ant-design/icons';
|
||||
import AnimatedSVG, { ICONS } from 'Shared/AnimatedSVG/AnimatedSVG';
|
||||
import FunnelIssueModal from '../FunnelIssueModal';
|
||||
import FunnelIssuesListItem from '../FunnelIssuesListItem';
|
||||
const { Text } = Typography;
|
||||
import { useLocation, useNavigate } from "react-router";
|
||||
|
||||
interface Issue {
|
||||
issueId: string;
|
||||
|
|
@ -70,26 +69,25 @@ const columns: TableProps<Issue>['columns'] = [
|
|||
},
|
||||
];
|
||||
|
||||
interface Props extends RouteComponentProps {
|
||||
interface Props {
|
||||
loading?: boolean;
|
||||
issues: Issue[];
|
||||
history: any;
|
||||
location: any;
|
||||
}
|
||||
function FunnelIssuesList(props: Props) {
|
||||
const { issues, loading } = props;
|
||||
const location = useLocation();
|
||||
const navigate = useNavigate();
|
||||
const { funnelStore } = useStore();
|
||||
const issuesSort = useObserver(() => funnelStore.issuesSort);
|
||||
const issuesFilter = useObserver(() =>
|
||||
funnelStore.issuesFilter.map((issue: any) => issue.value)
|
||||
);
|
||||
const { showModal } = useModal();
|
||||
const issueId = new URLSearchParams(props.location.search).get('issueId');
|
||||
const issueId = new URLSearchParams(location.search).get('issueId');
|
||||
|
||||
const onIssueClick = (issue: any) => {
|
||||
props.history.replace({
|
||||
search: new URLSearchParams({ issueId: issue.issueId }).toString(),
|
||||
});
|
||||
const search = new URLSearchParams({ issueId: issue.issueId }).toString();
|
||||
navigate(location.pathname + '?' + search, { replace: true });
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
|
|
@ -99,8 +97,8 @@ function FunnelIssuesList(props: Props) {
|
|||
right: true,
|
||||
width: 1000,
|
||||
onClose: () => {
|
||||
if (props.history.location.pathname.includes('/metric')) {
|
||||
props.history.replace({ search: '' });
|
||||
if (location.pathname.includes('/metric')) {
|
||||
navigate(location.pathname, { replace: true });
|
||||
}
|
||||
},
|
||||
});
|
||||
|
|
@ -147,4 +145,4 @@ function FunnelIssuesList(props: Props) {
|
|||
));
|
||||
}
|
||||
|
||||
export default withRouter(FunnelIssuesList);
|
||||
export default FunnelIssuesList;
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ import { TYPE_ICONS, TYPE_NAMES } from 'App/constants/card';
|
|||
import { useStore } from 'App/mstore';
|
||||
import { observer } from 'mobx-react-lite';
|
||||
import { toast } from 'react-toastify';
|
||||
import { useHistory } from 'react-router';
|
||||
import { useNavigate } from 'react-router';
|
||||
import { EllipsisVertical } from 'lucide-react';
|
||||
import cn from 'classnames'
|
||||
|
||||
|
|
@ -61,7 +61,7 @@ const MetricListItem: React.FC<Props> = ({
|
|||
renderColumn,
|
||||
inLibrary,
|
||||
}) => {
|
||||
const history = useHistory();
|
||||
const navigate = useNavigate();
|
||||
const { metricStore } = useStore();
|
||||
const [isEdit, setIsEdit] = useState(false);
|
||||
const [newName, setNewName] = useState(metric.name);
|
||||
|
|
@ -75,7 +75,7 @@ const MetricListItem: React.FC<Props> = ({
|
|||
return toggleSelection(e);
|
||||
}
|
||||
const path = withSiteId(`/metrics/${metric.metricId}`, siteId);
|
||||
history.push(path);
|
||||
navigate(path);
|
||||
};
|
||||
|
||||
const onMenuClick = async ({ key }: { key: string }) => {
|
||||
|
|
@ -99,7 +99,7 @@ const MetricListItem: React.FC<Props> = ({
|
|||
try {
|
||||
metric.update({ name: newName });
|
||||
await metricStore.save(metric);
|
||||
metricStore.fetchList();
|
||||
void metricStore.fetchList();
|
||||
setIsEdit(false);
|
||||
} catch (e) {
|
||||
toast.error('Failed to rename card');
|
||||
|
|
|
|||
|
|
@ -3,21 +3,22 @@ import React from 'react';
|
|||
import MetricsLibraryModal from '../MetricsLibraryModal';
|
||||
import MetricTypeItem, { MetricType } from '../MetricTypeItem/MetricTypeItem';
|
||||
import { TYPES, LIBRARY, INSIGHTS } from 'App/constants/card';
|
||||
import { withRouter, RouteComponentProps } from 'react-router-dom';
|
||||
import { dashboardMetricCreate, metricCreate, withSiteId } from 'App/routes';
|
||||
import { useStore } from 'App/mstore';
|
||||
import { observer } from 'mobx-react-lite';
|
||||
import { ENTERPRISE_REQUEIRED } from 'App/constants';
|
||||
import { useNavigate } from "react-router";
|
||||
|
||||
interface Props extends RouteComponentProps {
|
||||
interface Props {
|
||||
dashboardId?: number;
|
||||
siteId: string;
|
||||
isList?: boolean;
|
||||
}
|
||||
|
||||
function MetricTypeList(props: Props) {
|
||||
const { dashboardId, siteId, history, isList = false } = props;
|
||||
const { metricStore, userStore } = useStore();
|
||||
const navigate = useNavigate();
|
||||
const { dashboardId, isList = false } = props;
|
||||
const { metricStore, userStore, projectsStore } = useStore();
|
||||
const siteId = projectsStore.activeSiteId;
|
||||
const { showModal, hideModal } = useModal();
|
||||
const isEnterprise = userStore.isEnterprise;
|
||||
|
||||
|
|
@ -49,13 +50,11 @@ function MetricTypeList(props: Props) {
|
|||
});
|
||||
}
|
||||
|
||||
const path = dashboardId ? withSiteId(dashboardMetricCreate(dashboardId + ''), siteId) :
|
||||
withSiteId(metricCreate(), siteId);
|
||||
const path = dashboardId
|
||||
? withSiteId(dashboardMetricCreate(dashboardId + ''), siteId)
|
||||
: withSiteId(metricCreate(), siteId);
|
||||
const queryString = new URLSearchParams({ type: slug }).toString();
|
||||
history.push({
|
||||
pathname: path,
|
||||
search: `?${queryString}`
|
||||
});
|
||||
navigate(path + `?${queryString}`);
|
||||
};
|
||||
|
||||
return (
|
||||
|
|
@ -67,4 +66,4 @@ function MetricTypeList(props: Props) {
|
|||
);
|
||||
}
|
||||
|
||||
export default withRouter(observer(MetricTypeList));
|
||||
export default observer(MetricTypeList);
|
||||
|
|
|
|||
|
|
@ -1,18 +1,20 @@
|
|||
import React from 'react';
|
||||
import WidgetWrapper from 'App/components/Dashboard/components/WidgetWrapper';
|
||||
import { withRouter, RouteComponentProps } from 'react-router-dom';
|
||||
import { withSiteId } from 'App/routes';
|
||||
interface Props extends RouteComponentProps {
|
||||
import { useNavigate } from "react-router";
|
||||
|
||||
interface Props {
|
||||
list: any;
|
||||
siteId: any;
|
||||
selectedList: any;
|
||||
}
|
||||
function GridView(props: Props) {
|
||||
const { siteId, list, selectedList, history } = props;
|
||||
const { siteId, list, selectedList } = props;
|
||||
const navigate = useNavigate();
|
||||
|
||||
const onItemClick = (metricId: number) => {
|
||||
const path = withSiteId(`/metrics/${metricId}`, siteId);
|
||||
history.push(path);
|
||||
navigate(path);
|
||||
};
|
||||
|
||||
return (
|
||||
|
|
@ -33,4 +35,4 @@ function GridView(props: Props) {
|
|||
);
|
||||
}
|
||||
|
||||
export default withRouter(GridView);
|
||||
export default GridView;
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ import { EllipsisVertical } from 'lucide-react';
|
|||
import { TablePaginationConfig, SorterResult } from 'antd/lib/table/interface';
|
||||
import { useStore } from 'App/mstore';
|
||||
import { toast } from 'react-toastify';
|
||||
import { useHistory } from 'react-router';
|
||||
import { useNavigate } from 'react-router';
|
||||
import { withSiteId } from 'App/routes';
|
||||
import { Icon } from 'UI';
|
||||
import cn from 'classnames';
|
||||
|
|
@ -49,7 +49,7 @@ const ListView: React.FC<Props> = ({
|
|||
const [editingMetricId, setEditingMetricId] = useState<number | null>(null);
|
||||
const [newName, setNewName] = useState('');
|
||||
const { metricStore } = useStore();
|
||||
const history = useHistory();
|
||||
const navigate = useNavigate();
|
||||
|
||||
const sortedData = useMemo(() => {
|
||||
return [...list].sort((a, b) => {
|
||||
|
|
@ -142,7 +142,7 @@ const ListView: React.FC<Props> = ({
|
|||
const onItemClick = (metric: Widget) => {
|
||||
if (disableSelection) {
|
||||
const path = withSiteId(`/metrics/${metric.metricId}`, siteId);
|
||||
history.push(path);
|
||||
navigate(path);
|
||||
} else {
|
||||
toggleSelection?.(metric.metricId);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ import FilterItem from 'Shared/Filters/FilterItem';
|
|||
import {
|
||||
TIMESERIES, TABLE, HEATMAP, FUNNEL, ERRORS, INSIGHTS, USER_PATH, RETENTION
|
||||
} from 'App/constants/card';
|
||||
import {useHistory} from "react-router";
|
||||
import { useNavigate } from "react-router";
|
||||
|
||||
const tableOptions = metricOf.filter((i) => i.type === 'table');
|
||||
|
||||
|
|
@ -217,8 +217,8 @@ interface CardBuilderProps {
|
|||
}
|
||||
|
||||
const CardBuilder = observer((props: CardBuilderProps) => {
|
||||
const history = useHistory();
|
||||
const {siteId, dashboardId, metricId} = props;
|
||||
const navigate = useNavigate();
|
||||
const { siteId, dashboardId, metricId } = props;
|
||||
const {metricStore, dashboardStore, aiFiltersStore} = useStore();
|
||||
const [aiQuery, setAiQuery] = useState('');
|
||||
const [aiAskChart, setAiAskChart] = useState('');
|
||||
|
|
@ -259,7 +259,7 @@ const CardBuilder = observer((props: CardBuilderProps) => {
|
|||
const route = parseInt(dashboardId, 10) > 0
|
||||
? withSiteId(dashboardMetricDetails(dashboardId, savedMetric.metricId), siteId)
|
||||
: withSiteId(metricDetails(savedMetric.metricId), siteId);
|
||||
history.replace(route);
|
||||
navigate(route, { replace: true });
|
||||
if (parseInt(dashboardId, 10) > 0) {
|
||||
dashboardStore.addWidgetToDashboard(
|
||||
dashboardStore.getDashboard(parseInt(dashboardId, 10)),
|
||||
|
|
@ -267,7 +267,7 @@ const CardBuilder = observer((props: CardBuilderProps) => {
|
|||
);
|
||||
}
|
||||
}
|
||||
}, [dashboardId, dashboardStore, history, metric, metricStore, siteId]);
|
||||
}, [dashboardId, dashboardStore, metric, metricStore, siteId]);
|
||||
|
||||
const onDelete = useCallback(async () => {
|
||||
if (await confirm({
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { useHistory } from 'react-router';
|
||||
import { useNavigate } from 'react-router';
|
||||
import { useStore } from 'App/mstore';
|
||||
import { observer } from 'mobx-react-lite';
|
||||
import { Button, Dropdown, MenuProps, Modal } from 'antd';
|
||||
|
|
@ -10,7 +10,7 @@ import AlertFormModal from 'Components/Alerts/AlertFormModal/AlertFormModal';
|
|||
import { showAddToDashboardModal } from 'Components/Dashboard/components/AddToDashboardButton';
|
||||
|
||||
const CardViewMenu = () => {
|
||||
const history = useHistory();
|
||||
const navigate = useNavigate();
|
||||
const { alertsStore, metricStore, dashboardStore } = useStore();
|
||||
const widget = metricStore.instance;
|
||||
const { openModal, closeModal } = useModal();
|
||||
|
|
@ -60,7 +60,7 @@ const CardViewMenu = () => {
|
|||
metricStore
|
||||
.delete(widget)
|
||||
.then(() => {
|
||||
history.goBack();
|
||||
navigate(-1)
|
||||
})
|
||||
.catch(() => {
|
||||
toast.error('Failed to remove card');
|
||||
|
|
|
|||
|
|
@ -1,13 +1,13 @@
|
|||
import React, { useState, useEffect } from 'react';
|
||||
import { useStore } from 'App/mstore';
|
||||
import { Loader } from 'UI';
|
||||
import { Loader, NavPrompt } from 'UI';
|
||||
import WidgetPreview from '../WidgetPreview';
|
||||
import WidgetSessions from '../WidgetSessions';
|
||||
import { observer } from 'mobx-react-lite';
|
||||
import { dashboardMetricDetails, metricDetails, withSiteId } from 'App/routes';
|
||||
import Breadcrumb from 'Shared/Breadcrumb';
|
||||
import { FilterKey } from 'Types/filter/filterType';
|
||||
import { Prompt, useHistory, useLocation } from 'react-router';
|
||||
import { useNavigate, useLocation } from 'react-router';
|
||||
import {
|
||||
TIMESERIES,
|
||||
TABLE,
|
||||
|
|
@ -29,7 +29,6 @@ import { CARD_LIST, CardType } from 'Components/Dashboard/components/DashboardLi
|
|||
import FilterSeries from '@/mstore/types/filterSeries';
|
||||
|
||||
interface Props {
|
||||
history: any;
|
||||
match: any;
|
||||
siteId: any;
|
||||
}
|
||||
|
|
@ -50,7 +49,7 @@ function WidgetView({ match: { params: { siteId, dashboardId, metricId } } }: Pr
|
|||
const dashboard = dashboardStore.dashboards.find((d: any) => d.dashboardId == dashboardId);
|
||||
const dashboardName = dashboard ? dashboard.name : null;
|
||||
const [metricNotFound, setMetricNotFound] = useState(false);
|
||||
const history = useHistory();
|
||||
const navigate = useNavigate();
|
||||
const location = useLocation();
|
||||
const [initialInstance, setInitialInstance] = useState();
|
||||
const isClickMap = widget.metricType === HEATMAP;
|
||||
|
|
@ -112,9 +111,9 @@ function WidgetView({ match: { params: { siteId, dashboardId, metricId } } }: Pr
|
|||
|
||||
useEffect(() => {
|
||||
if (metricNotFound) {
|
||||
history.replace(withSiteId('/metrics', siteId));
|
||||
navigate(withSiteId('/metrics', siteId), { replace: true });
|
||||
}
|
||||
}, [metricNotFound, history, siteId]);
|
||||
}, [metricNotFound, siteId]);
|
||||
|
||||
const undoChanges = () => {
|
||||
const w = new Widget();
|
||||
|
|
@ -134,15 +133,15 @@ function WidgetView({ match: { params: { siteId, dashboardId, metricId } } }: Pr
|
|||
setInitialInstance(widget.toJson());
|
||||
if (wasCreating) {
|
||||
if (parseInt(dashboardId, 10) > 0) {
|
||||
history.replace(
|
||||
navigate(
|
||||
withSiteId(dashboardMetricDetails(dashboardId, savedMetric.metricId), siteId)
|
||||
);
|
||||
, { replace: true });
|
||||
void dashboardStore.addWidgetToDashboard(
|
||||
dashboardStore.getDashboard(parseInt(dashboardId, 10))!,
|
||||
[savedMetric.metricId]
|
||||
);
|
||||
} else {
|
||||
history.replace(withSiteId(metricDetails(savedMetric.metricId), siteId));
|
||||
navigate(withSiteId(metricDetails(savedMetric.metricId), siteId), { replace: true });
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
@ -154,7 +153,7 @@ function WidgetView({ match: { params: { siteId, dashboardId, metricId } } }: Pr
|
|||
|
||||
return (
|
||||
<Loader loading={loading}>
|
||||
<Prompt
|
||||
<NavPrompt
|
||||
when={hasChanged}
|
||||
message={(loc: any) =>
|
||||
loc.pathname.includes('/metrics/') || loc.pathname.includes('/metric/')
|
||||
|
|
|
|||
|
|
@ -1,48 +1,48 @@
|
|||
import React from 'react';
|
||||
import {useHistory} from "react-router";
|
||||
import {useStore} from "App/mstore";
|
||||
import {useObserver} from "mobx-react-lite";
|
||||
import {Button, Dropdown, MenuProps, message, Modal} from "antd";
|
||||
import {BellIcon, EllipsisVertical, EyeOffIcon, PencilIcon, TrashIcon} from "lucide-react";
|
||||
import {toast} from "react-toastify";
|
||||
import {dashboardMetricDetails, withSiteId} from "App/routes";
|
||||
import { useNavigate } from 'react-router';
|
||||
import { useStore } from 'App/mstore';
|
||||
import { Button, Dropdown, MenuProps } from 'antd';
|
||||
import { EllipsisVertical, EyeOffIcon, PencilIcon } from 'lucide-react';
|
||||
import { dashboardMetricDetails, withSiteId } from 'App/routes';
|
||||
|
||||
function CardMenu({card}: any) {
|
||||
const siteId = location.pathname.split('/')[1];
|
||||
const history = useHistory();
|
||||
const {dashboardStore, metricStore} = useStore();
|
||||
const dashboardId = dashboardStore.selectedDashboard?.dashboardId;
|
||||
function CardMenu({ card }: any) {
|
||||
const siteId = location.pathname.split('/')[1];
|
||||
const navigate = useNavigate();
|
||||
const { dashboardStore } = useStore();
|
||||
const dashboardId = dashboardStore.selectedDashboard?.dashboardId;
|
||||
|
||||
const items: MenuProps['items'] = [
|
||||
{
|
||||
key: 'edit',
|
||||
label: "Edit",
|
||||
icon: <PencilIcon size={16}/>,
|
||||
},
|
||||
{
|
||||
key: 'hide',
|
||||
label: 'Remove from Dashboard',
|
||||
icon: <EyeOffIcon size={16}/>,
|
||||
},
|
||||
];
|
||||
const items: MenuProps['items'] = [
|
||||
{
|
||||
key: 'edit',
|
||||
label: 'Edit',
|
||||
icon: <PencilIcon size={16} />,
|
||||
},
|
||||
{
|
||||
key: 'hide',
|
||||
label: 'Remove from Dashboard',
|
||||
icon: <EyeOffIcon size={16} />,
|
||||
},
|
||||
];
|
||||
|
||||
const onClick: MenuProps['onClick'] = ({key}) => {
|
||||
if (key === 'edit') {
|
||||
history.push(
|
||||
withSiteId(dashboardMetricDetails(dashboardId, card.metricId), siteId)
|
||||
)
|
||||
} else if (key === 'hide') {
|
||||
dashboardStore.deleteDashboardWidget(dashboardId!, card.widgetId).then(r => null);
|
||||
}
|
||||
};
|
||||
const onClick: MenuProps['onClick'] = ({ key }) => {
|
||||
if (key === 'edit') {
|
||||
navigate(
|
||||
withSiteId(dashboardMetricDetails(dashboardId, card.metricId), siteId)
|
||||
);
|
||||
} else if (key === 'hide') {
|
||||
dashboardStore
|
||||
.deleteDashboardWidget(dashboardId!, card.widgetId)
|
||||
.then((r) => null);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="flex items-center justify-between">
|
||||
<Dropdown menu={{items, onClick}} overlayStyle={{minWidth: '120px'}}>
|
||||
<Button type="text" icon={<EllipsisVertical size={16}/>}/>
|
||||
</Dropdown>
|
||||
</div>
|
||||
);
|
||||
return (
|
||||
<div className="flex items-center justify-between">
|
||||
<Dropdown menu={{ items, onClick }} overlayStyle={{ minWidth: '120px' }}>
|
||||
<Button type="text" icon={<EllipsisVertical size={16} />} />
|
||||
</Dropdown>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default CardMenu;
|
||||
|
|
|
|||
|
|
@ -1,14 +1,14 @@
|
|||
import React, { useRef, lazy } from 'react';
|
||||
import cn from 'classnames';
|
||||
import { ItemMenu, TextEllipsis } from 'UI';
|
||||
import { TextEllipsis } from 'UI';
|
||||
import { useDrag, useDrop } from 'react-dnd';
|
||||
import { observer } from 'mobx-react-lite';
|
||||
import { useStore } from 'App/mstore';
|
||||
import { withRouter, RouteComponentProps } from 'react-router-dom';
|
||||
import { withSiteId, dashboardMetricDetails } from 'App/routes';
|
||||
import TemplateOverlay from './TemplateOverlay';
|
||||
import { FilterKey } from 'App/types/filter/filterType';
|
||||
import { TIMESERIES } from 'App/constants/card';
|
||||
import { useNavigate } from "react-router";
|
||||
|
||||
const WidgetChart = lazy(
|
||||
() => import('Components/Dashboard/components/WidgetChart')
|
||||
|
|
@ -22,17 +22,17 @@ interface Props {
|
|||
isPreview?: boolean;
|
||||
isTemplate?: boolean;
|
||||
dashboardId?: string;
|
||||
siteId?: string;
|
||||
active?: boolean;
|
||||
history?: any;
|
||||
onClick?: () => void;
|
||||
isSaved?: boolean;
|
||||
hideName?: boolean;
|
||||
grid?: string;
|
||||
isGridView?: boolean;
|
||||
}
|
||||
function WidgetWrapper(props: Props & RouteComponentProps) {
|
||||
const { dashboardStore } = useStore();
|
||||
function WidgetWrapper(props: Props) {
|
||||
const { dashboardStore, projectsStore } = useStore();
|
||||
const siteId = projectsStore.activeSiteId;
|
||||
const navigate = useNavigate();
|
||||
const {
|
||||
isSaved = false,
|
||||
active = false,
|
||||
|
|
@ -40,7 +40,6 @@ function WidgetWrapper(props: Props & RouteComponentProps) {
|
|||
moveListItem = null,
|
||||
isPreview = false,
|
||||
isTemplate = false,
|
||||
siteId,
|
||||
grid = '',
|
||||
isGridView = false,
|
||||
} = props;
|
||||
|
|
@ -83,7 +82,7 @@ function WidgetWrapper(props: Props & RouteComponentProps) {
|
|||
const onChartClick = () => {
|
||||
if (!isSaved || isPredefined) return;
|
||||
|
||||
props.history.push(
|
||||
navigate(
|
||||
withSiteId(
|
||||
dashboardMetricDetails(dashboard?.dashboardId, widget.metricId),
|
||||
siteId
|
||||
|
|
@ -150,4 +149,4 @@ function WidgetWrapper(props: Props & RouteComponentProps) {
|
|||
);
|
||||
}
|
||||
|
||||
export default withRouter(observer(WidgetWrapper));
|
||||
export default observer(WidgetWrapper);
|
||||
|
|
|
|||
|
|
@ -4,8 +4,8 @@ import { Card, Tooltip } from 'antd';
|
|||
import { useDrag, useDrop } from 'react-dnd';
|
||||
import { observer } from 'mobx-react-lite';
|
||||
import { useStore } from 'App/mstore';
|
||||
import { withRouter, RouteComponentProps } from 'react-router-dom';
|
||||
import { withSiteId, dashboardMetricDetails } from 'App/routes';
|
||||
import { useNavigate } from "react-router";
|
||||
import TemplateOverlay from './TemplateOverlay';
|
||||
import stl from './widgetWrapper.module.css';
|
||||
import { FilterKey } from 'App/types/filter/filterType';
|
||||
|
|
@ -25,7 +25,6 @@ interface Props {
|
|||
dashboardId?: string;
|
||||
siteId?: string;
|
||||
active?: boolean;
|
||||
history?: any;
|
||||
onClick?: () => void;
|
||||
isWidget?: boolean;
|
||||
hideName?: boolean;
|
||||
|
|
@ -35,8 +34,10 @@ interface Props {
|
|||
isSaved?: boolean;
|
||||
}
|
||||
|
||||
function WidgetWrapperNew(props: Props & RouteComponentProps) {
|
||||
const { dashboardStore, metricStore } = useStore();
|
||||
function WidgetWrapperNew(props: Props) {
|
||||
const navigate = useNavigate()
|
||||
const { dashboardStore, metricStore, projectsStore } = useStore();
|
||||
const siteId = projectsStore.activeSiteId;
|
||||
const {
|
||||
isWidget = false,
|
||||
active = false,
|
||||
|
|
@ -44,7 +45,6 @@ function WidgetWrapperNew(props: Props & RouteComponentProps) {
|
|||
moveListItem = null,
|
||||
isPreview = false,
|
||||
isTemplate = false,
|
||||
siteId,
|
||||
grid = '',
|
||||
isGridView = false,
|
||||
showMenu = false,
|
||||
|
|
@ -80,7 +80,7 @@ function WidgetWrapperNew(props: Props & RouteComponentProps) {
|
|||
|
||||
const onChartClick = () => {
|
||||
// if (!isWidget || isPredefined) return;
|
||||
props.history.push(
|
||||
navigate(
|
||||
withSiteId(dashboardMetricDetails(dashboard?.dashboardId, widget.metricId), siteId)
|
||||
);
|
||||
};
|
||||
|
|
@ -164,4 +164,4 @@ function WidgetWrapperNew(props: Props & RouteComponentProps) {
|
|||
);
|
||||
}
|
||||
|
||||
export default withRouter(observer(WidgetWrapperNew));
|
||||
export default observer(WidgetWrapperNew);
|
||||
|
|
|
|||
|
|
@ -3,8 +3,7 @@ import { FilterKey } from 'Types/filter/filterType';
|
|||
import cn from 'classnames';
|
||||
import { observer } from 'mobx-react-lite';
|
||||
import React from 'react';
|
||||
import { withRouter } from 'react-router-dom';
|
||||
|
||||
import { useNavigate } from 'react-router'
|
||||
import { resentOrDate } from 'App/date';
|
||||
import { useStore } from 'App/mstore';
|
||||
import { sessions as sessionsRoute } from 'App/routes';
|
||||
|
|
@ -17,6 +16,7 @@ import { Button } from 'antd'
|
|||
import SessionBar from './SessionBar';
|
||||
|
||||
function MainSection(props) {
|
||||
const navigate = useNavigate();
|
||||
const { errorStore, searchStore } = useStore();
|
||||
const error = errorStore.instance;
|
||||
const trace = errorStore.instanceTrace;
|
||||
|
|
@ -26,7 +26,7 @@ function MainSection(props) {
|
|||
|
||||
const findSessions = () => {
|
||||
searchStore.addFilterByKeyAndValue(FilterKey.ERROR, error.message);
|
||||
props.history.push(sessionsRoute());
|
||||
navigate(sessionsRoute());
|
||||
};
|
||||
return (
|
||||
<div
|
||||
|
|
@ -129,6 +129,4 @@ function MainSection(props) {
|
|||
);
|
||||
}
|
||||
|
||||
export default withRouter(
|
||||
(observer(MainSection))
|
||||
);
|
||||
export default observer(MainSection)
|
||||
|
|
|
|||
|
|
@ -2,11 +2,11 @@ import React from 'react'
|
|||
import { PageTitle } from 'UI'
|
||||
import { Button } from 'antd'
|
||||
import FFlagsSearch from "Components/FFlags/FFlagsSearch";
|
||||
import { useHistory } from "react-router";
|
||||
import { useNavigate } from "react-router";
|
||||
import { newFFlag, withSiteId } from 'App/routes';
|
||||
|
||||
function FFlagsListHeader({ siteId }: { siteId: string }) {
|
||||
const history = useHistory();
|
||||
const navigate = useNavigate();
|
||||
|
||||
return (
|
||||
<div className="flex items-center justify-between px-6">
|
||||
|
|
@ -14,7 +14,7 @@ function FFlagsListHeader({ siteId }: { siteId: string }) {
|
|||
<PageTitle title="Feature Flags" />
|
||||
</div>
|
||||
<div className="ml-auto flex items-center">
|
||||
<Button type="primary" onClick={() => history.push(withSiteId(newFFlag(), siteId))}>
|
||||
<Button type="primary" onClick={() => navigate(withSiteId(newFFlag(), siteId))}>
|
||||
Create Feature Flag
|
||||
</Button>
|
||||
<div className="mx-2"></div>
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import { useStore } from 'App/mstore';
|
|||
import { Loader, NoContent, ItemMenu } from 'UI';
|
||||
import { Button, Switch } from 'antd'
|
||||
import Breadcrumb from 'Shared/Breadcrumb';
|
||||
import { useHistory } from 'react-router';
|
||||
import { useNavigate } from 'react-router';
|
||||
import { withSiteId, fflag, fflags } from 'App/routes';
|
||||
import Multivariant from "Components/FFlags/NewFFlag/Multivariant";
|
||||
import { toast } from 'react-toastify';
|
||||
|
|
@ -12,7 +12,7 @@ import RolloutCondition from "Shared/ConditionSet";
|
|||
|
||||
function FlagView({ siteId, fflagId }: { siteId: string; fflagId: string }) {
|
||||
const { featureFlagsStore } = useStore();
|
||||
const history = useHistory();
|
||||
const navigate = useNavigate();
|
||||
|
||||
React.useEffect(() => {
|
||||
if (fflagId) {
|
||||
|
|
@ -27,7 +27,7 @@ function FlagView({ siteId, fflagId }: { siteId: string; fflagId: string }) {
|
|||
const deleteHandler = () => {
|
||||
featureFlagsStore.deleteFlag(current.featureFlagId).then(() => {
|
||||
toast.success('Feature flag deleted.');
|
||||
history.push(withSiteId(fflags(), siteId));
|
||||
navigate(withSiteId(fflags(), siteId));
|
||||
});
|
||||
};
|
||||
|
||||
|
|
@ -63,7 +63,7 @@ function FlagView({ siteId, fflagId }: { siteId: string; fflagId: string }) {
|
|||
className={'ml-auto text-main'}
|
||||
type={'text'}
|
||||
onClick={() =>
|
||||
history.push(
|
||||
navigate(
|
||||
withSiteId(
|
||||
fflag(
|
||||
featureFlagsStore.currentFflag?.featureFlagId.toString()
|
||||
|
|
|
|||
|
|
@ -3,19 +3,19 @@ import { observer } from 'mobx-react-lite';
|
|||
import cn from 'classnames';
|
||||
import { ItemMenu } from 'UI';
|
||||
import { useStore } from 'App/mstore';
|
||||
import { useHistory } from 'react-router';
|
||||
import { useNavigate } from 'react-router';
|
||||
import { toast } from 'react-toastify';
|
||||
import { fflags, withSiteId } from "App/routes";
|
||||
import { Button } from 'antd';
|
||||
|
||||
function Header({ current, onCancel, onSave, isNew, siteId }: any) {
|
||||
const { featureFlagsStore } = useStore();
|
||||
const history = useHistory();
|
||||
const navigate = useNavigate()
|
||||
|
||||
const deleteHandler = () => {
|
||||
featureFlagsStore.deleteFlag(current.featureFlagId).then(() => {
|
||||
toast.success('Feature flag deleted.');
|
||||
history.push(withSiteId(fflags(), siteId));
|
||||
navigate(withSiteId(fflags(), siteId));
|
||||
});
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
import React from 'react';
|
||||
import { observer } from 'mobx-react-lite';
|
||||
import { useStore } from 'App/mstore';
|
||||
import { Input, SegmentSelection, Loader, NoContent } from 'UI';
|
||||
import { Input, SegmentSelection, Loader, NoContent, NavPrompt } from 'UI';
|
||||
import Breadcrumb from 'Shared/Breadcrumb';
|
||||
import { Button, Switch } from 'antd'
|
||||
import { useModal } from 'App/components/Modal';
|
||||
import HowTo from 'Components/FFlags/NewFFlag/HowTo';
|
||||
import {Prompt, useHistory} from 'react-router';
|
||||
import { useNavigate } from 'react-router';
|
||||
import {withSiteId, fflags, fflagRead} from 'App/routes';
|
||||
import Description from './Description';
|
||||
import Header from './Header';
|
||||
|
|
@ -32,7 +32,7 @@ function NewFFlag({ siteId, fflagId }: { siteId: string; fflagId?: string }) {
|
|||
|
||||
const current = featureFlagsStore.currentFflag;
|
||||
const { showModal } = useModal();
|
||||
const history = useHistory();
|
||||
const navigate = useNavigate()
|
||||
|
||||
if (featureFlagsStore.isLoading) return <Loader loading={true} />;
|
||||
if (!current) return (
|
||||
|
|
@ -52,7 +52,7 @@ function NewFFlag({ siteId, fflagId }: { siteId: string; fflagId?: string }) {
|
|||
};
|
||||
|
||||
const onCancel = () => {
|
||||
history.goBack()
|
||||
navigate(-1)
|
||||
};
|
||||
|
||||
const onSave = () => {
|
||||
|
|
@ -61,7 +61,7 @@ function NewFFlag({ siteId, fflagId }: { siteId: string; fflagId?: string }) {
|
|||
if (fflagId) {
|
||||
featureFlagsStore.updateFlag().then(() => {
|
||||
toast.success('Feature flag updated.');
|
||||
history.push(withSiteId(fflagRead(fflagId), siteId));
|
||||
navigate(withSiteId(fflagRead(fflagId), siteId));
|
||||
})
|
||||
.catch(() => {
|
||||
toast.error(`Failed to update flag, check your data and try again.`)
|
||||
|
|
@ -69,7 +69,7 @@ function NewFFlag({ siteId, fflagId }: { siteId: string; fflagId?: string }) {
|
|||
} else {
|
||||
featureFlagsStore.createFlag().then(() => {
|
||||
toast.success('Feature flag created.');
|
||||
history.push(withSiteId(fflags(), siteId));
|
||||
navigate(withSiteId(fflags(), siteId));
|
||||
}).catch(() => {
|
||||
toast.error('Failed to create flag.');
|
||||
})
|
||||
|
|
@ -79,7 +79,7 @@ function NewFFlag({ siteId, fflagId }: { siteId: string; fflagId?: string }) {
|
|||
const showDescription = Boolean(current.description?.length);
|
||||
return (
|
||||
<div className={'w-full mx-auto mb-4'} style={{ maxWidth: '1360px' }}>
|
||||
<Prompt
|
||||
<NavPrompt
|
||||
when={current.hasChanged}
|
||||
message={() => {
|
||||
return 'You have unsaved changes. Are you sure you want to leave?';
|
||||
|
|
|
|||
|
|
@ -1,13 +1,12 @@
|
|||
import React from 'react';
|
||||
import { Icon } from 'UI';
|
||||
import { withRouter } from 'react-router-dom';
|
||||
import { useNavigate } from "react-router";
|
||||
|
||||
interface Props {
|
||||
history: any;
|
||||
}
|
||||
function PreferencesView(props: Props) {
|
||||
|
||||
function PreferencesView() {
|
||||
const navigate = useNavigate();
|
||||
const onExit = () => {
|
||||
props.history.push('/');
|
||||
navigate('/');
|
||||
};
|
||||
return (
|
||||
<>
|
||||
|
|
@ -24,4 +23,4 @@ function PreferencesView(props: Props) {
|
|||
);
|
||||
}
|
||||
|
||||
export default withRouter(PreferencesView);
|
||||
export default PreferencesView;
|
||||
|
|
|
|||
|
|
@ -1,39 +1,38 @@
|
|||
import React from 'react';
|
||||
import cn from 'classnames';
|
||||
import { Icon } from 'UI';
|
||||
import { CLIENT_TABS, client as clientRoute } from 'App/routes';
|
||||
import { withRouter, RouteComponentProps } from 'react-router';
|
||||
import { useNavigate } from "react-router";
|
||||
|
||||
interface Props {
|
||||
history: any;
|
||||
className: string;
|
||||
account: any;
|
||||
}
|
||||
|
||||
function SettingsMenu(props: RouteComponentProps<Props>) {
|
||||
const { history, account, className }: any = props;
|
||||
function SettingsMenu(props: Props) {
|
||||
const navigate = useNavigate();
|
||||
const { account, className }: any = props;
|
||||
const isAdmin = account.admin || account.superAdmin;
|
||||
const isEnterprise = account.edition === 'ee';
|
||||
const navigateTo = (path: any) => {
|
||||
switch (path) {
|
||||
case 'sessions-listing':
|
||||
return history.push(clientRoute(CLIENT_TABS.SESSIONS_LISTING));
|
||||
return navigate(clientRoute(CLIENT_TABS.SESSIONS_LISTING));
|
||||
case 'projects':
|
||||
return history.push(clientRoute(CLIENT_TABS.SITES));
|
||||
return navigate(clientRoute(CLIENT_TABS.SITES));
|
||||
case 'team':
|
||||
return history.push(clientRoute(CLIENT_TABS.MANAGE_USERS));
|
||||
return navigate(clientRoute(CLIENT_TABS.MANAGE_USERS));
|
||||
case 'metadata':
|
||||
return history.push(clientRoute(CLIENT_TABS.CUSTOM_FIELDS));
|
||||
return navigate(clientRoute(CLIENT_TABS.CUSTOM_FIELDS));
|
||||
case 'webhooks':
|
||||
return history.push(clientRoute(CLIENT_TABS.WEBHOOKS));
|
||||
return navigate(clientRoute(CLIENT_TABS.WEBHOOKS));
|
||||
case 'integrations':
|
||||
return history.push(clientRoute(CLIENT_TABS.INTEGRATIONS));
|
||||
return navigate(clientRoute(CLIENT_TABS.INTEGRATIONS));
|
||||
case 'notifications':
|
||||
return history.push(clientRoute(CLIENT_TABS.NOTIFICATIONS));
|
||||
return navigate(clientRoute(CLIENT_TABS.NOTIFICATIONS));
|
||||
case 'roles':
|
||||
return history.push(clientRoute(CLIENT_TABS.MANAGE_ROLES));
|
||||
return navigate(clientRoute(CLIENT_TABS.MANAGE_ROLES));
|
||||
case 'audit':
|
||||
return history.push(clientRoute(CLIENT_TABS.AUDIT));
|
||||
return navigate(clientRoute(CLIENT_TABS.AUDIT));
|
||||
}
|
||||
};
|
||||
return (
|
||||
|
|
@ -64,7 +63,7 @@ function SettingsMenu(props: RouteComponentProps<Props>) {
|
|||
);
|
||||
}
|
||||
|
||||
export default withRouter(SettingsMenu);
|
||||
export default SettingsMenu;
|
||||
|
||||
function MenuItem({ onClick, label, icon }: any) {
|
||||
return (
|
||||
|
|
|
|||
|
|
@ -1,24 +1,21 @@
|
|||
import React from 'react';
|
||||
import { withRouter } from 'react-router-dom';
|
||||
import { client, CLIENT_DEFAULT_TAB } from 'App/routes';
|
||||
import { Icon } from 'UI';
|
||||
import { getInitials } from 'App/utils';
|
||||
import { useStore } from "App/mstore";
|
||||
import { observer } from 'mobx-react-lite';
|
||||
import { useNavigate } from "react-router";
|
||||
|
||||
const CLIENT_PATH = client(CLIENT_DEFAULT_TAB);
|
||||
|
||||
interface Props {
|
||||
history: any;
|
||||
}
|
||||
function UserMenu(props: Props) {
|
||||
const { history }: any = props;
|
||||
function UserMenu() {
|
||||
const navigate = useNavigate();
|
||||
const { loginStore, userStore } = useStore();
|
||||
const account = userStore.account;
|
||||
const onLogoutClick = userStore.logout;
|
||||
|
||||
const onAccountClick = () => {
|
||||
history.push(CLIENT_PATH);
|
||||
navigate(CLIENT_PATH);
|
||||
};
|
||||
|
||||
const onLogout = () => {
|
||||
|
|
@ -59,4 +56,4 @@ function UserMenu(props: Props) {
|
|||
);
|
||||
}
|
||||
|
||||
export default withRouter(observer(UserMenu))
|
||||
export default observer(UserMenu)
|
||||
|
|
|
|||
|
|
@ -12,11 +12,11 @@ import { toast } from 'react-toastify';
|
|||
import EditHlModal from './EditHlModal';
|
||||
import HighlightsListHeader from './HighlightsListHeader';
|
||||
import withPermissions from 'HOCs/withPermissions';
|
||||
import { useHistory } from 'react-router';
|
||||
import { useNavigate } from 'react-router';
|
||||
import { highlights, withSiteId } from 'App/routes'
|
||||
|
||||
function HighlightsList() {
|
||||
const history = useHistory();
|
||||
const navigate = useNavigate()
|
||||
const params = new URLSearchParams(window.location.search);
|
||||
const hlId = params.get('highlight');
|
||||
const { notesStore, projectsStore, userStore } = useStore();
|
||||
|
|
@ -31,7 +31,7 @@ function HighlightsList() {
|
|||
React.useEffect(() => {
|
||||
if (hlId) {
|
||||
setActiveId(hlId);
|
||||
history.replace(withSiteId(highlights(), projectsStore.siteId));
|
||||
navigate(withSiteId(highlights(), projectsStore.siteId), { replace: true });
|
||||
}
|
||||
}, [hlId])
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import cn from 'classnames';
|
|||
import React, { useEffect, useRef, useState } from 'react';
|
||||
// Consider using a different approach for titles in functional components
|
||||
import ReCAPTCHA from 'react-google-recaptcha';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
import { useNavigate, useLocation } from 'react-router';
|
||||
import { observer } from 'mobx-react-lite';
|
||||
import { toast } from 'react-toastify';
|
||||
|
||||
|
|
@ -20,13 +20,8 @@ import stl from './login.module.css';
|
|||
const FORGOT_PASSWORD = forgotPassword();
|
||||
const SIGNUP_ROUTE = signup();
|
||||
|
||||
interface LoginProps {
|
||||
location: Location;
|
||||
}
|
||||
|
||||
const Login = ({
|
||||
location
|
||||
}: LoginProps) => {
|
||||
const Login = () => {
|
||||
const location = useLocation()
|
||||
const [email, setEmail] = useState('');
|
||||
const [password, setPassword] = useState('');
|
||||
const CAPTCHA_ENABLED = React.useMemo(() => {
|
||||
|
|
@ -38,12 +33,12 @@ const Login = ({
|
|||
const loading = loginStore.loading;
|
||||
const authDetails = userStore.authStore.authDetails;
|
||||
const setJwt = userStore.updateJwt;
|
||||
const history = useHistory();
|
||||
const navigate = useNavigate()
|
||||
const params = new URLSearchParams(location.search);
|
||||
|
||||
useEffect(() => {
|
||||
if (authDetails && !authDetails.tenants) {
|
||||
history.push(SIGNUP_ROUTE);
|
||||
navigate(SIGNUP_ROUTE);
|
||||
}
|
||||
}, [authDetails]);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,7 @@
|
|||
import React, { useEffect } from 'react';
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import ModalOverlay from './ModalOverlay';
|
||||
import cn from 'classnames';
|
||||
import { useHistory } from 'react-router';
|
||||
|
||||
const DEFAULT_WIDTH = 350;
|
||||
interface Props {
|
||||
|
|
@ -13,16 +12,6 @@ interface Props {
|
|||
width?: number;
|
||||
}
|
||||
function Modal({ component, className = 'bg-white', props, hideModal }: Props) {
|
||||
const history = useHistory();
|
||||
|
||||
useEffect(() => {
|
||||
return history.listen((location) => {
|
||||
if (history.action === 'POP') {
|
||||
document.querySelector('body').style.overflow = 'visible';
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
return component ? (
|
||||
ReactDOM.createPortal(
|
||||
<ModalOverlay hideModal={hideModal} left={!props.right} right={props.right}>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
import React from 'react';
|
||||
import { Redirect, Route, RouteComponentProps, Switch } from 'react-router';
|
||||
import { withRouter } from 'react-router-dom';
|
||||
|
||||
import { Navigate, Route, Routes } from 'react-router';
|
||||
import { useParams, useNavigate } from "react-router";
|
||||
import { OB_TABS, onboarding as onboardingRoute } from 'App/routes';
|
||||
import { withSiteId } from 'App/routes';
|
||||
import { Icon } from 'UI';
|
||||
|
|
@ -12,22 +11,14 @@ import IntegrationsTab from './components/IntegrationsTab';
|
|||
import ManageUsersTab from './components/ManageUsersTab';
|
||||
import SideMenu from './components/SideMenu';
|
||||
|
||||
interface Props {
|
||||
match: {
|
||||
params: {
|
||||
activeTab: string;
|
||||
siteId: string;
|
||||
};
|
||||
};
|
||||
history: RouteComponentProps['history'];
|
||||
}
|
||||
|
||||
const platformMap = {
|
||||
ios: 'mobile',
|
||||
web: 'web',
|
||||
};
|
||||
|
||||
const Onboarding = (props: Props) => {
|
||||
const Onboarding = (props) => {
|
||||
const navigate = useNavigate();
|
||||
const { activeTab, siteId } = useParams();
|
||||
const platforms = [
|
||||
{
|
||||
label: (
|
||||
|
|
@ -47,18 +38,13 @@ const Onboarding = (props: Props) => {
|
|||
} as const,
|
||||
] as const;
|
||||
const [platform, setPlatform] = React.useState(platforms[0]);
|
||||
const {
|
||||
match: {
|
||||
params: { activeTab, siteId },
|
||||
},
|
||||
} = props;
|
||||
|
||||
const route = (path: string) => {
|
||||
return withSiteId(onboardingRoute(path));
|
||||
};
|
||||
|
||||
const onMenuItemClick = (tab: string) => {
|
||||
props.history.push(withSiteId(onboardingRoute(tab), siteId));
|
||||
navigate(withSiteId(onboardingRoute(tab), siteId));
|
||||
};
|
||||
|
||||
return (
|
||||
|
|
@ -69,7 +55,7 @@ const Onboarding = (props: Props) => {
|
|||
className="bg-white w-full rounded-lg mx-auto mb-8 border"
|
||||
style={{ maxWidth: '1360px' }}
|
||||
>
|
||||
<Switch>
|
||||
<Routes>
|
||||
<Route exact strict path={route(OB_TABS.INSTALLING)}>
|
||||
<InstallOpenReplayTab
|
||||
platforms={platforms}
|
||||
|
|
@ -98,17 +84,14 @@ const Onboarding = (props: Props) => {
|
|||
path={route(OB_TABS.INTEGRATIONS)}
|
||||
component={IntegrationsTab}
|
||||
/>
|
||||
<Redirect to={route(OB_TABS.INSTALLING)} />
|
||||
</Switch>
|
||||
<Route path={'*'}>
|
||||
<Navigate to={route(OB_TABS.INSTALLING)} />
|
||||
</Route>
|
||||
</Routes>
|
||||
</div>
|
||||
</div>
|
||||
{/* <div className="py-6 px-4 w-full flex items-center fixed bottom-0 bg-white border-t z-10">
|
||||
<div className="ml-auto">
|
||||
<OnboardingNavButton />
|
||||
</div>
|
||||
</div> */}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default withRouter(Onboarding);
|
||||
export default Onboarding;
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
import React from 'react';
|
||||
import { Icon, SideMenuitem } from 'UI';
|
||||
import { SideMenuitem } from 'UI';
|
||||
import cn from 'classnames';
|
||||
import stl from './onboardingMenu.module.css';
|
||||
import { OB_TABS, onboarding as onboardingRoute } from 'App/routes';
|
||||
import { withRouter } from 'react-router-dom';
|
||||
import * as routes from '../../../../routes';
|
||||
import * as routes from 'App/routes';
|
||||
import { useParams, useNavigate } from "react-router";
|
||||
|
||||
const withSiteId = routes.withSiteId;
|
||||
|
||||
|
|
@ -15,7 +15,7 @@ const MENU_ITEMS = [
|
|||
OB_TABS.INTEGRATIONS,
|
||||
];
|
||||
|
||||
const Item = ({ icon, text, completed, active, onClick }) => (
|
||||
const Item = ({ text, completed, active, onClick }) => (
|
||||
<div
|
||||
className={cn('cursor-pointer', stl.stepWrapper, {
|
||||
[stl.completed]: completed,
|
||||
|
|
@ -39,17 +39,14 @@ const Item = ({ icon, text, completed, active, onClick }) => (
|
|||
</div>
|
||||
);
|
||||
|
||||
const OnboardingMenu = (props) => {
|
||||
const {
|
||||
match: {
|
||||
params: { activeTab, siteId },
|
||||
},
|
||||
history,
|
||||
} = props;
|
||||
const OnboardingMenu = () => {
|
||||
const { siteId, activeTab } = useParams();
|
||||
const navigate = useNavigate();
|
||||
|
||||
const activeIndex = MENU_ITEMS.findIndex((i) => i === activeTab);
|
||||
|
||||
const setTab = (tab) => {
|
||||
history.push(withSiteId(onboardingRoute(tab), siteId));
|
||||
navigate(withSiteId(onboardingRoute(tab), siteId));
|
||||
};
|
||||
|
||||
return (
|
||||
|
|
@ -61,28 +58,24 @@ const OnboardingMenu = (props) => {
|
|||
|
||||
<>
|
||||
<Item
|
||||
icon="check"
|
||||
text="Install OpenReplay"
|
||||
completed={activeIndex >= 0}
|
||||
active={activeIndex === 0}
|
||||
onClick={() => setTab(MENU_ITEMS[0])}
|
||||
/>
|
||||
<Item
|
||||
icon="check"
|
||||
text="Identify Users"
|
||||
completed={activeIndex >= 1}
|
||||
active={activeIndex === 1}
|
||||
onClick={() => setTab(MENU_ITEMS[1])}
|
||||
/>
|
||||
<Item
|
||||
icon="check"
|
||||
text="Invite Collaborators"
|
||||
completed={activeIndex >= 2}
|
||||
active={activeIndex === 2}
|
||||
onClick={() => setTab(MENU_ITEMS[2])}
|
||||
/>
|
||||
<Item
|
||||
icon="check"
|
||||
text="Integrations"
|
||||
completed={activeIndex >= 3}
|
||||
active={activeIndex === 3}
|
||||
|
|
@ -93,4 +86,4 @@ const OnboardingMenu = (props) => {
|
|||
);
|
||||
};
|
||||
|
||||
export default withRouter(OnboardingMenu);
|
||||
export default OnboardingMenu;
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
import React from 'react'
|
||||
import { withRouter } from 'react-router'
|
||||
import { Button } from 'antd'
|
||||
import { OB_TABS, onboarding as onboardingRoute, withSiteId } from 'App/routes'
|
||||
import { sessions } from 'App/routes';
|
||||
import { useStore } from 'App/mstore'
|
||||
import { useParams, useNavigate } from "react-router";
|
||||
|
||||
const MENU_ITEMS = [OB_TABS.INSTALLING, OB_TABS.IDENTIFY_USERS, OB_TABS.MANAGE_USERS, OB_TABS.INTEGRATIONS]
|
||||
const BTN_MSGS = [
|
||||
|
|
@ -13,7 +13,9 @@ const BTN_MSGS = [
|
|||
'See Recorded Sessions'
|
||||
]
|
||||
|
||||
const OnboardingNavButton = ({ match: { params: { activeTab, siteId } }, history }) => {
|
||||
const OnboardingNavButton = () => {
|
||||
const { activeTab, siteId } = useParams();
|
||||
const navigate = useNavigate();
|
||||
const { userStore } = useStore();
|
||||
const activeIndex = MENU_ITEMS.findIndex(i => i === activeTab);
|
||||
const completed = activeIndex == MENU_ITEMS.length - 1;
|
||||
|
|
@ -21,7 +23,7 @@ const OnboardingNavButton = ({ match: { params: { activeTab, siteId } }, history
|
|||
const setTab = () => {
|
||||
if (!completed) {
|
||||
const tab = MENU_ITEMS[activeIndex+1]
|
||||
history.push(withSiteId(onboardingRoute(tab), siteId));
|
||||
navigate(withSiteId(onboardingRoute(tab), siteId));
|
||||
} else {
|
||||
onDone()
|
||||
}
|
||||
|
|
@ -29,7 +31,7 @@ const OnboardingNavButton = ({ match: { params: { activeTab, siteId } }, history
|
|||
|
||||
const onDone = () => {
|
||||
userStore.setOnboarding(true);
|
||||
history.push(sessions());
|
||||
navigate(sessions());
|
||||
}
|
||||
|
||||
return (
|
||||
|
|
@ -53,4 +55,4 @@ const OnboardingNavButton = ({ match: { params: { activeTab, siteId } }, history
|
|||
)
|
||||
}
|
||||
|
||||
export default withRouter(OnboardingNavButton)
|
||||
export default OnboardingNavButton
|
||||
|
|
@ -1,53 +1,38 @@
|
|||
import React, { useMemo } from 'react';
|
||||
import { withRouter, RouteComponentProps } from 'react-router-dom';
|
||||
import { sessions, withSiteId, onboarding as onboardingRoute } from 'App/routes';
|
||||
import { observer } from 'mobx-react-lite';
|
||||
import { useStore } from 'App/mstore';
|
||||
import { useParams, useNavigate } from "react-router";
|
||||
|
||||
export interface WithOnboardingProps {
|
||||
history: RouteComponentProps['history'];
|
||||
skip?: () => void;
|
||||
navTo?: (tab: string) => void;
|
||||
site?: any;
|
||||
match: {
|
||||
params: {
|
||||
activeTab: string;
|
||||
siteId: string;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
const withOnboarding = <P extends RouteComponentProps>(
|
||||
Component: React.ComponentType<P & WithOnboardingProps>
|
||||
const withOnboarding = <P extends Record<string, any>>(
|
||||
Component: React.ComponentType<P>
|
||||
) => {
|
||||
const WithOnboarding: React.FC<P & WithOnboardingProps> = (props) => {
|
||||
const { siteId } = useParams();
|
||||
const navigate = useNavigate();
|
||||
const { projectsStore, userStore } = useStore();
|
||||
const sites = projectsStore.list;
|
||||
const {
|
||||
match: {
|
||||
params: { siteId },
|
||||
},
|
||||
} = props;
|
||||
const site = useMemo(() => sites.find((s: any) => s.id === siteId), [sites, siteId]);
|
||||
|
||||
const skip = () => {
|
||||
userStore.setOnboarding(true);
|
||||
props.history.push(withSiteId(sessions(), siteId));
|
||||
navigate(withSiteId(sessions(), siteId));
|
||||
};
|
||||
|
||||
const navTo = (tab: string) => {
|
||||
props.history.push(withSiteId(onboardingRoute(tab), siteId));
|
||||
navigate(withSiteId(onboardingRoute(tab), siteId));
|
||||
};
|
||||
|
||||
return <Component skip={skip} navTo={navTo} {...props} site={site} />;
|
||||
};
|
||||
|
||||
return withRouter(
|
||||
observer(
|
||||
WithOnboarding
|
||||
)
|
||||
);
|
||||
return observer(WithOnboarding)
|
||||
};
|
||||
|
||||
export default withOnboarding;
|
||||
|
|
|
|||
|
|
@ -3,27 +3,25 @@ import withPageTitle from 'HOCs/withPageTitle';
|
|||
import SessionsTabOverview from 'Shared/SessionsTabOverview/SessionsTabOverview';
|
||||
import FFlagsList from 'Components/FFlags';
|
||||
import NewFFlag from 'Components/FFlags/NewFFlag';
|
||||
import { Switch, Route } from 'react-router';
|
||||
import { sessions, fflags, withSiteId, newFFlag, fflag, fflagRead, bookmarks } from 'App/routes';
|
||||
import { withRouter, RouteComponentProps, useLocation } from 'react-router-dom';
|
||||
import { Routes, Route } from 'react-router';
|
||||
import {
|
||||
sessions,
|
||||
fflags,
|
||||
withSiteId,
|
||||
newFFlag,
|
||||
fflag,
|
||||
fflagRead,
|
||||
bookmarks,
|
||||
} from 'App/routes';
|
||||
import { useLocation, useParams, useNavigate } from 'react-router';
|
||||
import FlagView from 'Components/FFlags/FlagView/FlagView';
|
||||
import { observer } from 'mobx-react-lite';
|
||||
import { useStore } from '@/mstore';
|
||||
import Bookmarks from 'Shared/SessionsTabOverview/components/Bookmarks/Bookmarks';
|
||||
|
||||
// @ts-ignore
|
||||
interface IProps extends RouteComponentProps {
|
||||
match: {
|
||||
params: {
|
||||
siteId: string;
|
||||
fflagId?: string;
|
||||
};
|
||||
};
|
||||
}
|
||||
// TODO should move these routes to the Routes file
|
||||
function Overview({ match: { params } }: IProps) {
|
||||
function Overview() {
|
||||
const { searchStore } = useStore();
|
||||
const { siteId, fflagId } = params;
|
||||
const { siteId, fflagId } = useParams();
|
||||
const location = useLocation();
|
||||
const tab = location.pathname.split('/')[2];
|
||||
|
||||
|
|
@ -31,34 +29,50 @@ function Overview({ match: { params } }: IProps) {
|
|||
searchStore.setActiveTab(tab);
|
||||
}, [tab]);
|
||||
|
||||
return (
|
||||
<Switch>
|
||||
<Route exact strict
|
||||
path={withSiteId(sessions(), siteId)}>
|
||||
console.log(location.pathname)
|
||||
const renderContent = () => {
|
||||
const path = location.pathname;
|
||||
|
||||
if (path.startsWith(withSiteId(sessions()), siteId)) {
|
||||
return (
|
||||
<div className="mb-5 w-full mx-auto" style={{ maxWidth: '1360px' }}>
|
||||
<SessionsTabOverview />
|
||||
</div>
|
||||
</Route>
|
||||
<Route exact strict
|
||||
path={withSiteId(bookmarks(), siteId)}>
|
||||
);
|
||||
}
|
||||
|
||||
if (path.startsWith(withSiteId(bookmarks()), siteId)) {
|
||||
return (
|
||||
<div className="mb-5 w-full mx-auto" style={{ maxWidth: '1360px' }}>
|
||||
<Bookmarks />
|
||||
</div>
|
||||
</Route>
|
||||
<Route exact strict path={withSiteId(fflags(), siteId)}>
|
||||
<FFlagsList siteId={siteId} />
|
||||
</Route>
|
||||
<Route exact strict path={withSiteId(newFFlag(), siteId)}>
|
||||
<NewFFlag siteId={siteId} />
|
||||
</Route>
|
||||
<Route exact strict path={withSiteId(fflag(), siteId)}>
|
||||
<NewFFlag siteId={siteId} fflagId={fflagId} />
|
||||
</Route>
|
||||
<Route exact strict path={withSiteId(fflagRead(), siteId)}>
|
||||
<FlagView siteId={siteId} fflagId={fflagId!} />
|
||||
</Route>
|
||||
</Switch>
|
||||
);
|
||||
);
|
||||
}
|
||||
|
||||
if (path.startsWith(withSiteId(fflags()), siteId)) {
|
||||
return <FFlagsList siteId={siteId} />;
|
||||
}
|
||||
|
||||
if (path.startsWith(withSiteId(newFFlag()), siteId)) {
|
||||
return <NewFFlag siteId={siteId} />;
|
||||
}
|
||||
|
||||
if (path.match(new RegExp(`^${withSiteId(fflag(), siteId).replace(':fflagId', '\\d+')}$`))) {
|
||||
return <NewFFlag siteId={siteId} fflagId={fflagId} />;
|
||||
}
|
||||
|
||||
if (path.match(new RegExp(`^${withSiteId(fflagRead(), siteId).replace(':fflagId', '\\d+')}$`))) {
|
||||
return <FlagView siteId={siteId} fflagId={fflagId!} />;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="mb-5 w-full mx-auto" style={{ maxWidth: '1360px' }}>
|
||||
<SessionsTabOverview />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
return renderContent();
|
||||
}
|
||||
|
||||
export default withPageTitle('Sessions - OpenReplay')(withRouter(observer(Overview)));
|
||||
export default withPageTitle('Sessions - OpenReplay')(observer(Overview));
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
import { ArrowRightOutlined } from '@ant-design/icons';
|
||||
import { Button, Card, Radio } from 'antd';
|
||||
import React from 'react';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
import { useNavigate } from 'react-router';
|
||||
import * as routes from 'App/routes'
|
||||
import { SPOT_ONBOARDING } from "App/constants/storageKeys";
|
||||
import { useStore } from 'App/mstore';
|
||||
|
|
@ -27,24 +27,24 @@ function ScopeForm() {
|
|||
const downgradeScope = userStore.downgradeScope
|
||||
const scopeState = userStore.scopeState
|
||||
const [scope, setScope] = React.useState(getDefaultSetup);
|
||||
const navigate = useNavigate()
|
||||
React.useEffect(() => {
|
||||
if (scopeState !== 0) {
|
||||
if (scopeState === 2) {
|
||||
history.replace(routes.onboarding())
|
||||
navigate(routes.onboarding(), { replace: true })
|
||||
} else {
|
||||
history.replace(routes.spotsList())
|
||||
navigate(routes.spotsList(), { replace: true })
|
||||
}
|
||||
}
|
||||
}, [scopeState])
|
||||
|
||||
const history = useHistory();
|
||||
const onContinue = () => {
|
||||
if (scope === Scope.FULL) {
|
||||
void upgradeScope();
|
||||
history.replace(routes.onboarding())
|
||||
navigate(routes.onboarding(), { replace: true })
|
||||
} else {
|
||||
void downgradeScope();
|
||||
history.replace(routes.spotsList())
|
||||
navigate(routes.spotsList(), { replace: true })
|
||||
}
|
||||
};
|
||||
return (
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import { PlayButton, PlayingState } from '@/player-ui';
|
|||
import { PlayerContext } from 'Components/Session/playerContext';
|
||||
import { observer } from 'mobx-react-lite';
|
||||
import { Button } from 'antd';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
import { useNavigate } from 'react-router';
|
||||
import { CirclePlay } from 'lucide-react';
|
||||
import { withSiteId } from '@/routes';
|
||||
import * as routes from '@/routes';
|
||||
|
|
@ -20,7 +20,7 @@ function ClipPlayerControls({
|
|||
}) {
|
||||
const { projectsStore } = useStore();
|
||||
const { player, store } = React.useContext(PlayerContext);
|
||||
const history = useHistory();
|
||||
const navigate = useNavigate();
|
||||
const siteId = projectsStore.siteId;
|
||||
|
||||
const { playing, completed } = store.get();
|
||||
|
|
@ -37,7 +37,7 @@ function ClipPlayerControls({
|
|||
|
||||
const showFullSession = () => {
|
||||
const path = withSiteId(routes.session(session.sessionId), siteId);
|
||||
history.push(path + '?jumpto=' + Math.round(range[0]));
|
||||
navigate(path + '?jumpto=' + Math.round(range[0]));
|
||||
};
|
||||
|
||||
return (
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import cn from 'classnames';
|
|||
import { Icon } from 'UI';
|
||||
import { useStore } from 'App/mstore';
|
||||
import { observer } from 'mobx-react-lite';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
import { useNavigate } from 'react-router';
|
||||
import { multiview, liveSession, withSiteId } from 'App/routes';
|
||||
import { PlayerContext, ILivePlayerContext } from 'App/components/Session/playerContext';
|
||||
|
||||
|
|
@ -44,7 +44,7 @@ const CurrentTab = React.memo(() => (
|
|||
));
|
||||
|
||||
function AssistTabs({ session }: { session: Record<string, any> }) {
|
||||
const history = useHistory();
|
||||
const navigate = useNavigate();
|
||||
const { store } = React.useContext(PlayerContext) as unknown as ILivePlayerContext
|
||||
const { recordingState, calling, remoteControl } = store.get()
|
||||
const isDisabled = recordingState !== 0 || calling !== 0 || remoteControl !== 0
|
||||
|
|
@ -63,12 +63,12 @@ function AssistTabs({ session }: { session: Record<string, any> }) {
|
|||
const openGrid = () => {
|
||||
if (isDisabled) return;
|
||||
const sessionIdQuery = encodeURIComponent(assistMultiviewStore.sessions.map((s) => s.sessionId).join(','));
|
||||
return history.push(withSiteId(multiview(sessionIdQuery), siteId));
|
||||
return navigate(withSiteId(multiview(sessionIdQuery), siteId));
|
||||
};
|
||||
const openLiveSession = (sessionId: string) => {
|
||||
if (isDisabled) return;
|
||||
assistMultiviewStore.setActiveSession(sessionId);
|
||||
history.push(withSiteId(liveSession(sessionId), siteId));
|
||||
navigate(withSiteId(liveSession(sessionId), siteId));
|
||||
};
|
||||
|
||||
return (
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import React from 'react';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
import { useNavigate } from 'react-router';
|
||||
import {
|
||||
withSiteId,
|
||||
multiview,
|
||||
|
|
@ -24,7 +24,7 @@ function LivePlayerBlockHeader({
|
|||
const session = sessionStore.current;
|
||||
const closedLive = sessionStore.fetchFailed || (isAssist && !session.live);
|
||||
const siteId = projectsStore.siteId;
|
||||
const history = useHistory();
|
||||
const navigate = useNavigate()
|
||||
const { width, height } = store.get();
|
||||
|
||||
const metaList = customFieldStore.list.map((i: any) => i.key)
|
||||
|
|
@ -35,7 +35,7 @@ function LivePlayerBlockHeader({
|
|||
}, []);
|
||||
|
||||
const backHandler = () => {
|
||||
history.goBack();
|
||||
navigate(-1)
|
||||
};
|
||||
|
||||
const { userId, metadata, isCallActive, agentIds } = session;
|
||||
|
|
@ -48,7 +48,7 @@ function LivePlayerBlockHeader({
|
|||
|
||||
const openGrid = () => {
|
||||
const sessionIdQuery = encodeURIComponent(assistMultiviewStore.sessions.map((s) => s?.sessionId).join(','));
|
||||
return history.push(withSiteId(multiview(sessionIdQuery), siteId));
|
||||
return navigate(withSiteId(multiview(sessionIdQuery), siteId));
|
||||
};
|
||||
|
||||
return (
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import cn from 'classnames';
|
||||
import { observer } from 'mobx-react-lite';
|
||||
import React from 'react';
|
||||
import { useHistory } from 'react-router';
|
||||
import { useNavigate } from 'react-router';
|
||||
|
||||
import { MobilePlayerContext } from 'App/components/Session/playerContext';
|
||||
import { FullScreenButton, PlayButton, PlayingState } from 'App/player-ui';
|
||||
|
|
@ -28,7 +28,6 @@ import {
|
|||
import { useStore } from 'App/mstore';
|
||||
import { session as sessionRoute, withSiteId } from 'App/routes';
|
||||
import { SummaryButton } from 'Components/Session_/Player/Controls/Controls';
|
||||
import { MobEventsList, WebEventsList } from "../../../Session_/Player/Controls/EventsList";
|
||||
import useShortcuts from '../ReplayPlayer/useShortcuts';
|
||||
|
||||
export const SKIP_INTERVALS = {
|
||||
|
|
@ -46,7 +45,7 @@ function Controls(props: any) {
|
|||
const permissions = userStore.account.permissions || [];
|
||||
const disableDevtools = userStore.isEnterprise && !(permissions.includes('DEV_TOOLS') || permissions.includes('SERVICE_DEV_TOOLS'));
|
||||
const { player, store } = React.useContext(MobilePlayerContext);
|
||||
const history = useHistory();
|
||||
const navigate = useNavigate()
|
||||
const { playing, completed, skip, speed, messagesLoading } = store.get();
|
||||
const { uiPlayerStore, projectsStore } = useStore();
|
||||
const fullscreen = uiPlayerStore.fullscreen;
|
||||
|
|
@ -68,11 +67,11 @@ function Controls(props: any) {
|
|||
const sessionTz = session?.timezone;
|
||||
|
||||
const nextHandler = () => {
|
||||
history.push(withSiteId(sessionRoute(nextSessionId), siteId));
|
||||
navigate(withSiteId(sessionRoute(nextSessionId), siteId));
|
||||
};
|
||||
|
||||
const prevHandler = () => {
|
||||
history.push(withSiteId(sessionRoute(previousSessionId), siteId));
|
||||
navigate(withSiteId(sessionRoute(previousSessionId), siteId));
|
||||
};
|
||||
|
||||
useShortcuts({
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import React from 'react';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
import { useNavigate } from 'react-router';
|
||||
import { sessions as sessionsRoute, withSiteId } from 'App/routes';
|
||||
import { BackLink } from 'UI';
|
||||
import cn from 'classnames';
|
||||
|
|
@ -30,7 +30,7 @@ function PlayerBlockHeader(props: Props) {
|
|||
const { customFieldStore, projectsStore, sessionStore } = useStore();
|
||||
const session = sessionStore.current;
|
||||
const siteId = projectsStore.siteId!;
|
||||
const history = useHistory();
|
||||
const navigate = useNavigate();
|
||||
const {
|
||||
fullscreen,
|
||||
setActiveTab,
|
||||
|
|
@ -46,7 +46,7 @@ function PlayerBlockHeader(props: Props) {
|
|||
}, []);
|
||||
|
||||
const backHandler = () => {
|
||||
history.push(withSiteId(SESSIONS_ROUTE, siteId));
|
||||
navigate(withSiteId(SESSIONS_ROUTE, siteId));
|
||||
};
|
||||
|
||||
const { metadata } = session;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
import { useStore } from "App/mstore";
|
||||
import React from 'react';
|
||||
import { withRouter } from 'react-router-dom';
|
||||
import {
|
||||
sessions as sessionsRoute,
|
||||
liveSession as liveSessionRoute,
|
||||
|
|
@ -15,6 +14,7 @@ import { PlayerContext } from 'App/components/Session/playerContext';
|
|||
import { observer } from 'mobx-react-lite';
|
||||
import stl from './playerBlockHeader.module.css';
|
||||
import { IFRAME } from 'App/constants/storageKeys';
|
||||
import { useNavigate } from "react-router";
|
||||
|
||||
const SESSIONS_ROUTE = sessionsRoute();
|
||||
|
||||
|
|
@ -28,13 +28,12 @@ function PlayerBlockHeader(props: any) {
|
|||
const playerState = store?.get?.() || { width: 0, height: 0, showEvents: false }
|
||||
const { width = 0, height = 0, showEvents = false } = playerState
|
||||
const metaList = customFieldStore.list.map((i: any) => i.key)
|
||||
|
||||
const navigate = useNavigate();
|
||||
const {
|
||||
fullscreen,
|
||||
closedLive = false,
|
||||
setActiveTab,
|
||||
activeTab,
|
||||
history,
|
||||
} = props;
|
||||
|
||||
React.useEffect(() => {
|
||||
|
|
@ -46,12 +45,12 @@ function PlayerBlockHeader(props: any) {
|
|||
|
||||
const backHandler = () => {
|
||||
if (
|
||||
sessionPath.pathname === history.location.pathname ||
|
||||
sessionPath.pathname === location.pathname ||
|
||||
sessionPath.pathname.includes('/session/') || sessionPath.pathname.includes('/assist/')
|
||||
) {
|
||||
history.push(withSiteId(SESSIONS_ROUTE, siteId));
|
||||
navigate(withSiteId(SESSIONS_ROUTE, siteId));
|
||||
} else {
|
||||
history.push(
|
||||
navigate(
|
||||
sessionPath ? sessionPath.pathname + sessionPath.search : withSiteId(SESSIONS_ROUTE, siteId)
|
||||
);
|
||||
}
|
||||
|
|
@ -127,4 +126,4 @@ function PlayerBlockHeader(props: any) {
|
|||
|
||||
const PlayerHeaderCont = observer(PlayerBlockHeader);
|
||||
|
||||
export default withRouter(PlayerHeaderCont);
|
||||
export default PlayerHeaderCont;
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import React from 'react';
|
|||
import { client as settingsPath, CLIENT_TABS } from 'App/routes';
|
||||
import { Icon } from 'UI';
|
||||
import { LoadingOutlined } from '@ant-design/icons';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
import { useNavigate } from 'react-router';
|
||||
import { Button } from 'antd';
|
||||
|
||||
export function LoadingFetch({ provider }: { provider: string }) {
|
||||
|
|
@ -25,7 +25,7 @@ export function FailedFetch({
|
|||
provider: string;
|
||||
onRetry: () => void;
|
||||
}) {
|
||||
const history = useHistory();
|
||||
const navigate = useNavigate();
|
||||
const intPath = settingsPath(CLIENT_TABS.INTEGRATIONS);
|
||||
return (
|
||||
<div
|
||||
|
|
@ -45,7 +45,7 @@ export function FailedFetch({
|
|||
Retry
|
||||
</Button>
|
||||
|
||||
<Button type='text' size='small' onClick={() => history.push(intPath)}>
|
||||
<Button type='text' size='small' onClick={() => navigate(intPath)}>
|
||||
Check Configuration
|
||||
</Button>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import React from 'react';
|
||||
import { Button, Checkbox, Input } from 'antd';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
import { useNavigate } from 'react-router';
|
||||
import { withSiteId, sessions } from 'App/routes';
|
||||
import { useStore } from 'App/mstore';
|
||||
|
||||
|
|
@ -14,7 +14,7 @@ interface Props {
|
|||
}
|
||||
|
||||
function SaveModal({ onSave, hideModal }: Props) {
|
||||
const history = useHistory();
|
||||
const navigate = useNavigate();
|
||||
const { projectsStore, searchStore } = useStore();
|
||||
const [name, setName] = React.useState('');
|
||||
const [ignoreClRage, setIgnoreClRage] = React.useState(false);
|
||||
|
|
@ -32,7 +32,7 @@ function SaveModal({ onSave, hideModal }: Props) {
|
|||
'tag',
|
||||
tagId.toString(),
|
||||
)
|
||||
history.push(
|
||||
navigate(
|
||||
withSiteId(
|
||||
sessions(),
|
||||
siteId
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import React from 'react';
|
|||
import { useStore } from 'App/mstore';
|
||||
import { BackLink } from 'UI';
|
||||
import { observer } from 'mobx-react-lite';
|
||||
import { useHistory, useParams } from 'react-router-dom';
|
||||
import { useNavigate, useParams } from 'react-router';
|
||||
import { liveSession, assist, withSiteId, multiview } from 'App/routes';
|
||||
import AssistSessionsModal from 'App/components/Session_/Player/Controls/AssistSessionsModal';
|
||||
import { useModal } from 'App/components/Modal';
|
||||
|
|
@ -19,14 +19,14 @@ function Multiview({
|
|||
const { showModal, hideModal } = useModal();
|
||||
const { assistMultiviewStore, projectsStore, searchStoreLive, sessionStore } = useStore();
|
||||
const siteId = projectsStore.siteId!;
|
||||
const history = useHistory();
|
||||
const navigate = useNavigate()
|
||||
// @ts-ignore
|
||||
const { sessionsquery } = useParams();
|
||||
const total = sessionStore.totalLiveSessions;
|
||||
|
||||
const onSessionsChange = (sessions: Array<Record<string, any> | undefined>) => {
|
||||
const sessionIdQuery = encodeURIComponent(sessions.map((s) => s && s.sessionId).join(','));
|
||||
return history.replace(withSiteId(multiview(sessionIdQuery), siteId));
|
||||
return navigate(withSiteId(multiview(sessionIdQuery), siteId), { replace: true });
|
||||
};
|
||||
|
||||
React.useEffect(() => {
|
||||
|
|
@ -46,12 +46,12 @@ function Multiview({
|
|||
const openLiveSession = (e: React.MouseEvent, sessionId: string) => {
|
||||
e.stopPropagation();
|
||||
assistMultiviewStore.setActiveSession(sessionId);
|
||||
history.push(withSiteId(liveSession(sessionId) + '?multi=true', siteId));
|
||||
navigate(withSiteId(liveSession(sessionId) + '?multi=true', siteId));
|
||||
};
|
||||
|
||||
const returnToList = () => {
|
||||
assistMultiviewStore.reset();
|
||||
history.push(withSiteId(assist(), siteId));
|
||||
navigate(withSiteId(assist(), siteId));
|
||||
};
|
||||
|
||||
const openListModal = () => {
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import cn from 'classnames';
|
|||
import { Icon } from 'UI';
|
||||
import { useStore } from 'App/mstore';
|
||||
import { observer } from 'mobx-react-lite';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
import { useNavigate } from 'react-router';
|
||||
import { multiview, liveSession, withSiteId } from 'App/routes';
|
||||
|
||||
interface ITab {
|
||||
|
|
@ -42,7 +42,7 @@ const CurrentTab = React.memo(() => (
|
|||
));
|
||||
|
||||
function AssistTabs({ session }: { session: Record<string, any> }) {
|
||||
const history = useHistory();
|
||||
const navigate = useNavigate()
|
||||
const { assistMultiviewStore, projectsStore } = useStore();
|
||||
const siteId = projectsStore.siteId!;
|
||||
|
||||
|
|
@ -56,11 +56,11 @@ function AssistTabs({ session }: { session: Record<string, any> }) {
|
|||
|
||||
const openGrid = () => {
|
||||
const sessionIdQuery = encodeURIComponent(assistMultiviewStore.sessions.map((s) => s.sessionId).join(','));
|
||||
return history.push(withSiteId(multiview(sessionIdQuery), siteId));
|
||||
return navigate(withSiteId(multiview(sessionIdQuery), siteId));
|
||||
};
|
||||
const openLiveSession = (sessionId: string) => {
|
||||
assistMultiviewStore.setActiveSession(sessionId);
|
||||
history.push(withSiteId(liveSession(sessionId), siteId));
|
||||
navigate(withSiteId(liveSession(sessionId), siteId));
|
||||
};
|
||||
|
||||
return (
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import { Switch } from 'antd';
|
|||
import cn from 'classnames';
|
||||
import { observer } from 'mobx-react-lite';
|
||||
import React from 'react';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
import { useNavigate } from 'react-router';
|
||||
import { PlayerContext } from 'App/components/Session/playerContext';
|
||||
import { useStore } from 'App/mstore';
|
||||
import { FullScreenButton, PlayButton, PlayingState } from 'App/player-ui';
|
||||
|
|
@ -34,7 +34,6 @@ import { Icon } from 'UI';
|
|||
import LogsButton from 'App/components/Session/Player/SharedComponents/BackendLogs/LogsButton';
|
||||
|
||||
import ControlButton from './ControlButton';
|
||||
import { WebEventsList } from "./EventsList";
|
||||
import Timeline from './Timeline';
|
||||
import PlayerControls from './components/PlayerControls';
|
||||
import styles from './controls.module.css';
|
||||
|
|
@ -92,7 +91,7 @@ function Controls({ setActiveTab }: any) {
|
|||
const changeSkipInterval = uiPlayerStore.changeSkipInterval;
|
||||
const skipInterval = uiPlayerStore.skipInterval;
|
||||
const showStorageRedux = !uiPlayerStore.hiddenHints.storage;
|
||||
const history = useHistory();
|
||||
const navigate = useNavigate()
|
||||
const siteId = projectsStore.siteId;
|
||||
const {
|
||||
playing,
|
||||
|
|
@ -113,11 +112,11 @@ function Controls({ setActiveTab }: any) {
|
|||
const sessionTz = session?.timezone;
|
||||
|
||||
const nextHandler = () => {
|
||||
history.push(withSiteId(sessionRoute(nextSessionId), siteId));
|
||||
navigate(withSiteId(sessionRoute(nextSessionId), siteId));
|
||||
};
|
||||
|
||||
const prevHandler = () => {
|
||||
history.push(withSiteId(sessionRoute(previousSessionId), siteId));
|
||||
navigate(withSiteId(sessionRoute(previousSessionId), siteId));
|
||||
};
|
||||
|
||||
useShortcuts({
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import React, { useEffect, useState } from 'react';
|
||||
import cn from 'classnames';
|
||||
import { observer } from 'mobx-react-lite';
|
||||
import { withRouter } from 'react-router-dom';
|
||||
import { useNavigate } from "react-router";
|
||||
import { Link } from 'UI';
|
||||
import { Button } from 'antd'
|
||||
import { session as sessionRoute, withSiteId } from 'App/routes';
|
||||
|
|
@ -10,7 +10,8 @@ import clsOv from './overlay.module.css';
|
|||
import AutoplayToggle from 'Shared/AutoplayToggle';
|
||||
import { useStore } from 'App/mstore';
|
||||
|
||||
function AutoplayTimer({ history }: any) {
|
||||
function AutoplayTimer() {
|
||||
const navigate = useNavigate();
|
||||
let timer: NodeJS.Timer;
|
||||
const [cancelled, setCancelled] = useState(false);
|
||||
const [counter, setCounter] = useState(5);
|
||||
|
|
@ -25,8 +26,8 @@ function AutoplayTimer({ history }: any) {
|
|||
}
|
||||
|
||||
if (counter === 0) {
|
||||
const siteId = projectsStore.getSiteId().siteId;
|
||||
history.push(withSiteId(sessionRoute(nextId), siteId));
|
||||
const siteId = projectsStore.activeSiteId;
|
||||
navigate(withSiteId(sessionRoute(nextId), siteId));
|
||||
}
|
||||
|
||||
return () => clearTimeout(timer);
|
||||
|
|
@ -60,14 +61,10 @@ function AutoplayTimer({ history }: any) {
|
|||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
{/* <div className="mt-2 flex items-center color-gray-dark">
|
||||
Turn on/off auto-replay in <Icon name="ellipsis-v" className="mx-1" /> More options
|
||||
</div> */}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default withRouter(
|
||||
observer(AutoplayTimer)
|
||||
);
|
||||
export default observer(AutoplayTimer)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,16 +1,16 @@
|
|||
import React, { useEffect } from 'react';
|
||||
import { withSiteId, session as sessionRoute } from 'App/routes';
|
||||
import AutoplayToggle from 'Shared/AutoplayToggle/AutoplayToggle';
|
||||
import { withRouter, RouteComponentProps } from 'react-router-dom';
|
||||
import cn from 'classnames';
|
||||
import { LeftOutlined, RightOutlined } from '@ant-design/icons';
|
||||
import { Button, Popover } from 'antd';
|
||||
import { useStore } from 'App/mstore';
|
||||
import { observer } from 'mobx-react-lite';
|
||||
import { useParams, useNavigate } from 'react-router';
|
||||
|
||||
const PER_PAGE = 10;
|
||||
|
||||
interface Props extends RouteComponentProps {
|
||||
interface Props {
|
||||
defaultList: any;
|
||||
currentPage: number;
|
||||
latestRequestTime: any;
|
||||
|
|
@ -24,12 +24,8 @@ function QueueControls(props: Props) {
|
|||
const total = sessionStore.total;
|
||||
const sessionIds = sessionStore.sessionIds ?? [];
|
||||
const setAutoplayValues = sessionStore.setAutoplayValues;
|
||||
const {
|
||||
match: {
|
||||
// @ts-ignore
|
||||
params: { sessionId },
|
||||
},
|
||||
} = props;
|
||||
const { sessionId } = useParams();
|
||||
const navigate = useNavigate();
|
||||
|
||||
const currentPage = searchStore.currentPage;
|
||||
|
||||
|
|
@ -46,13 +42,13 @@ function QueueControls(props: Props) {
|
|||
}, []);
|
||||
|
||||
const nextHandler = () => {
|
||||
const siteId = projectsStore.getSiteId().siteId!;
|
||||
props.history.push(withSiteId(sessionRoute(nextId), siteId));
|
||||
const siteId = projectsStore.activeSiteId!;
|
||||
navigate(withSiteId(sessionRoute(nextId), siteId));
|
||||
};
|
||||
|
||||
const prevHandler = () => {
|
||||
const siteId = projectsStore.getSiteId().siteId!;
|
||||
props.history.push(withSiteId(sessionRoute(previousId), siteId));
|
||||
const siteId = projectsStore.activeSiteId!;
|
||||
navigate(withSiteId(sessionRoute(previousId), siteId));
|
||||
};
|
||||
|
||||
return (
|
||||
|
|
@ -108,4 +104,4 @@ function QueueControls(props: Props) {
|
|||
);
|
||||
}
|
||||
|
||||
export default withRouter(observer(QueueControls));
|
||||
export default observer(QueueControls);
|
||||
|
|
|
|||
|
|
@ -1,30 +1,19 @@
|
|||
import React, { useEffect, useState } from 'react';
|
||||
import { withRouter, RouteComponentProps } from 'react-router-dom';
|
||||
import { observer } from 'mobx-react-lite';
|
||||
import { useStore } from 'App/mstore';
|
||||
import { Icon } from 'UI';
|
||||
import SignupForm from './SignupForm';
|
||||
import HealthModal from 'Components/Header/HealthStatus/HealthModal/HealthModal';
|
||||
import { getHealthRequest } from 'Components/Header/HealthStatus/getHealth';
|
||||
import withPageTitle from 'HOCs/withPageTitle';
|
||||
import { login } from 'App/routes';
|
||||
import Copyright from 'Shared/Copyright';
|
||||
import { useNavigate } from "react-router";
|
||||
|
||||
const LOGIN_ROUTE = login();
|
||||
const BulletItem: React.FC<{ text: string }> = ({ text }) => (
|
||||
<div className='flex items-center mb-4'>
|
||||
<div className='mr-3 h-8 w-8 rounded-full bg-white shadow flex items-center justify-center'>
|
||||
<Icon name='check' size='26' />
|
||||
</div>
|
||||
<div>{text}</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
const healthStatusCheck_key = '__or__healthStatusCheck_key';
|
||||
|
||||
type SignupProps = RouteComponentProps;
|
||||
|
||||
const Signup: React.FC<SignupProps> = ({ history }) => {
|
||||
const Signup = () => {
|
||||
const navigate = useNavigate();
|
||||
const { userStore } = useStore();
|
||||
const authDetails = userStore.authStore.authDetails;
|
||||
const [healthModalPassed, setHealthModalPassed] = useState<boolean>(localStorage.getItem(healthStatusCheck_key) === 'true');
|
||||
|
|
@ -47,7 +36,7 @@ const Signup: React.FC<SignupProps> = ({ history }) => {
|
|||
if (!authDetails) return
|
||||
if (authDetails) {
|
||||
if (authDetails.tenants) {
|
||||
history.push(LOGIN_ROUTE);
|
||||
navigate(LOGIN_ROUTE);
|
||||
} else {
|
||||
void getHealth();
|
||||
}
|
||||
|
|
@ -79,4 +68,4 @@ const Signup: React.FC<SignupProps> = ({ history }) => {
|
|||
);
|
||||
};
|
||||
|
||||
export default withRouter(withPageTitle('Signup - OpenReplay')(observer(Signup)));
|
||||
export default withPageTitle('Signup - OpenReplay')(observer(Signup));
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import cn from 'classnames';
|
||||
import { observer } from 'mobx-react-lite';
|
||||
import React from 'react';
|
||||
import { useHistory, useParams } from 'react-router-dom';
|
||||
import { useNavigate, useParams } from 'react-router';
|
||||
|
||||
import { useStore } from 'App/mstore';
|
||||
import {
|
||||
|
|
@ -27,7 +27,7 @@ import spotPlayerStore, { PANELS } from './spotPlayerStore';
|
|||
|
||||
function SpotPlayer() {
|
||||
const defaultHeight = getDefaultPanelHeight();
|
||||
const history = useHistory();
|
||||
const navigate = useNavigate()
|
||||
const [panelHeight, setPanelHeight] = React.useState(defaultHeight);
|
||||
const { spotStore, userStore } = useStore();
|
||||
const userEmail = userStore.account.name;
|
||||
|
|
@ -47,7 +47,7 @@ function SpotPlayer() {
|
|||
if (pubKey) {
|
||||
spotStore.setAccessKey(pubKey);
|
||||
} else {
|
||||
history.push('/');
|
||||
navigate('/');
|
||||
}
|
||||
}
|
||||
}, [loggedIn]);
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ import {
|
|||
import copy from 'copy-to-clipboard';
|
||||
import { observer } from 'mobx-react-lite';
|
||||
import React, { useState } from 'react';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
import { useNavigate } from 'react-router';
|
||||
|
||||
import Tabs from 'App/components/Session/Tabs';
|
||||
import { useStore } from 'App/mstore';
|
||||
|
|
@ -58,7 +58,7 @@ function SpotPlayerHeader({
|
|||
const comments = spotStore.currentSpot?.comments ?? [];
|
||||
|
||||
const [dropdownOpen, setDropdownOpen] = useState(false);
|
||||
const history = useHistory();
|
||||
const navigate = useNavigate()
|
||||
|
||||
const onCopy = () => {
|
||||
copy(window.location.href);
|
||||
|
|
@ -66,7 +66,7 @@ function SpotPlayerHeader({
|
|||
};
|
||||
|
||||
const navigateToSpotsList = () => {
|
||||
history.push(spotLink);
|
||||
navigate(spotLink);
|
||||
};
|
||||
|
||||
const items: MenuProps['items'] = [
|
||||
|
|
@ -88,7 +88,7 @@ function SpotPlayerHeader({
|
|||
await downloadFile(url, `${spotStore.currentSpot!.title}.webm`);
|
||||
} else if (key === '2') {
|
||||
spotStore.deleteSpot([spotStore.currentSpot!.spotId]).then(() => {
|
||||
history.push(spotsList());
|
||||
navigate(spotsList());
|
||||
message.success('Spot successfully deleted');
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ import { Button, Checkbox, Dropdown, Tooltip } from 'antd';
|
|||
import copy from 'copy-to-clipboard';
|
||||
import { Link2 } from 'lucide-react';
|
||||
import React, { useState } from 'react';
|
||||
import { useHistory, useParams } from 'react-router-dom';
|
||||
import { useNavigate, useParams } from 'react-router';
|
||||
import { toast } from 'react-toastify';
|
||||
import { TextEllipsis } from "UI";
|
||||
|
||||
|
|
@ -45,7 +45,7 @@ function SpotListItem({
|
|||
const [isEdit, setIsEdit] = useState(false);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [tooltipText, setTooltipText] = useState('Copy link to clipboard');
|
||||
const history = useHistory();
|
||||
const navigate = useNavigate();
|
||||
const { siteId } = useParams<{ siteId: string }>();
|
||||
|
||||
const menuItems = [
|
||||
|
|
@ -104,7 +104,7 @@ function SpotListItem({
|
|||
const fullLink = `${window.location.origin}${spotLink}`;
|
||||
window.open(fullLink, '_blank');
|
||||
} else {
|
||||
history.push(withSiteId(spotUrl(spot.spotId.toString()), siteId));
|
||||
navigate(withSiteId(spotUrl(spot.spotId.toString()), siteId));
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -7,14 +7,14 @@ import {
|
|||
usabilityTestingView,
|
||||
usabilityTestingEdit,
|
||||
} from 'App/routes';
|
||||
import { useParams, useHistory, Prompt } from 'react-router-dom';
|
||||
import { useNavigate, useParams } from 'react-router';
|
||||
import Breadcrumb from 'Shared/Breadcrumb';
|
||||
import { EditOutlined, DeleteOutlined, MoreOutlined } from '@ant-design/icons';
|
||||
import {Power, Info, ListTodo} from 'lucide-react';
|
||||
import { useModal } from 'App/components/Modal';
|
||||
import { observer } from 'mobx-react-lite';
|
||||
import { useStore } from 'App/mstore';
|
||||
import { confirm } from 'UI';
|
||||
import { confirm, NavPrompt } from 'UI';
|
||||
import StepsModal from './StepsModal';
|
||||
import SidePanel from './SidePanel';
|
||||
import usePageTitle from 'App/hooks/usePageTitle';
|
||||
|
|
@ -48,12 +48,12 @@ function TestEdit() {
|
|||
const [isOverviewEditing, setIsOverviewEditing] = React.useState(false);
|
||||
|
||||
const { showModal, hideModal } = useModal();
|
||||
const history = useHistory();
|
||||
const navigate = useNavigate()
|
||||
usePageTitle(`Usability Tests | ${uxtestingStore.instance ? 'Edit' : 'Create'}`);
|
||||
|
||||
React.useEffect(() => {
|
||||
if (uxtestingStore.instanceCreationSiteId && siteId !== uxtestingStore.instanceCreationSiteId) {
|
||||
history.push(withSiteId(usabilityTesting(), siteId));
|
||||
navigate(withSiteId(usabilityTesting(), siteId));
|
||||
}
|
||||
}, [siteId]);
|
||||
React.useEffect(() => {
|
||||
|
|
@ -66,7 +66,7 @@ function TestEdit() {
|
|||
});
|
||||
} else {
|
||||
if (!uxtestingStore.instance) {
|
||||
history.push(withSiteId(usabilityTesting(), siteId));
|
||||
navigate(withSiteId(usabilityTesting(), siteId));
|
||||
} else {
|
||||
setConclusion(uxtestingStore.instance!.conclusionMessage);
|
||||
setGuidelines(uxtestingStore.instance!.guidelines);
|
||||
|
|
@ -89,16 +89,16 @@ function TestEdit() {
|
|||
);
|
||||
} else {
|
||||
toast.success('The usability test is now live and accessible to participants.');
|
||||
history.push(withSiteId(usabilityTestingView(testId!.toString()), siteId));
|
||||
navigate(withSiteId(usabilityTestingView(testId!.toString()), siteId));
|
||||
}
|
||||
});
|
||||
} else {
|
||||
uxtestingStore.createNewTest(isPreview).then((test) => {
|
||||
if (isPreview) {
|
||||
window.open(`${test.startingPath}?oruxt=${test.testId}`, '_blank', 'noopener,noreferrer');
|
||||
history.replace(withSiteId(usabilityTestingEdit(test.testId), siteId));
|
||||
navigate(withSiteId(usabilityTestingEdit(test.testId), siteId), { replace: true });
|
||||
} else {
|
||||
history.push(withSiteId(usabilityTestingView(test.testId), siteId));
|
||||
navigate(withSiteId(usabilityTestingView(test.testId), siteId));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
@ -128,7 +128,7 @@ function TestEdit() {
|
|||
})
|
||||
) {
|
||||
uxtestingStore.deleteTest(testId).then(() => {
|
||||
history.push(withSiteId(usabilityTesting(), siteId));
|
||||
navigate(withSiteId(usabilityTesting(), siteId));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -155,7 +155,7 @@ function TestEdit() {
|
|||
},
|
||||
]}
|
||||
/>
|
||||
<Prompt
|
||||
<NavPrompt
|
||||
when={hasChanged}
|
||||
message={() => {
|
||||
return 'You have unsaved changes. Are you sure you want to leave?';
|
||||
|
|
|
|||
|
|
@ -4,10 +4,10 @@ import { getPdf2 } from 'Components/AssistStats/pdfGenerator';
|
|||
import { useModal } from 'Components/Modal';
|
||||
import LiveTestsModal from 'Components/UsabilityTesting/LiveTestsModal';
|
||||
import React from 'react';
|
||||
import { Button, Typography, Select, Space, Popover, Dropdown, Tooltip } from 'antd';
|
||||
import { Button, Typography, Select, Space, Popover, Dropdown } from 'antd';
|
||||
import { InfoCircleOutlined } from '@ant-design/icons';
|
||||
import { withSiteId, usabilityTesting, usabilityTestingEdit } from 'App/routes';
|
||||
import { useParams, useHistory } from 'react-router-dom';
|
||||
import { useParams, useNavigate } from 'react-router';
|
||||
import Breadcrumb from 'Shared/Breadcrumb';
|
||||
import { observer } from 'mobx-react-lite';
|
||||
import { useStore } from 'App/mstore';
|
||||
|
|
@ -91,7 +91,7 @@ function TestOverview() {
|
|||
// @ts-ignore
|
||||
const { siteId, testId } = useParams();
|
||||
const { showModal, hideModal } = useModal();
|
||||
const history = useHistory();
|
||||
const navigate = useNavigate()
|
||||
const { uxtestingStore } = useStore();
|
||||
|
||||
React.useEffect(() => {
|
||||
|
|
@ -99,7 +99,7 @@ function TestOverview() {
|
|||
try {
|
||||
await uxtestingStore.getTest(testId);
|
||||
} catch {
|
||||
history.push(withSiteId(usabilityTesting(), siteId));
|
||||
navigate(withSiteId(usabilityTesting(), siteId));
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -375,7 +375,7 @@ const TaskSummary = observer(() => {
|
|||
const Title = observer(({ testId, siteId }: any) => {
|
||||
const [truncate, setTruncate] = React.useState(true);
|
||||
const { uxtestingStore } = useStore();
|
||||
const history = useHistory();
|
||||
const navigate = useNavigate()
|
||||
|
||||
const handleChange = (value: string) => {
|
||||
uxtestingStore.updateTestStatus(value);
|
||||
|
|
@ -411,7 +411,7 @@ const Title = observer(({ testId, siteId }: any) => {
|
|||
})
|
||||
) {
|
||||
uxtestingStore.deleteTest(testId).then(() => {
|
||||
history.push(withSiteId(usabilityTesting(), siteId));
|
||||
navigate(withSiteId(usabilityTesting(), siteId));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -441,7 +441,7 @@ const Title = observer(({ testId, siteId }: any) => {
|
|||
confirmButton: 'Edit'
|
||||
})
|
||||
) {
|
||||
history.push(withSiteId(usabilityTestingEdit(testId), siteId));
|
||||
navigate(withSiteId(usabilityTestingEdit(testId), siteId));
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ import { ICONS } from 'Shared/AnimatedSVG/AnimatedSVG';
|
|||
import { Loader, NoContent, Pagination, Link, Icon } from 'UI';
|
||||
import { checkForRecent, getDateFromMill } from 'App/date';
|
||||
import { ArrowRightOutlined, PlusOutlined } from '@ant-design/icons';
|
||||
import { useHistory, useParams } from 'react-router-dom';
|
||||
import { useNavigate, useParams } from 'react-router';
|
||||
import { withSiteId, usabilityTestingEdit, usabilityTestingView } from 'App/routes';
|
||||
import { debounce } from 'App/utils';
|
||||
import withPageTitle from 'HOCs/withPageTitle';
|
||||
|
|
@ -45,7 +45,7 @@ function TestsTable() {
|
|||
|
||||
// @ts-ignore
|
||||
const { siteId } = useParams();
|
||||
const history = useHistory();
|
||||
const navigate = useNavigate()
|
||||
|
||||
const onClose = (confirmed: boolean) => {
|
||||
if (confirmed) {
|
||||
|
|
@ -65,7 +65,7 @@ function TestsTable() {
|
|||
};
|
||||
|
||||
const redirect = (path: string) => {
|
||||
history.push(withSiteId(usabilityTestingEdit(path), siteId));
|
||||
navigate(withSiteId(usabilityTestingEdit(path), siteId));
|
||||
};
|
||||
|
||||
return (
|
||||
|
|
@ -197,10 +197,10 @@ const statusMap = {
|
|||
function Row({ test, siteId }: { test: UxTListEntry; siteId: string }) {
|
||||
const link = usabilityTestingView(test.testId.toString());
|
||||
const editLink = usabilityTestingEdit(test.testId.toString());
|
||||
const history = useHistory();
|
||||
const navigate = useNavigate()
|
||||
|
||||
const redirect = () => {
|
||||
history.push(withSiteId(test.status === 'preview' ? editLink : link, siteId));
|
||||
navigate(withSiteId(test.status === 'preview' ? editLink : link, siteId));
|
||||
};
|
||||
return (
|
||||
<div
|
||||
|
|
|
|||
|
|
@ -1,75 +1,77 @@
|
|||
import React from 'react';
|
||||
import { withRouter } from 'react-router-dom';
|
||||
import { useLocation, useNavigate } from 'react-router';
|
||||
import { removeQueryParams, addQueryParams, setQueryParams, parseQuery } from 'App/routes';
|
||||
|
||||
/* eslint-disable react/sort-comp */
|
||||
|
||||
const withLocationHandlers = (propNames) => (BaseComponent) => {
|
||||
@withRouter
|
||||
class WrapperClass extends React.Component {
|
||||
getQuery = (names) => parseQuery(this.props.location, names);
|
||||
getParam = (name) => parseQuery(this.props.location)[name];
|
||||
addQuery = (params) => {
|
||||
const { location, history } = this.props;
|
||||
history.push(addQueryParams(location, params));
|
||||
};
|
||||
removeQuery = (names = [], replace = false) => {
|
||||
const { location, history } = this.props;
|
||||
const WrapperComponent = (props) => {
|
||||
const location = useLocation();
|
||||
const navigate = useNavigate();
|
||||
|
||||
const getQuery = (names) => parseQuery(location, names);
|
||||
const getParam = (name) => parseQuery(location)[name];
|
||||
|
||||
const addQuery = (params) => {
|
||||
navigate(addQueryParams(location, params));
|
||||
};
|
||||
|
||||
const removeQuery = (names = [], replace = false) => {
|
||||
const namesArray = Array.isArray(names) ? names : [names];
|
||||
/* to avoid update stack overflow */
|
||||
const actualNames = Object.keys(this.getQuery(namesArray));
|
||||
const actualNames = Object.keys(getQuery(namesArray));
|
||||
|
||||
if (actualNames.length > 0) {
|
||||
history[replace ? 'replace' : 'push'](removeQueryParams(location, actualNames));
|
||||
const path = removeQueryParams(location, actualNames);
|
||||
navigate(path, { replace });
|
||||
}
|
||||
};
|
||||
setQuery = (params, replace = false) => {
|
||||
const { location, history } = this.props;
|
||||
history[replace ? 'replace' : 'push'](setQueryParams(location, params));
|
||||
};
|
||||
query = {
|
||||
all: this.getQuery,
|
||||
get: this.getParam,
|
||||
add: this.addQuery,
|
||||
remove: this.removeQuery,
|
||||
set: this.setQuery, // TODO: use namespaces
|
||||
|
||||
const setQuery = (params, replace = false) => {
|
||||
navigate(setQueryParams(location, params), { replace });
|
||||
};
|
||||
|
||||
getHash = () => this.props.location.hash.substring(1);
|
||||
setHash = (hash) => {
|
||||
const { location, history } = this.props;
|
||||
history.push({ ...location, hash: `#${hash}` });
|
||||
};
|
||||
removeHash = () => {
|
||||
const { location, history } = this.props;
|
||||
history.push({ ...location, hash: '' });
|
||||
};
|
||||
hash = {
|
||||
get: this.getHash,
|
||||
set: this.setHash,
|
||||
remove: this.removeHash,
|
||||
const query = {
|
||||
all: getQuery,
|
||||
get: getParam,
|
||||
add: addQuery,
|
||||
remove: removeQuery,
|
||||
set: setQuery, // TODO: use namespaces
|
||||
};
|
||||
|
||||
getQueryProps() {
|
||||
if (Array.isArray(propNames)) return this.getQuery(propNames);
|
||||
const getHash = () => location.hash.substring(1);
|
||||
|
||||
const setHash = (hash) => {
|
||||
navigate({ ...location, hash: `#${hash}` });
|
||||
};
|
||||
|
||||
const removeHash = () => {
|
||||
navigate({ ...location, hash: '' });
|
||||
};
|
||||
|
||||
const hash = {
|
||||
get: getHash,
|
||||
set: setHash,
|
||||
remove: removeHash,
|
||||
};
|
||||
|
||||
const getQueryProps = () => {
|
||||
if (Array.isArray(propNames)) return getQuery(propNames);
|
||||
if (propNames !== null && typeof propNames === 'object') {
|
||||
const values = Object.values(propNames);
|
||||
const query = this.getQuery(values);
|
||||
const query = getQuery(values);
|
||||
const queryProps = {};
|
||||
Object.keys(propNames).map((key) => {
|
||||
Object.keys(propNames).forEach((key) => {
|
||||
queryProps[key] = query[propNames[key]];
|
||||
});
|
||||
return queryProps;
|
||||
}
|
||||
return {};
|
||||
}
|
||||
};
|
||||
|
||||
render() {
|
||||
const queryProps = this.getQueryProps();
|
||||
return <BaseComponent query={this.query} hash={this.hash} {...queryProps} {...this.props} />;
|
||||
}
|
||||
}
|
||||
return WrapperClass;
|
||||
const queryProps = getQueryProps();
|
||||
return <BaseComponent query={query} hash={hash} {...queryProps} {...props} />;
|
||||
};
|
||||
|
||||
return WrapperComponent;
|
||||
};
|
||||
export default withLocationHandlers;
|
||||
|
||||
export default withLocationHandlers;
|
||||
|
|
@ -1,21 +0,0 @@
|
|||
import React from 'react';
|
||||
import { withRouter } from 'react-router-dom';
|
||||
import { withSiteId } from 'App/routes';
|
||||
import { observer } from 'mobx-react-lite'
|
||||
import { useStore } from "App/mstore";
|
||||
|
||||
export default BaseComponent => withRouter(observer((props) => {
|
||||
const { history, ...other } = props
|
||||
const { projectsStore } = useStore();
|
||||
const siteId = projectsStore.siteId
|
||||
|
||||
const push = (location) => {
|
||||
if (typeof location === 'string') {
|
||||
history.push(withSiteId(location, siteId));
|
||||
} else if (typeof location === 'object') {
|
||||
history.push({ ...location, pathname: withSiteId(location.pathname, siteId) });
|
||||
}
|
||||
}
|
||||
|
||||
return <BaseComponent {...other} history={{ ...history, push: push }} />
|
||||
}))
|
||||
|
|
@ -1,13 +1,15 @@
|
|||
import React, { useEffect, useRef } from 'react';
|
||||
import { useStore } from "App/mstore";
|
||||
import { observer } from 'mobx-react-lite'
|
||||
import { useParams, useNavigate } from 'react-router';
|
||||
|
||||
const withSiteIdUpdater = (BaseComponent) => {
|
||||
const WrapperComponent = (props) => {
|
||||
const { siteId: urlSiteId } = useParams();
|
||||
const navigate = useNavigate();
|
||||
const { projectsStore } = useStore();
|
||||
const siteId = projectsStore.siteId;
|
||||
const setSiteId = projectsStore.setSiteId;
|
||||
const urlSiteId = props.match.params.siteId
|
||||
const prevSiteIdRef = useRef(siteId);
|
||||
|
||||
useEffect(() => {
|
||||
|
|
@ -17,15 +19,15 @@ const withSiteIdUpdater = (BaseComponent) => {
|
|||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
const { location: { pathname }, history } = props;
|
||||
const pathname = location.pathname;
|
||||
|
||||
const shouldUrlUpdate = urlSiteId && parseInt(urlSiteId, 10) !== parseInt(siteId, 10);
|
||||
if (shouldUrlUpdate) {
|
||||
const path = ['', siteId].concat(pathname.split('/').slice(2)).join('/');
|
||||
history.push(path);
|
||||
navigate(path);
|
||||
}
|
||||
prevSiteIdRef.current = siteId;
|
||||
}, [urlSiteId, siteId, props.location.pathname, props.history]);
|
||||
}, [urlSiteId, siteId, location.pathname]);
|
||||
|
||||
const key = siteId;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,14 +1,14 @@
|
|||
import React from 'react';
|
||||
import { Button } from 'antd';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
import { useNavigate } from 'react-router';
|
||||
import { LeftOutlined, ArrowLeftOutlined } from '@ant-design/icons';
|
||||
|
||||
function BackButton({ compact }: { compact?: boolean }) {
|
||||
const history = useHistory();
|
||||
const navigate = useNavigate()
|
||||
const siteId = location.pathname.split('/')[1];
|
||||
|
||||
const handleBackClick = () => {
|
||||
history.push(`/${siteId}/dashboard`);
|
||||
navigate(`/${siteId}/dashboard`);
|
||||
};
|
||||
if (compact) {
|
||||
return (
|
||||
|
|
|
|||
|
|
@ -1,13 +1,13 @@
|
|||
import React from 'react';
|
||||
import { useNavigate } from "react-router";
|
||||
import { Icon } from 'UI';
|
||||
import cn from 'classnames';
|
||||
import { Step } from 'App/mstore/types/gettingStarted';
|
||||
import { useStore } from 'App/mstore';
|
||||
import { onboarding as onboardingRoute, withSiteId } from 'App/routes';
|
||||
import { RouteComponentProps, withRouter } from 'react-router';
|
||||
import { useModal } from 'App/components/Modal';
|
||||
|
||||
interface StepListProps extends RouteComponentProps {
|
||||
interface StepListProps {
|
||||
title: string;
|
||||
steps: Step[];
|
||||
status: 'pending' | 'completed';
|
||||
|
|
@ -61,6 +61,7 @@ const StepItem = React.memo(
|
|||
);
|
||||
|
||||
const StepList = React.memo((props: StepListProps) => {
|
||||
const navigate = useNavigate()
|
||||
const { title, steps } = props;
|
||||
const { hideModal } = useModal();
|
||||
|
||||
|
|
@ -79,10 +80,9 @@ const StepList = React.memo((props: StepListProps) => {
|
|||
}
|
||||
|
||||
const onClick = (step: any) => {
|
||||
const { history } = props;
|
||||
const siteId = projectsStore.getSiteId().siteId!;
|
||||
hideModal();
|
||||
history.push(withSiteId(onboardingRoute(step.url), siteId));
|
||||
navigate(withSiteId(onboardingRoute(step.url), siteId));
|
||||
};
|
||||
|
||||
return (
|
||||
|
|
@ -97,4 +97,4 @@ const StepList = React.memo((props: StepListProps) => {
|
|||
);
|
||||
});
|
||||
|
||||
export default withRouter(StepList);
|
||||
export default StepList;
|
||||
|
|
|
|||
|
|
@ -2,12 +2,12 @@ import React from 'react'
|
|||
import { Icon } from 'UI'
|
||||
import { Button } from 'antd'
|
||||
import { CLIENT_TABS, client as clientRoute } from 'App/routes';
|
||||
import { withRouter } from 'react-router-dom';
|
||||
|
||||
function IntegrateSlackTeamsButton({ history }) {
|
||||
import { useNavigate } from "react-router";
|
||||
|
||||
function IntegrateSlackTeamsButton() {
|
||||
const navigate = useNavigate();
|
||||
const gotoPreferencesIntegrations = () => {
|
||||
history.push(clientRoute(CLIENT_TABS.INTEGRATIONS));
|
||||
navigate(clientRoute(CLIENT_TABS.INTEGRATIONS));
|
||||
}
|
||||
|
||||
return (
|
||||
|
|
@ -26,4 +26,4 @@ function IntegrateSlackTeamsButton({ history }) {
|
|||
)
|
||||
}
|
||||
|
||||
export default withRouter(IntegrateSlackTeamsButton)
|
||||
export default IntegrateSlackTeamsButton
|
||||
|
|
|
|||
|
|
@ -3,17 +3,16 @@ import { Alert, Space, Button } from 'antd';
|
|||
import { observer } from 'mobx-react-lite'
|
||||
import { useStore } from "App/mstore";
|
||||
import { onboarding as onboardingRoute } from 'App/routes';
|
||||
import { withRouter } from 'react-router-dom';
|
||||
import * as routes from '../../../routes';
|
||||
import { SquareArrowOutUpRight } from 'lucide-react';
|
||||
import { useHistory } from 'react-router';
|
||||
import { useNavigate } from 'react-router';
|
||||
|
||||
const withSiteId = routes.withSiteId;
|
||||
|
||||
const NoSessionsMessage = () => {
|
||||
const { projectsStore } = useStore();
|
||||
const siteId = projectsStore.siteId;
|
||||
const history = useHistory();
|
||||
const navigate = useNavigate();
|
||||
const activeSite = projectsStore.active;
|
||||
const showNoSessions = !!activeSite && !activeSite.recorded;
|
||||
const onboardingPath = withSiteId(onboardingRoute('installing'), siteId);
|
||||
|
|
@ -41,7 +40,7 @@ const NoSessionsMessage = () => {
|
|||
<Button
|
||||
type="default"
|
||||
size="small"
|
||||
onClick={() => history.push(onboardingPath)}
|
||||
onClick={() => navigate(onboardingPath)}
|
||||
>
|
||||
Complete Project Setup
|
||||
</Button>
|
||||
|
|
@ -55,4 +54,4 @@ const NoSessionsMessage = () => {
|
|||
);
|
||||
};
|
||||
|
||||
export default withRouter(observer(NoSessionsMessage));
|
||||
export default observer(NoSessionsMessage)
|
||||
|
|
|
|||
|
|
@ -5,11 +5,10 @@ import {
|
|||
import { Button, Dropdown, MenuProps, Space, Typography } from 'antd';
|
||||
import cn from 'classnames';
|
||||
import React from 'react';
|
||||
import { withRouter } from 'react-router-dom';
|
||||
import { useLocation } from 'react-router'
|
||||
import { useStore } from 'App/mstore';
|
||||
import { observer } from 'mobx-react-lite';
|
||||
import { hasSiteId, siteChangeAvailable } from 'App/routes';
|
||||
import NewSiteForm from 'Components/Client/Sites/NewSiteForm';
|
||||
import { Icon } from 'UI';
|
||||
import { useModal } from 'Components/ModalContext';
|
||||
import ProjectForm from 'Components/Client/Projects/ProjectForm';
|
||||
|
|
@ -17,15 +16,15 @@ import Project from '@/mstore/types/project';
|
|||
|
||||
const { Text } = Typography;
|
||||
|
||||
function ProjectDropdown(props: { location: any }) {
|
||||
function ProjectDropdown() {
|
||||
const mstore = useStore();
|
||||
const location = useLocation();
|
||||
const { projectsStore, searchStore, searchStoreLive, userStore } = mstore;
|
||||
const account = userStore.account;
|
||||
const sites = projectsStore.list;
|
||||
const siteId = projectsStore.siteId;
|
||||
const setSiteId = projectsStore.setSiteId;
|
||||
const initProject = projectsStore.initProject;
|
||||
const { location } = props;
|
||||
const isAdmin = account.admin || account.superAdmin;
|
||||
const activeSite = sites.find((s) => s.id === siteId);
|
||||
const showCurrent =
|
||||
|
|
@ -139,6 +138,4 @@ function ProjectDropdown(props: { location: any }) {
|
|||
);
|
||||
}
|
||||
|
||||
export default withRouter(
|
||||
observer(ProjectDropdown)
|
||||
);
|
||||
export default observer(ProjectDropdown)
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
import React, { useEffect, useState } from 'react';
|
||||
import { useHistory } from 'react-router';
|
||||
import { useNavigate } from 'react-router';
|
||||
|
||||
import {
|
||||
liveSession as liveSessionRoute,
|
||||
|
|
@ -31,7 +31,7 @@ interface Props {
|
|||
function PlayLink(props: Props) {
|
||||
const { projectsStore } = useStore();
|
||||
const { isAssist, viewed, sessionId, onClick = null, queryParams } = props;
|
||||
const history = useHistory();
|
||||
const navigate = useNavigate()
|
||||
const defaultIconName = getIconName(viewed);
|
||||
|
||||
const [iconName, setIconName] = useState<typeof PLAY_ICON_NAMES[keyof typeof PLAY_ICON_NAMES]>(defaultIconName);
|
||||
|
|
@ -58,7 +58,7 @@ function PlayLink(props: Props) {
|
|||
} else {
|
||||
e.preventDefault();
|
||||
props.beforeOpen();
|
||||
history.push(replayLink);
|
||||
navigate(replayLink);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@ import cn from 'classnames';
|
|||
import { Duration } from 'luxon';
|
||||
import { observer } from 'mobx-react-lite';
|
||||
import React, { useState, useCallback, useMemo } from 'react';
|
||||
import { RouteComponentProps, useHistory, withRouter } from 'react-router-dom';
|
||||
|
||||
import { durationFormatted, formatTimeOrDate } from 'App/date';
|
||||
import { useStore } from 'App/mstore';
|
||||
|
|
@ -14,7 +13,7 @@ import {
|
|||
} from 'App/routes';
|
||||
import { capitalize } from 'App/utils';
|
||||
import { Avatar, CountryFlag, Icon, Label, TextEllipsis } from 'UI';
|
||||
|
||||
import { useLocation } from "react-router";
|
||||
import Counter from './Counter';
|
||||
import ErrorBars from './ErrorBars';
|
||||
import PlayLink from './PlayLink';
|
||||
|
|
@ -78,8 +77,8 @@ const PREFETCH_STATE = {
|
|||
fetched: 2
|
||||
};
|
||||
|
||||
function SessionItem(props: RouteComponentProps & Props) {
|
||||
const { location } = useHistory();
|
||||
function SessionItem(props: Props) {
|
||||
const location = useLocation();
|
||||
const { settingsStore, sessionStore } = useStore();
|
||||
const { timezone, shownTimezone } = settingsStore.sessionSettings;
|
||||
const [prefetchState, setPrefetched] = useState(PREFETCH_STATE.none);
|
||||
|
|
@ -449,4 +448,4 @@ function SessionItem(props: RouteComponentProps & Props) {
|
|||
);
|
||||
}
|
||||
|
||||
export default withRouter(observer(SessionItem));
|
||||
export default observer(SessionItem);
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import { FilterKey } from 'Types/filter/filterType';
|
|||
import SessionItem from 'Shared/SessionItem';
|
||||
import { NoContent, Loader, Pagination, Icon } from 'UI';
|
||||
import { Button } from 'antd'
|
||||
import { useLocation, withRouter } from 'react-router-dom';
|
||||
import { useLocation } from 'react-router';
|
||||
import AnimatedSVG, { ICONS } from 'Shared/AnimatedSVG/AnimatedSVG';
|
||||
import { numberWithCommas } from 'App/utils';
|
||||
import SessionDateRange from './SessionDateRange';
|
||||
|
|
@ -237,4 +237,4 @@ function SessionList() {
|
|||
);
|
||||
}
|
||||
|
||||
export default withRouter(observer(SessionList));
|
||||
export default observer(SessionList);
|
||||
|
|
|
|||
46
frontend/app/components/ui/NavPrompt/index.tsx
Normal file
46
frontend/app/components/ui/NavPrompt/index.tsx
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
import { useCallback, useEffect } from 'react';
|
||||
import { useBlocker } from 'react-router';
|
||||
|
||||
function NavigationPrompt({ when, message }: any) {
|
||||
const blocker = useCallback(
|
||||
(tx) => {
|
||||
if (!when) return false;
|
||||
|
||||
if (typeof message === 'function') {
|
||||
const result = message(tx.nextLocation);
|
||||
if (result === true) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
},
|
||||
[when, message]
|
||||
);
|
||||
|
||||
const { state, proceed, reset, location: nextLocation } = useBlocker(blocker);
|
||||
|
||||
useEffect(() => {
|
||||
if (state === 'blocked') {
|
||||
let promptMessage = 'Are you sure you want to leave this page?';
|
||||
if (typeof message === 'function') {
|
||||
const result = message(nextLocation);
|
||||
if (typeof result === 'string') {
|
||||
promptMessage = result;
|
||||
}
|
||||
} else if (typeof message === 'string') {
|
||||
promptMessage = message;
|
||||
}
|
||||
|
||||
const confirmed = window.confirm(promptMessage);
|
||||
|
||||
if (confirmed) {
|
||||
proceed();
|
||||
} else {
|
||||
reset();
|
||||
}
|
||||
}
|
||||
}, [state, proceed, reset, nextLocation, message]);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
export default NavigationPrompt;
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
import { observer } from 'mobx-react-lite';
|
||||
import React from 'react';
|
||||
import { RouteComponentProps, withRouter } from 'react-router-dom';
|
||||
import { useNavigate, useLocation } from "react-router";
|
||||
|
||||
import { useStore } from 'App/mstore';
|
||||
import {
|
||||
|
|
@ -16,8 +16,7 @@ import stl from './NoSessionPermission.module.css';
|
|||
const SESSIONS_ROUTE = sessionsRoute();
|
||||
const ASSIST_ROUTE = assistRoute();
|
||||
|
||||
interface Props extends RouteComponentProps {
|
||||
history: any;
|
||||
interface Props {
|
||||
isLive?: boolean;
|
||||
}
|
||||
function NoSessionPermission(props: Props) {
|
||||
|
|
@ -26,19 +25,20 @@ function NoSessionPermission(props: Props) {
|
|||
const sessionPath = sessionStore.sessionPath;
|
||||
const isAssist = window.location.pathname.includes('/assist/');
|
||||
const siteId = projectsStore.siteId!;
|
||||
const { history } = props;
|
||||
const navigate = useNavigate();
|
||||
const location = useLocation();
|
||||
|
||||
const backHandler = () => {
|
||||
if (
|
||||
sessionPath.pathname === history.location.pathname ||
|
||||
sessionPath.pathname === location.pathname ||
|
||||
sessionPath.pathname.includes('/session/') ||
|
||||
isAssist
|
||||
) {
|
||||
history.push(
|
||||
navigate(
|
||||
withSiteId(isAssist ? ASSIST_ROUTE : SESSIONS_ROUTE, siteId)
|
||||
);
|
||||
} else {
|
||||
history.push(
|
||||
navigate(
|
||||
sessionPath
|
||||
? sessionPath.pathname + sessionPath.search
|
||||
: withSiteId(SESSIONS_ROUTE, siteId)
|
||||
|
|
@ -50,7 +50,7 @@ function NoSessionPermission(props: Props) {
|
|||
<div className={stl.wrapper}>
|
||||
<Icon name="shield-lock" size="50" className="py-16" />
|
||||
<div className={stl.title}>Not allowed</div>
|
||||
{session.isLive ? (
|
||||
{session.live ? (
|
||||
<span>
|
||||
This session is still live, and you don’t have the necessary
|
||||
permissions to access this feature. Please check with your admin.
|
||||
|
|
@ -68,6 +68,4 @@ function NoSessionPermission(props: Props) {
|
|||
);
|
||||
}
|
||||
|
||||
export default withRouter(
|
||||
observer(NoSessionPermission)
|
||||
);
|
||||
export default observer(NoSessionPermission)
|
||||
|
|
|
|||
|
|
@ -47,4 +47,5 @@ export { default as Message } from './Message';
|
|||
export { default as Popover } from './Popover';
|
||||
export { default as Switch } from './Switch';
|
||||
export { default as Divider } from './Divider';
|
||||
export { default as CodeBlock } from './CodeBlock'
|
||||
export { default as CodeBlock } from './CodeBlock'
|
||||
export { default as NavPrompt } from './NavPrompt';
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
import { useEffect, useState } from 'react';
|
||||
import { useHistory } from 'react-router';
|
||||
import { useNavigate } from 'react-router';
|
||||
import { JsonUrlConverter } from 'App/utils/search';
|
||||
import { useStore } from '@/mstore';
|
||||
import Search from '@/mstore/types/search';
|
||||
|
|
@ -15,7 +15,7 @@ interface Props {
|
|||
const useSessionSearchQueryHandler = ({ onBeforeLoad, appliedFilter, loading, onLoaded = () => null }: Props) => {
|
||||
const { searchStore } = useStore();
|
||||
const [beforeHookLoaded, setBeforeHookLoaded] = useState(!onBeforeLoad);
|
||||
const history = useHistory();
|
||||
const navigate = useNavigate()
|
||||
|
||||
// Apply filter from the query string when the component mounts
|
||||
useEffect(() => {
|
||||
|
|
@ -27,7 +27,7 @@ const useSessionSearchQueryHandler = ({ onBeforeLoad, appliedFilter, loading, on
|
|||
setBeforeHookLoaded(true);
|
||||
}
|
||||
|
||||
const converter = JsonUrlConverter.urlParamsToJson(history.location.search);
|
||||
const converter = JsonUrlConverter.urlParamsToJson(location.search);
|
||||
const json = getFilterFromJson(converter.toJSON());
|
||||
const filter = new Search(json);
|
||||
|
||||
|
|
@ -57,27 +57,27 @@ const useSessionSearchQueryHandler = ({ onBeforeLoad, appliedFilter, loading, on
|
|||
};
|
||||
|
||||
void applyFilterFromQuery();
|
||||
}, [loading, searchStore, history.location.search, onBeforeLoad]);
|
||||
}, [loading, searchStore, location.search, onBeforeLoad]);
|
||||
|
||||
// Update the URL whenever the appliedFilter changes
|
||||
useEffect(() => {
|
||||
const updateUrlWithFilter = () => {
|
||||
if (!loading && beforeHookLoaded) {
|
||||
const query = JsonUrlConverter.jsonToUrlParams(appliedFilter);
|
||||
history.replace({ search: query });
|
||||
navigate({ search: query }, { replace: true });
|
||||
}
|
||||
};
|
||||
|
||||
updateUrlWithFilter();
|
||||
}, [appliedFilter, loading, beforeHookLoaded, history]);
|
||||
}, [appliedFilter, loading, beforeHookLoaded]);
|
||||
|
||||
// Ensure the URL syncs on remount if already parsed
|
||||
useEffect(() => {
|
||||
if (searchStore.urlParsed) {
|
||||
const query = JsonUrlConverter.jsonToUrlParams(appliedFilter);
|
||||
history.replace({ search: query });
|
||||
navigate({ search: query }, { replace: true });
|
||||
}
|
||||
}, [appliedFilter, searchStore.urlParsed, history]);
|
||||
}, [appliedFilter, searchStore.urlParsed]);
|
||||
|
||||
return null;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,9 +1,8 @@
|
|||
import { Divider, Menu, Tag, Typography, Popover, Button } from 'antd';
|
||||
import cn from 'classnames';
|
||||
import React from 'react';
|
||||
import { RouteComponentProps, withRouter } from 'react-router-dom';
|
||||
import { observer } from 'mobx-react-lite';
|
||||
|
||||
import { useLocation, useNavigate } from 'react-router';
|
||||
import SupportModal from 'App/layout/SupportModal';
|
||||
import * as routes from 'App/routes';
|
||||
import {
|
||||
|
|
@ -30,15 +29,15 @@ import AnimatedSVG, { ICONS } from 'Shared/AnimatedSVG/AnimatedSVG';
|
|||
|
||||
const { Text } = Typography;
|
||||
|
||||
interface Props extends RouteComponentProps {
|
||||
siteId?: string;
|
||||
interface Props {
|
||||
isCollapsed?: boolean;
|
||||
}
|
||||
|
||||
function SideMenu(props: Props) {
|
||||
const location = useLocation();
|
||||
const navigate = useNavigate();
|
||||
const {
|
||||
location,
|
||||
isCollapsed
|
||||
isCollapsed,
|
||||
} = props;
|
||||
|
||||
const isPreferencesActive = location.pathname.includes('/client/');
|
||||
|
|
@ -118,7 +117,7 @@ function SideMenu(props: Props) {
|
|||
|
||||
const menuRoutes: any = {
|
||||
[MENU.EXIT]: () =>
|
||||
props.history.push(withSiteId(routes.sessions(), siteId)),
|
||||
navigate(withSiteId(routes.sessions(), siteId)),
|
||||
[MENU.SESSIONS]: () => withSiteId(routes.sessions(), siteId),
|
||||
[MENU.BOOKMARKS]: () => withSiteId(routes.bookmarks(), siteId),
|
||||
[MENU.VAULT]: () => withSiteId(routes.bookmarks(), siteId),
|
||||
|
|
@ -169,7 +168,7 @@ function SideMenu(props: Props) {
|
|||
};
|
||||
|
||||
const pushTo = (path: string) => {
|
||||
props.history.push(path);
|
||||
navigate(path);
|
||||
};
|
||||
|
||||
const RenderDivider = (props: { index: number }) => {
|
||||
|
|
@ -324,8 +323,7 @@ function SideMenu(props: Props) {
|
|||
);
|
||||
}
|
||||
|
||||
export default withRouter(observer(SideMenu));
|
||||
|
||||
export default observer(SideMenu);
|
||||
|
||||
const SpotMenuItem = ({ isCollapsed }: any) => {
|
||||
const [isModalVisible, setIsModalVisible] = React.useState(false);
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import React from 'react';
|
||||
import { Modal, Button, List, Divider } from 'antd';
|
||||
import { CircleDot, Play, TrendingUp, Radio, Sparkles, Plug, ArrowRight } from 'lucide-react';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
import { useNavigate } from 'react-router';
|
||||
import { onboarding } from 'App/routes';
|
||||
import { useStore } from 'App/mstore';
|
||||
|
||||
|
|
@ -15,7 +15,7 @@ const SpotToOpenReplayPrompt = ({ isVisible, onCancel }: {
|
|||
onCancel: () => void;
|
||||
}) => {
|
||||
const { userStore } = useStore();
|
||||
const history = useHistory();
|
||||
const navigate = useNavigate()
|
||||
const features = [
|
||||
{ icon: <CircleDot />, text: 'Spot', noBorder: true },
|
||||
{ isDivider: true },
|
||||
|
|
@ -28,7 +28,7 @@ const SpotToOpenReplayPrompt = ({ isVisible, onCancel }: {
|
|||
|
||||
const onUpgrade = () => {
|
||||
userStore.upgradeScope().then(() => {
|
||||
history.push(onboarding());
|
||||
navigate(onboarding());
|
||||
onCancel();
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -62,8 +62,8 @@
|
|||
"react-draggable": "^4.4.5",
|
||||
"react-google-recaptcha": "^2.1.0",
|
||||
"react-intersection-observer": "^9.13.1",
|
||||
"react-router": "^5.3.3",
|
||||
"react-router-dom": "^5.3.3",
|
||||
"react-router": "^6.30.0",
|
||||
"react-router-dom": "^6.30.0",
|
||||
"react-select": "^5.3.2",
|
||||
"react-svg-map": "^2.2.0",
|
||||
"react-toastify": "^9.1.1",
|
||||
|
|
|
|||
|
|
@ -1581,7 +1581,7 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@babel/runtime@npm:^7.1.2, @babel/runtime@npm:^7.10.1, @babel/runtime@npm:^7.10.4, @babel/runtime@npm:^7.11.1, @babel/runtime@npm:^7.11.2, @babel/runtime@npm:^7.12.0, @babel/runtime@npm:^7.12.13, @babel/runtime@npm:^7.12.5, @babel/runtime@npm:^7.16.7, @babel/runtime@npm:^7.18.0, @babel/runtime@npm:^7.18.3, @babel/runtime@npm:^7.20.0, @babel/runtime@npm:^7.20.7, @babel/runtime@npm:^7.21.0, @babel/runtime@npm:^7.22.5, @babel/runtime@npm:^7.23.2, @babel/runtime@npm:^7.23.6, @babel/runtime@npm:^7.23.9, @babel/runtime@npm:^7.24.4, @babel/runtime@npm:^7.24.7, @babel/runtime@npm:^7.24.8, @babel/runtime@npm:^7.25.7, @babel/runtime@npm:^7.26.0, @babel/runtime@npm:^7.5.5, @babel/runtime@npm:^7.8.4, @babel/runtime@npm:^7.8.7, @babel/runtime@npm:^7.9.2":
|
||||
"@babel/runtime@npm:^7.10.1, @babel/runtime@npm:^7.10.4, @babel/runtime@npm:^7.11.1, @babel/runtime@npm:^7.11.2, @babel/runtime@npm:^7.12.0, @babel/runtime@npm:^7.12.5, @babel/runtime@npm:^7.16.7, @babel/runtime@npm:^7.18.0, @babel/runtime@npm:^7.18.3, @babel/runtime@npm:^7.20.0, @babel/runtime@npm:^7.20.7, @babel/runtime@npm:^7.21.0, @babel/runtime@npm:^7.22.5, @babel/runtime@npm:^7.23.2, @babel/runtime@npm:^7.23.6, @babel/runtime@npm:^7.23.9, @babel/runtime@npm:^7.24.4, @babel/runtime@npm:^7.24.7, @babel/runtime@npm:^7.24.8, @babel/runtime@npm:^7.25.7, @babel/runtime@npm:^7.26.0, @babel/runtime@npm:^7.5.5, @babel/runtime@npm:^7.8.4, @babel/runtime@npm:^7.8.7, @babel/runtime@npm:^7.9.2":
|
||||
version: 7.26.9
|
||||
resolution: "@babel/runtime@npm:7.26.9"
|
||||
dependencies:
|
||||
|
|
@ -2930,6 +2930,13 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@remix-run/router@npm:1.23.0":
|
||||
version: 1.23.0
|
||||
resolution: "@remix-run/router@npm:1.23.0"
|
||||
checksum: 10c1/c87d2227dc07ec5575cb3349dc388c0abd77a7f04bbdde531b183880c19c9550c3adbeb67a1a2ad677fbf13dd6192e2c42f479d5d99e4f01c7b53f250cec6c00
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@sentry/browser@npm:^5.21.1":
|
||||
version: 5.30.0
|
||||
resolution: "@sentry/browser@npm:5.30.0"
|
||||
|
|
@ -8528,20 +8535,6 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"history@npm:^4.9.0":
|
||||
version: 4.10.1
|
||||
resolution: "history@npm:4.10.1"
|
||||
dependencies:
|
||||
"@babel/runtime": "npm:^7.1.2"
|
||||
loose-envify: "npm:^1.2.0"
|
||||
resolve-pathname: "npm:^3.0.0"
|
||||
tiny-invariant: "npm:^1.0.2"
|
||||
tiny-warning: "npm:^1.0.0"
|
||||
value-equal: "npm:^1.0.1"
|
||||
checksum: 10c1/52b1a0cc62f6bff70d29325ce3e16078f070e8d51405866ce617c266dbf66a8b3898b5dbd9272514844760e8c3d1e657240d64175ab6b133b8bb100161218b5b
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"hls.js@npm:^1.5.13":
|
||||
version: 1.5.20
|
||||
resolution: "hls.js@npm:1.5.20"
|
||||
|
|
@ -8549,7 +8542,7 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"hoist-non-react-statics@npm:^3.1.0, hoist-non-react-statics@npm:^3.3.0, hoist-non-react-statics@npm:^3.3.1, hoist-non-react-statics@npm:^3.3.2":
|
||||
"hoist-non-react-statics@npm:^3.3.0, hoist-non-react-statics@npm:^3.3.1, hoist-non-react-statics@npm:^3.3.2":
|
||||
version: 3.3.2
|
||||
resolution: "hoist-non-react-statics@npm:3.3.2"
|
||||
dependencies:
|
||||
|
|
@ -9387,13 +9380,6 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"isarray@npm:0.0.1":
|
||||
version: 0.0.1
|
||||
resolution: "isarray@npm:0.0.1"
|
||||
checksum: 10c1/abd2b120df9b6e06385e1d2d109dc4eabac0b950e1a02448cde7416691462d809c32d2acdd28d6c2e2ede3527e6251debc9a56f7c7c8515da4ead1993f6ba514
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"isarray@npm:^2.0.5":
|
||||
version: 2.0.5
|
||||
resolution: "isarray@npm:2.0.5"
|
||||
|
|
@ -10563,7 +10549,7 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"loose-envify@npm:^1.0.0, loose-envify@npm:^1.1.0, loose-envify@npm:^1.2.0, loose-envify@npm:^1.3.1, loose-envify@npm:^1.4.0":
|
||||
"loose-envify@npm:^1.0.0, loose-envify@npm:^1.1.0, loose-envify@npm:^1.3.1, loose-envify@npm:^1.4.0":
|
||||
version: 1.4.0
|
||||
resolution: "loose-envify@npm:1.4.0"
|
||||
dependencies:
|
||||
|
|
@ -11663,8 +11649,8 @@ __metadata:
|
|||
react-draggable: "npm:^4.4.5"
|
||||
react-google-recaptcha: "npm:^2.1.0"
|
||||
react-intersection-observer: "npm:^9.13.1"
|
||||
react-router: "npm:^5.3.3"
|
||||
react-router-dom: "npm:^5.3.3"
|
||||
react-router: "npm:^6.30.0"
|
||||
react-router-dom: "npm:^6.30.0"
|
||||
react-select: "npm:^5.3.2"
|
||||
react-svg-map: "npm:^2.2.0"
|
||||
react-toastify: "npm:^9.1.1"
|
||||
|
|
@ -11969,15 +11955,6 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"path-to-regexp@npm:^1.7.0":
|
||||
version: 1.9.0
|
||||
resolution: "path-to-regexp@npm:1.9.0"
|
||||
dependencies:
|
||||
isarray: "npm:0.0.1"
|
||||
checksum: 10c1/79d0f8f5221b7d1a2c3de08775f7ea158ef7bd978e9ed3c6b0813a89ffcc59edb9eee435913ce73e2aad99384b7101d40d81dfe312cf2f54da53990305108695
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"path-type@npm:^4.0.0":
|
||||
version: 4.0.0
|
||||
resolution: "path-type@npm:4.0.0"
|
||||
|
|
@ -13676,7 +13653,7 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"react-is@npm:^16.12.0, react-is@npm:^16.13.1, react-is@npm:^16.6.0, react-is@npm:^16.7.0":
|
||||
"react-is@npm:^16.12.0, react-is@npm:^16.13.1, react-is@npm:^16.7.0":
|
||||
version: 16.13.1
|
||||
resolution: "react-is@npm:16.13.1"
|
||||
checksum: 10c1/b1d8be84f510ec19f3dc7cebd9790076f708943e333e03a26dfadc225bd36b3ac6bbdc94a19e1cd72f43d366de47e21fa04396aba0e86ae0e50610fb4c7a47c8
|
||||
|
|
@ -13697,39 +13674,27 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"react-router-dom@npm:^5.3.3":
|
||||
version: 5.3.4
|
||||
resolution: "react-router-dom@npm:5.3.4"
|
||||
"react-router-dom@npm:^6.30.0":
|
||||
version: 6.30.0
|
||||
resolution: "react-router-dom@npm:6.30.0"
|
||||
dependencies:
|
||||
"@babel/runtime": "npm:^7.12.13"
|
||||
history: "npm:^4.9.0"
|
||||
loose-envify: "npm:^1.3.1"
|
||||
prop-types: "npm:^15.6.2"
|
||||
react-router: "npm:5.3.4"
|
||||
tiny-invariant: "npm:^1.0.2"
|
||||
tiny-warning: "npm:^1.0.0"
|
||||
"@remix-run/router": "npm:1.23.0"
|
||||
react-router: "npm:6.30.0"
|
||||
peerDependencies:
|
||||
react: ">=15"
|
||||
checksum: 10c1/1a00acf223dc8ffb7eb6c189dcc858858c4df37b51dd92b5d38aca456b9813596094e19fdcdcc8044daad054c5392de051643988c217e3a296d1df803e5106f4
|
||||
react: ">=16.8"
|
||||
react-dom: ">=16.8"
|
||||
checksum: 10c1/00e36b130dcd6fdf7c2867b35ad547b28dfcdbc5b342699baaea785dbfbabd6d3e1d9213c3eb1ffb64e4b418b3a1053882b7ab568a68624f301c2ed88f6d38e5
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"react-router@npm:5.3.4, react-router@npm:^5.3.3":
|
||||
version: 5.3.4
|
||||
resolution: "react-router@npm:5.3.4"
|
||||
"react-router@npm:6.30.0, react-router@npm:^6.30.0":
|
||||
version: 6.30.0
|
||||
resolution: "react-router@npm:6.30.0"
|
||||
dependencies:
|
||||
"@babel/runtime": "npm:^7.12.13"
|
||||
history: "npm:^4.9.0"
|
||||
hoist-non-react-statics: "npm:^3.1.0"
|
||||
loose-envify: "npm:^1.3.1"
|
||||
path-to-regexp: "npm:^1.7.0"
|
||||
prop-types: "npm:^15.6.2"
|
||||
react-is: "npm:^16.6.0"
|
||||
tiny-invariant: "npm:^1.0.2"
|
||||
tiny-warning: "npm:^1.0.0"
|
||||
"@remix-run/router": "npm:1.23.0"
|
||||
peerDependencies:
|
||||
react: ">=15"
|
||||
checksum: 10c1/b920516e84fc10980a108b1ad368c4ebd3b5541c4de1bb071053c91ccc6410d1a7326aed6da6101d6728ca825ec661e73b87518078502e3a4879f5be924af2d6
|
||||
react: ">=16.8"
|
||||
checksum: 10c1/6d8b9dfcfa38b930f49a511d635f02dd66dfed6c120df08c41ebfc661c6c4aa388b59ac63e01ffba55a3f334e199ce2f9f76f1fd50d14fca52e213373c18368f
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
|
|
@ -14111,13 +14076,6 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"resolve-pathname@npm:^3.0.0":
|
||||
version: 3.0.0
|
||||
resolution: "resolve-pathname@npm:3.0.0"
|
||||
checksum: 10c1/7951bb47cbfc98a2cc0e4b62a099ce4191f01e42557b048cf8bf857092e0719a4d021f9765d770ec8967630656f0a78c4b656908183d09dd680649d20d56851b
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"resolve-pkg-maps@npm:^1.0.0":
|
||||
version: 1.0.0
|
||||
resolution: "resolve-pkg-maps@npm:1.0.0"
|
||||
|
|
@ -15607,20 +15565,13 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"tiny-invariant@npm:^1.0.2, tiny-invariant@npm:^1.3.1":
|
||||
"tiny-invariant@npm:^1.3.1":
|
||||
version: 1.3.3
|
||||
resolution: "tiny-invariant@npm:1.3.3"
|
||||
checksum: 10c1/e9baa182794cfa0499134b3e7a886ab8be2e2cd15e070eedb81e2ae8ff379b8ddba146cb25093242c6768d127a93e7f2ce774c7be9a8035c1b34d02c9a5b0a8c
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"tiny-warning@npm:^1.0.0":
|
||||
version: 1.0.3
|
||||
resolution: "tiny-warning@npm:1.0.3"
|
||||
checksum: 10c1/b559861279695929d2ed06390b7a455186cb796a5fd3fb8efa45de786b45976dcb46d038f1bd9aaa744abe3c3cbc08e6650ce34fabf419bc50e3150106e78751
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"tinyglobby@npm:^0.2.7":
|
||||
version: 0.2.12
|
||||
resolution: "tinyglobby@npm:0.2.12"
|
||||
|
|
@ -16259,13 +16210,6 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"value-equal@npm:^1.0.1":
|
||||
version: 1.0.1
|
||||
resolution: "value-equal@npm:1.0.1"
|
||||
checksum: 10c1/90eacdf332d054e39b44e190d72c4975cf3daee09084e16146eb5ae8590683b11a097d552efe9a6bbb3ea56489a06e5ea02c20acba83c1a84e20912a864d7981
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"vary@npm:~1.1.2":
|
||||
version: 1.1.2
|
||||
resolution: "vary@npm:1.1.2"
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue