pixel-react-excel-sheet 1.0.31 → 1.0.32
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/components/Charts/DashboardDonutChart/types.d.ts +1 -0
- package/lib/components/ConditionalDropdown/types.d.ts +1 -1
- package/lib/components/ConnectingBranch/ConnectingBranch.d.ts +2 -1
- package/lib/components/ConnectingBranch/data.d.ts +19 -33
- package/lib/components/ConnectingBranch/types.d.ts +10 -0
- package/lib/components/Excel/ExcelFile/ExcelFileComponents/actions.d.ts +7 -1
- package/lib/components/FileDropzone/types.d.ts +12 -4
- package/lib/components/MachineInputField/MachineInputField.d.ts +4 -1
- package/lib/components/Select/types.d.ts +1 -1
- package/lib/components/TextArea/Textarea.d.ts +1 -1
- package/lib/components/TextArea/Types.d.ts +1 -0
- package/lib/components/ThemeProvider/types.d.ts +1 -1
- package/lib/index.d.ts +88 -66
- package/lib/index.esm.js +175 -103
- package/lib/index.esm.js.map +1 -1
- package/lib/index.js +175 -103
- package/lib/index.js.map +1 -1
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/lib/utils/validateFile/validateFile.d.ts +2 -0
- package/package.json +2 -2
- package/src/assets/Themes/BaseTheme.scss +1 -0
- package/src/assets/Themes/BlueTheme.scss +279 -0
- package/src/assets/Themes/DarkTheme.scss +1 -0
- package/src/assets/Themes/Theme.scss +5 -0
- package/src/components/AppHeader/AppHeader.tsx +4 -2
- package/src/components/Charts/DashboardDonutChart/DashboardDonutChart.stories.tsx +1 -0
- package/src/components/Charts/DashboardDonutChart/DashboardDonutChart.tsx +3 -1
- package/src/components/Charts/DashboardDonutChart/types.ts +1 -0
- package/src/components/ConditionalDropdown/ConditionalDropdown.stories.tsx +1 -1
- package/src/components/ConditionalDropdown/types.ts +1 -1
- package/src/components/ConnectingBranch/BranchComponents/MachineInstances.tsx +94 -79
- package/src/components/ConnectingBranch/ConnectingBranch.scss +31 -45
- package/src/components/ConnectingBranch/ConnectingBranch.stories.tsx +33 -1
- package/src/components/ConnectingBranch/ConnectingBranch.tsx +36 -23
- package/src/components/ConnectingBranch/{data.ts → data.tsx} +106 -17
- package/src/components/ConnectingBranch/types.ts +21 -0
- package/src/components/Excel/ExcelFile/ExcelFile.tsx +1 -1
- package/src/components/Excel/ExcelFile/ExcelFileComponents/ActiveCell.tsx +7 -5
- package/src/components/Excel/ExcelFile/ExcelFileComponents/FloatingRect.tsx +6 -1
- package/src/components/Excel/ExcelFile/ExcelFileComponents/Spreadsheet.scss +30 -11
- package/src/components/Excel/ExcelFile/ExcelFileComponents/Spreadsheet.tsx +65 -19
- package/src/components/Excel/ExcelFile/ExcelFileComponents/actions.ts +14 -0
- package/src/components/Excel/ExcelFile/ExcelFileComponents/reducer.ts +16 -0
- package/src/components/Excel/ExcelToolBar/ExcelToolBar.tsx +6 -5
- package/src/components/FileDropzone/Dropzone.tsx +3 -0
- package/src/components/FileDropzone/FileDropzone.scss +18 -0
- package/src/components/FileDropzone/FileDropzone.stories.tsx +75 -7
- package/src/components/FileDropzone/FileDropzone.tsx +2 -0
- package/src/components/FileDropzone/RadioFilePreview.tsx +7 -3
- package/src/components/FileDropzone/types.ts +13 -4
- package/src/components/Icon/iconList.ts +2 -2
- package/src/components/InputWithDropdown/InputWithDropdown.tsx +1 -1
- package/src/components/MachineInputField/MachineInputField.tsx +67 -70
- package/src/components/Search/Search.tsx +3 -1
- package/src/components/Select/types.ts +1 -1
- package/src/components/SequentialConnectingBranch/components/Branches/Branches.scss +1 -0
- package/src/components/SequentialConnectingBranch/components/Branches/Branches.tsx +2 -8
- package/src/components/TextArea/Textarea.tsx +2 -0
- package/src/components/TextArea/Types.ts +3 -0
- package/src/components/ThemeProvider/types.ts +1 -1
- package/src/utils/validateFile/validateFile.stories.tsx +49 -0
- package/src/utils/validateFile/validateFile.ts +39 -0
- package/src/components/SequentialConnectingBranch/components/AddBrowserModal/AddBrowserModal.scss +0 -51
- package/src/components/SequentialConnectingBranch/components/AddBrowserModal/AddBrowserModal.tsx +0 -107
- package/src/components/SequentialConnectingBranch/components/AddBrowserModal/types.ts +0 -5
- package/src/components/SequentialConnectingBranch/components/DatasetListModal/DatasetListModal.scss +0 -31
- package/src/components/SequentialConnectingBranch/components/DatasetListModal/DatasetListModal.tsx +0 -85
- package/src/components/SequentialConnectingBranch/components/DatasetListModal/types.ts +0 -4
- /package/src/assets/icons/{impactList.svg → impact_list.svg} +0 -0
|
@@ -5,8 +5,10 @@ import Toaster from '../Toast';
|
|
|
5
5
|
import { useState } from 'react';
|
|
6
6
|
import { RadioOption } from './types';
|
|
7
7
|
import Drawer from '../Drawer/Drawer';
|
|
8
|
-
import
|
|
8
|
+
import ConditionalDropdown from '../ConditionalDropdown/ConditionalDropdown';
|
|
9
9
|
import './FileDropzone.scss';
|
|
10
|
+
import { DynamicObj } from '../CreateVariable/types';
|
|
11
|
+
import Button from '../Button';
|
|
10
12
|
|
|
11
13
|
const meta: Meta<typeof FileDropzone> = {
|
|
12
14
|
title: 'Components/FileDropzone',
|
|
@@ -107,8 +109,12 @@ export const WithRadioButton: Story = {
|
|
|
107
109
|
|
|
108
110
|
const [selectedRadioOption, setSelectedRadioOption] =
|
|
109
111
|
useState<RadioOption>();
|
|
110
|
-
const [selectedFile, setSelectedFile] = useState<File | null>(
|
|
111
|
-
|
|
112
|
+
const [selectedFile, setSelectedFile] = useState<File | DynamicObj | null>(
|
|
113
|
+
null
|
|
114
|
+
);
|
|
115
|
+
const [testDataSelectedFile, setTestDataSelectedFile] = useState<
|
|
116
|
+
DynamicObj | File | null
|
|
117
|
+
>(null);
|
|
112
118
|
|
|
113
119
|
const drawerArgs = {
|
|
114
120
|
primaryButtonProps: {
|
|
@@ -156,6 +162,42 @@ export const WithRadioButton: Story = {
|
|
|
156
162
|
}, 2000);
|
|
157
163
|
};
|
|
158
164
|
|
|
165
|
+
const testData = [
|
|
166
|
+
{
|
|
167
|
+
_id: '1',
|
|
168
|
+
name: 'File1.txt',
|
|
169
|
+
actualPath: '/documents/File1.txt',
|
|
170
|
+
searchKey: 'file1',
|
|
171
|
+
parentId: 'root',
|
|
172
|
+
},
|
|
173
|
+
{
|
|
174
|
+
_id: '2',
|
|
175
|
+
name: 'File2.doc',
|
|
176
|
+
actualPath: '/documents/File2.doc',
|
|
177
|
+
searchKey: 'file2',
|
|
178
|
+
parentId: 'root',
|
|
179
|
+
},
|
|
180
|
+
{
|
|
181
|
+
_id: '3',
|
|
182
|
+
name: 'Image1.png',
|
|
183
|
+
actualPath: '/images/Image1.png',
|
|
184
|
+
searchKey: 'image1',
|
|
185
|
+
parentId: 'folder1',
|
|
186
|
+
},
|
|
187
|
+
{
|
|
188
|
+
_id: '4',
|
|
189
|
+
name: 'Presentation.ppt',
|
|
190
|
+
actualPath: '/presentations/Presentation.ppt',
|
|
191
|
+
searchKey: 'presentation',
|
|
192
|
+
parentId: 'folder2',
|
|
193
|
+
},
|
|
194
|
+
];
|
|
195
|
+
|
|
196
|
+
const handleSaveButton = () => {
|
|
197
|
+
setSelectedFile(testDataSelectedFile);
|
|
198
|
+
setShowModal(false);
|
|
199
|
+
};
|
|
200
|
+
|
|
159
201
|
return (
|
|
160
202
|
<>
|
|
161
203
|
<FileDropzone
|
|
@@ -176,6 +218,7 @@ export const WithRadioButton: Story = {
|
|
|
176
218
|
selectedFile={selectedFile}
|
|
177
219
|
handleFileChange={handleFileChange}
|
|
178
220
|
handleRemoveFile={handleRemoveFile}
|
|
221
|
+
setShowDrawer={setShowModal}
|
|
179
222
|
/>
|
|
180
223
|
{showToaster && (
|
|
181
224
|
<Toaster
|
|
@@ -185,18 +228,43 @@ export const WithRadioButton: Story = {
|
|
|
185
228
|
toastMessage={'Max 5 files can be uploaded'}
|
|
186
229
|
/>
|
|
187
230
|
)}
|
|
188
|
-
{selectedRadioOption?.value === '
|
|
231
|
+
{selectedRadioOption?.value === 'Test Data' && (
|
|
189
232
|
<Drawer
|
|
190
233
|
{...drawerArgs}
|
|
191
234
|
isOpen={showModal}
|
|
192
235
|
onClose={() => setShowModal(false)}
|
|
193
|
-
isFooterRequired={
|
|
236
|
+
isFooterRequired={false}
|
|
194
237
|
_isExpanded={false}
|
|
195
238
|
size="small"
|
|
239
|
+
|
|
196
240
|
>
|
|
197
|
-
<
|
|
241
|
+
<ConditionalDropdown
|
|
242
|
+
label="Select Path Using #"
|
|
243
|
+
placeholder="Enter # to search files"
|
|
244
|
+
isHash
|
|
245
|
+
dataFiles={testData}
|
|
246
|
+
dropdownWidth="auto"
|
|
247
|
+
setHashInputValue={setTestDataSelectedFile}
|
|
248
|
+
/>
|
|
249
|
+
<div className="footer_basic_button">
|
|
250
|
+
<Button
|
|
251
|
+
type="button"
|
|
252
|
+
variant="secondary"
|
|
253
|
+
size="small"
|
|
254
|
+
onClick={() => setShowModal(false)}
|
|
255
|
+
label={'Cancel'}
|
|
256
|
+
/>
|
|
257
|
+
|
|
258
|
+
<Button
|
|
259
|
+
type={'button'}
|
|
260
|
+
variant="primary"
|
|
261
|
+
size="small"
|
|
262
|
+
label={'Save'}
|
|
263
|
+
onClick={handleSaveButton}
|
|
264
|
+
/>
|
|
265
|
+
</div>
|
|
198
266
|
</Drawer>
|
|
199
|
-
}
|
|
267
|
+
)}
|
|
200
268
|
</>
|
|
201
269
|
);
|
|
202
270
|
},
|
|
@@ -38,6 +38,7 @@ const FileDropzone: React.FC<FileDropzoneProps> = ({
|
|
|
38
38
|
handleRemoveFile,
|
|
39
39
|
isApiResponseError = false,
|
|
40
40
|
isDisable = false,
|
|
41
|
+
setShowDrawer,
|
|
41
42
|
}) => {
|
|
42
43
|
const fileInputRef = useRef<HTMLInputElement | null>(null);
|
|
43
44
|
const {
|
|
@@ -131,6 +132,7 @@ const FileDropzone: React.FC<FileDropzoneProps> = ({
|
|
|
131
132
|
handleRemoveFile={handleRemoveFile}
|
|
132
133
|
setSelectedFile={setSelectedFile}
|
|
133
134
|
isDisable={isDisable}
|
|
135
|
+
setShowDrawer={setShowDrawer}
|
|
134
136
|
/>
|
|
135
137
|
|
|
136
138
|
{isWebServiceFileDropZone && (
|
|
@@ -8,14 +8,18 @@ import { useRef } from 'react';
|
|
|
8
8
|
const RadioFilePreview: React.FC<RadioFilePreviewProps> = ({
|
|
9
9
|
selectedFile,
|
|
10
10
|
onFileRemoveClick,
|
|
11
|
-
onFileReplaceClick
|
|
11
|
+
onFileReplaceClick,
|
|
12
|
+
selectedRadioOption,
|
|
13
|
+
setShowDrawer,
|
|
12
14
|
}) => {
|
|
13
15
|
const fileInputRef = useRef<HTMLInputElement | null>(null);
|
|
14
16
|
|
|
15
17
|
const handleReplaceClick = () => {
|
|
16
|
-
if (
|
|
17
|
-
|
|
18
|
+
if (selectedRadioOption?.value === 'Test Data') {
|
|
19
|
+
setShowDrawer?.(true);
|
|
20
|
+
return;
|
|
18
21
|
}
|
|
22
|
+
fileInputRef.current?.click();
|
|
19
23
|
};
|
|
20
24
|
|
|
21
25
|
const handleFileChange = (event: React.ChangeEvent<HTMLInputElement>) => {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { ReactNode } from 'react';
|
|
2
|
+
import { DynamicObj } from '../CreateVariable/types';
|
|
2
3
|
export interface RadioOption {
|
|
3
4
|
label: string;
|
|
4
5
|
value: string;
|
|
@@ -93,12 +94,12 @@ export interface FileDropzoneProps {
|
|
|
93
94
|
/**
|
|
94
95
|
* Its the File Name of File Selected from Local File.
|
|
95
96
|
**/
|
|
96
|
-
setSelectedFile?: (file: File | null) => void;
|
|
97
|
+
setSelectedFile?: (file: File | DynamicObj | null) => void;
|
|
97
98
|
|
|
98
99
|
/**
|
|
99
100
|
* Its the File Name of File Selected from Local File.
|
|
100
101
|
**/
|
|
101
|
-
selectedFile?: File | null;
|
|
102
|
+
selectedFile?: File | DynamicObj | null;
|
|
102
103
|
|
|
103
104
|
/**
|
|
104
105
|
* Its the function which updates the Selected file from Local Directory.
|
|
@@ -120,6 +121,11 @@ export interface FileDropzoneProps {
|
|
|
120
121
|
**/
|
|
121
122
|
isDisable?: boolean;
|
|
122
123
|
|
|
124
|
+
/**
|
|
125
|
+
* Its the boolean value setted when the replace is clicked for TestData radio option .
|
|
126
|
+
**/
|
|
127
|
+
setShowDrawer?: (value: boolean | ((prevState: boolean) => boolean)) => void;
|
|
128
|
+
|
|
123
129
|
}
|
|
124
130
|
export interface FileState {
|
|
125
131
|
accepted: File[];
|
|
@@ -176,11 +182,12 @@ export interface DroppableProps {
|
|
|
176
182
|
selectedRadioOption?: Option,
|
|
177
183
|
radioOptions?: RadioOption[],
|
|
178
184
|
handleOptionChange?: (option: RadioOption)=> void,
|
|
179
|
-
selectedFile?: File | null,
|
|
180
|
-
setSelectedFile?: (file: File | null) => void;
|
|
185
|
+
selectedFile?: File | DynamicObj | null,
|
|
186
|
+
setSelectedFile?: (file: File | DynamicObj | null) => void;
|
|
181
187
|
handleFileChange?: (event: React.ChangeEvent<HTMLInputElement>) => void;
|
|
182
188
|
handleRemoveFile?: () => void;
|
|
183
189
|
isDisable?: boolean;
|
|
190
|
+
setShowDrawer?: (value: boolean | ((prevState: boolean) => boolean)) => void;
|
|
184
191
|
}
|
|
185
192
|
|
|
186
193
|
export interface FilePreviewProps {
|
|
@@ -196,4 +203,6 @@ export interface RadioFilePreviewProps {
|
|
|
196
203
|
onFileRemoveClick?: () => void;
|
|
197
204
|
onFileReplaceClick?: (file: File | null) => void;
|
|
198
205
|
setSelectedFile?: (file: File | null) => void;
|
|
206
|
+
selectedRadioOption?: Option,
|
|
207
|
+
setShowDrawer?: (value: boolean | ((prevState: boolean) => boolean)) => void
|
|
199
208
|
}
|
|
@@ -45,7 +45,7 @@ import ManualLocator from '../../assets/icons/manual_locator.svg?react';
|
|
|
45
45
|
import LicenseIcon from '../../assets/icons/active_license_icon.svg?react';
|
|
46
46
|
import DeleteIcon from '../../assets/icons/delete.svg?react';
|
|
47
47
|
import DetailsIcon from '../../assets/icons/details.svg?react';
|
|
48
|
-
import ImpactListIcon from '../../assets/icons/
|
|
48
|
+
import ImpactListIcon from '../../assets/icons/impact_list.svg?react';
|
|
49
49
|
import Export from '../../assets/icons/export.svg?react';
|
|
50
50
|
import FormatePainter from '../../assets/icons/formate_painter.svg?react';
|
|
51
51
|
import Bold from '../../assets/icons/bold.svg?react';
|
|
@@ -295,7 +295,7 @@ Components['run_icon'] = RunIcon;
|
|
|
295
295
|
Components['license'] = LicenseIcon;
|
|
296
296
|
Components['delete'] = DeleteIcon;
|
|
297
297
|
Components['details'] = DetailsIcon;
|
|
298
|
-
Components['
|
|
298
|
+
Components['impact_list'] = ImpactListIcon;
|
|
299
299
|
Components['beautify_icon'] = BeautifyIcon;
|
|
300
300
|
Components['add_variable_icon'] = AddVariable;
|
|
301
301
|
Components['replace_file'] = ReplaceFile;
|
|
@@ -18,7 +18,7 @@ const InputWithDropdown = forwardRef<HTMLInputElement, InputWithDropdownProps>(
|
|
|
18
18
|
error,
|
|
19
19
|
helperText,
|
|
20
20
|
optionsList,
|
|
21
|
-
selectedOption,
|
|
21
|
+
selectedOption = { label: '', value: '' },
|
|
22
22
|
autoComplete = 'off',
|
|
23
23
|
onDropdownChangeHandler = () => {},
|
|
24
24
|
onInputChangeHandler,
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { forwardRef } from 'react';
|
|
2
1
|
import './MachineInputField.scss';
|
|
3
2
|
import Typography from '../Typography';
|
|
4
3
|
import Icon from '../Icon';
|
|
@@ -6,81 +5,79 @@ import { MachineInputFieldProps, MachineType } from './types';
|
|
|
6
5
|
import classNames from 'classnames';
|
|
7
6
|
import { truncateText } from '../../utils/truncateText/truncateText';
|
|
8
7
|
|
|
9
|
-
const MachineInputField =
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
};
|
|
8
|
+
const MachineInputField = ({
|
|
9
|
+
width = '',
|
|
10
|
+
options = [],
|
|
11
|
+
runCount = 0,
|
|
12
|
+
className = '',
|
|
13
|
+
contentReverse = false,
|
|
14
|
+
onClick = () => {},
|
|
15
|
+
modalId = '',
|
|
16
|
+
}: MachineInputFieldProps) => {
|
|
17
|
+
const getIcon: Record<MachineType['type'], string> = {
|
|
18
|
+
local: 'local',
|
|
19
|
+
browserstack: 'browserstack_icon',
|
|
20
|
+
sauceLabs: 'sause_lab',
|
|
21
|
+
lambdaTest: 'lambda_icon',
|
|
22
|
+
mac: 'mac_icon',
|
|
23
|
+
android: 'android_icon',
|
|
24
|
+
linux: 'linux',
|
|
25
|
+
'google chrome': 'chrome_icon',
|
|
26
|
+
'mozilla firefox': 'fire_fox',
|
|
27
|
+
'microsoft edge': 'edge',
|
|
28
|
+
'internet explorer': 'internet_explorer',
|
|
29
|
+
safari: 'safari_icon',
|
|
30
|
+
opera: 'opera',
|
|
31
|
+
windows: 'windows',
|
|
32
|
+
};
|
|
35
33
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
34
|
+
return (
|
|
35
|
+
<div
|
|
36
|
+
id={modalId}
|
|
37
|
+
style={{ width: width }}
|
|
38
|
+
className={classNames('ff-machine-input-field-wrapper', className)}
|
|
39
|
+
onClick={() => onClick()}
|
|
40
|
+
>
|
|
41
|
+
<Typography
|
|
42
|
+
as="span"
|
|
43
|
+
color="var(--ff-machine-input-field-text-color)"
|
|
44
|
+
fontSize={8}
|
|
45
|
+
textAlign="center"
|
|
46
|
+
className="ff-machine-input-label"
|
|
42
47
|
>
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
color="var(--ff-machine-input-field-text-color)"
|
|
46
|
-
fontSize={8}
|
|
47
|
-
textAlign="center"
|
|
48
|
-
className="ff-machine-input-label"
|
|
49
|
-
>
|
|
50
|
-
Run {runCount}
|
|
51
|
-
</Typography>
|
|
48
|
+
Run {runCount}
|
|
49
|
+
</Typography>
|
|
52
50
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
51
|
+
<div
|
|
52
|
+
className={classNames('ff-machine-input-field', {
|
|
53
|
+
'ff-machine-input-field-reverse': contentReverse,
|
|
54
|
+
})}
|
|
55
|
+
>
|
|
56
|
+
{options.map(({ label, type }) => (
|
|
57
|
+
<div
|
|
58
|
+
key={type}
|
|
59
|
+
className={classNames('ff-machine-icon-text-wrapper', {
|
|
60
|
+
'ff-machine-icon-text-wrapper-reverse': contentReverse,
|
|
61
|
+
})}
|
|
62
|
+
>
|
|
63
|
+
<Icon
|
|
64
|
+
name={getIcon[type.toLowerCase()] || 'local'}
|
|
65
|
+
className="ff-machine-icon"
|
|
66
|
+
/>
|
|
67
|
+
<Typography
|
|
68
|
+
className={classNames('ff-machine-text', {
|
|
69
|
+
'ff-machine-text-reverse': contentReverse,
|
|
63
70
|
})}
|
|
71
|
+
color="var(--ff-machine-input-field-text-color)"
|
|
64
72
|
>
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
<Typography
|
|
70
|
-
className={classNames('ff-machine-text', {
|
|
71
|
-
'ff-machine-text-reverse': contentReverse,
|
|
72
|
-
})}
|
|
73
|
-
color="var(--ff-machine-input-field-text-color)"
|
|
74
|
-
>
|
|
75
|
-
{truncateText(label, 15)}
|
|
76
|
-
</Typography>
|
|
77
|
-
</div>
|
|
78
|
-
))}
|
|
79
|
-
</div>
|
|
73
|
+
{truncateText(label, 15)}
|
|
74
|
+
</Typography>
|
|
75
|
+
</div>
|
|
76
|
+
))}
|
|
80
77
|
</div>
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
78
|
+
</div>
|
|
79
|
+
);
|
|
80
|
+
};
|
|
84
81
|
|
|
85
82
|
MachineInputField.displayName = 'MachineInputField';
|
|
86
83
|
|
|
@@ -72,12 +72,6 @@ const Branches = ({
|
|
|
72
72
|
machineInfo: { osVersion, iconName },
|
|
73
73
|
deviceInfo,
|
|
74
74
|
} = machineInstance as ExecutionContext;
|
|
75
|
-
// Helper to handle device info safely
|
|
76
|
-
const getDeviceOption = (platform: string, defaultType: string = '', index = 0) =>
|
|
77
|
-
deviceInfo?.[index]?.platform?.toLowerCase().includes(platform ?? '')
|
|
78
|
-
? defaultType
|
|
79
|
-
: undefined;
|
|
80
|
-
|
|
81
75
|
const getEnvironment = (environment: string = '') => {
|
|
82
76
|
if (environment.toLowerCase().includes('browserstack'))
|
|
83
77
|
return 'Browserstack';
|
|
@@ -110,11 +104,11 @@ const Branches = ({
|
|
|
110
104
|
const mobileOptions = [
|
|
111
105
|
{
|
|
112
106
|
label: deviceInfo?.[0]?.name,
|
|
113
|
-
type:
|
|
107
|
+
type: 'android',
|
|
114
108
|
},
|
|
115
109
|
{
|
|
116
110
|
label: deviceInfo?.[1]?.name,
|
|
117
|
-
type:
|
|
111
|
+
type: 'mac',
|
|
118
112
|
},
|
|
119
113
|
];
|
|
120
114
|
|
|
@@ -17,6 +17,7 @@ const Textarea = ({
|
|
|
17
17
|
onChange,
|
|
18
18
|
onBlur,
|
|
19
19
|
onFocus,
|
|
20
|
+
onPaste,
|
|
20
21
|
rows = 4,
|
|
21
22
|
cols = 40,
|
|
22
23
|
resize = false,
|
|
@@ -65,6 +66,7 @@ const Textarea = ({
|
|
|
65
66
|
onChange={onChange}
|
|
66
67
|
onBlur={onBlur}
|
|
67
68
|
onFocus={onFocus}
|
|
69
|
+
onPaste={onPaste}
|
|
68
70
|
required={required}
|
|
69
71
|
rows={rows}
|
|
70
72
|
cols={cols}
|
|
@@ -49,6 +49,9 @@ export interface TextareaProps {
|
|
|
49
49
|
onBlur?: (event: React.FocusEvent<HTMLTextAreaElement>) => void;
|
|
50
50
|
|
|
51
51
|
onFocus?: (event: React.FocusEvent<HTMLTextAreaElement>) => void;
|
|
52
|
+
|
|
53
|
+
onPaste?: (event: React.ClipboardEvent<HTMLTextAreaElement>) => void;
|
|
54
|
+
|
|
52
55
|
/**
|
|
53
56
|
* id to select the textarea field uniquely
|
|
54
57
|
*/
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ReactNode } from "react";
|
|
2
2
|
|
|
3
|
-
export type Theme = 'ff-light-theme' | 'ff-dark-theme' | 'ff-grey-theme';
|
|
3
|
+
export type Theme = 'ff-light-theme' | 'ff-dark-theme' | 'ff-grey-theme' | 'ff-blue-theme';
|
|
4
4
|
|
|
5
5
|
export interface ThemeContextType {
|
|
6
6
|
currentTheme: Theme;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import React, { useState } from 'react';
|
|
2
|
+
import {
|
|
3
|
+
validateFileExtension,
|
|
4
|
+
validateZipFileExtension,
|
|
5
|
+
} from './validateFile';
|
|
6
|
+
|
|
7
|
+
export default {
|
|
8
|
+
title: 'Utils/validateFile',
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
const allowedFileTypes = {
|
|
12
|
+
'.txt': 'text/plain',
|
|
13
|
+
'.zip': 'application/zip',
|
|
14
|
+
'.jpg': 'image/jpeg',
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export const ValidateFileExtension = () => {
|
|
18
|
+
const [result, setResult] = useState<string | boolean>('');
|
|
19
|
+
|
|
20
|
+
const handleFileChange = (event: React.ChangeEvent<HTMLInputElement>) => {
|
|
21
|
+
const isValid = validateFileExtension(event, allowedFileTypes);
|
|
22
|
+
setResult(isValid ? 'Valid file type' : 'Invalid file type');
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
return (
|
|
26
|
+
<div>
|
|
27
|
+
<h3>Validate File Extension</h3>
|
|
28
|
+
<input type="file" onChange={handleFileChange} />
|
|
29
|
+
<p>Result: {result.toString()}</p>
|
|
30
|
+
</div>
|
|
31
|
+
);
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
export const ValidateZipFileExtension = () => {
|
|
35
|
+
const [result, setResult] = useState<string | boolean>('');
|
|
36
|
+
|
|
37
|
+
const handleFileChange = (event: React.ChangeEvent<HTMLInputElement>) => {
|
|
38
|
+
const isValid = validateZipFileExtension(event);
|
|
39
|
+
setResult(isValid ? 'Valid ZIP file' : 'Invalid ZIP file');
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
return (
|
|
43
|
+
<div>
|
|
44
|
+
<h3>Validate ZIP File Extension</h3>
|
|
45
|
+
<input type="file" onChange={handleFileChange} />
|
|
46
|
+
<p>Result: {result.toString()}</p>
|
|
47
|
+
</div>
|
|
48
|
+
);
|
|
49
|
+
};
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
export const validateFileExtension = (
|
|
2
|
+
file: File | React.ChangeEvent<HTMLInputElement>,
|
|
3
|
+
allowedFileTypes: Record<string, string>
|
|
4
|
+
) => {
|
|
5
|
+
const selectedFile =
|
|
6
|
+
(file as React.ChangeEvent<HTMLInputElement>).target?.files?.[0] ||
|
|
7
|
+
(file as File);
|
|
8
|
+
const fileExtension =
|
|
9
|
+
'.' + selectedFile?.name?.split('.')?.pop()?.toLowerCase();
|
|
10
|
+
const fileType = selectedFile?.type;
|
|
11
|
+
if (
|
|
12
|
+
['.ipa', '.y4m', '.yml', '.md', '.pem', '.properties'].includes(
|
|
13
|
+
fileExtension
|
|
14
|
+
) &&
|
|
15
|
+
Object.keys(allowedFileTypes)?.includes(fileExtension)
|
|
16
|
+
) {
|
|
17
|
+
return true;
|
|
18
|
+
}
|
|
19
|
+
return (
|
|
20
|
+
allowedFileTypes[fileExtension] &&
|
|
21
|
+
fileType === allowedFileTypes[fileExtension]
|
|
22
|
+
);
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export const validateZipFileExtension = (
|
|
26
|
+
file: File | React.ChangeEvent<HTMLInputElement>
|
|
27
|
+
) => {
|
|
28
|
+
const selectedFile =
|
|
29
|
+
(file as React.ChangeEvent<HTMLInputElement>).target?.files?.[0] ||
|
|
30
|
+
(file as File);
|
|
31
|
+
// List of valid MIME types
|
|
32
|
+
const validMimeTypes = ['application/zip', 'application/x-zip-compressed'];
|
|
33
|
+
// Validating the file extension and MIME type
|
|
34
|
+
return (
|
|
35
|
+
selectedFile &&
|
|
36
|
+
validMimeTypes?.includes(selectedFile?.type) &&
|
|
37
|
+
selectedFile?.name?.toLowerCase()?.endsWith('.zip')
|
|
38
|
+
);
|
|
39
|
+
};
|
package/src/components/SequentialConnectingBranch/components/AddBrowserModal/AddBrowserModal.scss
DELETED
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
.ff-connecting-datalist-modal-header-wrapper,
|
|
2
|
-
.ff-connecting-modal-child-wrapper {
|
|
3
|
-
width: 534px;
|
|
4
|
-
padding: 0 4px;
|
|
5
|
-
}
|
|
6
|
-
|
|
7
|
-
.ff-connecting-datalist-modal-header-wrapper {
|
|
8
|
-
border-bottom: 1px solid var(--ff-connecting-branch-modal-border);
|
|
9
|
-
margin-bottom: 4px;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
.ff-connecting-modal-child-wrapper {
|
|
13
|
-
.ff-branch-select-input-wrapper {
|
|
14
|
-
display: flex;
|
|
15
|
-
align-items: center;
|
|
16
|
-
gap: 8px;
|
|
17
|
-
|
|
18
|
-
.ff-select-browser {
|
|
19
|
-
width: 263px;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
.ff-branch-input-wrapper {
|
|
23
|
-
display: flex;
|
|
24
|
-
align-items: flex-end;
|
|
25
|
-
height: 38px;
|
|
26
|
-
|
|
27
|
-
.ff-input-browser {
|
|
28
|
-
width: 245px;
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
.ff-connecting-modal-footer-wrapper {
|
|
35
|
-
display: flex;
|
|
36
|
-
align-items: center;
|
|
37
|
-
justify-content: space-between;
|
|
38
|
-
padding: 0 8px;
|
|
39
|
-
margin-top: 8px;
|
|
40
|
-
border-top: 1px solid var(--ff-connecting-branch-modal-border);
|
|
41
|
-
|
|
42
|
-
.ff-branch-toggle-wrapper,
|
|
43
|
-
.ff-datalist-button-wrapper {
|
|
44
|
-
display: flex;
|
|
45
|
-
gap: 8px;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
.ff-branch-toggle-wrapper {
|
|
49
|
-
gap: 4px;
|
|
50
|
-
}
|
|
51
|
-
}
|