Merge pull request #276 from shamoon/dark-mode
This commit is contained in:
@@ -58,11 +58,12 @@ Scrutiny uses `smartctl --scan` to detect devices/drives.
|
||||
- All RAID controllers supported by `smartctl` are automatically supported by Scrutiny.
|
||||
- While some RAID controllers support passing through the underlying SMART data to `smartctl` others do not.
|
||||
- In some cases `--scan` does not correctly detect the device type, returning [incomplete SMART data](https://github.com/AnalogJ/scrutiny/issues/45).
|
||||
Scrutiny will eventually support overriding detected device type via the config file.
|
||||
Scrutiny supports overriding detected device type via the config file: see [example.collector.yaml](https://github.com/AnalogJ/scrutiny/blob/master/example.collector.yaml)
|
||||
- If you use docker, you **must** pass though the RAID virtual disk to the container using `--device` (see below)
|
||||
- This device may be in `/dev/*` or `/dev/bus/*`.
|
||||
- If you're unsure, run `smartctl --scan` on your host, and pass all listed devices to the container.
|
||||
|
||||
See [docs/TROUBLESHOOTING_DEVICE_COLLECTOR.md](./docs/TROUBLESHOOTING_DEVICE_COLLECTOR.md) for help
|
||||
|
||||
## Docker
|
||||
|
||||
|
||||
@@ -83,9 +83,11 @@ Now that we have downloaded the required files, let's prepare the filesystem.
|
||||
chmod +x /opt/scrutiny/bin/scrutiny-web-linux-amd64
|
||||
|
||||
# Next, lets extract the frontend files.
|
||||
# NOTE: after extraction, there **should not** be a `dist` subdirectory in `/opt/scrutiny/web` directory.
|
||||
cd /opt/scrutiny/web
|
||||
tar xvzf scrutiny-web-frontend.tar.gz --strip-components 1 -C .
|
||||
|
||||
|
||||
# Cleanup
|
||||
rm -rf scrutiny-web-frontend.tar.gz
|
||||
```
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
# pfsense Install
|
||||
|
||||
This bascially follows the [Manual collector instructions](https://github.com/AnalogJ/scrutiny/blob/master/docs/INSTALL_MANUAL.md#collector) and assumes you are running a hub and spoke deployment and already have the web app setup.
|
||||
|
||||
|
||||
### Dependencies
|
||||
|
||||
SSH into pfsense, hit `8` for the shell and install the required dependencies.
|
||||
|
||||
```
|
||||
pkg install smartmontools
|
||||
```
|
||||
|
||||
Ensure smartmontools is v7+. This won't be a problem in pfsense 2.6.0+
|
||||
|
||||
|
||||
### Directory Structure
|
||||
|
||||
Now let's create a directory structure to contain the Scrutiny collector binary.
|
||||
|
||||
```
|
||||
mkdir -p /opt/scrutiny/bin
|
||||
```
|
||||
|
||||
|
||||
### Download Files
|
||||
|
||||
Next, we'll download the Scrutiny collector binary from the [latest Github release](https://github.com/analogj/scrutiny/releases).
|
||||
|
||||
> NOTE: Ensure you have the latest version in the below command
|
||||
|
||||
```
|
||||
fetch -o /opt/scrutiny/bin https://github.com/AnalogJ/scrutiny/releases/download/vX.X.X/scrutiny-collector-metrics-freebsd-amd64
|
||||
```
|
||||
|
||||
|
||||
### Prepare Scrutiny
|
||||
|
||||
Now that we have downloaded the required files, let's prepare the filesystem.
|
||||
|
||||
```
|
||||
chmod +x /opt/scrutiny/bin/scrutiny-collector-metrics-freebsd-amd64
|
||||
```
|
||||
|
||||
|
||||
### Start Scrutiny Collector, Populate Webapp
|
||||
|
||||
Next, we will manually trigger the collector, to populate the Scrutiny dashboard:
|
||||
|
||||
> NOTE: if you need to pass a config file to the scrutiny collector, you can provide it using the `--config` flag.
|
||||
|
||||
```
|
||||
/opt/scrutiny/bin/scrutiny-collector-metrics-freebsd-amd64 run --api-endpoint "http://localhost:8080"
|
||||
```
|
||||
> NOTE: change the IP address to that of your web app
|
||||
|
||||
### Schedule Collector with Cron
|
||||
|
||||
Finally you need to schedule the collector to run periodically.
|
||||
|
||||
Login to the pfsense webGUI and head to `Services/Cron` add an entry with the following details:
|
||||
|
||||
```
|
||||
Minute: */15
|
||||
Hour: *
|
||||
Day of the Month: *
|
||||
Month of the Year: *
|
||||
Day of the Week: *
|
||||
User: root
|
||||
Command: /opt/scrutiny/bin/scrutiny-collector-metrics-freebsd-amd64 run --api-endpoint "http://localhost:8080" >/dev/null 2>&1
|
||||
```
|
||||
> NOTE: `>/dev/null 2>&1` is used to stop cron confirmation emails being sent.
|
||||
@@ -4,11 +4,13 @@ These are the officially supported NAS OS's (with documentation and setup guides
|
||||
Once a guide is created (in `docs/guides/`) it will be linked here.
|
||||
|
||||
- [ ] freenas/truenas
|
||||
- [x] [unraid](https://github.com/AnalogJ/scrutiny/blob/master/docs/INSTALL_UNRAID.md)
|
||||
- [x] [unraid](./INSTALL_UNRAID.md)
|
||||
- [ ] ESXI
|
||||
- [ ] Proxmox
|
||||
- [ ] Synology
|
||||
- [ ] OMV
|
||||
- [ ] Amahi
|
||||
- [ ] Running in a LXC container
|
||||
- [x] [PFSense](./INSTALL_UNRAID.md)
|
||||
- [ ] QNAP
|
||||
|
||||
|
||||
@@ -52,6 +52,8 @@ If the output is the same, your devices will be processed by Scrutiny.
|
||||
In some cases `--scan` does not correctly detect the device type, returning [incomplete SMART data](https://github.com/AnalogJ/scrutiny/issues/45).
|
||||
Scrutiny will supports overriding the detected device type via the config file.
|
||||
|
||||
[example.collector.yaml](https://github.com/AnalogJ/scrutiny/blob/master/example.collector.yaml)
|
||||
|
||||
### RAID Controllers (Megaraid/3ware/HBA/Adaptec/HPE/etc)
|
||||
Smartctl has support for a large number of [RAID controllers](https://www.smartmontools.org/wiki/Supported_RAID-Controllers), however this
|
||||
support is not automatic, and may require some additional device type hinting. You can provide this information to the Scrutiny collector
|
||||
@@ -186,3 +188,17 @@ Thankfully the collector has a special `--host-id` flag (or `COLLECTOR_HOST_ID`
|
||||
|
||||
See the [docs/INSTALL_HUB_SPOKE.md](/docs/INSTALL_HUB_SPOKE.md) guide for more information.
|
||||
|
||||
## Collector DEBUG mode
|
||||
|
||||
You can use environmental variables to enable debug logging and/or log files for the collector:
|
||||
|
||||
```bash
|
||||
DEBUG=true
|
||||
COLLECTOR_LOG_FILE=/tmp/collector.log
|
||||
```
|
||||
|
||||
Or if you're not using docker, you can pass CLI arguments to the collector during startup:
|
||||
|
||||
```bash
|
||||
scrutiny-collector-metrics run --debug --log-file /tmp/collector.log
|
||||
```
|
||||
@@ -2,6 +2,7 @@ import { Inject, Injectable } from '@angular/core';
|
||||
import { BehaviorSubject, Observable } from 'rxjs';
|
||||
import * as _ from 'lodash';
|
||||
import { TREO_APP_CONFIG } from '@treo/services/config/config.constants';
|
||||
import { AppConfig } from 'app/core/config/app.config';
|
||||
|
||||
const SCRUTINY_CONFIG_LOCAL_STORAGE_KEY = 'scrutiny';
|
||||
|
||||
@@ -12,20 +13,26 @@ export class TreoConfigService
|
||||
{
|
||||
// Private
|
||||
private _config: BehaviorSubject<any>;
|
||||
private systemPrefersDark: boolean;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
constructor(@Inject(TREO_APP_CONFIG) defaultConfig: any)
|
||||
{
|
||||
this.systemPrefersDark = window.matchMedia && window.matchMedia("(prefers-color-scheme: dark)").matches;
|
||||
|
||||
let currentScrutinyConfig = defaultConfig
|
||||
|
||||
const localConfigStr = localStorage.getItem(SCRUTINY_CONFIG_LOCAL_STORAGE_KEY)
|
||||
if(localConfigStr){
|
||||
// check localstorage for a value
|
||||
const localConfig = JSON.parse(localConfigStr)
|
||||
let localConfigStr = localStorage.getItem(SCRUTINY_CONFIG_LOCAL_STORAGE_KEY)
|
||||
if (localConfigStr){
|
||||
//check localstorage for a value
|
||||
let localConfig = JSON.parse(localConfigStr)
|
||||
currentScrutinyConfig = Object.assign({}, localConfig, currentScrutinyConfig) // make sure defaults are available if missing from localStorage.
|
||||
}
|
||||
|
||||
currentScrutinyConfig.theme = this.determineTheme(currentScrutinyConfig);
|
||||
|
||||
// Set the private defaults
|
||||
this._config = new BehaviorSubject(currentScrutinyConfig);
|
||||
}
|
||||
@@ -41,10 +48,12 @@ export class TreoConfigService
|
||||
set config(value: any)
|
||||
{
|
||||
// Merge the new config over to the current config
|
||||
const config = _.merge({}, this._config.getValue(), value);
|
||||
let config = _.merge({}, this._config.getValue(), value);
|
||||
|
||||
//Store the config in localstorage
|
||||
localStorage.setItem(SCRUTINY_CONFIG_LOCAL_STORAGE_KEY, JSON.stringify(config));
|
||||
|
||||
config.theme = this.determineTheme(config);
|
||||
|
||||
// Execute the observable
|
||||
this._config.next(config);
|
||||
@@ -56,6 +65,17 @@ export class TreoConfigService
|
||||
return this._config.asObservable();
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------
|
||||
// @ Private methods
|
||||
// -----------------------------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Checks if theme should be set to dark based on config & system settings
|
||||
*/
|
||||
private determineTheme(config:AppConfig): string {
|
||||
return (config.darkModeUseSystem && this.systemPrefersDark) ? "dark" : config.theme;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------
|
||||
// @ Public methods
|
||||
// -----------------------------------------------------------------------------------------------------
|
||||
|
||||
@@ -17,6 +17,8 @@ export interface AppConfig
|
||||
dashboardSort: string;
|
||||
|
||||
temperatureUnit: string;
|
||||
|
||||
darkModeUseSystem: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -35,5 +37,7 @@ export const appConfig: AppConfig = {
|
||||
dashboardSort: "status",
|
||||
|
||||
temperatureUnit: "celsius",
|
||||
|
||||
darkModeUseSystem: true,
|
||||
};
|
||||
|
||||
|
||||
+27
-12
@@ -2,6 +2,21 @@
|
||||
<mat-dialog-content class="mat-typography">
|
||||
|
||||
<div class="flex flex-col p-8 pb-0 overflow-hidden">
|
||||
<div class="flex flex-col gt-md:flex-row">
|
||||
<mat-slide-toggle class="mb-2" [(ngModel)]="darkModeUseSystem">Use system settings for dark mode</mat-slide-toggle>
|
||||
<p [class.text-hint]="darkModeUseSystem">
|
||||
Theme:
|
||||
<mat-button-toggle-group class="ml-2" #group="matButtonToggleGroup" [(ngModel)]="theme" [disabled]="darkModeUseSystem">
|
||||
<mat-button-toggle value="light" aria-label="Light mode">
|
||||
<mat-icon>light_mode</mat-icon>
|
||||
</mat-button-toggle>
|
||||
<mat-button-toggle value="dark" aria-label="Dark mode">
|
||||
<mat-icon>dark_mode</mat-icon>
|
||||
</mat-button-toggle>
|
||||
</mat-button-toggle-group>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-col mt-5 gt-md:flex-row">
|
||||
<mat-form-field class="flex-auto gt-xs:pr-3 gt-md:pr-3">
|
||||
<mat-label>Display Title</mat-label>
|
||||
@@ -38,24 +53,24 @@
|
||||
<mat-tab-group mat-align-tabs="start">
|
||||
<mat-tab label="Ata">
|
||||
|
||||
<div matTooltip="not yet implemented" class="gray-200 flex flex-col mt-5 gt-md:flex-row">
|
||||
<div matTooltip="not yet implemented" class="flex flex-col mt-5 gt-md:flex-row">
|
||||
<mat-form-field class="flex-auto gt-md:pr-3">
|
||||
<mat-label>Critical Error Threshold</mat-label>
|
||||
<mat-label class="text-hint">Critical Error Threshold</mat-label>
|
||||
<input disabled matInput [value]="'10%'">
|
||||
</mat-form-field>
|
||||
<mat-form-field class="flex-auto gt-md:pl-3">
|
||||
<mat-label>Critical Warning Threshold</mat-label>
|
||||
<mat-label class="text-hint">Critical Warning Threshold</mat-label>
|
||||
<input disabled matInput>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
|
||||
<div matTooltip="not yet implemented" class="gray-200 flex flex-col gt-md:flex-row">
|
||||
<div matTooltip="not yet implemented" class="flex flex-col gt-md:flex-row">
|
||||
<mat-form-field class="flex-auto gt-md:pr-3">
|
||||
<mat-label>Error Threshold</mat-label>
|
||||
<mat-label class="text-hint">Error Threshold</mat-label>
|
||||
<input disabled matInput [value]="'20%'">
|
||||
</mat-form-field>
|
||||
<mat-form-field class="flex-auto gt-md:pl-3">
|
||||
<mat-label>Warning Threshold</mat-label>
|
||||
<mat-label class="text-hint">Warning Threshold</mat-label>
|
||||
<input disabled matInput [value]="'10%'">
|
||||
</mat-form-field>
|
||||
</div>
|
||||
@@ -63,26 +78,26 @@
|
||||
</mat-tab>
|
||||
<mat-tab label="NVMe">
|
||||
|
||||
<div matTooltip="not yet implemented" class="gray-200 flex flex-col mt-5 gt-md:flex-row">
|
||||
<div matTooltip="not yet implemented" class="flex flex-col mt-5 gt-md:flex-row">
|
||||
<mat-form-field class="flex-auto gt-md:pr-3">
|
||||
<mat-label>Critical Error Threshold</mat-label>
|
||||
<mat-label class="text-hint">Critical Error Threshold</mat-label>
|
||||
<input disabled matInput [value]="'enabled'">
|
||||
</mat-form-field>
|
||||
<mat-form-field class="flex-auto gt-md:pl-3">
|
||||
<mat-label>Critical Warning Threshold</mat-label>
|
||||
<mat-label class="text-hint">Critical Warning Threshold</mat-label>
|
||||
<input disabled matInput>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
|
||||
</mat-tab>
|
||||
<mat-tab label="SCSI">
|
||||
<div matTooltip="not yet implemented" class="gray-200 flex flex-col mt-5 gt-md:flex-row">
|
||||
<div matTooltip="not yet implemented" class="flex flex-col mt-5 gt-md:flex-row">
|
||||
<mat-form-field class="flex-auto gt-md:pr-3">
|
||||
<mat-label>Critical Error Threshold</mat-label>
|
||||
<mat-label class="text-hint">Critical Error Threshold</mat-label>
|
||||
<input disabled matInput [value]="'enabled'">
|
||||
</mat-form-field>
|
||||
<mat-form-field class="flex-auto gt-md:pl-3">
|
||||
<mat-label>Critical Warning Threshold</mat-label>
|
||||
<mat-label class="text-hint">Critical Warning Threshold</mat-label>
|
||||
<input disabled matInput>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
|
||||
+9
-1
@@ -13,7 +13,9 @@ export class DashboardSettingsComponent implements OnInit {
|
||||
|
||||
dashboardDisplay: string;
|
||||
dashboardSort: string;
|
||||
temperatureUnit: string
|
||||
temperatureUnit: string;
|
||||
darkModeUseSystem: boolean;
|
||||
theme: string;
|
||||
|
||||
// Private
|
||||
private _unsubscribeAll: Subject<any>;
|
||||
@@ -35,7 +37,11 @@ export class DashboardSettingsComponent implements OnInit {
|
||||
this.dashboardDisplay = config.dashboardDisplay;
|
||||
this.dashboardSort = config.dashboardSort;
|
||||
this.temperatureUnit = config.temperatureUnit;
|
||||
this.darkModeUseSystem = config.darkModeUseSystem;
|
||||
this.theme = config.theme;
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
saveSettings(): void {
|
||||
@@ -43,6 +49,8 @@ export class DashboardSettingsComponent implements OnInit {
|
||||
dashboardDisplay: this.dashboardDisplay,
|
||||
dashboardSort: this.dashboardSort,
|
||||
temperatureUnit: this.temperatureUnit,
|
||||
darkModeUseSystem: this.darkModeUseSystem,
|
||||
theme: this.theme
|
||||
}
|
||||
this._configService.config = newSettings
|
||||
console.log(`Saved Settings: ${JSON.stringify(newSettings)}`)
|
||||
|
||||
@@ -4,3 +4,15 @@
|
||||
// @ Styles from this file will override anything from 'vendors.scss' file allowing customizations and
|
||||
// modifications of third party libraries.
|
||||
// -----------------------------------------------------------------------------------------------------
|
||||
|
||||
.treo-theme-dark .yellow-50 {
|
||||
background-color: #242b38 !important;
|
||||
|
||||
.mat-icon {
|
||||
color: #6f4315 !important;
|
||||
}
|
||||
|
||||
.text-secondary {
|
||||
color: rgb(203 101 37 / 70%) !important
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user