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