Merge branch 'develop' into persist-fix

This commit is contained in:
Rohit
2025-11-20 21:08:22 +05:30
committed by GitHub
4 changed files with 45 additions and 33 deletions

View File

@@ -11,6 +11,7 @@
<p align="center"> <p align="center">
Maxun lets you train a robot in 2 minutes and scrape the web on auto-pilot. Web data extraction doesn't get easier than this! Maxun lets you train a robot in 2 minutes and scrape the web on auto-pilot. Web data extraction doesn't get easier than this!
<br /> Maxun is the open-source alternative to BrowseAI, Octoparse and likes.
</p> </p>

View File

@@ -1187,7 +1187,7 @@ export default class Interpreter extends EventEmitter {
}).catch(e => { }).catch(e => {
throw e; throw e;
}), }),
button.click() page.locator(workingSelector).first().click()
]); ]);
debugLog("Navigation successful after regular click"); debugLog("Navigation successful after regular click");
await page.waitForTimeout(2000); await page.waitForTimeout(2000);
@@ -1202,17 +1202,17 @@ export default class Interpreter extends EventEmitter {
}).catch(e => { }).catch(e => {
throw e; throw e;
}), }),
button.dispatchEvent('click') page.locator(workingSelector).first().dispatchEvent('click')
]); ]);
debugLog("Navigation successful after dispatch event"); debugLog("Navigation successful after dispatch event");
await page.waitForTimeout(2000); await page.waitForTimeout(2000);
paginationSuccess = true; paginationSuccess = true;
} catch (dispatchNavError) { } catch (dispatchNavError) {
try { try {
await button.click(); await page.locator(workingSelector).first().click();
await page.waitForTimeout(2000); await page.waitForTimeout(2000);
} catch (clickError) { } catch (clickError) {
await button.dispatchEvent('click'); await page.locator(workingSelector).first().dispatchEvent('click');
await page.waitForTimeout(2000); await page.waitForTimeout(2000);
} }
} }

View File

@@ -550,22 +550,17 @@ export class WorkflowInterpreter {
}, },
serializableCallback: async (data: any) => { serializableCallback: async (data: any) => {
try { try {
if (!data || typeof data !== "object") return; if (!this.currentActionType || !this.currentActionName) return;
if (!this.currentActionType && Array.isArray(data) && data.length > 0) { let typeKey = this.currentActionType;
const first = data[0]; let actionName = this.currentActionName;
if (first && Object.keys(first).some(k => k.toLowerCase().includes("label") || k.toLowerCase().includes("text"))) {
this.currentActionType = "scrapeSchema";
}
}
let typeKey = this.currentActionType || "unknown"; let subtree =
typeKey === "scrapeList"
if (this.currentActionType === "scrapeList") { ? data?.scrapeList
typeKey = "scrapeList"; : typeKey === "scrapeSchema"
} else if (this.currentActionType === "scrapeSchema") { ? data?.scrapeSchema
typeKey = "scrapeSchema"; : null;
}
if (typeKey === "scrapeList" && data.scrapeList) { if (typeKey === "scrapeList" && data.scrapeList) {
data = data.scrapeList; data = data.scrapeList;
@@ -617,7 +612,7 @@ export class WorkflowInterpreter {
data: flattened, data: flattened,
}); });
} catch (err: any) { } catch (err: any) {
logger.log('error', `serializableCallback handler failed: ${err.message}`); logger.log("error", `serializableCallback failed: ${err.message}`);
} }
}, },
binaryCallback: async (payload: { name: string; data: Buffer; mimeType: string }) => { binaryCallback: async (payload: { name: string; data: Buffer; mimeType: string }) => {

View File

@@ -152,20 +152,36 @@ export const RobotSettingsPage = ({ handleStart }: RobotSettingsProps) => {
}} }}
style={{ marginBottom: "20px" }} style={{ marginBottom: "20px" }}
/> />
{robot.recording.workflow?.[0]?.what?.[0]?.args?.[0]?.limit !== {(() => {
undefined && ( let listCounter = 1;
<TextField
label={t("robot_settings.robot_limit")} return robot.recording.workflow.flatMap((wf, wfIndex) =>
type="number" wf.what.flatMap((action, actionIndex) => {
value={ const argsWithLimit = action.args?.filter(
robot.recording.workflow[0].what[0].args[0].limit || "" (arg: any) => arg && typeof arg === "object" && arg.limit !== undefined
} );
InputProps={{
readOnly: true, if (!argsWithLimit?.length) return [];
}}
style={{ marginBottom: "20px" }} return argsWithLimit.map((arg, limitIndex) => {
/> const labelName = action.name || `List ${listCounter++}`;
)} return (
<TextField
key={`limit-${wfIndex}-${actionIndex}-${limitIndex}`}
label={`${t("robot_settings.robot_limit")} (${labelName})`}
type="number"
value={arg.limit || ""}
InputProps={{
readOnly: true,
}}
style={{ marginBottom: "20px" }}
/>
);
});
})
);
})()}
<TextField <TextField
label={t("robot_settings.created_by_user")} label={t("robot_settings.created_by_user")}
key="Created By User" key="Created By User"