* feat spot: init commit for extension * nvmrc * fix login flow * Spots Gridview Updates (#2422) * feat ui: login flow for spot extension * spot list, store and service created * some fixing for header * start work on single spot * spot player start * header for player, comments, icons, etc * split stuff into compoennts, create player state manager * player controls, activity panel etc etc * comments, empty page, rename and stuff * interval buttons etc * access modal * pubkey support * fix tooltip * limit 10 -> 9 * hls lib instead of videojs * some warnings * fix date display for exp * change public links * display more client data * fix cleaning, init comment * map network to replay player network ev * stream support, console panel, close panels on X * fixing streaming, destroy on leave * fix autoplay * show notification on spot login * fix spot login * backup player added, fix audio issue * show thumbnail when no video, add spot roles * add poster thumbnail * some fixes to video check * fix events jump * fix play btn * try catch over pubkey * feat ui: login flow for spot extension * spot list, store and service created * some fixing for header * start work on single spot * spot player start * header for player, comments, icons, etc * split stuff into compoennts, create player state manager * player controls, activity panel etc etc * comments, empty page, rename and stuff * interval buttons etc * access modal * pubkey support * fix tooltip * limit 10 -> 9 * hls lib instead of videojs * some warnings * fix date display for exp * change public links * display more client data * fix cleaning, init comment * map network to replay player network ev * stream support, console panel, close panels on X * fixing streaming, destroy on leave * fix autoplay * show notification on spot login * fix spot login * backup player added, fix audio issue * show thumbnail when no video, add spot roles * add poster thumbnail * some fixes to video check * fix events jump * fix play btn * try catch over pubkey * icons * Various updates * Update SVG.tsx * Update SideMenu.tsx * SpotList & Menu updates * feat ui: login flow for spot extension * spot list, store and service created * some fixing for header * start work on single spot * spot player start * header for player, comments, icons, etc * split stuff into compoennts, create player state manager * player controls, activity panel etc etc * comments, empty page, rename and stuff * interval buttons etc * access modal * pubkey support * fix tooltip * limit 10 -> 9 * hls lib instead of videojs * some warnings * fix date display for exp * change public links * display more client data * fix cleaning, init comment * map network to replay player network ev * stream support, console panel, close panels on X * fixing streaming, destroy on leave * fix autoplay * show notification on spot login * fix spot login * backup player added, fix audio issue * show thumbnail when no video, add spot roles * add poster thumbnail * some fixes to video check * fix events jump * fix play btn * try catch over pubkey * icons * spot login pinging * Spot List & Player Updates * move spot login flow to login comp, use separate spot login path for unique jwt * invalidate spot jwt on logout * add visual data on page load event * typo fix * Spot Listing improvements post review. * Update SpotListItem.tsx * Improved Spot List and Item Details * Minor improvements * More improvements * Public player header improvements * Moved formatExpirationTime to utils * fixes after merge --------- Co-authored-by: nick-delirium <nikita@openreplay.com> * set sso link to <a>? * some small perf fixes * login duck reformat... * Update frontend.yaml * add observer to spot list header * split list header * update spotjwt param in router * fix toast in router * fix async fetch, move ctx * capture space btn ev * fix header link * public sharing error msg * fix err msg for unsuccessful rec start * fix list alignment * Caching assets. Finally!!! * fix typing in comment field * add pubkey to comments, fix console jump btn * no content comp * change refresh token logic * move thumbnail ts * move thumbnail ts * fix tab change * switch up toggler * early exit if no jwt present * regenerate icons * fix location str * fix ctx * change thumnail res, return autoplay for video player * parse links in console rows, fix injected method parse? * remove ts from js * fix console parsing order? * fixes for autoplay * xray for spot player * move to spot list after login; esc to cancel; fix signup link; move ux commit * kb sc for skipping; xray for spot ext * track aborted requests * tooltip for readability * fixing empty state * New blank state + various minor improvements (#2471) * New blank state + various minor improvements * apres merge --------- Co-authored-by: nick-delirium <nikita@openreplay.com> * rm temp v * init or card * empty state debug * empty state debug * empty state debug * fix initor img * spotonly scope support * Improved Spot dead-end pages (#2475) * Improved Spot dead-end pages * Initiate OpenReplay Setup and some more * get scope changes * fix crash * scope upgrade/downgrade * scope setup flow * ping for backend * upgrade wxt deps * cancel ping int on expiration * check rec status * fix ping * check video processing state * check video processing state * fix xray close, network highlight, fcp rounding * update wxt, move open spot stuff to settings * fix some history issues * fix spot login flow * fix spot login again * fix spot login again * don't send two requests * limit messages for logged users * limit messages for logged users * fix public ignore * microphone stuff * microphone stuff * Various improvements (#2509) * Various improvements - Updated icons in mic settings - Included prefix in Spot title - Save recording notification has been updated - Other minor UI improvements * Inline declaration of spot name field, and settings UI * str f --------- Co-authored-by: nick-delirium <nikita@openreplay.com> * UI changes in player header, spot list (#2510) * Added UI elements in player page - Badge with counts for comments - Download and Delete dropdown in player - Spot selection -- UI improvement * Minor copy updates * completing changes --------- Co-authored-by: nick-delirium <nikita@openreplay.com> * rm cmt * fix cellmeasurer * thumbnail dur * fix download * Minor fixes (#2512) - Spot delete confirmation - Spot comments UI update - Minor copy updates * limit number of notif messages * add spot title to doc title, add cache groups for webpack * drop mic controls from recording popup view * fix for webpack compress * fix for auto mic pickup * change status banners * move svgs around, remove undefined check * refactor svgs * fix timetable scaling * fix error popup * self contain css * pre-select spot on spot onboarding --------- Co-authored-by: Sudheer Salavadi <connect.uxmaster@gmail.com> Co-authored-by: Rajesh Rajendran <rjshrjndrn@users.noreply.github.com>
285 lines
7.9 KiB
TypeScript
285 lines
7.9 KiB
TypeScript
import { Map } from 'immutable';
|
|
import React, { useEffect, useRef } from 'react';
|
|
import { ConnectedProps, connect } from 'react-redux';
|
|
import { RouteComponentProps, withRouter } from 'react-router-dom';
|
|
|
|
import IFrameRoutes from 'App/IFrameRoutes';
|
|
import PrivateRoutes from 'App/PrivateRoutes';
|
|
import PublicRoutes from 'App/PublicRoutes';
|
|
import {
|
|
GLOBAL_DESTINATION_PATH,
|
|
IFRAME,
|
|
JWT_PARAM, SPOT_ONBOARDING
|
|
} from "App/constants/storageKeys";
|
|
import Layout from 'App/layout/Layout';
|
|
import { withStore } from "App/mstore";
|
|
import { checkParam } from 'App/utils';
|
|
import { ModalProvider } from 'Components/Modal';
|
|
import { ModalProvider as NewModalProvider } from 'Components/ModalContext';
|
|
import { fetchListActive as fetchMetadata } from 'Duck/customField';
|
|
import { setSessionPath } from 'Duck/sessions';
|
|
import { fetchList as fetchSiteList } from 'Duck/site';
|
|
import { init as initSite } from 'Duck/site';
|
|
import { fetchUserInfo, setJwt } from 'Duck/user';
|
|
import { fetchTenants } from 'Duck/user';
|
|
import { Loader } from 'UI';
|
|
import { spotsList } from "./routes";
|
|
import * as routes from './routes';
|
|
import { toast } from 'react-toastify'
|
|
|
|
interface RouterProps
|
|
extends RouteComponentProps,
|
|
ConnectedProps<typeof connector> {
|
|
isLoggedIn: boolean;
|
|
sites: Map<string, any>;
|
|
loading: boolean;
|
|
changePassword: boolean;
|
|
isEnterprise: boolean;
|
|
fetchUserInfo: () => any;
|
|
fetchTenants: () => any;
|
|
setSessionPath: (path: any) => any;
|
|
fetchSiteList: (siteId?: number) => any;
|
|
match: {
|
|
params: {
|
|
siteId: string;
|
|
};
|
|
};
|
|
mstore: any;
|
|
setJwt: (params: { jwt: string, spotJwt: string | null }) => any;
|
|
fetchMetadata: (siteId: string) => void;
|
|
initSite: (site: any) => void;
|
|
scopeSetup: boolean;
|
|
localSpotJwt: string | null;
|
|
}
|
|
|
|
const Router: React.FC<RouterProps> = (props) => {
|
|
const {
|
|
isLoggedIn,
|
|
siteId,
|
|
sites,
|
|
loading,
|
|
location,
|
|
fetchUserInfo,
|
|
fetchSiteList,
|
|
history,
|
|
setSessionPath,
|
|
scopeSetup,
|
|
localSpotJwt,
|
|
} = props;
|
|
const params = new URLSearchParams(location.search)
|
|
const spotCb = params.get('spotCallback');
|
|
const spotReqSent = React.useRef(false)
|
|
const [isIframe, setIsIframe] = React.useState(false);
|
|
const [isJwt, setIsJwt] = React.useState(false);
|
|
const handleJwtFromUrl = () => {
|
|
const params = new URLSearchParams(location.search)
|
|
const urlJWT = params.get('jwt');
|
|
const spotJwt = params.get('spotJwt');
|
|
if (spotJwt) {
|
|
handleSpotLogin(spotJwt);
|
|
}
|
|
if (urlJWT) {
|
|
props.setJwt({ jwt: urlJWT, spotJwt: spotJwt ?? null });
|
|
}
|
|
};
|
|
|
|
const handleSpotLogin = (jwt: string) => {
|
|
if (spotReqSent.current) {
|
|
return;
|
|
} else {
|
|
spotReqSent.current = true;
|
|
}
|
|
let tries = 0;
|
|
if (!jwt) {
|
|
return;
|
|
}
|
|
let int: ReturnType<typeof setInterval>;
|
|
|
|
const onSpotMsg = (event: any) => {
|
|
if (event.data.type === 'orspot:logged') {
|
|
clearInterval(int);
|
|
window.removeEventListener('message', onSpotMsg);
|
|
}
|
|
};
|
|
window.addEventListener('message', onSpotMsg);
|
|
|
|
int = setInterval(() => {
|
|
if (tries > 20) {
|
|
clearInterval(int);
|
|
window.removeEventListener('message', onSpotMsg);
|
|
return;
|
|
}
|
|
window.postMessage(
|
|
{
|
|
type: 'orspot:token',
|
|
token: jwt,
|
|
},
|
|
'*'
|
|
);
|
|
tries += 1;
|
|
}, 250);
|
|
};
|
|
|
|
const handleDestinationPath = () => {
|
|
if (!isLoggedIn && location.pathname !== routes.login()) {
|
|
localStorage.setItem(
|
|
GLOBAL_DESTINATION_PATH,
|
|
location.pathname + location.search
|
|
);
|
|
}
|
|
};
|
|
|
|
const handleUserLogin = async () => {
|
|
await fetchUserInfo();
|
|
const siteIdFromPath = parseInt(location.pathname.split('/')[1]);
|
|
await fetchSiteList(siteIdFromPath);
|
|
props.mstore.initClient();
|
|
|
|
const destinationPath = localStorage.getItem(GLOBAL_DESTINATION_PATH);
|
|
if (
|
|
destinationPath &&
|
|
destinationPath !== routes.login() &&
|
|
destinationPath !== routes.signup() &&
|
|
destinationPath !== '/'
|
|
) {
|
|
const url = new URL(destinationPath, window.location.origin);
|
|
checkParams(url.search);
|
|
history.push(destinationPath);
|
|
localStorage.removeItem(GLOBAL_DESTINATION_PATH);
|
|
}
|
|
};
|
|
|
|
const checkParams = (search?: string) => {
|
|
const _isIframe = checkParam('iframe', IFRAME, search);
|
|
const _isJwt = checkParam('jwt', JWT_PARAM, search);
|
|
setIsIframe(_isIframe);
|
|
setIsJwt(_isJwt);
|
|
};
|
|
|
|
useEffect(() => {
|
|
checkParams();
|
|
handleJwtFromUrl();
|
|
}, []);
|
|
|
|
useEffect(() => {
|
|
// handleJwtFromUrl();
|
|
handleDestinationPath();
|
|
|
|
setSessionPath(previousLocation ? previousLocation : location);
|
|
}, [location]);
|
|
|
|
useEffect(() => {
|
|
if (prevIsLoggedIn !== isLoggedIn && isLoggedIn) {
|
|
handleUserLogin();
|
|
if (scopeSetup) {
|
|
history.push(routes.scopeSetup())
|
|
} else if (spotCb) {
|
|
history.push(spotsList())
|
|
localStorage.setItem(SPOT_ONBOARDING, 'true')
|
|
}
|
|
}
|
|
}, [isLoggedIn, scopeSetup]);
|
|
|
|
useEffect(() => {
|
|
if (isLoggedIn && location.pathname.includes('login') && localSpotJwt) {
|
|
handleSpotLogin(localSpotJwt);
|
|
}
|
|
}, [location, isLoggedIn, localSpotJwt])
|
|
|
|
useEffect(() => {
|
|
if (siteId && siteId !== lastFetchedSiteIdRef.current) {
|
|
const activeSite = sites.find((s) => s.id == siteId);
|
|
props.initSite(activeSite);
|
|
props.fetchMetadata(siteId);
|
|
lastFetchedSiteIdRef.current = siteId;
|
|
}
|
|
}, [siteId]);
|
|
|
|
const lastFetchedSiteIdRef = useRef<any>(null);
|
|
|
|
function usePrevious(value: any) {
|
|
const ref = useRef();
|
|
useEffect(() => {
|
|
ref.current = value;
|
|
}, [value]);
|
|
return ref.current;
|
|
}
|
|
|
|
const prevIsLoggedIn = usePrevious(isLoggedIn);
|
|
const previousLocation = usePrevious(location);
|
|
|
|
const hideHeader =
|
|
(location.pathname && location.pathname.includes('/session/')) ||
|
|
location.pathname.includes('/assist/') ||
|
|
location.pathname.includes('multiview') ||
|
|
location.pathname.includes('/view-spot/') ||
|
|
location.pathname.includes('/spots/') ||
|
|
location.pathname.includes('/scope-setup')
|
|
|
|
|
|
if (isIframe) {
|
|
return (
|
|
<IFrameRoutes isJwt={isJwt} isLoggedIn={isLoggedIn} loading={loading} />
|
|
);
|
|
}
|
|
|
|
return isLoggedIn ? (
|
|
<NewModalProvider>
|
|
<ModalProvider>
|
|
<Loader loading={loading} className="flex-1">
|
|
<Layout hideHeader={hideHeader} siteId={siteId}>
|
|
<PrivateRoutes />
|
|
</Layout>
|
|
</Loader>
|
|
</ModalProvider>
|
|
</NewModalProvider>
|
|
) : (
|
|
<PublicRoutes />
|
|
);
|
|
};
|
|
|
|
const mapStateToProps = (state: Map<string, any>) => {
|
|
const siteId = state.getIn(['site', 'siteId']);
|
|
const jwt = state.getIn(['user', 'jwt']);
|
|
const changePassword = state.getIn(['user', 'account', 'changePassword']);
|
|
const userInfoLoading = state.getIn([
|
|
'user',
|
|
'fetchUserInfoRequest',
|
|
'loading',
|
|
]);
|
|
const sitesLoading = state.getIn(['site', 'fetchListRequest', 'loading']);
|
|
const scopeSetup = state.getIn(['user', 'scopeSetup'])
|
|
const loading = Boolean(userInfoLoading) || Boolean(sitesLoading)
|
|
return {
|
|
siteId,
|
|
changePassword,
|
|
sites: state.getIn(['site', 'list']),
|
|
jwt,
|
|
localSpotJwt: state.getIn(['user', 'spotJwt']),
|
|
isLoggedIn: jwt !== null && !changePassword,
|
|
scopeSetup,
|
|
loading,
|
|
email: state.getIn(['user', 'account', 'email']),
|
|
account: state.getIn(['user', 'account']),
|
|
organisation: state.getIn(['user', 'account', 'name']),
|
|
tenantId: state.getIn(['user', 'account', 'tenantId']),
|
|
tenants: state.getIn(['user', 'tenants']),
|
|
isEnterprise:
|
|
state.getIn(['user', 'account', 'edition']) === 'ee' ||
|
|
state.getIn(['user', 'authDetails', 'edition']) === 'ee',
|
|
};
|
|
};
|
|
|
|
const mapDispatchToProps = {
|
|
fetchUserInfo,
|
|
fetchTenants,
|
|
setSessionPath,
|
|
fetchSiteList,
|
|
setJwt,
|
|
fetchMetadata,
|
|
initSite,
|
|
};
|
|
|
|
const connector = connect(mapStateToProps, mapDispatchToProps);
|
|
|
|
export default withStore(withRouter(connector(Router)));
|