Skip to content

Commit afb47ab

Browse files
committed
fixes
1 parent dbffabd commit afb47ab

File tree

17 files changed

+1299
-328
lines changed

17 files changed

+1299
-328
lines changed

release/app/package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

release/app/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "todo-my-app-name",
3-
"version": "1.47.0",
3+
"version": "1.48.0",
44
"description": "Todo my app description",
55
"license": "MIT",
66
"main": "./dist/main/main.js",

src/main/utils/set-up-renderer-to-server-call.ts

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { shell, dialog } from 'electron';
22
import { ipcMain } from './ipc-main';
33
import * as routes from 'botasaurus-server/task-routes';
44
import { config } from '../config'
5+
import { getWindow } from './window';
56

67
let isBackendSetUp = false;
78
let isRoutesAdded = false;
@@ -10,11 +11,54 @@ let isRoutesAdded = false;
1011
function pickId(x) {
1112
return { id: x.id }
1213
}
14+
15+
function sendToRenderer(channel: string, data: any) {
16+
const window = getWindow();
17+
window?.webContents.send(channel, data);
18+
}
19+
1320
export function addRoutesHandler() {
1421
if (isRoutesAdded) return;
1522

1623
for (const [key, value] of Object.entries(routes)) {
17-
if (key === 'createAsyncTask') {
24+
if (key === 'patchTask') {
25+
ipcMain.handle(key, async (event, ...data) => {
26+
27+
if(data[1].action !== 'abort' ){
28+
// @ts-ignore
29+
return value(...data)
30+
}
31+
32+
const taskId = data[1].task_ids[0];
33+
const requestId = data[0].requestId;
34+
35+
36+
// @ts-ignore
37+
value(...data).then(async (result: any) => {
38+
// Send success to unique channel
39+
sendToRenderer(`task-abort-result-${requestId}`, {
40+
taskId,
41+
success: true,
42+
result,
43+
error: null
44+
});
45+
})
46+
.catch((error: any) => {
47+
// Send error to unique channel
48+
sendToRenderer(`task-abort-result-${requestId}`, {
49+
taskId,
50+
success: false,
51+
52+
result: null,
53+
error: error?.message || 'Failed to abort task'
54+
});
55+
});
56+
57+
// Return immediately - don't wait for abort to complete
58+
return {};
59+
})
60+
}
61+
else if (key === 'createAsyncTask') {
1862
ipcMain.handle(key, async (_, ...data) => {
1963
// @ts-ignore
2064
let result = await value(...data)
Lines changed: 26 additions & 203 deletions
Original file line numberDiff line numberDiff line change
@@ -1,209 +1,32 @@
11
import { EuiButton } from '@elastic/eui/optimize/es/components/button/button';
2-
import { EuiForm } from '@elastic/eui/optimize/es/components/form/form';
3-
import { EuiFormRow } from '@elastic/eui/optimize/es/components/form/form_row/form_row';
42
import { EuiIcon } from '@elastic/eui/optimize/es/components/icon/icon';
5-
import { EuiModal } from '@elastic/eui/optimize/es/components/modal/modal';
6-
import { EuiModalBody } from '@elastic/eui/optimize/es/components/modal/modal_body';
7-
import { EuiModalHeader } from '@elastic/eui/optimize/es/components/modal/modal_header';
8-
import { EuiModalHeaderTitle } from '@elastic/eui/optimize/es/components/modal/modal_header_title';
9-
import { EuiToolTip } from '@elastic/eui/optimize/es/components/tool_tip/tool_tip';
10-
import { useState } from 'react';
113

12-
import ClickOutside from '../ClickOutside/ClickOutside';
13-
import CheckboxField from '../inputs/CheckBoxField';
14-
import Tabs from '../Tabs/Tabs';
15-
import { openFolderPicker } from '../../utils/electron'
16-
17-
function getprefs() {
18-
if (typeof window === 'undefined') {
19-
return { format: 'csv', convert_to_english: true, downloadFolder: null }
20-
}
21-
22-
let downloadPreference
23-
try {
24-
downloadPreference = JSON.parse(
25-
localStorage.getItem('download_preference') ||
26-
'{"format": "csv", "convert_to_english": true, "downloadFolder": null}'
27-
)
28-
} catch (error) {
29-
console.error('Error parsing download preferences:', error)
30-
downloadPreference = { format: 'csv', convert_to_english: true, downloadFolder: null } // Default value in case of error
31-
}
32-
return downloadPreference
33-
}
34-
35-
let prefs = getprefs()
36-
37-
const tabs = [
38-
{
39-
id: 'csv',
40-
name: 'CSV',
41-
content: <></>, // Assuming no content is needed for the sorting tabs
42-
},
43-
{
44-
id: 'json',
45-
name: 'JSON',
46-
content: <></>, // Assuming no content is needed for the sorting tabs
47-
},
48-
{
49-
id: 'excel',
50-
name: 'Excel',
51-
content: <></>, // Assuming no content is needed for the sorting tabs
52-
},
53-
]
54-
55-
function isWindowsBrowser() {
56-
return navigator.platform.indexOf('Win') > -1;
57-
}
58-
59-
export function getSeparator(): string {
60-
return isWindowsBrowser() ? '\\' : '/';
61-
}
62-
63-
const DownloadForm = ({ onSubmit , productName}) => {
64-
65-
function updatePrefs(change) {
66-
prefs = change
67-
localStorage.setItem('download_preference', JSON.stringify(change))
68-
}
69-
70-
const [state, setState] = useState(getprefs)
71-
72-
73-
74-
function onTabClick(selectedTab) {
75-
const change = {
76-
...state,
77-
format: selectedTab.id,
78-
}
79-
updatePrefs(change)
80-
setState(change)
81-
}
82-
83-
function handleCheckboxChange(e) {
84-
const change = {
85-
...state,
86-
convert_to_english: e,
87-
}
88-
updatePrefs(change)
89-
setState(change)
90-
}
91-
92-
async function handleDownloadFolderChange() {
93-
try {
94-
const folderPath = await openFolderPicker(state.downloadFolder)
95-
if (folderPath) {
96-
const change = {
97-
...state,
98-
downloadFolder: folderPath,
99-
}
100-
updatePrefs(change)
101-
setState(change)
102-
}
103-
} catch (error) {
104-
console.error('Error selecting download folder:', error)
105-
}
106-
}
107-
const handleSubmit = event => {
108-
event.preventDefault()
109-
updatePrefs(state)
110-
if (onSubmit) {
111-
onSubmit(state)
112-
}
113-
}
114-
115-
const downloadLabel = `Save downloads to folder: ${state.downloadFolder ?? 'Downloads'}${getSeparator()}${productName}`
116-
return (
117-
<EuiForm component="form" onSubmit={handleSubmit}>
118-
<EuiFormRow
119-
className="remove-tabs-bottom-border"
120-
label="Format"
121-
fullWidth>
122-
<Tabs tabs={tabs} selectedTab={state.format} onTabChange={onTabClick} />
123-
</EuiFormRow>
124-
125-
<EuiFormRow
126-
className="text-left"
127-
128-
label={downloadLabel }
129-
fullWidth>
130-
<EuiButton
131-
132-
size="s"
133-
onClick={handleDownloadFolderChange}
134-
>
135-
Change
136-
</EuiButton>
137-
</EuiFormRow>
138-
139-
<EuiFormRow
140-
className="text-left"
141-
label={
142-
<EuiToolTip content="Convert non-English characters (like é, ñ, あ) to their English equivalents (e, n, a).">
143-
<span>
144-
Convert non-English characters to English characters
145-
<EuiIcon type="questionInCircle" color="subdued" />
146-
</span>
147-
</EuiToolTip>
148-
}
149-
fullWidth>
150-
<CheckboxField
151-
id="convert_to_english"
152-
value={state.convert_to_english}
153-
onChange={handleCheckboxChange}
154-
/>
155-
</EuiFormRow>
156-
157-
<EuiButton type="submit" fill>
158-
Download
159-
</EuiButton>
160-
</EuiForm>
161-
)
162-
}
163-
164-
function useDownloadModal(onDownload, productName) {
165-
const [isModalVisible, setIsModalVisible] = useState(false)
166-
167-
const toggleModal = () => {
168-
setIsModalVisible(!isModalVisible)
169-
}
170-
171-
// Call this function when the download is successfully initiated
172-
function successClose(data) {
173-
toggleModal()
174-
onDownload(data) // Call the passed function on successful submission/download
175-
}
176-
177-
const modal = isModalVisible && (
178-
<EuiModal className="max-w-xl text-center" onClose={toggleModal}>
179-
<ClickOutside
180-
handleClickOutside={() => {
181-
toggleModal()
182-
}}>
183-
<div>
184-
<EuiModalHeader className="justify-center">
185-
<EuiModalHeaderTitle>Download Results</EuiModalHeaderTitle>
186-
</EuiModalHeader>
187-
<EuiModalBody>
188-
<DownloadForm productName={productName} onSubmit={successClose} />
189-
</EuiModalBody>
190-
</div>
191-
</ClickOutside>
192-
</EuiModal>
193-
)
194-
195-
return { showModal: () => setIsModalVisible(true), modal }
196-
}
197-
const DownloadStickyBar = ({ productName, onDownload, showPagination }) => {
4+
import {
5+
downloadPrefs,
6+
getFormatLabel,
7+
useDownloadModal,
8+
DownloadPreferences,
9+
} from './download-utils';
10+
11+
// Re-export for backwards compatibility
12+
export { getSeparator } from './download-utils';
13+
14+
const DownloadStickyBar = ({
15+
productName,
16+
onDownload,
17+
showPagination,
18+
}: {
19+
productName: string;
20+
onDownload: (data: DownloadPreferences) => void;
21+
showPagination: boolean;
22+
}) => {
19823
function directDownload() {
199-
// gets download preference from local storage, if not then it is {"format": "csv", "convert_to_english": true }
200-
// if convert_to_english is true then the language will be converted to english
201-
onDownload(prefs)
24+
onDownload(downloadPrefs);
20225
}
20326

204-
const { modal, showModal } = useDownloadModal(onDownload, productName)
205-
// @ts-ignore
206-
const fmt = `Download ${tabs.find(x => x.id === prefs.format).name}`
27+
const { modal, showModal } = useDownloadModal(onDownload, productName);
28+
const fmt = `Download ${getFormatLabel(downloadPrefs.format)}`;
29+
20730
return (
20831
<div className={showPagination ? 'pt-2' : 'pt-6'}>
20932
{modal}
@@ -216,7 +39,7 @@ const DownloadStickyBar = ({ productName, onDownload, showPagination }) => {
21639
onClick={showModal}
21740
/>
21841
</div>
219-
)
220-
}
42+
);
43+
};
22144

222-
export default DownloadStickyBar
45+
export default DownloadStickyBar;

0 commit comments

Comments
 (0)