Merge pull request #23 from amhsirak/develop
feat: attribute selection UI
This commit is contained in:
@@ -37,9 +37,9 @@ const defaultModalStyle = {
|
|||||||
bgcolor: 'background.paper',
|
bgcolor: 'background.paper',
|
||||||
boxShadow: 24,
|
boxShadow: 24,
|
||||||
p: 4,
|
p: 4,
|
||||||
height: '60%',
|
height: '30%',
|
||||||
display: 'block',
|
display: 'block',
|
||||||
overflow: 'scroll',
|
overflow: 'hidden',
|
||||||
padding: '5px 25px 10px 25px',
|
padding: '5px 25px 10px 25px',
|
||||||
zIndex: 3147483647,
|
zIndex: 3147483647,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import React, { useCallback, useEffect, useState } from 'react';
|
import React, { useCallback, useEffect, useState } from 'react';
|
||||||
import { useSocketStore } from '../../context/socket';
|
import { useSocketStore } from '../../context/socket';
|
||||||
|
import { Button } from '@mui/material';
|
||||||
import Canvas from "../atoms/canvas";
|
import Canvas from "../atoms/canvas";
|
||||||
import { useBrowserDimensionsStore } from "../../context/browserDimensions";
|
import { useBrowserDimensionsStore } from "../../context/browserDimensions";
|
||||||
import { Highlighter } from "../atoms/Highlighter";
|
import { Highlighter } from "../atoms/Highlighter";
|
||||||
@@ -20,20 +21,29 @@ interface AttributeOption {
|
|||||||
value: string;
|
value: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const getAttributeOptions = (tagName: string): AttributeOption[] => {
|
const getAttributeOptions = (tagName: string, elementInfo: ElementInfo | null): AttributeOption[] => {
|
||||||
|
if (!elementInfo) return [];
|
||||||
switch (tagName.toLowerCase()) {
|
switch (tagName.toLowerCase()) {
|
||||||
case 'a':
|
case 'a':
|
||||||
return [
|
const anchorOptions: AttributeOption[] = [];
|
||||||
{ label: 'Text', value: 'innerText' },
|
if (elementInfo.innerText) {
|
||||||
{ label: 'URL', value: 'href' }
|
anchorOptions.push({ label: `Text: ${elementInfo.innerText}`, value: 'innerText' });
|
||||||
];
|
}
|
||||||
|
if (elementInfo.url) {
|
||||||
|
anchorOptions.push({ label: `URL: ${elementInfo.url}`, value: 'href' });
|
||||||
|
}
|
||||||
|
return anchorOptions;
|
||||||
case 'img':
|
case 'img':
|
||||||
return [
|
const imgOptions: AttributeOption[] = [];
|
||||||
{ label: 'Alt Text', value: 'alt' },
|
if (elementInfo.innerText) {
|
||||||
{ label: 'Source URL', value: 'src' }
|
imgOptions.push({ label: `Alt Text: ${elementInfo.innerText}`, value: 'alt' });
|
||||||
];
|
}
|
||||||
|
if (elementInfo.imageUrl) {
|
||||||
|
imgOptions.push({ label: `Image URL: ${elementInfo.imageUrl}`, value: 'src' });
|
||||||
|
}
|
||||||
|
return imgOptions;
|
||||||
default:
|
default:
|
||||||
return [{ label: 'Text', value: 'innerText' }];
|
return [{ label: `Text: ${elementInfo.innerText}`, value: 'innerText' }];
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -117,36 +127,38 @@ export const BrowserWindow = () => {
|
|||||||
clickY >= highlightRect.top &&
|
clickY >= highlightRect.top &&
|
||||||
clickY <= highlightRect.bottom
|
clickY <= highlightRect.bottom
|
||||||
) {
|
) {
|
||||||
|
const options = getAttributeOptions(highlighterData.elementInfo?.tagName || '', highlighterData.elementInfo);
|
||||||
|
|
||||||
if (getText === true) {
|
if (getText === true) {
|
||||||
const options = getAttributeOptions(highlighterData.elementInfo?.tagName || '');
|
if (options.length === 1) {
|
||||||
if (options.length > 1) {
|
// Directly use the available attribute if only one option is present
|
||||||
|
const attribute = options[0].value;
|
||||||
|
const data = attribute === 'href' ? highlighterData.elementInfo?.url || '' :
|
||||||
|
attribute === 'src' ? highlighterData.elementInfo?.imageUrl || '' :
|
||||||
|
highlighterData.elementInfo?.innerText || '';
|
||||||
|
|
||||||
|
addTextStep('', data, {
|
||||||
|
selector: highlighterData.selector,
|
||||||
|
tag: highlighterData.elementInfo?.tagName,
|
||||||
|
attribute
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// Show the modal if there are multiple options
|
||||||
setAttributeOptions(options);
|
setAttributeOptions(options);
|
||||||
setSelectedElement({
|
setSelectedElement({
|
||||||
selector: highlighterData.selector,
|
selector: highlighterData.selector,
|
||||||
info: highlighterData.elementInfo
|
info: highlighterData.elementInfo
|
||||||
});
|
});
|
||||||
setShowAttributeModal(true);
|
setShowAttributeModal(true);
|
||||||
} else {
|
|
||||||
addTextStep('', highlighterData.elementInfo?.innerText || '', {
|
|
||||||
selector: highlighterData.selector,
|
|
||||||
tag: highlighterData.elementInfo?.tagName,
|
|
||||||
attribute: 'innerText'
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (getList === true && !listSelector) {
|
if (getList === true && !listSelector) {
|
||||||
setListSelector(highlighterData.selector);
|
setListSelector(highlighterData.selector);
|
||||||
} else if (getList === true && listSelector) {
|
} else if (getList === true && listSelector) {
|
||||||
const options = getAttributeOptions(highlighterData.elementInfo?.tagName || '');
|
if (options.length === 1) {
|
||||||
if (options.length > 1) {
|
// Handle directly without showing the modal
|
||||||
setAttributeOptions(options);
|
const attribute = options[0].value;
|
||||||
setSelectedElement({
|
|
||||||
selector: highlighterData.selector,
|
|
||||||
info: highlighterData.elementInfo
|
|
||||||
});
|
|
||||||
setShowAttributeModal(true);
|
|
||||||
} else {
|
|
||||||
const newField: TextStep = {
|
const newField: TextStep = {
|
||||||
id: Date.now(),
|
id: Date.now(),
|
||||||
type: 'text',
|
type: 'text',
|
||||||
@@ -155,7 +167,7 @@ export const BrowserWindow = () => {
|
|||||||
selectorObj: {
|
selectorObj: {
|
||||||
selector: highlighterData.selector,
|
selector: highlighterData.selector,
|
||||||
tag: highlighterData.elementInfo?.tagName,
|
tag: highlighterData.elementInfo?.tagName,
|
||||||
attribute: 'innerText'
|
attribute
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -170,8 +182,15 @@ export const BrowserWindow = () => {
|
|||||||
if (listSelector) {
|
if (listSelector) {
|
||||||
addListStep(listSelector, { ...fields, [newField.label]: newField });
|
addListStep(listSelector, { ...fields, [newField.label]: newField });
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
// Show the modal if there are multiple options
|
||||||
|
setAttributeOptions(options);
|
||||||
|
setSelectedElement({
|
||||||
|
selector: highlighterData.selector,
|
||||||
|
info: highlighterData.elementInfo
|
||||||
|
});
|
||||||
|
setShowAttributeModal(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -239,13 +258,33 @@ export const BrowserWindow = () => {
|
|||||||
>
|
>
|
||||||
<div>
|
<div>
|
||||||
<h2>Select Attribute</h2>
|
<h2>Select Attribute</h2>
|
||||||
{attributeOptions.map((option) => (
|
<div style={{ display: 'flex', flexDirection: 'column', gap: '20px', marginTop: '30px' }}>
|
||||||
<button key={option.value} onClick={() => handleAttributeSelection(option.value)}>
|
{attributeOptions.map((option) => (
|
||||||
{option.label}
|
<Button
|
||||||
</button>
|
variant="outlined"
|
||||||
))}
|
size="medium"
|
||||||
|
key={option.value}
|
||||||
|
onClick={() => handleAttributeSelection(option.value)}
|
||||||
|
style={{
|
||||||
|
justifyContent: 'flex-start',
|
||||||
|
maxWidth: '80%',
|
||||||
|
overflow: 'hidden',
|
||||||
|
padding: '5px 10px',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<span style={{
|
||||||
|
display: 'block',
|
||||||
|
whiteSpace: 'nowrap',
|
||||||
|
overflow: 'hidden',
|
||||||
|
textOverflow: 'ellipsis',
|
||||||
|
maxWidth: '100%'
|
||||||
|
}}>
|
||||||
|
{option.label}
|
||||||
|
</span>
|
||||||
|
</Button>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</GenericModal>
|
</GenericModal>
|
||||||
) : null
|
) : null
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user