Merge pull request #28 from amhsirak/develop
feat: list step field modification
This commit is contained in:
@@ -214,7 +214,7 @@ export const BrowserWindow = () => {
|
||||
const newField: TextStep = {
|
||||
id: Date.now(),
|
||||
type: 'text',
|
||||
label: `Label ${Object.keys(fields).length + 1}`,
|
||||
label: ``,
|
||||
data: data,
|
||||
selectorObj: {
|
||||
selector: highlighterData.selector,
|
||||
@@ -274,7 +274,7 @@ export const BrowserWindow = () => {
|
||||
const newField: TextStep = {
|
||||
id: Date.now(),
|
||||
type: 'text',
|
||||
label: `Label ${Object.keys(fields).length + 1}`,
|
||||
label: ``,
|
||||
data: data,
|
||||
selectorObj: {
|
||||
selector: selectedElement.selector,
|
||||
|
||||
@@ -19,29 +19,34 @@ import Radio from '@mui/material/Radio';
|
||||
import RadioGroup from '@mui/material/RadioGroup';
|
||||
|
||||
// TODO:
|
||||
// 1. Handle field label update
|
||||
// 2. Handle field deletion | confirmation
|
||||
// 3. Add description for each browser step
|
||||
// 4. Handle non custom action steps
|
||||
// 1. Add description for each browser step
|
||||
// 2. Handle non custom action steps
|
||||
interface RightSidePanelProps {
|
||||
onFinishCapture: () => void;
|
||||
}
|
||||
|
||||
export const RightSidePanel: React.FC<RightSidePanelProps> = ({ onFinishCapture }) => {
|
||||
const [textLabels, setTextLabels] = useState<{ [id: number]: string }>({});
|
||||
const [errors, setErrors] = useState<{ [id: number]: string }>({});
|
||||
const [confirmedTextSteps, setConfirmedTextSteps] = useState<{ [id: number]: boolean }>({});
|
||||
const [textLabels, setTextLabels] = useState<{ [id: string]: string }>({});
|
||||
const [errors, setErrors] = useState<{ [id: string]: string }>({});
|
||||
const [confirmedTextSteps, setConfirmedTextSteps] = useState<{ [id: string]: boolean }>({});
|
||||
const [confirmedListTextFields, setConfirmedListTextFields] = useState<{ [listId: string]: { [fieldKey: string]: boolean } }>({});
|
||||
const [showPaginationOptions, setShowPaginationOptions] = useState(false);
|
||||
const [showLimitOptions, setShowLimitOptions] = useState(false);
|
||||
const [captureStage, setCaptureStage] = useState<'initial' | 'pagination' | 'limit' | 'complete'>('initial');
|
||||
|
||||
const { lastAction, notify } = useGlobalInfoStore();
|
||||
const { getText, startGetText, stopGetText, getScreenshot, startGetScreenshot, stopGetScreenshot, paginationMode, getList, startGetList, stopGetList, startPaginationMode, stopPaginationMode, paginationType, updatePaginationType, limitMode, limitType, customLimit, updateLimitType, updateCustomLimit, stopLimitMode, startLimitMode } = useActionContext();
|
||||
const { browserSteps, updateBrowserTextStepLabel, deleteBrowserStep, addScreenshotStep } = useBrowserSteps();
|
||||
const { browserSteps, updateBrowserTextStepLabel, deleteBrowserStep, addScreenshotStep, updateListTextFieldLabel, removeListTextField } = useBrowserSteps();
|
||||
const { socket } = useSocketStore();
|
||||
|
||||
const handleTextLabelChange = (id: number, label: string) => {
|
||||
setTextLabels(prevLabels => ({ ...prevLabels, [id]: label }));
|
||||
const handleTextLabelChange = (id: number, label: string, listId?: number, fieldKey?: string) => {
|
||||
if (listId !== undefined && fieldKey !== undefined) {
|
||||
// This is a text field within a list step
|
||||
updateListTextFieldLabel(listId, fieldKey, label);
|
||||
} else {
|
||||
// This is a standalone text step
|
||||
setTextLabels(prevLabels => ({ ...prevLabels, [id]: label }));
|
||||
}
|
||||
if (!label.trim()) {
|
||||
setErrors(prevErrors => ({ ...prevErrors, [id]: 'Label cannot be empty' }));
|
||||
} else {
|
||||
@@ -71,6 +76,32 @@ export const RightSidePanel: React.FC<RightSidePanelProps> = ({ onFinishCapture
|
||||
});
|
||||
};
|
||||
|
||||
const handleListTextFieldConfirm = (listId: number, fieldKey: string) => {
|
||||
setConfirmedListTextFields(prev => ({
|
||||
...prev,
|
||||
[listId]: {
|
||||
...(prev[listId] || {}),
|
||||
[fieldKey]: true
|
||||
}
|
||||
}));
|
||||
};
|
||||
|
||||
const handleListTextFieldDiscard = (listId: number, fieldKey: string) => {
|
||||
removeListTextField(listId, fieldKey);
|
||||
setConfirmedListTextFields(prev => {
|
||||
const updatedListFields = { ...(prev[listId] || {}) };
|
||||
delete updatedListFields[fieldKey];
|
||||
return {
|
||||
...prev,
|
||||
[listId]: updatedListFields
|
||||
};
|
||||
});
|
||||
setErrors(prev => {
|
||||
const { [fieldKey]: _, ...rest } = prev;
|
||||
return rest;
|
||||
});
|
||||
};
|
||||
|
||||
const getTextSettingsObject = useCallback(() => {
|
||||
const settings: Record<string, { selector: string; tag?: string;[key: string]: any }> = {};
|
||||
browserSteps.forEach(step => {
|
||||
@@ -131,6 +162,7 @@ export const RightSidePanel: React.FC<RightSidePanelProps> = ({ onFinishCapture
|
||||
|
||||
return settings;
|
||||
}, [browserSteps, paginationType, limitType, customLimit]);
|
||||
|
||||
|
||||
const resetListState = useCallback(() => {
|
||||
setShowPaginationOptions(false);
|
||||
@@ -369,7 +401,7 @@ export const RightSidePanel: React.FC<RightSidePanelProps> = ({ onFinishCapture
|
||||
<TextField
|
||||
label="Field Label"
|
||||
value={field.label || ''}
|
||||
onChange={() => { }}
|
||||
onChange={(e) => handleTextLabelChange(field.id, e.target.value, step.id, key)}
|
||||
fullWidth
|
||||
margin="normal"
|
||||
InputProps={{
|
||||
@@ -394,6 +426,23 @@ export const RightSidePanel: React.FC<RightSidePanelProps> = ({ onFinishCapture
|
||||
)
|
||||
}}
|
||||
/>
|
||||
{!confirmedListTextFields[step.id]?.[key] && (
|
||||
<Box display="flex" justifyContent="space-between" gap={2}>
|
||||
<Button
|
||||
variant="contained"
|
||||
onClick={() => handleListTextFieldConfirm(step.id, key)}
|
||||
disabled={!field.label?.trim()}
|
||||
>
|
||||
Confirm
|
||||
</Button>
|
||||
<Button
|
||||
variant="contained"
|
||||
onClick={() => handleListTextFieldDiscard(step.id, key)}
|
||||
>
|
||||
Discard
|
||||
</Button>
|
||||
</Box>
|
||||
)}
|
||||
</Box>
|
||||
))}
|
||||
</>
|
||||
|
||||
@@ -42,12 +42,15 @@ interface BrowserStepsContextType {
|
||||
addScreenshotStep: (fullPage: boolean) => void;
|
||||
deleteBrowserStep: (id: number) => void;
|
||||
updateBrowserTextStepLabel: (id: number, newLabel: string) => void;
|
||||
updateListTextFieldLabel: (listId: number, fieldKey: string, newLabel: string) => void;
|
||||
removeListTextField: (listId: number, fieldKey: string) => void;
|
||||
}
|
||||
|
||||
const BrowserStepsContext = createContext<BrowserStepsContextType | undefined>(undefined);
|
||||
|
||||
export const BrowserStepsProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => {
|
||||
const [browserSteps, setBrowserSteps] = useState<BrowserStep[]>([]);
|
||||
const [discardedFields, setDiscardedFields] = useState<Set<string>>(new Set());
|
||||
|
||||
const addTextStep = (label: string, data: string, selectorObj: SelectorObject) => {
|
||||
setBrowserSteps(prevSteps => [
|
||||
@@ -62,12 +65,19 @@ export const BrowserStepsProvider: React.FC<{ children: React.ReactNode }> = ({
|
||||
step => step.type === 'list' && step.id === listId
|
||||
);
|
||||
if (existingListStepIndex !== -1) {
|
||||
// Update the existing ListStep with new fields
|
||||
// Update the existing ListStep with new fields, excluding discarded ones
|
||||
const updatedSteps = [...prevSteps];
|
||||
const existingListStep = updatedSteps[existingListStepIndex] as ListStep;
|
||||
const filteredNewFields = Object.entries(newFields).reduce((acc, [key, value]) => {
|
||||
if (!discardedFields.has(`${listId}-${key}`)) {
|
||||
acc[key] = value;
|
||||
}
|
||||
return acc;
|
||||
}, {} as { [key: string]: TextStep });
|
||||
|
||||
updatedSteps[existingListStepIndex] = {
|
||||
...existingListStep,
|
||||
fields: { ...existingListStep.fields, ...newFields },
|
||||
fields: { ...existingListStep.fields, ...filteredNewFields },
|
||||
pagination: pagination,
|
||||
limit: limit,
|
||||
};
|
||||
@@ -81,7 +91,6 @@ export const BrowserStepsProvider: React.FC<{ children: React.ReactNode }> = ({
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const addScreenshotStep = (fullPage: boolean) => {
|
||||
setBrowserSteps(prevSteps => [
|
||||
...prevSteps,
|
||||
@@ -101,6 +110,41 @@ export const BrowserStepsProvider: React.FC<{ children: React.ReactNode }> = ({
|
||||
);
|
||||
};
|
||||
|
||||
const updateListTextFieldLabel = (listId: number, fieldKey: string, newLabel: string) => {
|
||||
setBrowserSteps(prevSteps =>
|
||||
prevSteps.map(step => {
|
||||
if (step.type === 'list' && step.id === listId) {
|
||||
return {
|
||||
...step,
|
||||
fields: {
|
||||
...step.fields,
|
||||
[fieldKey]: {
|
||||
...step.fields[fieldKey],
|
||||
label: newLabel
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
return step;
|
||||
})
|
||||
);
|
||||
};
|
||||
|
||||
const removeListTextField = (listId: number, fieldKey: string) => {
|
||||
setBrowserSteps(prevSteps =>
|
||||
prevSteps.map(step => {
|
||||
if (step.type === 'list' && step.id === listId) {
|
||||
const { [fieldKey]: _, ...remainingFields } = step.fields;
|
||||
return {
|
||||
...step,
|
||||
fields: remainingFields
|
||||
};
|
||||
}
|
||||
return step;
|
||||
})
|
||||
);
|
||||
setDiscardedFields(prevDiscarded => new Set(prevDiscarded).add(`${listId}-${fieldKey}`));
|
||||
};
|
||||
return (
|
||||
<BrowserStepsContext.Provider value={{
|
||||
browserSteps,
|
||||
@@ -109,6 +153,8 @@ export const BrowserStepsProvider: React.FC<{ children: React.ReactNode }> = ({
|
||||
addScreenshotStep,
|
||||
deleteBrowserStep,
|
||||
updateBrowserTextStepLabel,
|
||||
updateListTextFieldLabel,
|
||||
removeListTextField,
|
||||
}}>
|
||||
{children}
|
||||
</BrowserStepsContext.Provider>
|
||||
|
||||
Reference in New Issue
Block a user