mirror of
https://github.com/ConnectedHumber/Air-Quality-Web
synced 2024-11-22 06:23:01 +00:00
Merge branch 'master' of github.com:ConnectedHumber/Air-Quality-Web
This commit is contained in:
commit
0cd1032a3b
8 changed files with 153 additions and 30 deletions
|
@ -1,5 +1,12 @@
|
||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## v0.5.3 - 7th March 2019
|
||||||
|
- Tweak x axis labels
|
||||||
|
- Build script: Improve first-time setup experience
|
||||||
|
|
||||||
|
## v0.5.2 - 1st March 2019
|
||||||
|
- [API] Added `version` action
|
||||||
|
|
||||||
## v0.5.1 - 26th February 2019
|
## v0.5.1 - 26th February 2019
|
||||||
- Fixed issue with non-linear sensor reading reports ([#15](https://github.com/ConnectedHumber/Air-Quality-Web/issues/15))
|
- Fixed issue with non-linear sensor reading reports ([#15](https://github.com/ConnectedHumber/Air-Quality-Web/issues/15))
|
||||||
|
|
||||||
|
|
104
README.md
104
README.md
|
@ -25,7 +25,9 @@ In order to run this program, you'll need the following:
|
||||||
The client-side code requires building. Currently, no pre-built versions are available (though these can be provided upon request), so this must be done from source. A build script is available, however, which automates the process - as explained below.
|
The client-side code requires building. Currently, no pre-built versions are available (though these can be provided upon request), so this must be done from source. A build script is available, however, which automates the process - as explained below.
|
||||||
|
|
||||||
### System Requirements
|
### System Requirements
|
||||||
- PHP-enabled web server (Nginx is recommended, but Apache works too)
|
- PHP-enabled web server
|
||||||
|
- _Nginx_ + _PHP-FPM_ is recommended
|
||||||
|
- Apache works too
|
||||||
- MariaDB database with the appropriate table structure pre-loaded
|
- MariaDB database with the appropriate table structure pre-loaded
|
||||||
- PHP 7+
|
- PHP 7+
|
||||||
- Node.JS (preferably 10+) + npm 6+ (for installing & building the client-side app code)
|
- Node.JS (preferably 10+) + npm 6+ (for installing & building the client-side app code)
|
||||||
|
@ -33,53 +35,101 @@ The client-side code requires building. Currently, no pre-built versions are ava
|
||||||
- PHP modules:
|
- PHP modules:
|
||||||
- `pdo-mysql` (for the database connection)
|
- `pdo-mysql` (for the database connection)
|
||||||
|
|
||||||
### Building From Source
|
### Installation
|
||||||
The build script ensures that everything it does will not go outside the current directory (i.e. all dependencies are installed locally).
|
1. Start by cloning this repository:
|
||||||
|
|
||||||
To build from source, start off by cloning this repository.
|
```bash
|
||||||
|
git clone https://github.com/ConnectedHumber/Air-Quality-Web.git
|
||||||
|
```
|
||||||
|
|
||||||
Then run the `setup` and `setup-dev` build commands from the root of the repository like this:
|
|
||||||
|
2. Change the ownership to allow your web server user to access the created directory. Usually, the web server will be running under the `www-data` user:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo chown -R www-data:www-data path/to/Air-Quality-Web
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
3. `cd` into the root of the cloned repository. Then install the dependencies (these are installed locally):
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
./build setup setup-dev
|
./build setup setup-dev
|
||||||
```
|
```
|
||||||
|
|
||||||
This will initialise any git submodules and install both the server-side and client-side dependencies. Once done, all you need to do is build the client-side code:
|
|
||||||
|
4. Build the client-side application:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
# For development, run this:
|
||||||
./build client
|
./build client
|
||||||
|
# For production, run this:
|
||||||
|
NODE_ENV=production ./build client
|
||||||
|
# If you're actively working on the codebase and need to auto-recompile on every change, run this:
|
||||||
|
./build client-watch
|
||||||
```
|
```
|
||||||
|
|
||||||
For development purposes, the `client-watch` command is available.
|
|
||||||
|
|
||||||
In production, you probably want to do this instead:
|
5. Edit `data/settings.toml` to enter your database credentials.
|
||||||
|
|
||||||
|
You can edit other settings here too. See `settings.default.toml` for the settings you can change, but do **not** edit `settings.default.toml`! Edit `data/settings.toml` instead. You'll probably want to give the entire default settings file a careful read.
|
||||||
|
|
||||||
|
|
||||||
|
6. Configure your web server to serve the root of the repository you've cloned if you haven't already. Skip this step if you cloned the repository into a directory that your web server already serves.
|
||||||
|
|
||||||
|
|
||||||
|
7. Disallow public access to the private `data` directory.
|
||||||
|
|
||||||
|
In Nginx:
|
||||||
|
|
||||||
|
```nginx
|
||||||
|
# put this inside the "server { }" block:
|
||||||
|
location ^~ /path/to/data/directory {
|
||||||
|
deny all;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
In Apache:
|
||||||
|
|
||||||
|
```htaccess
|
||||||
|
# Create a file with this content inside the data/ directory
|
||||||
|
Require all denied
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
8. Test the application with an API call. If this returns valid JSON, then you've set it up correctly
|
||||||
|
|
||||||
|
```
|
||||||
|
http://example.com/path/to/Air-Quality-Web/api.php?action=list-devices
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
9. (Optional) Setup HTTPS:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
NODE_ENV=production ./build client
|
sudo apt install certbot
|
||||||
|
# On Nginx:
|
||||||
|
sudo certbot --nginx --domain example.com
|
||||||
|
# On Apache:
|
||||||
|
sudo certbot --apache --domain example.com
|
||||||
```
|
```
|
||||||
|
|
||||||
This will take longer, as it causes the build system to additionally minify the client code, saving a significant amount of bandwidth and speeding up loading times.
|
|
||||||
|
|
||||||
|
|
||||||
### Configuration
|
|
||||||
#### Web server
|
|
||||||
Configure your php-enabled web server to:
|
|
||||||
- ...serve the root directory of this repository in PHP
|
|
||||||
- ...block access to the `data` directory (created on first page load)
|
|
||||||
- ...be able to write to the repository root (technically only the `data` directory requires write access)
|
|
||||||
- Example: `sudo chown -R www-data:www-data path/to/repository_root`
|
|
||||||
|
|
||||||
#### Application
|
|
||||||
Some configuration must be done before the application is ready for use.
|
|
||||||
|
|
||||||
The first time `api.php` is called from a browser, it will create a new blank configuration file at `data/settings.toml`, if it doesn't already exist. See the `settings.default.toml` file in this repository for a list of configurable settings, but do **not** edit `settings.default.toml`!
|
|
||||||
|
|
||||||
Instead, enter your configuration details into `data/settings.toml`, which overrides `settings.default.toml`. In particular, you'll probably want to change the settings under the `[database]` header - but ensure you give the entire file a careful read.
|
|
||||||
|
|
||||||
|
|
||||||
## API
|
## API
|
||||||
The server-side API is accessed through `api.php`, and supports a number of GET parameters. The most important of these is the `action` parameter, Which determines what the API will do. The following values are supported:
|
The server-side API is accessed through `api.php`, and supports a number of GET parameters. The most important of these is the `action` parameter, Which determines what the API will do. The following values are supported:
|
||||||
|
|
||||||
|
### version
|
||||||
|
> Returns the version of the application.
|
||||||
|
|
||||||
|
_No parameters are currently supported by this action._
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
|
||||||
|
|
||||||
|
```
|
||||||
|
https://example.com/path/to/api.php?action=version
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
### fetch-data
|
### fetch-data
|
||||||
> Fetches air quality data from the system for a specific data type at a specific date and time.
|
> Fetches air quality data from the system for a specific data type at a specific date and time.
|
||||||
|
|
||||||
|
|
13
build
13
build
|
@ -86,6 +86,19 @@ function task_setup {
|
||||||
composer install --no-dev;
|
composer install --no-dev;
|
||||||
task_end $?;
|
task_end $?;
|
||||||
|
|
||||||
|
if [ ! -d "./data" ]; then
|
||||||
|
task_begin "Setting up initial data folder";
|
||||||
|
mkdir "./data"; chmod 0700 "./data";
|
||||||
|
|
||||||
|
echo -e "# -------[ Custom Settings File - Last updated $(date) ]-------" >"./data/settings.toml";
|
||||||
|
echo -e '[database]\nusername = "INSERT_DATABASE_USERNAME_HERE"\npassword = "INSERT_DATABASE_PASSWORD_HERE";' >>"./data/settings.toml";
|
||||||
|
|
||||||
|
echo -e "${HC}Don't forget to edit './data/settings.toml' to specify the database username and password${RS}";
|
||||||
|
echo -e "";
|
||||||
|
|
||||||
|
task_end $?;
|
||||||
|
fi
|
||||||
|
|
||||||
stage_end $?;
|
stage_end $?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,7 @@ import Chart from '../../node_modules/chart.js/dist/Chart.bundle.min.js';
|
||||||
import GetFromUrl from './Helpers/GetFromUrl.mjs';
|
import GetFromUrl from './Helpers/GetFromUrl.mjs';
|
||||||
import GetContainingElement from './Helpers/GetContainingElement.mjs';
|
import GetContainingElement from './Helpers/GetContainingElement.mjs';
|
||||||
import Postify from './Helpers/Postify.mjs';
|
import Postify from './Helpers/Postify.mjs';
|
||||||
|
import { human_duration_unit } from './Helpers/DateHelper.mjs';
|
||||||
|
|
||||||
|
|
||||||
class DeviceReadingDisplay {
|
class DeviceReadingDisplay {
|
||||||
|
@ -238,7 +239,7 @@ class DeviceReadingDisplay {
|
||||||
type: "time",
|
type: "time",
|
||||||
time: {
|
time: {
|
||||||
format: "YYYY-MM-DD HH:mm",
|
format: "YYYY-MM-DD HH:mm",
|
||||||
tooltipFormat: 'll HH:mm'
|
tooltipFormat: 'll HH:mm',
|
||||||
},
|
},
|
||||||
scaleLabel: {
|
scaleLabel: {
|
||||||
display: true,
|
display: true,
|
||||||
|
@ -354,7 +355,8 @@ class DeviceReadingDisplay {
|
||||||
|
|
||||||
// Update the x axis labels
|
// Update the x axis labels
|
||||||
// this.chart.data.labels = new_data_obj.data.map((point) => point.t);
|
// this.chart.data.labels = new_data_obj.data.map((point) => point.t);
|
||||||
|
this.chart.options.scales.xAxes[0].time.unit = human_duration_unit(this.end_time.diff(this.start_time));
|
||||||
|
console.log(`New unit: ${this.chart.options.scales.xAxes[0].time.unit}`);
|
||||||
// Update the chart
|
// Update the chart
|
||||||
this.chart.update();
|
this.chart.update();
|
||||||
|
|
||||||
|
|
13
client_src/js/Helpers/DateHelper.mjs
Normal file
13
client_src/js/Helpers/DateHelper.mjs
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
function human_duration_unit(milliseconds) {
|
||||||
|
let seconds = Math.floor(milliseconds / 1000);
|
||||||
|
if(seconds <= 60) return "second";
|
||||||
|
if(seconds <= 60*60) return "minute";
|
||||||
|
if(seconds <= 60*60*24) return "hour";
|
||||||
|
if(seconds <= 60*60*24*45) return "day";
|
||||||
|
if(seconds <= 60*60*24*365) return "month";
|
||||||
|
return "year";
|
||||||
|
}
|
||||||
|
|
||||||
|
export { human_duration_unit };
|
2
design/Application Structure.drawio.svg
Normal file
2
design/Application Structure.drawio.svg
Normal file
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 47 KiB |
36
logic/Actions/Version.php
Normal file
36
logic/Actions/Version.php
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace AirQuality\Actions;
|
||||||
|
|
||||||
|
use \SBRL\TomlConfig;
|
||||||
|
|
||||||
|
use \AirQuality\PerfFormatter;
|
||||||
|
|
||||||
|
class Version implements IAction {
|
||||||
|
/** @var TomlConfig */
|
||||||
|
private $settings;
|
||||||
|
|
||||||
|
|
||||||
|
public function __construct(
|
||||||
|
TomlConfig $in_settings) {
|
||||||
|
$this->settings = $in_settings;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function handle() : bool {
|
||||||
|
global $start_time;
|
||||||
|
|
||||||
|
$start_handle = microtime(true);
|
||||||
|
|
||||||
|
|
||||||
|
// 1: Parse markdown
|
||||||
|
$result = file_get_contents(ROOT_DIR."version");
|
||||||
|
|
||||||
|
|
||||||
|
// 2: Send response
|
||||||
|
header("content-length: " . strlen($result));
|
||||||
|
header("content-type: text/plain");
|
||||||
|
header("x-time-taken: " . PerfFormatter::format_perf_data($start_time, $start_handle, null));
|
||||||
|
echo($result);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
2
version
2
version
|
@ -1 +1 @@
|
||||||
v0.5.1
|
v0.5.3
|
||||||
|
|
Loading…
Reference in a new issue