Merge pull request #16 from amhsirak/develop
feat: global context & constants
This commit is contained in:
15
src/App.tsx
Normal file
15
src/App.tsx
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
import { GlobalInfoProvider } from "./context/globalInfo";
|
||||||
|
import { PageWrapper } from "./pages/PageWrappper";
|
||||||
|
|
||||||
|
function App() {
|
||||||
|
|
||||||
|
return (
|
||||||
|
<GlobalInfoProvider>
|
||||||
|
<PageWrapper />
|
||||||
|
</GlobalInfoProvider>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default App;
|
||||||
@@ -36,8 +36,6 @@ export const Highlighter = ({ unmodifiedRect, displayedSelector = '', width, hei
|
|||||||
height: unmodifiedRect.height,
|
height: unmodifiedRect.height,
|
||||||
};
|
};
|
||||||
|
|
||||||
const adjustedWidth = Math.min(rect.width, width - rect.left); // Adjust width if it extends beyond canvas boundary
|
|
||||||
const adjustedHeight = Math.min(rect.height, height - rect.top); // Adjust height if it extends beyond canvas boundary
|
|
||||||
|
|
||||||
console.log('unmodifiedRect:', unmodifiedRect)
|
console.log('unmodifiedRect:', unmodifiedRect)
|
||||||
console.log('rectangle:', rect)
|
console.log('rectangle:', rect)
|
||||||
|
|||||||
5
src/constants/const.ts
Normal file
5
src/constants/const.ts
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
export const VIEWPORT_W = 1280;
|
||||||
|
export const VIEWPORT_H = 720;
|
||||||
|
|
||||||
|
export const ONE_PERCENT_OF_VIEWPORT_W = VIEWPORT_W / 100;
|
||||||
|
export const ONE_PERCENT_OF_VIEWPORT_H = VIEWPORT_H / 100;
|
||||||
83
src/context/globalInfo.tsx
Normal file
83
src/context/globalInfo.tsx
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
import React, { createContext, useContext, useState } from "react";
|
||||||
|
import { AlertSnackbarProps } from "../components/atoms/AlertSnackbar";
|
||||||
|
|
||||||
|
|
||||||
|
interface GlobalInfo {
|
||||||
|
browserId: string | null;
|
||||||
|
setBrowserId: (newId: string | null) => void;
|
||||||
|
lastAction: string;
|
||||||
|
setLastAction: (action: string) => void;
|
||||||
|
notification: AlertSnackbarProps;
|
||||||
|
notify: (severity: 'error' | 'warning' | 'info' | 'success', message: string) => void;
|
||||||
|
closeNotify: () => void;
|
||||||
|
recordings: string[];
|
||||||
|
setRecordings: (recordings: string[]) => void;
|
||||||
|
rerenderRuns: boolean;
|
||||||
|
setRerenderRuns: (rerenderRuns: boolean) => void;
|
||||||
|
recordingLength: number;
|
||||||
|
setRecordingLength: (recordingLength: number) => void;
|
||||||
|
};
|
||||||
|
|
||||||
|
class GlobalInfoStore implements Partial<GlobalInfo> {
|
||||||
|
browserId = null;
|
||||||
|
lastAction = '';
|
||||||
|
recordingLength = 0;
|
||||||
|
notification: AlertSnackbarProps = {
|
||||||
|
severity: 'info',
|
||||||
|
message: '',
|
||||||
|
isOpen: false,
|
||||||
|
};
|
||||||
|
recordings: string[] = [];
|
||||||
|
rerenderRuns = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
const globalInfoStore = new GlobalInfoStore();
|
||||||
|
const globalInfoContext = createContext<GlobalInfo>(globalInfoStore as GlobalInfo);
|
||||||
|
|
||||||
|
export const useGlobalInfoStore = () => useContext(globalInfoContext);
|
||||||
|
|
||||||
|
export const GlobalInfoProvider = ({ children }: { children: JSX.Element }) => {
|
||||||
|
const [browserId, setBrowserId] = useState<string | null>(globalInfoStore.browserId);
|
||||||
|
const [lastAction, setLastAction] = useState<string>(globalInfoStore.lastAction);
|
||||||
|
const [notification, setNotification] = useState<AlertSnackbarProps>(globalInfoStore.notification);
|
||||||
|
const [recordings, setRecordings] = useState<string[]>(globalInfoStore.recordings);
|
||||||
|
const [rerenderRuns, setRerenderRuns] = useState<boolean>(globalInfoStore.rerenderRuns);
|
||||||
|
const [recordingLength, setRecordingLength] = useState<number>(globalInfoStore.recordingLength);
|
||||||
|
|
||||||
|
const notify = (severity: 'error' | 'warning' | 'info' | 'success', message: string) => {
|
||||||
|
setNotification({ severity, message, isOpen: true });
|
||||||
|
}
|
||||||
|
|
||||||
|
const closeNotify = () => {
|
||||||
|
setNotification(globalInfoStore.notification);
|
||||||
|
}
|
||||||
|
|
||||||
|
const setBrowserIdWithValidation = (browserId: string | null) => {
|
||||||
|
setBrowserId(browserId);
|
||||||
|
if (!browserId) {
|
||||||
|
setRecordingLength(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<globalInfoContext.Provider
|
||||||
|
value={{
|
||||||
|
browserId,
|
||||||
|
setBrowserId: setBrowserIdWithValidation,
|
||||||
|
lastAction,
|
||||||
|
setLastAction,
|
||||||
|
notification,
|
||||||
|
notify,
|
||||||
|
closeNotify,
|
||||||
|
recordings,
|
||||||
|
setRecordings,
|
||||||
|
rerenderRuns,
|
||||||
|
setRerenderRuns,
|
||||||
|
recordingLength,
|
||||||
|
setRecordingLength,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</globalInfoContext.Provider>
|
||||||
|
);
|
||||||
|
};
|
||||||
52
src/context/socket.tsx
Normal file
52
src/context/socket.tsx
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
import React, { createContext, useCallback, useContext, useMemo, useState } from 'react';
|
||||||
|
import { io, Socket } from 'socket.io-client';
|
||||||
|
|
||||||
|
const SERVER_ENDPOINT = 'http://localhost:8080';
|
||||||
|
|
||||||
|
interface SocketState {
|
||||||
|
socket: Socket | null;
|
||||||
|
id: string;
|
||||||
|
setId: (id: string) => void;
|
||||||
|
};
|
||||||
|
|
||||||
|
class SocketStore implements Partial<SocketState> {
|
||||||
|
socket = null;
|
||||||
|
id = '';
|
||||||
|
};
|
||||||
|
|
||||||
|
const socketStore = new SocketStore();
|
||||||
|
const socketStoreContext = createContext<SocketState>(socketStore as SocketState);
|
||||||
|
|
||||||
|
export const useSocketStore = () => useContext(socketStoreContext);
|
||||||
|
|
||||||
|
export const SocketProvider = ({ children }: { children: JSX.Element }) => {
|
||||||
|
const [socket, setSocket] = useState<Socket | null>(socketStore.socket);
|
||||||
|
const [id, setActiveId] = useState<string>(socketStore.id);
|
||||||
|
|
||||||
|
const setId = useCallback((id: string) => {
|
||||||
|
// the socket client connection is recomputed whenever id changes -> the new browser has been initialized
|
||||||
|
const socket =
|
||||||
|
io(`${SERVER_ENDPOINT}/${id}`, {
|
||||||
|
transports: ["websocket"],
|
||||||
|
rejectUnauthorized: false
|
||||||
|
});
|
||||||
|
|
||||||
|
socket.on('connect', () => console.log('connected to socket'));
|
||||||
|
socket.on("connect_error", (err) => console.log(`connect_error due to ${err.message}`));
|
||||||
|
|
||||||
|
setSocket(socket);
|
||||||
|
setActiveId(id);
|
||||||
|
}, [setSocket]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<socketStoreContext.Provider
|
||||||
|
value={{
|
||||||
|
socket,
|
||||||
|
id,
|
||||||
|
setId,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</socketStoreContext.Provider>
|
||||||
|
);
|
||||||
|
};
|
||||||
17
src/index.css
Normal file
17
src/index.css
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
|
||||||
|
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
|
||||||
|
sans-serif;
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
|
-moz-osx-font-smoothing: grayscale;
|
||||||
|
}
|
||||||
|
|
||||||
|
code {
|
||||||
|
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
|
||||||
|
monospace;
|
||||||
|
}
|
||||||
|
|
||||||
|
html {
|
||||||
|
overflow-y:scroll;
|
||||||
|
}
|
||||||
14
src/index.tsx
Normal file
14
src/index.tsx
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import ReactDOM from 'react-dom/client';
|
||||||
|
import './index.css';
|
||||||
|
import App from './App';
|
||||||
|
|
||||||
|
const root = ReactDOM.createRoot(
|
||||||
|
document.getElementById('root') as HTMLElement
|
||||||
|
);
|
||||||
|
root.render(
|
||||||
|
<React.StrictMode>
|
||||||
|
<App />
|
||||||
|
</React.StrictMode>
|
||||||
|
);
|
||||||
|
|
||||||
3
src/shared/constants.ts
Normal file
3
src/shared/constants.ts
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
import { WorkflowFile } from "@wbr-project/wbr-interpret";
|
||||||
|
|
||||||
|
export const emptyWorkflow: WorkflowFile = { workflow: [] };
|
||||||
26
src/shared/types.ts
Normal file
26
src/shared/types.ts
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
import { WorkflowFile } from "@wbr-project/wbr-interpret";
|
||||||
|
import { Locator } from "playwright";
|
||||||
|
|
||||||
|
export type Workflow = WorkflowFile["workflow"];
|
||||||
|
|
||||||
|
export interface ScreenshotSettings {
|
||||||
|
animations?: "disabled" | "allow";
|
||||||
|
caret?: "hide" | "initial";
|
||||||
|
clip?: {
|
||||||
|
x: number;
|
||||||
|
y: number;
|
||||||
|
width: number;
|
||||||
|
height: number;
|
||||||
|
};
|
||||||
|
fullPage?: boolean;
|
||||||
|
mask?: Locator[];
|
||||||
|
omitBackground?: boolean;
|
||||||
|
// is this still needed? - @wbr-project/wbr-interpret outputs to a binary output
|
||||||
|
path?: string;
|
||||||
|
quality?: number;
|
||||||
|
scale?: "css" | "device";
|
||||||
|
timeout?: number;
|
||||||
|
type?: "jpeg" | "png";
|
||||||
|
};
|
||||||
|
|
||||||
|
export declare type CustomActions = 'scrape' | 'scrapeSchema' | 'scroll' | 'screenshot' | 'script' | 'enqueueLinks' | 'flag';
|
||||||
Reference in New Issue
Block a user