Compare commits

..

No commits in common. "master" and "v0.1.1" have entirely different histories.

22 changed files with 757 additions and 1635 deletions

View File

@ -6,6 +6,7 @@ pipeline:
build: build:
image: node:16 image: node:16
commands: commands:
- apt update && apt install -y ruby ruby-dev && gem install sass
- npm install - npm install
- npm run grunt - npm run grunt

View File

@ -4,7 +4,7 @@ module.exports = function(grunt) {
// Project configuration. // Project configuration.
grunt.initConfig({ grunt.initConfig({
'dart-sass': { sass: {
dist: { dist: {
options: { options: {
style: 'compressed' style: 'compressed'
@ -69,7 +69,7 @@ module.exports = function(grunt) {
}, },
css: { css: {
files: ['assets/sass/*.sass'], files: ['assets/sass/*.sass'],
tasks: ['dart-sass'], tasks: ['sass'],
options: { options: {
atBegin: true, atBegin: true,
spawn: false spawn: false
@ -96,12 +96,12 @@ module.exports = function(grunt) {
// Load task plugins // Load task plugins
grunt.loadNpmTasks('grunt-twig-render'); grunt.loadNpmTasks('grunt-twig-render');
grunt.loadNpmTasks('grunt-dart-sass'); grunt.loadNpmTasks('grunt-contrib-sass');
grunt.loadNpmTasks('grunt-contrib-coffee'); grunt.loadNpmTasks('grunt-contrib-coffee');
grunt.loadNpmTasks('grunt-contrib-copy'); grunt.loadNpmTasks('grunt-contrib-copy');
grunt.loadNpmTasks('grunt-contrib-watch'); grunt.loadNpmTasks('grunt-contrib-watch');
// Default task(s). // Default task(s).
grunt.registerTask('default', ['twigRender', 'dart-sass', 'coffee', 'copy']); grunt.registerTask('default', ['twigRender', 'sass', 'coffee', 'copy']);
}; };

View File

@ -1,27 +1,26 @@
si = require('systeminformation') si = require('systeminformation')
window.addEventListener('load', () -> window.onload = () ->
# Grab the static CPU information # Grab the static CPU information
si.cpu() si.cpu()
.then((data) -> .then((data) ->
document.getElementById('cpuInfo').innerText = data.brand document.getElementById('cpuInfo').innerText = data.brand
document.getElementById('cpuCores').innerText = data.physicalCores document.getElementById('cpuCores').innerText = data.physicalCores
document.getElementById('cpuThreads').innerText = data.cores document.getElementById('cpuThreads').innerText = data.cores
document.getElementById('cpuClockBase').innerText = data.speed document.getElementById('cpuClock').innerText = data.speed
document.getElementById('cpuClockBoost').innerText = data.speedMax console.log(data)
).catch((error) -> ).catch((error) ->
console.error(error) console.error(error)
) )
# Start the CPU temperature loop # Start the CPU temperature loop
setCpuTemp() setCpuTemp()
, false)
setCpuTemp = () -> setCpuTemp = () ->
si.cpuTemperature() si.cpuTemperature()
.then((data) -> .then((data) ->
document.getElementById('cpuTemp').innerText = data.main document.getElementById('cpuTemp').innerText = data.main
document.getElementById('cpuTempDisplay').children.item(0).style.height = ((100 - parseFloat(data.main)) + '%') console.log(data)
).catch((error) -> ).catch((error) ->
console.error(error) console.error(error)
) )

View File

@ -1,39 +1,10 @@
si = require('systeminformation') si = require('systeminformation')
window.addEventListener('load', () -> window.onload = () ->
# Set the option selector to trigger an info grab on element change
document.getElementById('gpuSelector').addEventListener('change', () ->
updateGpuInfo(@value)
)
# Load GPUs into the selector
loadGpus()
# Run the updateGpuInfo function with the default value of 0
updateGpuInfo()
, false)
loadGpus = () ->
si.graphics() si.graphics()
.then((data) -> .then((data) ->
i = 0 document.getElementById('gpuInfo').innerText = data.controllers[0].model
while i < data.controllers.length console.log(data)
optionElem = document.createElement('option')
optionElem.innerText = data.controllers[i].model
optionElem.setAttribute('value', i)
document.getElementById('gpuSelector').appendChild(optionElem)
i++
).catch((error) ->
console.error(error)
)
updateGpuInfo = (gpuId = 0) ->
si.graphics()
.then((data) ->
document.getElementById('gpuInfo').innerText = data.controllers[gpuId].model
document.getElementById('gpuVendor').innerText = data.controllers[gpuId].vendor
document.getElementById('gpuVram').innerText = data.controllers[gpuId].vram + 'MB'
document.getElementById('gpuBus').innerText = data.controllers[gpuId].bus
).catch((error) -> ).catch((error) ->
console.error(error) console.error(error)
) )

View File

@ -1,25 +0,0 @@
si = require('systeminformation')
window.addEventListener('load', () ->
# Grab the static CPU information
si.mem()
.then((data) ->
document.getElementById('memoryTotal').innerText = @formatBytes(data.total)
).catch((error) ->
console.error(error)
)
# Start the CPU temperature loop
getMemoryUsage()
, false)
getMemoryUsage = () ->
si.mem()
.then((data) ->
document.getElementById('memoryFree').innerText = @formatBytes(data.free)
document.getElementById('memoryActive').innerText = @formatBytes(data.active)
document.getElementById('memoryBuffCache').innerText = @formatBytes(data.buffcache)
).catch((error) ->
console.error(error)
)
setTimeout(getMemoryUsage, 2000)

View File

@ -1,45 +1,2 @@
shell = require('electron').shell @loadPage = (pagePath) ->
window.location.href = pagePath + '.html'
document.addEventListener('DOMContentLoaded', () ->
links = document.querySelectorAll('a[href^="http"]')
i = 0
while i < links.length
links[i].addEventListener('click', (event) ->
event.preventDefault()
shell.openExternal(this.href)
)
i++
)
@openTab = (tab) ->
# show the component info that's selected
tabs = document.querySelectorAll('.tab-button')
displays = document.querySelectorAll('.component-display')
i = 0
while i < displays.length
if displays[i].getAttribute('data-component') == tab
displays[i].classList.add('active')
tabs[i].classList.add('active')
else
displays[i].classList.remove('active')
tabs[i].classList.remove('active')
i++
@formatBytes = (bytes, decimals = 2) ->
if bytes == 0
return '0 Bytes'
k = 1024
dm = if decimals < 0 then 0 else decimals
sizes = [
'Bytes'
'KB'
'MB'
'GB'
'TB'
'PB'
'EB'
'ZB'
'YB'
]
i = Math.floor(Math.log(bytes) / Math.log(k))
parseFloat((bytes / k ** i).toFixed(dm)) + ' ' + sizes[i]

View File

@ -1,61 +0,0 @@
si = require('systeminformation')
window.addEventListener('load', () ->
# Set the option selector to trigger an info grab on element change
document.getElementById('diskSelector').addEventListener('change', () ->
updateDiskInfo(@value)
)
# Load GPUs into the selector
loadDisks()
# Run the updateGpuInfo function with the default value of 0
updateDiskInfo()
# Start running our function to update the drive's temperature
setDiskTemp()
, false)
loadDisks = () ->
si.diskLayout()
.then((data) ->
i = 0
while i < data.length
optionElem = document.createElement('option')
diskName = data[i].name + ' (' + data[i].device + ')'
optionElem.innerText = diskName
optionElem.setAttribute('value', i)
document.getElementById('diskSelector').appendChild(optionElem)
i++
).catch((error) ->
console.error(error)
)
updateDiskInfo = (diskId = 0) ->
si.diskLayout()
.then((data) ->
document.getElementById('diskInfo').innerText = data[diskId].name
document.getElementById('diskPath').innerText = data[diskId].device
document.getElementById('diskType').innerText = data[diskId].type
document.getElementById('diskSize').innerText = formatBytes(data[diskId].size)
document.getElementById('diskVendor').innerText = data[diskId].vendor
).catch((error) ->
console.error(error)
)
setDiskTemp = (diskId = -1) ->
selector = document.getElementById('diskSelector')
if selector.length < 1
return
if (diskId = -1)
diskId = selector.value
si.diskLayout()
.then((data) ->
if (data[diskId].temperature)
document.getElementById('diskTemp').innerText = data[diskId].temperature
).catch((error) ->
console.error(error)
)
setTimeout(setDiskTemp, 2000)

View File

@ -1,40 +1,26 @@
$tab-bar-height: 50px
$primary-color: #009688
$primary-color-light: lighten($primary-color, 10%)
$primary-color-dark: darken($primary-color, 10%)
$default-transition: all 230ms ease-in-out
body body
margin: 0
padding: $tab-bar-height 0 90px
background: white background: white
font-size: 18px
a a
color: $primary-color color: cornflowerblue
transition: $default-transition transition: all 200ms ease-in-out
&:hover &:hover
color: $primary-color-light color: darken(cornflowerblue, 10%)
input input
transition: $default-transition transition: all 200ms ease-in-out
input[type=submit], input[type=submit],
button button
background-color: cornflowerblue background-color: cornflowerblue
color: #f0f0f0 color: #f0f0f0
transition: $default-transition transition: all 200ms ease-in-out
&:hover &:hover
background-color: darken(cornflowerblue, 10%) background-color: darken(cornflowerblue, 10%)
color: white color: white
.faded-text
color: #999
.u-text-center .u-text-center
text-align: center text-align: center
@ -42,54 +28,7 @@ button
max-width: 1024px max-width: 1024px
.container.fluid .container.fluid
width: 100%
max-width: 100% max-width: 100%
margin: 0
#wrapper
margin-top: 25px
#tab-bar
position: fixed
top: 0
left: 0
z-index: 10
width: 100%
height: $tab-bar-height
margin: 0
padding: 0
background: #eee
border-bottom: 1px solid #bbb
box-shadow: 0 1px 2px rgba(0, 0, 0, .25)
.container.fluid
width: 100%
margin-right: 0
.row
display: relative
.tab-button
float: left
height: 50px
margin: 0
background-color: #eee
border: none
border-right: 1px solid #999
border-radius: 0
color: #212121
font-size: 2rem
font-weight: bold
transition: $default-transition
&.active,
&:hover
background-color: white
.component-display
display: none
&.active
display: block
.pageLink .pageLink
text-decoration: none text-decoration: none
@ -101,39 +40,6 @@ button
font-size: 2.5rem font-size: 2.5rem
text-decoration: none text-decoration: none
table.hardware-info
border-spacing: 0
padding: 8px
border: 1px solid #999
td
border: none
td:not(:nth-child(2))
border-right: 1px solid #bbb
tr:not(:last-child) td
border-bottom: 1px solid #bbb
.tempGauge
position: relative
box-sizing: border-box
width: 100%
max-width: 175px
height: 300px
margin-left: auto
margin-right: auto
border: 4px solid #212121
background: rgb(61,191,37)
background: linear-gradient(0deg, rgba(61,191,37,1) 45%, rgba(253,255,2,1) 65%, rgba(253,255,2,1) 75%, rgba(253,45,45,1) 100%)
.tempGaugeFill
display: block
position: absolute
left: 0
top: 0
box-sizing: border-box
width: 100%
height: 0
background: white
#header h1 #header h1
text-align: center text-align: center
@ -144,19 +50,10 @@ table.hardware-info
bottom: 0 bottom: 0
padding-top: 25px padding-top: 25px
padding-bottom: 25px padding-bottom: 25px
background: white
border-top: 1px solid #999 border-top: 1px solid #999
font-size: 16px
.row .row
position: relative position: relative
p.no-margin p.no-margin
margin-bottom: 0 margin-bottom: 0
p#version-info
text-decoration: underline
#systemPages
> div:nth-child(2n + 3)
margin-left: 0

View File

@ -1,12 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>About Sentry</title>
</head>
<body>
<p>This is a test.</p>
</body>
</html>

View File

@ -1,38 +1,27 @@
{% extends 'layout.twig' %}
{% block scripts %}
<script src="./js/cpu.js" charset="utf-8"></script>
{% endblock %}
{% block content %}
<header class="row"> <header class="row">
<div class="columns twelve u-text-center"> <div class="columns twelve u-text-center">
<h1>Sentry CPU Info</h1> <h1>Sentry System Info</h1>
</div> </div>
</header> </header>
<section class="row"> <section class="row">
<article class="columns eight"> <h5>CPU Model: <span id="cpuInfo">Random CPU</span></h5>
<h5>CPU Model: <span id="cpuInfo">Random CPU</span></h5> <p><span id="cpuCores">2</span>c/<span id="cpuThreads">4</span>t @ <span id="cpuClock">2.0</span>Ghz</p>
<table class="hardware-info u-full-width"> <p>CPU temperature: <span id="cpuTemp">12</span>&deg;C</p>
<tbody>
<tr>
<td>Physical cores</td>
<td><span id="cpuCores">2</span> cores</td>
</tr>
<tr>
<td>Logical threads</td>
<td><span id="cpuThreads">4</span> threads</td>
</tr>
<tr>
<td>Base clock</td>
<td><span id="cpuClockBase">2.0</span>Ghz</td>
</tr>
<tr>
<td>Boost clock</td>
<td><span id="cpuClockBoost">2.0</span>Ghz</td>
</tr>
</tbody>
</table>
<p>CPU temperature: <span id="cpuTemp">12</span>&deg;C</p>
</article>
<article class="columns four">
<div id="cpuTempDisplay" class="tempGauge">
<div class="tempGaugeFill"></div>
</div>
</article>
</section> </section>
<section class="row">
<div class="columns twelve">
<a href="index.html">Back</a>
</div>
</section>
{% endblock %}

View File

@ -1,28 +0,0 @@
<header class="row">
<div class="columns twelve u-text-center">
<h1>GPU Info</h1>
<select id="gpuSelector"></select>
</div>
</header>
<section class="row">
<article class="columns twelve">
<h5>GPU Model: <span id="gpuInfo">Random GPU</span></h5>
<table class="hardware-info u-full-width">
<tbody>
<tr>
<td>GPU vendor</td>
<td><span id="gpuVendor">N/a</span></td>
</tr>
<tr>
<td>GPU memory</td>
<td><span id="gpuVram">N/a</span></td>
</tr>
<tr>
<td>Bus</td>
<td><span id="gpuBus">N/a</span></td>
</tr>
</tbody>
</table>
</article>
</section>

View File

@ -8,7 +8,7 @@
</div> </div>
</header> </header>
<section id="systemPages" class="row"> <section class="row">
<!-- CPU info page link --> <!-- CPU info page link -->
<div class="columns six u-text-center"> <div class="columns six u-text-center">
<a class="pageLink" href="cpu.html"> <a class="pageLink" href="cpu.html">
@ -24,22 +24,6 @@
<p class="u-text-center">Graphics Card</p> <p class="u-text-center">Graphics Card</p>
</a> </a>
</div> </div>
<!-- Memory info page link -->
<div class="columns six u-text-center">
<a href="memory.html" class="pageLink">
<i class="fa-solid fa-memory"></i>
<p class="u-text-center">Memory</p>
</a>
</div>
<!-- Storage devices page link -->
<div class="columns six u-text-center">
<a href="storage.html" class="pageLink">
<i class="fa-solid fa-hard-drive"></i>
<p class="u-text-center">Storage devices</p>
</a>
</div>
</section> </section>
{% endblock %} {% endblock %}

View File

@ -8,56 +8,24 @@
<link rel="stylesheet" href="./styles/sentry.css"> <link rel="stylesheet" href="./styles/sentry.css">
<title>Sentry System Monitor</title> <title>Sentry System Monitor</title>
<script src="./js/sentry.js" charset="utf-8"></script> <script src="./js/sentry.js" charset="utf-8"></script>
<script src="./js/cpu.js"></script> {% block scripts %}{% endblock %}
<script src="./js/memory.js"></script>
<script src="./js/storage.js"></script>
<script src="./js/gpu.js"></script>
</head> </head>
<body> <body>
<!-- tab buttons --> <div class="container">
<div id="tab-bar"> {% block content %}{% endblock %}
<div class="container fluid">
<div class="row">
<div class="columns twelve">
<button class="tab-button active" onclick="openTab('overview')">Overview</button>
<button class="tab-button" onclick="openTab('cpu')">CPU</button>
<button class="tab-button" onclick="openTab('memory')">Memory</button>
<button class="tab-button" onclick="openTab('storage')">Storage</button>
<button class="tab-button" onclick="openTab('gpu')">GPU</button>
</div>
</div>
</div>
</div>
<div id="wrapper" class="container">
<div class="component-display active" data-component="overview">
{% include 'overview.twig' %}
</div>
<div class="component-display" data-component="cpu">
{% include 'cpu.twig' %}
</div>
<div class="component-display" data-component="memory">
{% include 'memory.twig' %}
</div>
<div class="component-display" data-component="storage">
{% include 'storage.twig' %}
</div>
<div class="component-display" data-component="gpu">
{% include 'gpu.twig' %}
</div>
</div> </div>
<footer id="footer"> <footer id="footer">
<div class="container fluid"> <div class="container fluid">
<div class="row"> <div class="row">
<div class="columns three"> <div class="columns three"><p></p></div>
<p id="version-info" class="no-margin u-text-center">Sentry v<span id="app-version"></span></p>
</div>
<div class="columns six"> <div class="columns six">
<p class="no-margin u-text-center">Developed by Bit Goblin free of charge.</p> <p class="no-margin">This app was built using:</p>
</div> <p class="no-margin">
<div class="columns three"> Node.js <span id="node-version"></span>,
<p class="no-margin u-text-center"><a href="https://git.metaunix.net/BitGoblin/Sentry">Source code</a></p> Chromium <span id="chrome-version"></span>,
and Electron <span id="electron-version"></span>.
</p>
</div> </div>
</div> </div>
</div> </div>

View File

@ -1,10 +0,0 @@
<header class="row">
<div class="columns twelve u-text-center">
<h1>Memory Info</h1>
</div>
</header>
<section class="row">
<p><span id="memoryFree">N/a</span> free out of <span id="memoryTotal">N/a</span>.</p>
<p><span id="memoryActive">N/a</span> is actively used | <span id="memoryBuffCache">N/a</span> is used in buffers/cache.</p>
</section>

View File

@ -1,5 +0,0 @@
<header class="row">
<div class="columns twelve u-text-center">
<h1>Sentry Overview</h1>
</div>
</header>

View File

@ -1,36 +0,0 @@
<header class="row">
<div class="columns twelve u-text-center">
<h1>Storage Device Info</h1>
<select id="diskSelector"></select>
</div>
</header>
<section class="row">
<article class="columns twelve">
<h5>Device Model: <span id="diskInfo">Loading...</span></h5>
<table class="hardware-info u-full-width">
<tbody>
<tr>
<td>Disk Path</td>
<td><span id="diskPath">N/a</span></td>
</tr>
<tr>
<td>Device Type</td>
<td><span id="diskType">N/a</span></td>
</tr>
<tr>
<td>Capacity</td>
<td><span id="diskSize">N/a</span></td>
</tr>
<tr>
<td>Vendor</td>
<td><span id="diskVendor">N/a</span></td>
</tr>
<tr>
<td>Current Temperature</td>
<td><span id="diskTemp">N/a</span></td>
</tr>
</tbody>
</table>
</article>
</section>

10
main.js
View File

@ -1,14 +1,12 @@
// Modules to control application life and create native browser window // Modules to control application life and create native browser window
const { app, BrowserWindow, Menu } = require('electron'); const {app, BrowserWindow} = require('electron');
const path = require('path'); const path = require('path');
function createWindow () { function createWindow () {
// Create the browser window. // Create the browser window.
const mainWindow = new BrowserWindow({ const mainWindow = new BrowserWindow({
width: 800, width: 800,
height: 700, height: 600,
minWidth: 735,
minHeight: 600,
webPreferences: { webPreferences: {
nodeIntegration: true, nodeIntegration: true,
contextIsolation: false, contextIsolation: false,
@ -23,10 +21,6 @@ function createWindow () {
// mainWindow.webContents.openDevTools() // mainWindow.webContents.openDevTools()
} }
// Set the application menu
const menu = require('./src/menu').createMenu(app);
Menu.setApplicationMenu(menu);
// This method will be called when Electron has finished // This method will be called when Electron has finished
// initialization and is ready to create browser windows. // initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs. // Some APIs can only be used after this event occurs.

1804
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
{ {
"name": "sentry", "name": "sentry",
"version": "0.3.3", "version": "0.1.1",
"description": "Desktop app to view system information and sensors", "description": "Desktop app to view system information and sensors",
"main": "main.js", "main": "main.js",
"scripts": { "scripts": {
@ -9,15 +9,15 @@
"build-windows": "electron-builder build --win", "build-windows": "electron-builder build --win",
"grunt": "grunt" "grunt": "grunt"
}, },
"repository": "https://git.metaunix.net/BitGoblin/sentry", "repository": "https://git.metaunix.net/metaunix/sentry",
"homepage": "https://git.metaunix.net/BitGoblin/sentry#readme", "homepage": "https://git.metaunix.net/metaunix/sentry#readme",
"keywords": [ "keywords": [
"sensors", "sensors",
"cpu", "cpu",
"gpu", "gpu",
"memory" "memory"
], ],
"author": "Gregory Ballantine <gballantine@bitgoblin.tech>", "author": "Gregory Ballantine <gballantine@metaunix.net>",
"license": "BSD-2-Clause", "license": "BSD-2-Clause",
"devDependencies": { "devDependencies": {
"electron": "^18.2.4", "electron": "^18.2.4",
@ -25,15 +25,15 @@
"grunt": "^1.5.3", "grunt": "^1.5.3",
"grunt-contrib-coffee": "^2.1.0", "grunt-contrib-coffee": "^2.1.0",
"grunt-contrib-copy": "^1.0.0", "grunt-contrib-copy": "^1.0.0",
"grunt-contrib-sass": "^2.0.0",
"grunt-contrib-watch": "^1.1.0", "grunt-contrib-watch": "^1.1.0",
"grunt-dart-sass": "^2.0.1",
"grunt-twig-render": "^1.8.3" "grunt-twig-render": "^1.8.3"
}, },
"dependencies": { "dependencies": {
"systeminformation": "^5.17.12" "systeminformation": "^5.11.15"
}, },
"build": { "build": {
"appId": "tech.bitgoblin.sentry", "appId": "net.metaunix.sentry",
"copyright": "Copyright © 2022 ${author}", "copyright": "Copyright © 2022 ${author}",
"win": { "win": {
"target": "nsis", "target": "nsis",

View File

@ -1,5 +1,3 @@
const appInfo = require('./package.json');
// All of the Node.js APIs are available in the preload process. // All of the Node.js APIs are available in the preload process.
// It has the same sandbox as a Chrome extension. // It has the same sandbox as a Chrome extension.
window.addEventListener('DOMContentLoaded', () => { window.addEventListener('DOMContentLoaded', () => {
@ -8,5 +6,7 @@ window.addEventListener('DOMContentLoaded', () => {
if (element) element.innerText = text if (element) element.innerText = text
} }
replaceText('app-version', appInfo.version); for (const type of ['chrome', 'node', 'electron']) {
}); replaceText(`${type}-version`, process.versions[type])
}
})

View File

@ -1,15 +0,0 @@
const { BrowserWindow } = require('electron');
exports.about = function() {
const aboutWindow = new BrowserWindow({
width: 600,
height: 400,
webPreferences: {
nodeIntegration: true,
contextIsolation: false
}
});
// and load the about.html of the app.
aboutWindow.loadFile('public/about.html');
};

View File

@ -1,30 +0,0 @@
const electron = require('electron');
// load event handlers
const helpHandlers = require('./help');
exports.createMenu = function(app) {
return electron.Menu.buildFromTemplate([
{
label: 'File',
submenu: [
{
label: 'Close',
click: function() {
app.quit();
}
}
]
},
{
label: 'Help',
submenu: [
{
label: 'About',
click: helpHandlers.about
}
]
}
]);
};