diff --git a/gui/src/main/electron.js b/gui/src/main/electron.js
index d33a9210..0f57d6cd 100644
--- a/gui/src/main/electron.js
+++ b/gui/src/main/electron.js
@@ -1,4 +1,4 @@
-const { app, BrowserWindow, ipcMain, dialog, shell, nativeTheme } = require('electron')
+const { app, BrowserWindow, Menu, ipcMain, dialog, shell, nativeTheme } = require('electron')
const osu = require('node-os-utils')
const path = require("path");
const writeYamlFile = require('write-yaml-file')
@@ -7,7 +7,9 @@ const os = require('os')
const { handleGetSingleFolder,handleGetMultipleFolders, handleGetSingleFile, handleGetMultipleFiles} = require('./modules/dialogHandler')
const { discoverWorkflows, workflowToConfig } = require('./modules/workflows')
-const { getEnvironmentStatus, lineBreakTransform, CondaEnvironment} = require('./modules/cmd');
+const { CondaEnvironment} = require('./modules/cmd');
+const { buildMenu } = require('./modules/menu')
+const { Profile } = require('./modules/profile')
// Handle creating/removing shortcuts on Windows when installing/uninstalling.
if (require('electron-squirrel-startup')) app.quit();
@@ -15,6 +17,7 @@ if (require('electron-squirrel-startup')) app.quit();
let mainWindow;
let workflows;
let environment;
+let profile;
function createWindow() {
// Create the browser window.
@@ -32,14 +35,18 @@ function createWindow() {
},
});
mainWindow.setTitle("alphaDIA");
- mainWindow.removeMenu()
mainWindow.loadFile(path.join(__dirname, "../dist/index.html"));
+ profile = new Profile()
+
+ Menu.setApplicationMenu(buildMenu(mainWindow, profile));
+
// Open the DevTools if NODE_ENV=dev
if (process.env.NODE_ENV === "dev"){
mainWindow.webContents.openDevTools({ mode: "detach" });
}
- environment = new CondaEnvironment("alpha")
+
+ environment = new CondaEnvironment(profile)
workflows = discoverWorkflows(mainWindow)
}
@@ -82,7 +89,7 @@ function handleStartWorkflow(workflow) {
// save config.yaml in workflow folder
writeYamlFile.sync(configPath, config, {lineWidth: -1})
- return environment.spawn(`conda run -n ${environment.envName} --no-capture-output alphadia extract --config ${configPath}`)
+ return environment.spawn(`conda run -n ${profile.config.conda.envName} --no-capture-output alphadia extract --config ${configPath}`)
}
// This method will be called when Electron has finished
@@ -122,15 +129,6 @@ app.whenReady().then(() => {
powerMonitor.on("suspend", () => {
powerSaveBlocker.start("prevent-app-suspension");
});
-
- mainWindow.webContents.on('render-process-gone', function (event, detailed) {
- console.log("!crashed, reason: " + detailed.reason + ", exitCode = " + detailed.exitCode)
- if (detailed.reason == "crashed"){
- // relaunch app
- app.relaunch({ args: process.argv.slice(1).concat(['--relaunch']) })
- app.exit(0)
- }
- })
});
app.on('window-all-closed', () => {
diff --git a/gui/src/main/modules/cmd.js b/gui/src/main/modules/cmd.js
index 5f17ce43..91da17e1 100644
--- a/gui/src/main/modules/cmd.js
+++ b/gui/src/main/modules/cmd.js
@@ -46,7 +46,6 @@ function testCommand(command, pathUpdate){
const CondaEnvironment = class {
pathUpdate = ""
- envName = "";
exists = {
conda: false,
python: false,
@@ -65,8 +64,8 @@ const CondaEnvironment = class {
std = [];
pid = null;
- constructor(envName){
- this.envName = envName;
+ constructor(profile){
+ this.profile = profile;
this.initPromise = this.discoverCondaPATH().then((pathUpdate) => {
this.pathUpdate = pathUpdate;
@@ -81,7 +80,7 @@ const CondaEnvironment = class {
// check if info exist and active_prefix is not null
if (info != null){
if (info["active_prefix"] != null){
- if (path.basename(info["active_prefix"]) == this.envName){
+ if (path.basename(info["active_prefix"]) == profile.config.conda.envName){
//dialog.showErrorBox("Conda environment already activated", "The conda environment " + this.envName + " is already activated. Please deactivate the environment and restart alphaDIA.")
return Promise.reject("Conda environment already activated")
}
@@ -103,8 +102,8 @@ const CondaEnvironment = class {
discoverCondaPATH(){
return new Promise((resolve, reject) => {
-
- const paths = ["", ...condaPATH(os.userInfo().username, os.platform())]
+
+ const paths = [this.profile.config.conda.path, ...condaPATH(os.userInfo().username, os.platform())]
Promise.all(paths.map((path) => {
return testCommand("conda", path)
})).then((codes) => {
@@ -124,7 +123,6 @@ const CondaEnvironment = class {
this.exec('conda info --json', (err, stdout, stderr) => {
if (err) {console.log(err); reject(err); return;}
const info = JSON.parse(stdout);
- console.log(info)
this.versions.conda = info["conda_version"];
this.exists.conda = true;
resolve(info);
@@ -134,7 +132,8 @@ const CondaEnvironment = class {
checkPythonVersion(){
return new Promise((resolve, reject) => {
- this.exec(`conda run -n ${this.envName} python --version`, (err, stdout, stderr) => {
+
+ this.exec(`conda run -n ${this.profile.config.conda.envName} python --version`, (err, stdout, stderr) => {
if (err) {console.log(err); reject(err); return;}
const versionPattern = /\d+\.\d+\.\d+/;
const versionList = stdout.match(versionPattern);
@@ -150,7 +149,7 @@ const CondaEnvironment = class {
}
checkAlphadiaVersion(){
return new Promise((resolve, reject) => {
- this.exec(`conda list -n ${this.envName} --json`, (err, stdout, stderr) => {
+ this.exec(`conda list -n ${this.profile.config.conda.envName} --json`, (err, stdout, stderr) => {
if (err) {console.log(err); reject(err); return;}
const info = JSON.parse(stdout);
const packageInfo = info.filter((p) => p.name == "alphadia");
@@ -170,7 +169,7 @@ const CondaEnvironment = class {
buildEnvironmentStatus(){
return {
- envName: this.envName,
+ envName: this.profile.config.conda.envName,
versions: this.versions,
exists: this.exists,
ready: this.ready
@@ -189,6 +188,7 @@ const CondaEnvironment = class {
spawn(cmd){
console.log(cmd)
+ this.std = [];
return new Promise((resolve, reject) => {
if (!this.ready){
reject("Environment not ready");
@@ -240,94 +240,6 @@ const CondaEnvironment = class {
}
-
-function getCondaInfo() {
- return new Promise((resolve, reject) => {
- exec('conda info --json', (err, stdout, stderr) => {
- if (err) {
- reject(err);
- }
- const info = JSON.parse(stdout);
- resolve(info);
- });
- });
-}
-
-function getPythonVersion(envName){
- return new Promise((resolve, reject) => {
- exec(`conda run -n ${envName} python --version`, (err, stdout, stderr) => {
- if (err) {
- reject(err);
- return;
- }
- const versionPattern = /\d+\.\d+\.\d+/;
- const versionList = stdout.match(versionPattern);
- // check if versionList is null
- if (versionList == null){
- reject("Python version not found");
- return;
- }
- if (versionList.length == 0){
- reject("Python version not found");
- return;
- }
- resolve(versionList[0]);
- });
- });
-}
-
-function getPackageVersion(envName, packageName){
- return new Promise((resolve, reject) => {
- exec(`conda list -n ${envName} --json`, (err, stdout, stderr) => {
- if (err) {
- reject(err);
- }
- const info = JSON.parse(stdout);
- const packageInfo = info.filter((package) => package.name == packageName);
- if (packageInfo.length == 0){
- reject(`Package ${packageName} not found in environment ${envName}`);
- }
- resolve(packageInfo[0].version);
- });
- });
-}
-
-function getEnvironmentStatus(envName){
- environment = {
- envName: envName,
- hasConda: false,
- condaVersion: "",
- hasEnv: false,
- hasPython: false,
- pythonVersion: "",
- hasAlphadia: false,
- alphadiaVersion: "",
- ready: false
- }
-
- return getCondaInfo().then((info) => {
- environment.hasConda = true;
- environment.condaVersion = info["conda_version"];
- environment.hasEnv = info["envs"].map((env) => path.basename(env)).includes(envName);
- return getPythonVersion(envName).then((version) => {
- environment.hasPython = true;
- environment.pythonVersion = version;
- return getPackageVersion(envName, "alphadia").then((version) => {
- environment.hasAlphadia = true;
- environment.alphadiaVersion = version;
- environment.ready = [environment.hasConda, environment.hasEnv, environment.hasPython, environment.hasAlphadia].every(Boolean);
- return environment
- }).catch((error) => {
- return environment
- })
- }).catch((error) => {
- return environment
- })
- }).catch((error) => {
- return environment
- })
-}
-
function lineBreakTransform () {
// https://stackoverflow.com/questions/40781713/getting-chunks-by-newline-in-node-js-data-stream
@@ -359,12 +271,6 @@ function lineBreakTransform () {
module.exports = {
- getCondaInfo,
- getPythonVersion,
- getPackageVersion,
- getEnvironmentStatus,
- lineBreakTransform,
- testCommand,
CondaEnvironment
}
diff --git a/gui/src/main/modules/menu.js b/gui/src/main/modules/menu.js
new file mode 100644
index 00000000..4926aaa4
--- /dev/null
+++ b/gui/src/main/modules/menu.js
@@ -0,0 +1,69 @@
+const {app, Menu} = require('electron')
+const path = require('path')
+const {shell} = require('electron')
+
+function buildMenu(mainWindow, profile) {
+
+ const isMac = process.platform === 'darwin'
+
+ const template = [
+ ...(isMac
+ ? [{
+ label: app.name,
+ submenu: [
+ { role: 'about' },
+ { type: 'separator' },
+ { id: 'preferences', label: 'Preferences', click: () => { profile.openProfile() } },
+ { type: 'separator' },
+ { role: 'hide' },
+ { role: 'hideOthers' },
+ { role: 'unhide' },
+ { type: 'separator' },
+ { role: 'quit' }
+ ]
+ }]
+ : []),
+ {
+ label: 'File',
+ submenu: [
+ isMac ? { role: 'close' } : { role: 'quit' },
+ ...(isMac ? []: [{ id: 'preferences', label: 'Preferences', click: () => { profile.openProfile() } }])
+ ]
+ },
+ {
+ label: 'Window',
+ submenu: [
+ { role: 'minimize' },
+ { role: 'zoom' },
+ ...(isMac
+ ? [
+ { type: 'separator' },
+ { role: 'front' },
+ { type: 'separator' },
+ { role: 'window' }
+ ]
+ : [
+ { role: 'close' }
+ ])
+ ]
+ },
+ {
+ role: 'help',
+ submenu: [
+ {
+ label: 'Learn More',
+ click: async () => {
+ const { shell } = require('electron')
+ await shell.openExternal('https://electronjs.org')
+ }
+ }
+ ]
+ }
+ ]
+
+ return Menu.buildFromTemplate(template)
+}
+
+module.exports = {
+ buildMenu
+}
\ No newline at end of file
diff --git a/gui/src/main/modules/profile.js b/gui/src/main/modules/profile.js
new file mode 100644
index 00000000..0960c65e
--- /dev/null
+++ b/gui/src/main/modules/profile.js
@@ -0,0 +1,48 @@
+
+const fs = require("fs")
+const path = require("path")
+const { app, shell} = require("electron")
+
+const Profile = class {
+
+ config = {
+ "version": "1.3.0",
+ "conda": {
+ "envName": "alpha",
+ "path": ""
+ },
+ "clippy": false,
+ }
+
+ constructor() {
+
+ // check if profile exists
+ if (!fs.existsSync(this.getProfilePath())) {
+ this.saveProfile()
+ } else {
+ this.loadProfile()
+ }
+
+ console.log(this.getProfilePath())
+ }
+
+ saveProfile() {
+ fs.writeFileSync(this.getProfilePath(), JSON.stringify(this.config, null, 4))
+ }
+
+ loadProfile() {
+ this.config = JSON.parse(fs.readFileSync(this.getProfilePath()))
+ }
+
+ getProfilePath() {
+ return path.join(app.getPath("userData"), "profile.json")
+ }
+
+ openProfile() {
+ shell.openPath(this.getProfilePath())
+ }
+}
+
+module.exports = {
+ Profile
+}
\ No newline at end of file
diff --git a/gui/src/renderer/components/MenuDrawer.js b/gui/src/renderer/components/MenuDrawer.js
index 2316cc0e..9edd2d53 100644
--- a/gui/src/renderer/components/MenuDrawer.js
+++ b/gui/src/renderer/components/MenuDrawer.js
@@ -9,6 +9,7 @@ import HomeIcon from '@mui/icons-material/Home';
import FolderIcon from '@mui/icons-material/Folder';
import SettingsApplicationsIcon from '@mui/icons-material/SettingsApplications';
import SaveIcon from '@mui/icons-material/Save';
+import TerminalIcon from '@mui/icons-material/Terminal';
const DrawerContainer = styled('div')(({ theme }) => ({
width: 240,
@@ -133,11 +134,24 @@ const MenuDrawer = ({
+
+
+
+
+
+
+
+
+
-
+
)
diff --git a/gui/src/renderer/components/RunButton.js b/gui/src/renderer/components/RunButton.js
index 7547de40..15d18639 100644
--- a/gui/src/renderer/components/RunButton.js
+++ b/gui/src/renderer/components/RunButton.js
@@ -69,7 +69,6 @@ const RunButton = ({
function handleRunClick() {
const validation = validateMethod(method);
if (profile.running) {
- navigate("/run");
return;
}
if (!validation.valid) {
diff --git a/gui/src/renderer/pages/Run.js b/gui/src/renderer/pages/Run.js
index 40f69264..40f6ed1e 100644
--- a/gui/src/renderer/pages/Run.js
+++ b/gui/src/renderer/pages/Run.js
@@ -87,15 +87,21 @@ const Output = () => {
}
React.useEffect(() => {
+ setItems([]);
+ currentLengthRef.current = 0;
+
let isMounted = true;
const interval = setInterval(() => {
window.electronAPI.getOutputLength().then((length) => {
if (isMounted){
if (length > currentLengthRef.current) {
- console.log("updating items")
updateItems(currentLengthRef.current);
}
+ if (length < currentLengthRef.current) {
+ setItems([]);
+ currentLengthRef.current = 0;
+ }
}
});
}, 100);
@@ -104,6 +110,8 @@ const Output = () => {
isMounted = false;
clearInterval(interval);
}
+
+
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);