-
Notifications
You must be signed in to change notification settings - Fork 94
add fields to configure plugin conda executable and env paths #2654
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 7 commits
b1390ce
3021042
2a06ee1
365089e
c56f3e0
ccac65f
311957f
5c32b26
6ea2f34
44910ec
73d187e
19af607
c14539c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -4,6 +4,7 @@ import PropTypes from 'prop-types'; | |||||
| import Button from 'react-bootstrap/Button'; | ||||||
| import Col from 'react-bootstrap/Col'; | ||||||
| import Form from 'react-bootstrap/Form'; | ||||||
| import InputGroup from 'react-bootstrap/InputGroup'; | ||||||
| import Modal from 'react-bootstrap/Modal'; | ||||||
| import Row from 'react-bootstrap/Row'; | ||||||
| import Spinner from 'react-bootstrap/Spinner'; | ||||||
|
|
@@ -31,6 +32,8 @@ export default function PluginModal(props) { | |||||
| const [url, setURL] = useState(''); | ||||||
| const [revision, setRevision] = useState(''); | ||||||
| const [path, setPath] = useState(''); | ||||||
| const [condaPath, setCondaPath] = useState(''); | ||||||
| const [pluginEnvs, setPluginEnvs] = useState({}); | ||||||
| const [installErr, setInstallErr] = useState(''); | ||||||
| const [uninstallErr, setUninstallErr] = useState(''); | ||||||
| const [pluginToRemove, setPluginToRemove] = useState(''); | ||||||
|
|
@@ -62,6 +65,21 @@ export default function PluginModal(props) { | |||||
| setPluginSourceMissingError(false); | ||||||
| }; | ||||||
|
|
||||||
| useEffect(() => { | ||||||
| ipcRenderer.invoke( | ||||||
| ipcMainChannels.GET_SETTING, 'micromamba' | ||||||
| ).then((data) => setCondaPath(data)); | ||||||
| ipcRenderer.invoke( | ||||||
| ipcMainChannels.GET_SETTING, 'plugins' | ||||||
| ).then((data) => setPluginEnvs( | ||||||
| Object.fromEntries( | ||||||
| Object.keys(data).map( | ||||||
| (pluginID) => [pluginID, data[pluginID].env] | ||||||
| ) | ||||||
| ) | ||||||
| )) | ||||||
| }, []); | ||||||
|
|
||||||
| useEffect(() => { | ||||||
| clearFormErrors(); | ||||||
| }, [installFrom]); | ||||||
|
|
@@ -149,6 +167,37 @@ export default function PluginModal(props) { | |||||
| ); | ||||||
| }; | ||||||
|
|
||||||
| const resetCondaPath = () => { | ||||||
| console.log('reset conda path'); | ||||||
| ipcRenderer.invoke( | ||||||
| ipcMainChannels.GET_SETTING, 'defaultMicromamba' | ||||||
| ).then((data) => { | ||||||
| setCondaPath(data); | ||||||
| }); | ||||||
| }; | ||||||
|
|
||||||
| const saveCondaPath = () => { | ||||||
| ipcRenderer.send( | ||||||
| ipcMainChannels.SET_SETTING, 'micromamba', condaPath | ||||||
| ); | ||||||
| }; | ||||||
|
|
||||||
| const resetPluginEnv = (pluginID) => { | ||||||
| ipcRenderer.invoke( | ||||||
| ipcMainChannels.GET_SETTING, `plugins.${pluginID}.defaultEnv` | ||||||
| ).then((value) => { | ||||||
| setPluginEnvs({...pluginEnvs, [pluginID]: value}); | ||||||
| }); | ||||||
| }; | ||||||
|
|
||||||
| const savePluginEnvs = () => { | ||||||
| Object.entries(pluginEnvs).forEach(([pluginID, envPath]) => { | ||||||
| ipcRenderer.send( | ||||||
| ipcMainChannels.SET_SETTING, `plugins.${pluginID}.env`, envPath | ||||||
| ); | ||||||
| }); | ||||||
| }; | ||||||
|
|
||||||
| const selectDirectory = async (event) => { | ||||||
| const data = await ipcRenderer.invoke( | ||||||
| ipcMainChannels.SHOW_OPEN_DIALOG, { properties: ['openDirectory'] } | ||||||
|
|
@@ -157,9 +206,10 @@ export default function PluginModal(props) { | |||||
| // dialog defaults allow only 1 selection | ||||||
| setPath(data.filePaths[0]); | ||||||
| } | ||||||
| } | ||||||
| }; | ||||||
|
|
||||||
| useEffect(() => { | ||||||
|
|
||||||
| ipcRenderer.on('plugin-install-status', (msg) => { setStatusMessage(msg); }); | ||||||
| if (show) { | ||||||
| if (window.Workbench.OS === 'win32') { | ||||||
|
|
@@ -187,7 +237,6 @@ export default function PluginModal(props) { | |||||
| let pluginFields; | ||||||
| if (installFrom === 'url') { | ||||||
| pluginFields = ( | ||||||
|
|
||||||
| <Row> | ||||||
| <Form.Group as={Col} xs={7}> | ||||||
| <Form.Label htmlFor="url">{t('Git URL')}</Form.Label> | ||||||
|
|
@@ -433,6 +482,106 @@ export default function PluginModal(props) { | |||||
| } | ||||||
| </div> | ||||||
| </Form> | ||||||
| <hr /> | ||||||
| <Form aria-labelledby="configure-conda-form-title"> | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks for including the
Suggested change
|
||||||
| <Form.Group> | ||||||
| <h5 id="configure-conda-form-title" className="mb-3">{t('Configure conda executable (Advanced)')}</h5> | ||||||
| <Form.Text | ||||||
| as="span" | ||||||
| id="conda-executable-desciption" | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
| className="plugin-form-text mb-3" | ||||||
| > | ||||||
| {t('InVEST is distributed with a copy of micromamba, a conda-like ' | ||||||
| + 'package manager that is used to manage plugin environments. ' | ||||||
| + 'If you have conda or mamba installed elsewhere on the system, ' | ||||||
| + 'you can configure InVEST to use that executable instead. This ' | ||||||
| + 'may be useful if you run into limitations of the included ' | ||||||
| + 'micromamba distribution.')} | ||||||
| </Form.Text> | ||||||
| <Form.Label htmlFor="condaPath">{t('Conda or mamba executable')}</Form.Label> | ||||||
| <div className="d-flex flex-nowrap w-100"> | ||||||
| <Form.Control | ||||||
| id="condaPath" | ||||||
| type="text" | ||||||
| value={condaPath} | ||||||
| onChange={(event) => setCondaPath(event.target.value)} | ||||||
| className="me-1" | ||||||
| /> | ||||||
| <Button | ||||||
| aria-label="browse for conda executable" | ||||||
| className="ms-1 me-1" | ||||||
| id="browse-conda-button" | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No need for an |
||||||
| variant="outline-dark" | ||||||
| onClick={selectDirectory} | ||||||
| > | ||||||
| <MdFolderOpen /> | ||||||
| </Button> | ||||||
| <Button onClick={resetCondaPath} className="text-nowrap ms-1"> | ||||||
| {t('Reset')} | ||||||
| </Button> | ||||||
| </div> | ||||||
| <Button onClick={saveCondaPath} className="text-nowrap mt-3"> | ||||||
| {t('Save')} | ||||||
| </Button> | ||||||
| </Form.Group> | ||||||
| </Form> | ||||||
| <hr /> | ||||||
| <Form aria-labelledby="configure-plugin-envs-form-title"> | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
| <Form.Group> | ||||||
| <h5 id="configure-plugin-envs-form-title" className="mb-3">{t('Configure plugin environments (Advanced)')}</h5> | ||||||
| <Form.Text | ||||||
| as="span" | ||||||
| id="plugin-env-desciption" | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
| className="plugin-form-text mb-3" | ||||||
| > | ||||||
| {t('InVEST creates a separate conda environment for each installed ' | ||||||
| + 'plugin. You may override this and provide a path to a different ' | ||||||
| + 'conda environment, which may be useful for development and ' | ||||||
| + 'debugging.')} | ||||||
| </Form.Text> | ||||||
| {Object.keys(plugins).map((pluginID) => ( | ||||||
| <Form.Group key={`${pluginID}-env-group`}> | ||||||
| <Form.Label htmlFor={pluginID}> | ||||||
| {pluginID} | ||||||
| </Form.Label> | ||||||
| <div | ||||||
| className="d-flex flex-nowrap w-100 mb-1" | ||||||
| > | ||||||
| <Form.Control | ||||||
| id={pluginID} | ||||||
| type="text" | ||||||
| value={pluginEnvs[pluginID]} | ||||||
| onChange={(event) => setPluginEnvs( | ||||||
| {...pluginEnvs, [pluginID]: event.target.value} | ||||||
| )} | ||||||
| className="me-1" | ||||||
| /> | ||||||
| <Button | ||||||
| aria-label="browse for env" | ||||||
| className="ms-1 me-2" | ||||||
| id="browse-env-button" | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No need for an
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. …unless that |
||||||
| variant="outline-dark" | ||||||
| onClick={selectDirectory} | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I couldn't figure out why the
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Some automated tests might be helpful here, too! 😃 |
||||||
| > | ||||||
| <MdFolderOpen /> | ||||||
| </Button> | ||||||
| <Button | ||||||
| onClick={() => resetPluginEnv(pluginID)} | ||||||
| className="text-nowrap" | ||||||
| > | ||||||
| {t('Reset')} | ||||||
| </Button> | ||||||
| </div> | ||||||
| </Form.Group> | ||||||
| ))} | ||||||
| <Button | ||||||
| onClick={savePluginEnvs} | ||||||
| className="text-nowrap mt-3" | ||||||
| disabled={!Object.keys(pluginEnvs).length}> | ||||||
| {t('Save')} | ||||||
| </Button> | ||||||
| </Form.Group> | ||||||
| </Form> | ||||||
| </Modal.Body> | ||||||
| ); | ||||||
| if (installErr) { | ||||||
|
|
||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems that "env create" rather than just "create" is necessary for compatibility with conda.