Skip to content

Commit 6f99802

Browse files
authored
Merge pull request #156 from architecture-building-systems/release-4.0
Merge release-4.0 into master
2 parents df77f66 + 6159b91 commit 6f99802

File tree

181 files changed

+16086
-7019
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

181 files changed

+16086
-7019
lines changed

.env.development

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,4 @@
11
VITE_CEA_URL="http://localhost:5050"
2+
VITE_AUTH_URL="http://localhost:3000"
3+
4+
VITE_AUTH_COOKIE_NAME="stack-access"

.env.electron

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,4 @@
11
VITE_CEA_URL="http://localhost:5050"
2+
VITE_AUTH_URL="http://localhost:3000"
3+
4+
VITE_AUTH_COOKIE_NAME="stack-access"

.eslintrc.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,12 +38,17 @@ module.exports = {
3838
ecmaVersion: 'latest',
3939
sourceType: 'module',
4040
},
41-
plugins: ['react-refresh', 'simple-import-sort'],
41+
plugins: [
42+
'eslint-plugin-react-compiler',
43+
'react-refresh',
44+
'simple-import-sort',
45+
],
4246
rules: {
4347
'prettier/prettier': ['error', {}, { usePrettierrc: true }],
4448
'react/react-in-jsx-scope': 'off',
4549
'jsx-a11y/accessible-emoji': 'off',
4650
'react/prop-types': 'off',
51+
'react-compiler/react-compiler': 'warn',
4752
// 'simple-import-sort/imports': 'error',
4853
// 'simple-import-sort/exports': 'error',
4954
'jsx-a11y/anchor-is-valid': [

.yarnrc.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
nodeLinker: node-modules
2-
31
injectEnvironmentFiles:
42
- .env.electron.local?
3+
4+
nodeLinker: node-modules

Dockerfile

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,34 @@
1-
FROM node:current-alpine
1+
FROM node:current-alpine AS builder
2+
3+
ARG VITE_CEA_URL=""
4+
ENV VITE_CEA_URL=$VITE_CEA_URL
25

36
RUN corepack enable
47

58
WORKDIR /app
9+
10+
# Copy only package files first to leverage cache
611
COPY package.json yarn.lock .yarnrc.yml ./
712

8-
RUN yarn
13+
# Install dependencies
14+
RUN yarn install --frozen-lockfile
15+
16+
# Copy source code
917
COPY . .
1018

19+
# Build the application
1120
RUN yarn build
12-
EXPOSE 4173
1321

14-
CMD [ "yarn", "preview", "--host" ]
22+
# Create production image
23+
FROM nginx:alpine
24+
25+
LABEL org.opencontainers.image.source=https://github.com/architecture-building-systems/CityEnergyAnalyst-GUI
26+
27+
# Copy built assets from builder stage
28+
COPY --from=builder /app/dist /usr/share/nginx/html
29+
30+
# Expose port
31+
EXPOSE 80
32+
33+
# Use nginx to serve the static files
34+
CMD ["nginx", "-g", "daemon off;"]

dev-app-update.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
provider: github
2+
owner: architecture-building-systems
3+
repo: CityEnergyAnalyst-GUI

electron/cea/env.mjs

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { app } from 'electron';
2+
import { fileURLToPath } from 'url';
23
import path from 'path';
34
import os from 'os';
45
import { exec, execSync, spawn } from 'child_process';
@@ -11,7 +12,15 @@ const execAsync = promisify(exec);
1112

1213
const paths = {
1314
darwin: {
14-
micromamba: path.join(process.resourcesPath, os.arch(), 'micromamba'),
15+
micromamba: app.isPackaged
16+
? path.join(process.resourcesPath, os.arch(), 'micromamba')
17+
: // FIXME: Temp fix for dev env
18+
path.join(
19+
fileURLToPath(import.meta.url),
20+
'../../../dependencies',
21+
os.arch(),
22+
'micromamba',
23+
),
1524
root: path.join(app.getPath('documents'), 'CityEnergyAnalyst'),
1625
},
1726
win32: {
@@ -80,10 +89,17 @@ export const getCEAenvVersion = async () => {
8089
};
8190

8291
export const checkCEAenv = async () => {
92+
// Check if CEA is in the environment
8393
try {
8494
await execAsync(
8595
`"${getMicromambaPath(true)}" -r "${getCEARootPath()}" -n cea run cea --version`,
8696
);
97+
98+
// Check if CEA is installed as editable package (i.e. dev mode)
99+
const { stdout } = await execAsync(
100+
`"${getMicromambaPath(true)}" -r "${getCEARootPath()}" -n cea run pip show cityenergyanalyst`,
101+
);
102+
return stdout.toString().trim().includes('Editable project location');
87103
} catch (error) {
88104
console.error(error);
89105
throw new CEAError(
@@ -104,7 +120,7 @@ const fetchCondaLock = async (ceaVersion, condaLockPath) => {
104120
await downloadFile(condaLockUrl, condaLockPath);
105121
} catch (error) {
106122
console.error(error);
107-
new Error(`Unable to download file from ${condaLockUrl}`);
123+
throw new Error(`Unable to fetch conda environment file.`);
108124
}
109125
};
110126

@@ -206,7 +222,7 @@ export const updateCEAenv = async (ceaVersion) => {
206222
getCEARootPath(),
207223
'-n',
208224
'cea',
209-
'update',
225+
'create',
210226
'-f',
211227
condaLockPath,
212228
'-y',

electron/cea/process.mjs

Lines changed: 49 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
1-
import fs from 'fs';
2-
import path from 'path';
3-
import { spawn } from 'child_process';
1+
import { spawn, execSync } from 'child_process';
42

53
import { app, dialog } from 'electron';
64

@@ -15,21 +13,15 @@ export function createCEAProcess(url, BrowserWindow, callback) {
1513
console.log(`createCEAProcess(${url})`);
1614
// For windows
1715
if (process.platform === 'win32') {
18-
let scriptPath = path.join(
19-
path.dirname(process.execPath),
20-
'/../',
21-
'dashboard.bat',
22-
);
23-
// Fallback to default install path
24-
if (!fs.existsSync(scriptPath))
25-
scriptPath = path.join(
26-
process.env.USERPROFILE,
27-
'Documents',
28-
'CityEnergyAnalyst',
29-
'dashboard.bat',
30-
);
31-
console.log(scriptPath);
32-
cea = spawn('cmd.exe', ['/c', scriptPath]);
16+
cea = spawn(getMicromambaPath(), [
17+
'-r',
18+
getCEARootPath(),
19+
'-n',
20+
'cea',
21+
'run',
22+
'cea',
23+
'dashboard',
24+
]);
3325
} else if (process.platform === 'darwin') {
3426
cea = spawn(getMicromambaPath(), [
3527
'-r',
@@ -43,6 +35,8 @@ export function createCEAProcess(url, BrowserWindow, callback) {
4335
}
4436

4537
if (cea) {
38+
console.debug('CEA process started with PID:', cea.pid);
39+
4640
// Attach cea output to console
4741
cea.stdout.on('data', function (data) {
4842
console.log(data.toString('utf8').trim());
@@ -54,7 +48,10 @@ export function createCEAProcess(url, BrowserWindow, callback) {
5448

5549
// Show Error message box when CEA encounters any error on startup
5650
cea.stderr.on('data', saveStartupError);
57-
cea.on('exit', showStartupError);
51+
cea.on('exit', () => {
52+
cea = null;
53+
showStartupError();
54+
});
5855
}
5956

6057
function saveStartupError(message) {
@@ -85,10 +82,41 @@ export function createCEAProcess(url, BrowserWindow, callback) {
8582
}
8683

8784
// Kill process and stop all timed events
88-
export function killCEAProcess() {
85+
export function killCEAProcess(killTimeout = 10000) {
8986
if (cea) {
9087
cea.removeAllListeners('exit');
91-
process.kill(cea.pid);
88+
let result = false;
89+
90+
if (process.platform === 'win32') {
91+
// FIXME: Force kill on windows for now
92+
console.debug('Forcing process kill using taskkill on Windows');
93+
try {
94+
execSync(`taskkill /PID ${cea.pid} /T /F`);
95+
result = true;
96+
} catch (error) {
97+
console.error(`Error killing process: ${error?.message}`);
98+
}
99+
} else {
100+
try {
101+
setTimeout(() => process.kill(cea.pid, 'SIGKILL'), killTimeout);
102+
103+
result = process.kill(cea.pid, 'SIGTERM');
104+
} catch (error) {
105+
if (error.code === 'ESRCH') {
106+
console.error('Unable to kill CEA process. (Process not found)');
107+
} else {
108+
console.error(error);
109+
}
110+
}
111+
}
112+
113+
if (result) {
114+
console.debug('CEA process killed with PID:', cea.pid);
115+
} else {
116+
console.error('Failed to kill CEA process with PID:', cea.pid);
117+
}
118+
} else {
119+
console.debug('CEA process not found. Ignoring...');
92120
}
93121
interval && clearInterval(interval);
94122
timeout && clearTimeout(timeout);

0 commit comments

Comments
 (0)