diff --git a/src/components/molecules/ActionSettings.tsx b/src/components/molecules/ActionSettings.tsx
new file mode 100644
index 00000000..816c3e76
--- /dev/null
+++ b/src/components/molecules/ActionSettings.tsx
@@ -0,0 +1,79 @@
+import React, { useRef } from 'react';
+import styled from "styled-components";
+import { Button } from "@mui/material";
+import { ActionDescription } from "../organisms/RightSidePanel";
+import * as Settings from "./action-settings";
+import { useSocketStore } from "../../context/socket";
+
+interface ActionSettingsProps {
+ action: string;
+}
+
+export const ActionSettings = ({ action }: ActionSettingsProps) => {
+
+ const settingsRef = useRef<{ getSettings: () => object }>(null);
+ const { socket } = useSocketStore();
+
+ const DisplaySettings = () => {
+ switch (action) {
+ case "screenshot":
+ return ;
+ case 'scroll':
+ return ;
+ case 'scrape':
+ return ;
+ case 'scrapeSchema':
+ return ;
+ case 'script':
+ return ;
+ case 'enqueueLinks':
+ return ;
+ case 'mouse.click':
+ return ;
+ default:
+ return null;
+ }
+ }
+
+ const handleSubmit = (event: React.SyntheticEvent) => {
+ event.preventDefault();
+ //get the data from settings
+ const settings = settingsRef.current?.getSettings();
+ //Send notification to the server and generate the pair
+ socket?.emit(`action`, {
+ action,
+ settings
+ });
+ }
+
+ return (
+
+
Action settings:
+
+
+
+
+ );
+};
+
+const ActionSettingsWrapper = styled.div<{ action: string }>`
+ display: flex;
+ flex-direction: column;
+ align-items: ${({ action }) => action === 'script' ? 'stretch' : 'center'};;
+ justify-content: center;
+ margin-top: 20px;
+`;
diff --git a/src/components/molecules/action-settings/clickOnCoordinates.tsx b/src/components/molecules/action-settings/clickOnCoordinates.tsx
new file mode 100644
index 00000000..c68a53b0
--- /dev/null
+++ b/src/components/molecules/action-settings/clickOnCoordinates.tsx
@@ -0,0 +1,39 @@
+import React, { forwardRef, useImperativeHandle } from 'react';
+import { Stack, TextField } from "@mui/material";
+import { WarningText } from '../../atoms/texts';
+import InfoIcon from "@mui/icons-material/Info";
+
+export const ClickOnCoordinatesSettings = forwardRef((props, ref) => {
+ const [settings, setSettings] = React.useState([0, 0]);
+ useImperativeHandle(ref, () => ({
+ getSettings() {
+ return settings;
+ }
+ }));
+
+ return (
+
+ setSettings(prevState => ([Number(e.target.value), prevState[1]]))}
+ required
+ defaultValue={settings[0]}
+ />
+ setSettings(prevState => ([prevState[0], Number(e.target.value)]))}
+ required
+ defaultValue={settings[1]}
+ />
+
+
+ The click function will click on the given coordinates.
+ You need to put the coordinates by yourself.
+
+
+ );
+});
diff --git a/src/components/molecules/action-settings/enqueueLinks.tsx b/src/components/molecules/action-settings/enqueueLinks.tsx
new file mode 100644
index 00000000..2c383d47
--- /dev/null
+++ b/src/components/molecules/action-settings/enqueueLinks.tsx
@@ -0,0 +1,32 @@
+import React, { forwardRef, useImperativeHandle } from 'react';
+import { Stack, TextField } from "@mui/material";
+import { WarningText } from "../../atoms/texts";
+import WarningIcon from "@mui/icons-material/Warning";
+import InfoIcon from "@mui/icons-material/Info";
+
+export const EnqueueLinksSettings = forwardRef((props, ref) => {
+ const [settings, setSettings] = React.useState('');
+ useImperativeHandle(ref, () => ({
+ getSettings() {
+ return settings;
+ }
+ }));
+
+ return (
+
+ setSettings(e.target.value)}
+ />
+
+
+ Reads elements targeted by the selector and stores their links in a queue.
+ Those pages are then processed using the same workflow as the initial page
+ (in parallel if the maxConcurrency parameter is greater than 1).
+
+
+ );
+});
diff --git a/src/components/molecules/action-settings/index.ts b/src/components/molecules/action-settings/index.ts
new file mode 100644
index 00000000..32906db7
--- /dev/null
+++ b/src/components/molecules/action-settings/index.ts
@@ -0,0 +1,17 @@
+import { ScrollSettings } from './scroll';
+import { ScreenshotSettings } from "./screenshot";
+import { ScrapeSettings } from "./scrape";
+import { ScrapeSchemaSettings } from "./scrapeSchema";
+import { ScriptSettings } from "./script";
+import { EnqueueLinksSettings } from "./enqueueLinks";
+import { ClickOnCoordinatesSettings } from "./clickOnCoordinates";
+
+export {
+ ScrollSettings,
+ ScreenshotSettings,
+ ScrapeSettings,
+ ScrapeSchemaSettings,
+ ScriptSettings,
+ EnqueueLinksSettings,
+ ClickOnCoordinatesSettings,
+};
diff --git a/src/components/molecules/action-settings/scrape.tsx b/src/components/molecules/action-settings/scrape.tsx
new file mode 100644
index 00000000..80608b1e
--- /dev/null
+++ b/src/components/molecules/action-settings/scrape.tsx
@@ -0,0 +1,30 @@
+import React, { forwardRef, useImperativeHandle } from 'react';
+import { Stack, TextField } from "@mui/material";
+import { WarningText } from '../../atoms/texts';
+import InfoIcon from "@mui/icons-material/Info";
+
+export const ScrapeSettings = forwardRef((props, ref) => {
+ const [settings, setSettings] = React.useState('');
+ useImperativeHandle(ref, () => ({
+ getSettings() {
+ return settings;
+ }
+ }));
+
+ return (
+
+ setSettings(e.target.value)}
+ />
+
+
+ The scrape function uses heuristic algorithm to automatically scrape only important data from the page.
+ If a selector is used it will scrape and automatically parse all available
+ data inside of the selected element(s).
+
+
+ );
+});
diff --git a/src/components/molecules/action-settings/scrapeSchema.tsx b/src/components/molecules/action-settings/scrapeSchema.tsx
new file mode 100644
index 00000000..3f60c787
--- /dev/null
+++ b/src/components/molecules/action-settings/scrapeSchema.tsx
@@ -0,0 +1,25 @@
+import React, { forwardRef, useCallback, useImperativeHandle, useRef } from 'react';
+import { WarningText } from "../../atoms/texts";
+import InfoIcon from "@mui/icons-material/Info";
+import { KeyValueForm } from "../KeyValueForm";
+
+export const ScrapeSchemaSettings = forwardRef((props, ref) => {
+ const keyValueFormRef = useRef<{ getObject: () => object }>(null);
+
+ useImperativeHandle(ref, () => ({
+ getSettings() {
+ const settings = keyValueFormRef.current?.getObject() as Record
+ return settings;
+ }
+ }));
+
+ return (
+
+
+
+ The interpreter scrapes the data from a webpage into a "curated" table.
+
+
+
+ );
+});
diff --git a/src/components/molecules/action-settings/screenshot.tsx b/src/components/molecules/action-settings/screenshot.tsx
new file mode 100644
index 00000000..8e412afa
--- /dev/null
+++ b/src/components/molecules/action-settings/screenshot.tsx
@@ -0,0 +1,126 @@
+import React, { forwardRef, useImperativeHandle } from 'react';
+import { InputLabel, MenuItem, TextField, Select, FormControl } from "@mui/material";
+import { ScreenshotSettings as Settings } from "../../../shared/types";
+import styled from "styled-components";
+import { SelectChangeEvent } from "@mui/material/Select/Select";
+import { Dropdown } from "../../atoms/DropdownMui";
+
+export const ScreenshotSettings = forwardRef((props, ref) => {
+ const [settings, setSettings] = React.useState({});
+ useImperativeHandle(ref, () => ({
+ getSettings() {
+ return settings;
+ }
+ }));
+
+ const handleInput = (event: React.ChangeEvent) => {
+ const { id, value, type } = event.target;
+ let parsedValue: any = value;
+ if (type === "number") {
+ parsedValue = parseInt(value);
+ };
+ setSettings({
+ ...settings,
+ [id]: parsedValue,
+ });
+ };
+
+ const handleSelect = (event: SelectChangeEvent) => {
+ const { name, value } = event.target;
+ let parsedValue: any = value;
+ if (value === "true" || value === "false") {
+ parsedValue = value === "true";
+ };
+ setSettings({
+ ...settings,
+ [name]: parsedValue,
+ });
+ };
+
+ return (
+
+
+
+
+
+ {settings.type === "jpeg" ?
+ : null
+ }
+
+
+
+
+
+ {settings.type === "png" ?
+
+
+
+
+ : null
+ }
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+});
+
+const SettingsWrapper = styled.div`
+ margin-left: 15px;
+ * {
+ margin-bottom: 10px;
+ }
+`;
diff --git a/src/components/molecules/action-settings/script.tsx b/src/components/molecules/action-settings/script.tsx
new file mode 100644
index 00000000..2cece263
--- /dev/null
+++ b/src/components/molecules/action-settings/script.tsx
@@ -0,0 +1,63 @@
+import React, { forwardRef, useImperativeHandle } from 'react';
+import Editor from 'react-simple-code-editor';
+// @ts-ignore
+import { highlight, languages } from 'prismjs/components/prism-core';
+import 'prismjs/components/prism-clike';
+import 'prismjs/components/prism-javascript';
+import 'prismjs/themes/prism.css';
+import styled from "styled-components";
+import InfoIcon from '@mui/icons-material/Info';
+import { WarningText } from "../../atoms/texts";
+
+export const ScriptSettings = forwardRef((props, ref) => {
+ const [code, setCode] = React.useState('');
+
+ useImperativeHandle(ref, () => ({
+ getSettings() {
+ return code;
+ }
+ }));
+
+ return (
+
+
+
+ Allows to run an arbitrary asynchronous function evaluated at the server
+ side accepting the current page instance argument.
+
+ setCode(code)}
+ highlight={code => highlight(code, languages.js)}
+ padding={10}
+ style={{
+ fontFamily: '"Fira code", "Fira Mono", monospace',
+ fontSize: 12,
+ background: '#f0f0f0',
+ }}
+ />
+
+ );
+});
+
+const EditorWrapper = styled.div`
+ flex: 1;
+ overflow: auto;
+ /** hard-coded height */
+ height: 100%;
+ width: 100%;
+`;
+
+const StyledEditor = styled(Editor)`
+ white-space: pre;
+ caret-color: #fff;
+ min-width: 100%;
+ min-height: 100%;
+ float: left;
+ & > textarea,
+ & > pre {
+ outline: none;
+ white-space: pre !important;
+ }
+`;
diff --git a/src/components/molecules/action-settings/scroll.tsx b/src/components/molecules/action-settings/scroll.tsx
new file mode 100644
index 00000000..2e5743af
--- /dev/null
+++ b/src/components/molecules/action-settings/scroll.tsx
@@ -0,0 +1,21 @@
+import React, { forwardRef, useImperativeHandle } from 'react';
+import { TextField } from "@mui/material";
+
+export const ScrollSettings = forwardRef((props, ref) => {
+ const [settings, setSettings] = React.useState(0);
+ useImperativeHandle(ref, () => ({
+ getSettings() {
+ return settings;
+ }
+ }));
+
+ return (
+ setSettings(parseInt(e.target.value))}
+ />
+ );
+});