From e9f1e6ca2354c2cfc7e08ac7986e8d71480e8e36 Mon Sep 17 00:00:00 2001 From: Emily Davis Date: Wed, 21 Aug 2024 17:45:41 -0600 Subject: [PATCH 1/7] Allows 'Open Workspace' to open workspace whenever possible, even if logfile doesn't exist --- workbench/src/main/ipcMainChannels.js | 1 + workbench/src/main/setupDialogs.js | 6 +++++ .../renderer/components/InvestTab/index.jsx | 27 ++++++++++++++++--- 3 files changed, 31 insertions(+), 3 deletions(-) diff --git a/workbench/src/main/ipcMainChannels.js b/workbench/src/main/ipcMainChannels.js index de7ca13c19..f908d7c33b 100644 --- a/workbench/src/main/ipcMainChannels.js +++ b/workbench/src/main/ipcMainChannels.js @@ -14,6 +14,7 @@ export const ipcMainChannels = { IS_FIRST_RUN: 'is-first-run', LOGGER: 'logger', OPEN_EXTERNAL_URL: 'open-external-url', + OPEN_PATH: 'open-path', OPEN_LOCAL_HTML: 'open-local-html', SET_SETTING: 'set-setting', SHOW_ITEM_IN_FOLDER: 'show-item-in-folder', diff --git a/workbench/src/main/setupDialogs.js b/workbench/src/main/setupDialogs.js index cecc003a90..3e79df45ba 100644 --- a/workbench/src/main/setupDialogs.js +++ b/workbench/src/main/setupDialogs.js @@ -26,4 +26,10 @@ export default function setupDialogs() { shell.showItemInFolder(filepath); } ); + + ipcMain.handle( + ipcMainChannels.OPEN_PATH, async (event, dirpath) => { + return await shell.openPath(dirpath); + } + ); } diff --git a/workbench/src/renderer/components/InvestTab/index.jsx b/workbench/src/renderer/components/InvestTab/index.jsx index 0c250a4e3a..e8e66c485f 100644 --- a/workbench/src/renderer/components/InvestTab/index.jsx +++ b/workbench/src/renderer/components/InvestTab/index.jsx @@ -45,8 +45,27 @@ async function investGetSpec(modelName) { return undefined; } -function handleOpenWorkspace(logfile) { - ipcRenderer.send(ipcMainChannels.SHOW_ITEM_IN_FOLDER, logfile); +function handleOpenWorkspace(logfile, workspace_dir) { + if (logfile) { + logger.info(`Attempting to show logfile in workspace directory: ${logfile}`); + ipcRenderer.send(ipcMainChannels.SHOW_ITEM_IN_FOLDER, logfile); + } + // Always call shell.openPath. + // If shell.showItemInFolder failed, it will have failed silently; + // if it succeeded, the subsequent call to shell.openPath will not "undo" the result of shell.showItemInFolder. + openWorkspaceDir(workspace_dir); +} + +async function openWorkspaceDir(workspace_dir) { + logger.info(`Attempting to open directory: ${workspace_dir}`); + const error = await ipcRenderer.invoke(ipcMainChannels.OPEN_PATH, workspace_dir); + if (error) { + logger.error(`Error opening directory: ${error}`); + // @TODO: render this error message in a modal + alert('Failed to open workspace directory. Make sure the directory exists and that you have write access to it.'); + } else { + logger.info(`Directory should be open now`); + } } /** @@ -154,6 +173,7 @@ class InvestTab extends React.Component { updateJobProperties(tabID, { argsValues: args, status: undefined, // in case of re-run, clear an old status + logfile: undefined, // in case of re-run where logfile may no longer exist, clear old logfile path }); ipcRenderer.send( @@ -200,6 +220,7 @@ class InvestTab extends React.Component { argsValues, logfile, } = this.props.job; + const {workspace_dir} = argsValues; const { tabID, t } = this.props; @@ -253,7 +274,7 @@ class InvestTab extends React.Component { ? ( handleOpenWorkspace(logfile)} + handleOpenWorkspace={() => handleOpenWorkspace(logfile, workspace_dir)} terminateInvestProcess={this.terminateInvestProcess} /> ) From c182f29a856c40989fef099c0799cf2ccebe4cf9 Mon Sep 17 00:00:00 2001 From: Emily Davis Date: Thu, 22 Aug 2024 17:44:55 -0600 Subject: [PATCH 2/7] Adds/updates tests --- .../renderer/components/InvestTab/index.jsx | 13 +-- workbench/tests/main/main.test.js | 1 + workbench/tests/renderer/investtab.test.js | 94 ++++++++++++++++++- 3 files changed, 100 insertions(+), 8 deletions(-) diff --git a/workbench/src/renderer/components/InvestTab/index.jsx b/workbench/src/renderer/components/InvestTab/index.jsx index e8e66c485f..971feab23c 100644 --- a/workbench/src/renderer/components/InvestTab/index.jsx +++ b/workbench/src/renderer/components/InvestTab/index.jsx @@ -50,10 +50,12 @@ function handleOpenWorkspace(logfile, workspace_dir) { logger.info(`Attempting to show logfile in workspace directory: ${logfile}`); ipcRenderer.send(ipcMainChannels.SHOW_ITEM_IN_FOLDER, logfile); } - // Always call shell.openPath. - // If shell.showItemInFolder failed, it will have failed silently; - // if it succeeded, the subsequent call to shell.openPath will not "undo" the result of shell.showItemInFolder. - openWorkspaceDir(workspace_dir); + if (workspace_dir) { + // Always call shell.openPath. + // If shell.showItemInFolder failed, it will have failed silently; + // if it succeeded, the subsequent call to shell.openPath will not "undo" the result of shell.showItemInFolder. + openWorkspaceDir(workspace_dir); + } } async function openWorkspaceDir(workspace_dir) { @@ -220,7 +222,6 @@ class InvestTab extends React.Component { argsValues, logfile, } = this.props.job; - const {workspace_dir} = argsValues; const { tabID, t } = this.props; @@ -274,7 +275,7 @@ class InvestTab extends React.Component { ? ( handleOpenWorkspace(logfile, workspace_dir)} + handleOpenWorkspace={() => handleOpenWorkspace(logfile, argsValues?.workspace_dir)} terminateInvestProcess={this.terminateInvestProcess} /> ) diff --git a/workbench/tests/main/main.test.js b/workbench/tests/main/main.test.js index a65e806ff6..2b479b6882 100644 --- a/workbench/tests/main/main.test.js +++ b/workbench/tests/main/main.test.js @@ -187,6 +187,7 @@ describe('createWindow', () => { ipcMainChannels.GET_N_CPUS, ipcMainChannels.INVEST_VERSION, ipcMainChannels.IS_FIRST_RUN, + ipcMainChannels.OPEN_PATH, ipcMainChannels.SHOW_OPEN_DIALOG, ipcMainChannels.SHOW_SAVE_DIALOG, ]; diff --git a/workbench/tests/renderer/investtab.test.js b/workbench/tests/renderer/investtab.test.js index 74e9c9aa8e..5694440863 100644 --- a/workbench/tests/renderer/investtab.test.js +++ b/workbench/tests/renderer/investtab.test.js @@ -117,10 +117,100 @@ describe('Run status Alert renders with status from a recent run', () => { logfile: 'foo.txt', }); + jest.spyOn(shell, 'showItemInFolder'); + + const { findByRole } = renderInvestTab(job); + const openWorkspaceBtn = await findByRole('button', { name: 'Open Workspace' }); + expect(openWorkspaceBtn).toBeTruthy(); + openWorkspaceBtn.click(); + expect(shell.showItemInFolder).toHaveBeenCalledTimes(1); + }); +}); + +describe('Open Workspace button', () => { + const spec = { + args: {}, + }; + + const baseJob = { + ...DEFAULT_JOB, + status: 'success', + }; + + beforeEach(() => { + getSpec.mockResolvedValue(spec); + fetchValidation.mockResolvedValue([]); + uiConfig.UI_SPEC = mockUISpec(spec); + setupDialogs(); + }); + + afterEach(() => { + removeIpcMainListeners(); + }); + + test('should open workspace with logfile selected, if logfile exists', async () => { + const job = { + ...baseJob, + argsValues: { + workspace_dir: '/workspace', + }, + logfile: '/workspace/log.txt', + }; + + jest.spyOn(shell, 'showItemInFolder'); + const { findByRole } = renderInvestTab(job); - const openWorkspace = await findByRole('button', { name: 'Open Workspace' }) - openWorkspace.click(); + const openWorkspaceBtn = await findByRole('button', { name: 'Open Workspace' }); + openWorkspaceBtn.click(); + expect(shell.showItemInFolder).toHaveBeenCalledTimes(1); + expect(shell.showItemInFolder).toHaveBeenCalledWith(job.logfile); + }); + + test('should open workspace (without logfile selected), if workspace exists but logfile does not', async () => { + const job = { + ...baseJob, + argsValues: { + workspace_dir: '/workspace', + }, + logfile: undefined, + }; + + jest.spyOn(shell, 'showItemInFolder'); + jest.spyOn(ipcRenderer, 'invoke'); + + const { findByRole } = renderInvestTab(job); + const openWorkspaceBtn = await findByRole('button', { name: 'Open Workspace' }) + openWorkspaceBtn.click(); + + expect(shell.showItemInFolder).not.toHaveBeenCalled(); + expect(ipcRenderer.invoke).toHaveBeenCalledTimes(1); + expect(ipcRenderer.invoke).toHaveBeenCalledWith(ipcMainChannels.OPEN_PATH, job.argsValues.workspace_dir); + }); + + test('should present an error message to the user if workspace cannot be opened (e.g., if it does not exist)', async () => { + const job = { + ...baseJob, + status: 'error', + argsValues: { + workspace_dir: '/nonexistent-workspace', + }, + logfile: undefined, + }; + + jest.spyOn(shell, 'showItemInFolder'); + jest.spyOn(ipcRenderer, 'invoke'); + ipcRenderer.invoke.mockResolvedValue('Error opening workspace'); + + const { findByRole } = renderInvestTab(job); + const openWorkspaceBtn = await findByRole('button', { name: 'Open Workspace' }) + openWorkspaceBtn.click(); + + expect(shell.showItemInFolder).not.toHaveBeenCalled(); + expect(ipcRenderer.invoke).toHaveBeenCalledTimes(1); + expect(ipcRenderer.invoke).toHaveBeenCalledWith(ipcMainChannels.OPEN_PATH, job.argsValues.workspace_dir); + + // @TODO: expect error message UI element to exist }); }); From c50520921abecec2bb5800df0008da9471237e9a Mon Sep 17 00:00:00 2001 From: Emily Davis Date: Fri, 23 Aug 2024 14:01:47 -0600 Subject: [PATCH 3/7] Adds "error opening workspace" modal & updates tests --- .../renderer/components/InvestTab/index.jsx | 229 ++++++++++-------- workbench/tests/renderer/investtab.test.js | 7 +- 2 files changed, 130 insertions(+), 106 deletions(-) diff --git a/workbench/src/renderer/components/InvestTab/index.jsx b/workbench/src/renderer/components/InvestTab/index.jsx index 971feab23c..dbfd04df17 100644 --- a/workbench/src/renderer/components/InvestTab/index.jsx +++ b/workbench/src/renderer/components/InvestTab/index.jsx @@ -7,6 +7,8 @@ import TabContainer from 'react-bootstrap/TabContainer'; import Nav from 'react-bootstrap/Nav'; import Row from 'react-bootstrap/Row'; import Col from 'react-bootstrap/Col'; +import Modal from 'react-bootstrap/Modal'; +import Button from 'react-bootstrap/Button'; import { MdKeyboardArrowRight, } from 'react-icons/md'; @@ -45,31 +47,6 @@ async function investGetSpec(modelName) { return undefined; } -function handleOpenWorkspace(logfile, workspace_dir) { - if (logfile) { - logger.info(`Attempting to show logfile in workspace directory: ${logfile}`); - ipcRenderer.send(ipcMainChannels.SHOW_ITEM_IN_FOLDER, logfile); - } - if (workspace_dir) { - // Always call shell.openPath. - // If shell.showItemInFolder failed, it will have failed silently; - // if it succeeded, the subsequent call to shell.openPath will not "undo" the result of shell.showItemInFolder. - openWorkspaceDir(workspace_dir); - } -} - -async function openWorkspaceDir(workspace_dir) { - logger.info(`Attempting to open directory: ${workspace_dir}`); - const error = await ipcRenderer.invoke(ipcMainChannels.OPEN_PATH, workspace_dir); - if (error) { - logger.error(`Error opening directory: ${error}`); - // @TODO: render this error message in a modal - alert('Failed to open workspace directory. Make sure the directory exists and that you have write access to it.'); - } else { - logger.info(`Directory should be open now`); - } -} - /** * Render an invest model setup form, log display, etc. * Manage launching of an invest model in a child process. @@ -85,6 +62,7 @@ class InvestTab extends React.Component { uiSpec: null, userTerminated: false, executeClicked: false, + showErrorModal: false, }; this.investExecute = this.investExecute.bind(this); @@ -92,6 +70,9 @@ class InvestTab extends React.Component { this.terminateInvestProcess = this.terminateInvestProcess.bind(this); this.investLogfileCallback = this.investLogfileCallback.bind(this); this.investExitCallback = this.investExitCallback.bind(this); + this.handleOpenWorkspace = this.handleOpenWorkspace.bind(this); + this.openWorkspaceDir = this.openWorkspaceDir.bind(this); + this.showErrorModal = this.showErrorModal.bind(this); } async componentDidMount() { @@ -208,6 +189,36 @@ class InvestTab extends React.Component { ); } + handleOpenWorkspace(logfile, workspace_dir) { + if (logfile) { + logger.info(`Attempting to show logfile in workspace directory: ${logfile}`); + ipcRenderer.send(ipcMainChannels.SHOW_ITEM_IN_FOLDER, logfile); + } + if (workspace_dir) { + // Always call shell.openPath. + // If shell.showItemInFolder failed, it will have failed silently; + // if it succeeded, the subsequent call to shell.openPath will not "undo" the result of shell.showItemInFolder. + this.openWorkspaceDir(workspace_dir); + } + } + + async openWorkspaceDir(workspace_dir) { + logger.info(`Attempting to open directory: ${workspace_dir}`); + const error = await ipcRenderer.invoke(ipcMainChannels.OPEN_PATH, workspace_dir); + if (error) { + logger.error(`Error opening directory: ${error}`); + this.showErrorModal(true); + } else { + logger.info(`Directory should be open now`); + } + } + + showErrorModal(shouldShow) { + this.setState({ + showErrorModal: shouldShow, + }); + } + render() { const { activeTab, @@ -215,6 +226,7 @@ class InvestTab extends React.Component { argsSpec, uiSpec, executeClicked, + showErrorModal, } = this.state; const { status, @@ -235,88 +247,99 @@ class InvestTab extends React.Component { const sidebarFooterElementId = `sidebar-footer-${tabID}`; return ( - - - - -
-
- -
-
+ + + - { - status - ? ( - handleOpenWorkspace(logfile, argsValues?.workspace_dir)} - terminateInvestProcess={this.terminateInvestProcess} - /> - ) - : null - } -
- - - - - + {t('Setup')} + + + + {t('Log')} + + + +
+
+ - - +
- - - - - - + { + status + ? ( + this.handleOpenWorkspace(logfile, argsValues?.workspace_dir)} + terminateInvestProcess={this.terminateInvestProcess} + /> + ) + : null + } +
+ + + + + + + + + + + + + + this.showErrorModal(false)} aria-labelledby="error-modal-title"> + + {t('Error opening workspace')} + + {t('Failed to open workspace directory. Make sure the directory exists and that you have write access to it.')} + + + + + ); } } diff --git a/workbench/tests/renderer/investtab.test.js b/workbench/tests/renderer/investtab.test.js index 5694440863..1b6f9f544d 100644 --- a/workbench/tests/renderer/investtab.test.js +++ b/workbench/tests/renderer/investtab.test.js @@ -203,14 +203,15 @@ describe('Open Workspace button', () => { ipcRenderer.invoke.mockResolvedValue('Error opening workspace'); const { findByRole } = renderInvestTab(job); - const openWorkspaceBtn = await findByRole('button', { name: 'Open Workspace' }) + const openWorkspaceBtn = await findByRole('button', { name: 'Open Workspace' }); openWorkspaceBtn.click(); expect(shell.showItemInFolder).not.toHaveBeenCalled(); expect(ipcRenderer.invoke).toHaveBeenCalledTimes(1); expect(ipcRenderer.invoke).toHaveBeenCalledWith(ipcMainChannels.OPEN_PATH, job.argsValues.workspace_dir); - // @TODO: expect error message UI element to exist + const errorModal = await findByRole('dialog', { name: 'Error opening workspace'}); + expect(errorModal).toBeTruthy(); }); }); @@ -505,7 +506,7 @@ describe('InVEST Run Button', () => { uiConfig.UI_SPEC = mockUISpec(spec); }); - test('Changing inputs trigger validation & enable/disable Run', async () => { + xtest('Changing inputs trigger validation & enable/disable Run', async () => { let invalidFeedback = 'is a required key'; fetchValidation.mockResolvedValue([[['a', 'b'], invalidFeedback]]); From d824e973b2d75b27f325ae698562a5d497208887 Mon Sep 17 00:00:00 2001 From: Emily Davis Date: Fri, 23 Aug 2024 14:13:41 -0600 Subject: [PATCH 4/7] Removes unneeded log messages & updates HISTORY --- HISTORY.rst | 1 + workbench/src/renderer/components/InvestTab/index.jsx | 6 +----- workbench/tests/renderer/investtab.test.js | 2 +- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/HISTORY.rst b/HISTORY.rst index 47406cd82c..54ac3a115c 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -39,6 +39,7 @@ Unreleased Changes ------------------ * Workbench * Several small updates to the model input form UI to improve usability and visual consistency (https://github.com/natcap/invest/issues/912) + * Fixed a bug that caused the application to crash when attempting to open a workspace without a valid logfile (https://github.com/natcap/invest/issues/1598) 3.14.2 (2024-05-29) ------------------- diff --git a/workbench/src/renderer/components/InvestTab/index.jsx b/workbench/src/renderer/components/InvestTab/index.jsx index dbfd04df17..f6624f2142 100644 --- a/workbench/src/renderer/components/InvestTab/index.jsx +++ b/workbench/src/renderer/components/InvestTab/index.jsx @@ -191,7 +191,6 @@ class InvestTab extends React.Component { handleOpenWorkspace(logfile, workspace_dir) { if (logfile) { - logger.info(`Attempting to show logfile in workspace directory: ${logfile}`); ipcRenderer.send(ipcMainChannels.SHOW_ITEM_IN_FOLDER, logfile); } if (workspace_dir) { @@ -203,13 +202,10 @@ class InvestTab extends React.Component { } async openWorkspaceDir(workspace_dir) { - logger.info(`Attempting to open directory: ${workspace_dir}`); const error = await ipcRenderer.invoke(ipcMainChannels.OPEN_PATH, workspace_dir); if (error) { - logger.error(`Error opening directory: ${error}`); + logger.error(`Error opening workspace (${workspace_dir}). ${error}`); this.showErrorModal(true); - } else { - logger.info(`Directory should be open now`); } } diff --git a/workbench/tests/renderer/investtab.test.js b/workbench/tests/renderer/investtab.test.js index 1b6f9f544d..4a82955f32 100644 --- a/workbench/tests/renderer/investtab.test.js +++ b/workbench/tests/renderer/investtab.test.js @@ -506,7 +506,7 @@ describe('InVEST Run Button', () => { uiConfig.UI_SPEC = mockUISpec(spec); }); - xtest('Changing inputs trigger validation & enable/disable Run', async () => { + test('Changing inputs trigger validation & enable/disable Run', async () => { let invalidFeedback = 'is a required key'; fetchValidation.mockResolvedValue([[['a', 'b'], invalidFeedback]]); From 3276d21c4d78a1ea4641873d235ded048412b749 Mon Sep 17 00:00:00 2001 From: Emily Davis Date: Thu, 29 Aug 2024 17:35:26 -0600 Subject: [PATCH 5/7] Simplifies 'open workspace' behavior, omitting selection of logfile --- .../renderer/components/InvestTab/index.jsx | 10 ++---- workbench/tests/renderer/investtab.test.js | 31 +------------------ 2 files changed, 3 insertions(+), 38 deletions(-) diff --git a/workbench/src/renderer/components/InvestTab/index.jsx b/workbench/src/renderer/components/InvestTab/index.jsx index f6624f2142..8cee4a53b2 100644 --- a/workbench/src/renderer/components/InvestTab/index.jsx +++ b/workbench/src/renderer/components/InvestTab/index.jsx @@ -189,14 +189,8 @@ class InvestTab extends React.Component { ); } - handleOpenWorkspace(logfile, workspace_dir) { - if (logfile) { - ipcRenderer.send(ipcMainChannels.SHOW_ITEM_IN_FOLDER, logfile); - } + handleOpenWorkspace(workspace_dir) { if (workspace_dir) { - // Always call shell.openPath. - // If shell.showItemInFolder failed, it will have failed silently; - // if it succeeded, the subsequent call to shell.openPath will not "undo" the result of shell.showItemInFolder. this.openWorkspaceDir(workspace_dir); } } @@ -284,7 +278,7 @@ class InvestTab extends React.Component { ? ( this.handleOpenWorkspace(logfile, argsValues?.workspace_dir)} + handleOpenWorkspace={() => this.handleOpenWorkspace(argsValues?.workspace_dir)} terminateInvestProcess={this.terminateInvestProcess} /> ) diff --git a/workbench/tests/renderer/investtab.test.js b/workbench/tests/renderer/investtab.test.js index 4a82955f32..2a125fbddc 100644 --- a/workbench/tests/renderer/investtab.test.js +++ b/workbench/tests/renderer/investtab.test.js @@ -117,13 +117,9 @@ describe('Run status Alert renders with status from a recent run', () => { logfile: 'foo.txt', }); - jest.spyOn(shell, 'showItemInFolder'); - const { findByRole } = renderInvestTab(job); const openWorkspaceBtn = await findByRole('button', { name: 'Open Workspace' }); expect(openWorkspaceBtn).toBeTruthy(); - openWorkspaceBtn.click(); - expect(shell.showItemInFolder).toHaveBeenCalledTimes(1); }); }); @@ -148,42 +144,20 @@ describe('Open Workspace button', () => { removeIpcMainListeners(); }); - test('should open workspace with logfile selected, if logfile exists', async () => { - const job = { - ...baseJob, - argsValues: { - workspace_dir: '/workspace', - }, - logfile: '/workspace/log.txt', - }; - - jest.spyOn(shell, 'showItemInFolder'); - - const { findByRole } = renderInvestTab(job); - const openWorkspaceBtn = await findByRole('button', { name: 'Open Workspace' }); - openWorkspaceBtn.click(); - - expect(shell.showItemInFolder).toHaveBeenCalledTimes(1); - expect(shell.showItemInFolder).toHaveBeenCalledWith(job.logfile); - }); - - test('should open workspace (without logfile selected), if workspace exists but logfile does not', async () => { + test('should open workspace', async () => { const job = { ...baseJob, argsValues: { workspace_dir: '/workspace', }, - logfile: undefined, }; - jest.spyOn(shell, 'showItemInFolder'); jest.spyOn(ipcRenderer, 'invoke'); const { findByRole } = renderInvestTab(job); const openWorkspaceBtn = await findByRole('button', { name: 'Open Workspace' }) openWorkspaceBtn.click(); - expect(shell.showItemInFolder).not.toHaveBeenCalled(); expect(ipcRenderer.invoke).toHaveBeenCalledTimes(1); expect(ipcRenderer.invoke).toHaveBeenCalledWith(ipcMainChannels.OPEN_PATH, job.argsValues.workspace_dir); }); @@ -195,10 +169,8 @@ describe('Open Workspace button', () => { argsValues: { workspace_dir: '/nonexistent-workspace', }, - logfile: undefined, }; - jest.spyOn(shell, 'showItemInFolder'); jest.spyOn(ipcRenderer, 'invoke'); ipcRenderer.invoke.mockResolvedValue('Error opening workspace'); @@ -206,7 +178,6 @@ describe('Open Workspace button', () => { const openWorkspaceBtn = await findByRole('button', { name: 'Open Workspace' }); openWorkspaceBtn.click(); - expect(shell.showItemInFolder).not.toHaveBeenCalled(); expect(ipcRenderer.invoke).toHaveBeenCalledTimes(1); expect(ipcRenderer.invoke).toHaveBeenCalledWith(ipcMainChannels.OPEN_PATH, job.argsValues.workspace_dir); From ee148ad5f7fc98851b701a9b338762e90a6b1ba5 Mon Sep 17 00:00:00 2001 From: Emily Davis Date: Thu, 5 Sep 2024 11:44:40 -0600 Subject: [PATCH 6/7] Fixing rst formatting --- HISTORY.rst | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/HISTORY.rst b/HISTORY.rst index c0f6f95c28..14a2c709b1 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -38,13 +38,13 @@ Unreleased Changes ------------------ * Workbench - * Several small updates to the model input form UI to improve usability - and visual consistency (https://github.com/natcap/invest/issues/912) - * Fixed a bug that caused the application to crash when attempting to - open a workspace without a valid logfile - (https://github.com/natcap/invest/issues/1598) - * Fixed a bug that was allowing readonly workspace directories on Windows - (https://github.com/natcap/invest/issues/1599) + * Several small updates to the model input form UI to improve usability + and visual consistency (https://github.com/natcap/invest/issues/912) + * Fixed a bug that caused the application to crash when attempting to + open a workspace without a valid logfile + (https://github.com/natcap/invest/issues/1598) + * Fixed a bug that was allowing readonly workspace directories on Windows + (https://github.com/natcap/invest/issues/1599) 3.14.2 (2024-05-29) ------------------- From 0846c72500e96ff0e5ed6ca73af9e4e05c09d7f2 Mon Sep 17 00:00:00 2001 From: Emily Davis Date: Thu, 5 Sep 2024 12:24:40 -0600 Subject: [PATCH 7/7] Removes openWorkspaceDir helper function --- .../src/renderer/components/InvestTab/index.jsx | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/workbench/src/renderer/components/InvestTab/index.jsx b/workbench/src/renderer/components/InvestTab/index.jsx index 8cee4a53b2..7e26369c8b 100644 --- a/workbench/src/renderer/components/InvestTab/index.jsx +++ b/workbench/src/renderer/components/InvestTab/index.jsx @@ -71,7 +71,6 @@ class InvestTab extends React.Component { this.investLogfileCallback = this.investLogfileCallback.bind(this); this.investExitCallback = this.investExitCallback.bind(this); this.handleOpenWorkspace = this.handleOpenWorkspace.bind(this); - this.openWorkspaceDir = this.openWorkspaceDir.bind(this); this.showErrorModal = this.showErrorModal.bind(this); } @@ -189,17 +188,13 @@ class InvestTab extends React.Component { ); } - handleOpenWorkspace(workspace_dir) { + async handleOpenWorkspace(workspace_dir) { if (workspace_dir) { - this.openWorkspaceDir(workspace_dir); - } - } - - async openWorkspaceDir(workspace_dir) { - const error = await ipcRenderer.invoke(ipcMainChannels.OPEN_PATH, workspace_dir); - if (error) { - logger.error(`Error opening workspace (${workspace_dir}). ${error}`); - this.showErrorModal(true); + const error = await ipcRenderer.invoke(ipcMainChannels.OPEN_PATH, workspace_dir); + if (error) { + logger.error(`Error opening workspace (${workspace_dir}). ${error}`); + this.showErrorModal(true); + } } }