diff --git a/CHANGES.md b/CHANGES.md
index 319e5d4..fb8eeda 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -1,11 +1,13 @@
2019.1
------
+- Improve, fix, and update how to create an executable
- Turn `pyqmix-web` into a proper Python package that can be published on PyPI
- Add entry point script, such that the user can now simply enter `pyqmix-web`
in their terminal after installation, which will fire up the backend and
open the browser
- Add versioneer
- Enable user to specify pump configuration directory
+- Styling of frontend served via the build
- Update to `react-scripts` 2.1.3
2018.11.07
diff --git a/EXECUTABLE.md b/EXECUTABLE.md
index f8d4728..28ee260 100644
--- a/EXECUTABLE.md
+++ b/EXECUTABLE.md
@@ -3,14 +3,15 @@
## This guideline assumes that:
- A `run.py` file has been created.
Check out the `run.py` file in this repository.
-- Flask serves static files from the `pyqmix` sub-directory of an automatically created temporary folder. The exact location of this folder is saved in the environment variable `_MEIPASS` when the `PyInstaller`-created standalone exectuable is started. Typically it will be located inside the current user's `AppData\Local\Temp` folder.
+- Flask serves static files from an automatically created temporary folder. The exact location of this folder is saved in the environment variable `_MEIPASS` when the `PyInstaller`-created standalone exectuable is started. Typically it will be located inside the current user's `AppData\Local\Temp` folder.
Check out the `app.py` file in this repository.
- The frontend and backend are located in neighboring directories
## Prepare the Python virtual environment for the backend
- Create a virtual environment
-- Install the required dependencies: `flask`, `flask-restplus`, and, of course, `pyqmix`
-- Install `PyInstaller`
+- Install the required dependencies: ` pip install flask flask-restplus pyqmix`. The executable will only work if flask and flask-restplus are installed via pip.
+- Install PyInstaller: `pip install PyInstaller`
+- The newest `jsonschema` module does not work with PyInstaller. Instead, use `jsonchema` in an older version, for example: 2.6.0.
## Create a production build of the React frontend
1. Open a terminal
@@ -35,11 +36,12 @@ This will create a run.spec file in the backend directory.
```
* Edit pathex to: `pathex=[spec_root]`
* Edit datas to: `datas=[('../name_of_frontend_folder/build', 'name_of_web_application')]`
-
+ * Optionally, you can add an icon to your standalone. Add `icon='../pyqmix_frontend/public/pyqmixweb_desktop_icon.ico'` to the EXE-section of run.spec.
+
## Build the executable
1. Open a terminal
2. Browse to the `pyqmix_backend` directory
3. Activate the virtual environment
4. Type: `pyinstaller --clean run.spec`
-This generates a `run.exe` file inside the backend's `dist` folder.
+This generates a `.exe` file inside the backend's `dist` folder.
diff --git a/pyqmix_backend/run.py b/pyqmix_backend/run.py
index e81c4aa..4910669 100644
--- a/pyqmix_backend/run.py
+++ b/pyqmix_backend/run.py
@@ -1,5 +1,5 @@
import webbrowser
-from .backend_app import app
+from pyqmix_backend.backend_app import app
import threading
import time
from urllib import request
diff --git a/pyqmix_backend/run.spec b/pyqmix_backend/run.spec
index b1e1898..9f5dc38 100644
--- a/pyqmix_backend/run.spec
+++ b/pyqmix_backend/run.spec
@@ -4,10 +4,10 @@
# See:
# https://stackoverflow.com/a/50402636/1944216
# https://pythonhosted.org/PyInstaller/spec-files.html#globals-available-to-the-spec-file
+block_cipher = None
import os
spec_root = os.path.abspath(SPECPATH)
-
a = Analysis(['run.py'],
pathex=[spec_root],
binaries=[],
@@ -18,18 +18,20 @@ a = Analysis(['run.py'],
excludes=[],
win_no_prefer_redirects=False,
win_private_assemblies=False,
- cipher=block_cipher)
+ cipher=block_cipher,
+ noarchive=False)
pyz = PYZ(a.pure, a.zipped_data,
- cipher=None)
-
+ cipher=block_cipher)
exe = EXE(pyz,
a.scripts,
a.binaries,
a.zipfiles,
a.datas,
+ [],
name='pyqmix-web',
debug=False,
+ bootloader_ignore_signals=False,
strip=False,
upx=True,
runtime_tmpdir=None,
diff --git a/pyqmix_frontend/src/App.css b/pyqmix_frontend/src/App.css
index 3f2d170..9988ff4 100644
--- a/pyqmix_frontend/src/App.css
+++ b/pyqmix_frontend/src/App.css
@@ -70,8 +70,8 @@ body {
}
}
-.text-modal {
- white-space: pre-line;
+.modal-input {
+ text-align: left;
}
.form-control {
diff --git a/pyqmix_frontend/src/App.js b/pyqmix_frontend/src/App.js
index 228738b..9a0e203 100644
--- a/pyqmix_frontend/src/App.js
+++ b/pyqmix_frontend/src/App.js
@@ -730,7 +730,7 @@ class PumpForm extends Component {
+ className="modal-input">
Select a pump configuration
{/**/}
@@ -809,7 +809,7 @@ class PumpForm extends Component {
+ className="modal-input">
Error - no pumps were detected.
Ensure that:
@@ -860,7 +860,8 @@ class PumpForm extends Component {
disabled={this.state.selectedPumps.length === 0}
> Reference Move
Calibrate the selected pumps.
-
+
Reference Move
Detach all syringes from the pumps before continuing.
@@ -894,7 +895,8 @@ class PumpForm extends Component {
> Fill Cycle
Fill & empty the syringe multiple times. Ends with a filled syringe.
-
+
Fill
Insert the inlet tube into the stimulus reservoir and
@@ -971,7 +973,7 @@ class PumpForm extends Component {
Empty & fill the syringe multiple times. Ends with an empty syringe.
+ className="modal-input">
Empty
Remove the inlet tube from the stimulus reservoir and
@@ -1045,7 +1047,7 @@ class PumpForm extends Component {
> Bubble Cycle
Guided procedure to remove air bubbles trapped in the syringe. Ends with a filled syringe.
+ className="modal-input">
Bubble Cycle
Insert the inlet tube into the stimulus reservoir.
@@ -1060,7 +1062,7 @@ class PumpForm extends Component {
+ className="modal-input">
Bubble Cycle
Remove the inlet tube from the stimulus reservoir to aspirate air.
@@ -1077,7 +1079,7 @@ class PumpForm extends Component {
+ className="modal-input">
Bubble Cycle
Insert the inlet tube into the stimulus reservoir.
@@ -1140,7 +1142,7 @@ class PumpForm extends Component {
> Rinse Cycle
Empty & fill the syringe multiple times. Ends with an empty syringe.
+ className="modal-input">
Rinse
Insert the inlet tube into the rinsing fluid