Merge pull request #28 from amhsirak/develop

feat: list step field modification
This commit is contained in:
Karishma Shukla
2024-09-14 02:26:36 +05:30
committed by GitHub
3 changed files with 111 additions and 16 deletions

View File

@@ -214,7 +214,7 @@ export const BrowserWindow = () => {
const newField: TextStep = { const newField: TextStep = {
id: Date.now(), id: Date.now(),
type: 'text', type: 'text',
label: `Label ${Object.keys(fields).length + 1}`, label: ``,
data: data, data: data,
selectorObj: { selectorObj: {
selector: highlighterData.selector, selector: highlighterData.selector,
@@ -274,7 +274,7 @@ export const BrowserWindow = () => {
const newField: TextStep = { const newField: TextStep = {
id: Date.now(), id: Date.now(),
type: 'text', type: 'text',
label: `Label ${Object.keys(fields).length + 1}`, label: ``,
data: data, data: data,
selectorObj: { selectorObj: {
selector: selectedElement.selector, selector: selectedElement.selector,

View File

@@ -19,29 +19,34 @@ import Radio from '@mui/material/Radio';
import RadioGroup from '@mui/material/RadioGroup'; import RadioGroup from '@mui/material/RadioGroup';
// TODO: // TODO:
// 1. Handle field label update // 1. Add description for each browser step
// 2. Handle field deletion | confirmation // 2. Handle non custom action steps
// 3. Add description for each browser step
// 4. Handle non custom action steps
interface RightSidePanelProps { interface RightSidePanelProps {
onFinishCapture: () => void; onFinishCapture: () => void;
} }
export const RightSidePanel: React.FC<RightSidePanelProps> = ({ onFinishCapture }) => { export const RightSidePanel: React.FC<RightSidePanelProps> = ({ onFinishCapture }) => {
const [textLabels, setTextLabels] = useState<{ [id: number]: string }>({}); const [textLabels, setTextLabels] = useState<{ [id: string]: string }>({});
const [errors, setErrors] = useState<{ [id: number]: string }>({}); const [errors, setErrors] = useState<{ [id: string]: string }>({});
const [confirmedTextSteps, setConfirmedTextSteps] = useState<{ [id: number]: boolean }>({}); const [confirmedTextSteps, setConfirmedTextSteps] = useState<{ [id: string]: boolean }>({});
const [confirmedListTextFields, setConfirmedListTextFields] = useState<{ [listId: string]: { [fieldKey: string]: boolean } }>({});
const [showPaginationOptions, setShowPaginationOptions] = useState(false); const [showPaginationOptions, setShowPaginationOptions] = useState(false);
const [showLimitOptions, setShowLimitOptions] = useState(false); const [showLimitOptions, setShowLimitOptions] = useState(false);
const [captureStage, setCaptureStage] = useState<'initial' | 'pagination' | 'limit' | 'complete'>('initial'); const [captureStage, setCaptureStage] = useState<'initial' | 'pagination' | 'limit' | 'complete'>('initial');
const { lastAction, notify } = useGlobalInfoStore(); 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 { 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 { socket } = useSocketStore();
const handleTextLabelChange = (id: number, label: string) => { const handleTextLabelChange = (id: number, label: string, listId?: number, fieldKey?: string) => {
setTextLabels(prevLabels => ({ ...prevLabels, [id]: label })); 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()) { if (!label.trim()) {
setErrors(prevErrors => ({ ...prevErrors, [id]: 'Label cannot be empty' })); setErrors(prevErrors => ({ ...prevErrors, [id]: 'Label cannot be empty' }));
} else { } 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 getTextSettingsObject = useCallback(() => {
const settings: Record<string, { selector: string; tag?: string;[key: string]: any }> = {}; const settings: Record<string, { selector: string; tag?: string;[key: string]: any }> = {};
browserSteps.forEach(step => { browserSteps.forEach(step => {
@@ -131,6 +162,7 @@ export const RightSidePanel: React.FC<RightSidePanelProps> = ({ onFinishCapture
return settings; return settings;
}, [browserSteps, paginationType, limitType, customLimit]); }, [browserSteps, paginationType, limitType, customLimit]);
const resetListState = useCallback(() => { const resetListState = useCallback(() => {
setShowPaginationOptions(false); setShowPaginationOptions(false);
@@ -369,7 +401,7 @@ export const RightSidePanel: React.FC<RightSidePanelProps> = ({ onFinishCapture
<TextField <TextField
label="Field Label" label="Field Label"
value={field.label || ''} value={field.label || ''}
onChange={() => { }} onChange={(e) => handleTextLabelChange(field.id, e.target.value, step.id, key)}
fullWidth fullWidth
margin="normal" margin="normal"
InputProps={{ 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> </Box>
))} ))}
</> </>

View File

@@ -42,12 +42,15 @@ interface BrowserStepsContextType {
addScreenshotStep: (fullPage: boolean) => void; addScreenshotStep: (fullPage: boolean) => void;
deleteBrowserStep: (id: number) => void; deleteBrowserStep: (id: number) => void;
updateBrowserTextStepLabel: (id: number, newLabel: string) => 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); const BrowserStepsContext = createContext<BrowserStepsContextType | undefined>(undefined);
export const BrowserStepsProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => { export const BrowserStepsProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => {
const [browserSteps, setBrowserSteps] = useState<BrowserStep[]>([]); const [browserSteps, setBrowserSteps] = useState<BrowserStep[]>([]);
const [discardedFields, setDiscardedFields] = useState<Set<string>>(new Set());
const addTextStep = (label: string, data: string, selectorObj: SelectorObject) => { const addTextStep = (label: string, data: string, selectorObj: SelectorObject) => {
setBrowserSteps(prevSteps => [ setBrowserSteps(prevSteps => [
@@ -62,12 +65,19 @@ export const BrowserStepsProvider: React.FC<{ children: React.ReactNode }> = ({
step => step.type === 'list' && step.id === listId step => step.type === 'list' && step.id === listId
); );
if (existingListStepIndex !== -1) { if (existingListStepIndex !== -1) {
// Update the existing ListStep with new fields // Update the existing ListStep with new fields, excluding discarded ones
const updatedSteps = [...prevSteps]; const updatedSteps = [...prevSteps];
const existingListStep = updatedSteps[existingListStepIndex] as ListStep; 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] = { updatedSteps[existingListStepIndex] = {
...existingListStep, ...existingListStep,
fields: { ...existingListStep.fields, ...newFields }, fields: { ...existingListStep.fields, ...filteredNewFields },
pagination: pagination, pagination: pagination,
limit: limit, limit: limit,
}; };
@@ -81,7 +91,6 @@ export const BrowserStepsProvider: React.FC<{ children: React.ReactNode }> = ({
} }
}); });
}; };
const addScreenshotStep = (fullPage: boolean) => { const addScreenshotStep = (fullPage: boolean) => {
setBrowserSteps(prevSteps => [ setBrowserSteps(prevSteps => [
...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 ( return (
<BrowserStepsContext.Provider value={{ <BrowserStepsContext.Provider value={{
browserSteps, browserSteps,
@@ -109,6 +153,8 @@ export const BrowserStepsProvider: React.FC<{ children: React.ReactNode }> = ({
addScreenshotStep, addScreenshotStep,
deleteBrowserStep, deleteBrowserStep,
updateBrowserTextStepLabel, updateBrowserTextStepLabel,
updateListTextFieldLabel,
removeListTextField,
}}> }}>
{children} {children}
</BrowserStepsContext.Provider> </BrowserStepsContext.Provider>