Compare commits
No commits in common. "node" and "main" have entirely different histories.
141
.gitignore
vendored
141
.gitignore
vendored
@ -1,136 +1,13 @@
|
||||
# ---> Node
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
lerna-debug.log*
|
||||
.pnpm-debug.log*
|
||||
# Compiled binary
|
||||
blt
|
||||
|
||||
# Diagnostic reports (https://nodejs.org/api/report.html)
|
||||
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
|
||||
# Local data files
|
||||
data/
|
||||
|
||||
# Runtime data
|
||||
pids
|
||||
*.pid
|
||||
*.seed
|
||||
*.pid.lock
|
||||
|
||||
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||
lib-cov
|
||||
|
||||
# Coverage directory used by tools like istanbul
|
||||
coverage
|
||||
*.lcov
|
||||
|
||||
# nyc test coverage
|
||||
.nyc_output
|
||||
|
||||
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
|
||||
.grunt
|
||||
|
||||
# Bower dependency directory (https://bower.io/)
|
||||
bower_components
|
||||
|
||||
# node-waf configuration
|
||||
.lock-wscript
|
||||
|
||||
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
||||
build/Release
|
||||
|
||||
# Dependency directories
|
||||
node_modules/
|
||||
jspm_packages/
|
||||
|
||||
# Snowpack dependency directory (https://snowpack.dev/)
|
||||
web_modules/
|
||||
|
||||
# TypeScript cache
|
||||
*.tsbuildinfo
|
||||
|
||||
# Optional npm cache directory
|
||||
.npm
|
||||
|
||||
# Optional eslint cache
|
||||
.eslintcache
|
||||
|
||||
# Optional stylelint cache
|
||||
.stylelintcache
|
||||
|
||||
# Microbundle cache
|
||||
.rpt2_cache/
|
||||
.rts2_cache_cjs/
|
||||
.rts2_cache_es/
|
||||
.rts2_cache_umd/
|
||||
|
||||
# Optional REPL history
|
||||
.node_repl_history
|
||||
|
||||
# Output of 'npm pack'
|
||||
*.tgz
|
||||
|
||||
# Yarn Integrity file
|
||||
.yarn-integrity
|
||||
|
||||
# dotenv environment variable files
|
||||
.env
|
||||
.env.development.local
|
||||
.env.test.local
|
||||
.env.production.local
|
||||
.env.local
|
||||
|
||||
# parcel-bundler cache (https://parceljs.org/)
|
||||
.cache
|
||||
.parcel-cache
|
||||
|
||||
# Next.js build output
|
||||
.next
|
||||
out
|
||||
|
||||
# Nuxt.js build / generate output
|
||||
.nuxt
|
||||
dist
|
||||
|
||||
# Gatsby files
|
||||
.cache/
|
||||
# Comment in the public line in if your project uses Gatsby and not Next.js
|
||||
# https://nextjs.org/blog/next-9-1#public-directory-support
|
||||
# public
|
||||
|
||||
# vuepress build output
|
||||
.vuepress/dist
|
||||
|
||||
# vuepress v2.x temp and cache directory
|
||||
.temp
|
||||
.cache
|
||||
|
||||
# Docusaurus cache and generated files
|
||||
.docusaurus
|
||||
|
||||
# Serverless directories
|
||||
.serverless/
|
||||
|
||||
# FuseBox cache
|
||||
.fusebox/
|
||||
|
||||
# DynamoDB Local files
|
||||
.dynamodb/
|
||||
|
||||
# TernJS port file
|
||||
.tern-port
|
||||
|
||||
# Stores VSCode versions used for testing VSCode extensions
|
||||
.vscode-test
|
||||
|
||||
# yarn v2
|
||||
.yarn/cache
|
||||
.yarn/unplugged
|
||||
.yarn/build-state.yml
|
||||
.yarn/install-state.gz
|
||||
.pnp.*
|
||||
|
||||
|
||||
# Compiled CSS and JS files
|
||||
# Compiled assets
|
||||
public/css/
|
||||
public/js/
|
||||
|
||||
# Node modules
|
||||
node_modules/
|
||||
|
||||
|
28
Gruntfile.js
28
Gruntfile.js
@ -12,27 +12,31 @@ module.exports = function(grunt) {
|
||||
files: [{
|
||||
expand: true,
|
||||
cwd: 'assets/styles',
|
||||
src: ['**/*.scss'],
|
||||
src: ['**/*.sass'],
|
||||
dest: 'public/css',
|
||||
ext: '.css'
|
||||
}]
|
||||
}
|
||||
},
|
||||
|
||||
uglify: {
|
||||
coffee: {
|
||||
options: {
|
||||
mangle: false
|
||||
sourceMap: true,
|
||||
style: 'compressed'
|
||||
},
|
||||
compile: {
|
||||
files: {
|
||||
'public/js/bedabin.min.js': ['assets/js/**/*.js']
|
||||
}
|
||||
files: {
|
||||
expand: true,
|
||||
flatten: true,
|
||||
cwd: 'assets/scripts',
|
||||
src: ['*.coffee'],
|
||||
dest: 'public/js',
|
||||
ext: '.js'
|
||||
}
|
||||
},
|
||||
|
||||
watch: {
|
||||
css: {
|
||||
files: ['assets/styles/**/*.scss'],
|
||||
files: ['assets/styles/**/*.sass'],
|
||||
tasks: ['sass'],
|
||||
options: {
|
||||
atBegin: true,
|
||||
@ -40,8 +44,8 @@ module.exports = function(grunt) {
|
||||
}
|
||||
},
|
||||
js: {
|
||||
files: ['assets/js/**/*.js'],
|
||||
tasks: ['uglify'],
|
||||
files: ['assets/scripts/**/*.js'],
|
||||
tasks: ['coffee'],
|
||||
options: {
|
||||
atBegin: true,
|
||||
spawn: false
|
||||
@ -53,9 +57,9 @@ module.exports = function(grunt) {
|
||||
// Load plugins.
|
||||
grunt.loadNpmTasks('grunt-contrib-watch');
|
||||
grunt.loadNpmTasks('grunt-contrib-sass');
|
||||
grunt.loadNpmTasks('grunt-contrib-uglify');
|
||||
grunt.loadNpmTasks('grunt-contrib-coffee');
|
||||
|
||||
// CLI tasks.
|
||||
grunt.registerTask('default', ['sass', 'uglify']);
|
||||
grunt.registerTask('default', ['sass', 'coffee']);
|
||||
|
||||
};
|
||||
|
42
Makefile
Normal file
42
Makefile
Normal file
@ -0,0 +1,42 @@
|
||||
NAME=blt
|
||||
VERSION=`git describe --tags`
|
||||
|
||||
.PHONY: build
|
||||
## build: Compile the packages.
|
||||
build:
|
||||
@go build -o $(NAME) -ldflags "-X git.metaunix.net/bitgoblin/blt/app.AppVersion=$(VERSION)"
|
||||
|
||||
.PHONY: run
|
||||
## run: Build and Run in development mode.
|
||||
run: build
|
||||
@./$(NAME) -e development
|
||||
|
||||
.PHONY: run-prod
|
||||
## run-prod: Build and Run in production mode.
|
||||
run-prod: build
|
||||
@./$(NAME) -e production
|
||||
|
||||
.PHONY: clean
|
||||
## clean: Clean project and previous builds.
|
||||
clean:
|
||||
@rm -f $(NAME)
|
||||
|
||||
.PHONY: deps
|
||||
## deps: Download modules
|
||||
deps:
|
||||
@go mod download
|
||||
|
||||
.PHONY: test
|
||||
## test: Run tests with verbose mode
|
||||
test:
|
||||
@go test -v ./tests/*
|
||||
|
||||
.PHONY: help
|
||||
all: help
|
||||
# help: show this help message
|
||||
help: Makefile
|
||||
@echo
|
||||
@echo " Choose a command to run in "$(APP_NAME)":"
|
||||
@echo
|
||||
@sed -n 's/^##//p' $< | column -t -s ':' | sed -e 's/^/ /'
|
||||
@echo
|
30
README.md
30
README.md
@ -1,30 +0,0 @@
|
||||
# Benchmark Logging Tool
|
||||
|
||||
BLT is a web UI for recording and managing PC hardware benchmarking results comparisons.
|
||||
|
||||
## Project Goals
|
||||
|
||||
The goals of this project are to:
|
||||
|
||||
* Record benchmarking results from multiple devices - e.g. log from a laptop or a phone.
|
||||
* Group results into tests - it's good practice to run a benchmark multiple times for accuracy.
|
||||
* Create comparisons of hardware tests to compare performance.
|
||||
* Generate graphs of hardware comparisons for usage in videos and articles.
|
||||
|
||||
## Development
|
||||
|
||||
To run the BLT server in development mode with automatic reloading, you first need to install dependencies:
|
||||
|
||||
`npm install`
|
||||
|
||||
Then you need to run nodemon:
|
||||
|
||||
`npm run nodemon`
|
||||
|
||||
And that's it! You just need to visit http://localhost:3000 in a browser and you're good to go!
|
||||
|
||||
For reference, nodemon watches files in the following directories:
|
||||
|
||||
* `src/`
|
||||
* `views/`
|
||||
* `index.js`
|
15
app/vars.go
Normal file
15
app/vars.go
Normal file
@ -0,0 +1,15 @@
|
||||
package app
|
||||
|
||||
import (
|
||||
"runtime"
|
||||
)
|
||||
|
||||
var (
|
||||
AppVersion string = "N/a"
|
||||
RuntimeVersion string = runtimeVersion()
|
||||
)
|
||||
|
||||
func runtimeVersion() string {
|
||||
raw_string := runtime.Version()
|
||||
return raw_string[2:]
|
||||
}
|
@ -1,3 +0,0 @@
|
||||
$(document).ready(function() {
|
||||
console.log("ready");
|
||||
});
|
2
assets/scripts/kebos.coffee
Normal file
2
assets/scripts/kebos.coffee
Normal file
@ -0,0 +1,2 @@
|
||||
$ ->
|
||||
console.log('DOM is ready.')
|
133
assets/styles/kourend.sass
Normal file
133
assets/styles/kourend.sass
Normal file
@ -0,0 +1,133 @@
|
||||
html,
|
||||
body
|
||||
width: 100%
|
||||
height: 100%
|
||||
margin: 0
|
||||
padding: 0
|
||||
|
||||
body
|
||||
height: auto
|
||||
min-height: 100%
|
||||
box-sizing: border-box
|
||||
padding-top: 80px
|
||||
padding-bottom: 100px
|
||||
background: #eee
|
||||
|
||||
a
|
||||
color: teal
|
||||
transition: color 180ms ease-in-out
|
||||
&:hover
|
||||
color: darkcyan
|
||||
|
||||
button.button-primary
|
||||
background: teal
|
||||
transition: background 180ms ease-in-out
|
||||
&:hover
|
||||
background: darkcyan
|
||||
|
||||
textarea
|
||||
max-width: 100%
|
||||
min-width: 100%
|
||||
height: 100px
|
||||
|
||||
|
||||
form select[multiple]
|
||||
min-height: 100px
|
||||
|
||||
table
|
||||
border: 1px solid #ddd
|
||||
border-radius: 8px
|
||||
border-spacing: 0
|
||||
overflow: hidden
|
||||
|
||||
table th,
|
||||
table td,
|
||||
table th:first-child,
|
||||
table td:first-child
|
||||
border: none
|
||||
padding: 7px 12px
|
||||
|
||||
table thead tr
|
||||
border-radius: 8px 8px 0 0
|
||||
&:last-child
|
||||
border-radius: 0 0 8px 8px
|
||||
|
||||
table thead tr,
|
||||
table tr:nth-child(even)
|
||||
background: #eee
|
||||
|
||||
table tbody tr
|
||||
transition: background 180ms ease-in-out
|
||||
&:hover
|
||||
background: lightgrey
|
||||
|
||||
/* Material card styles */
|
||||
.card-1
|
||||
box-shadow: 0 1px 3px rgba(0,0,0,0.12), 0 1px 2px rgba(0,0,0,0.24)
|
||||
transition: all 0.3s cubic-bezier(.25,.8,.25,1)
|
||||
&:hover
|
||||
box-shadow: 0 14px 28px rgba(0,0,0,0.25), 0 10px 10px rgba(0,0,0,0.22)
|
||||
|
||||
.card-2
|
||||
box-shadow: 0 3px 6px rgba(0,0,0,0.16), 0 3px 6px rgba(0,0,0,0.23)
|
||||
|
||||
.card-3
|
||||
box-shadow: 0 10px 20px rgba(0,0,0,0.19), 0 6px 6px rgba(0,0,0,0.23)
|
||||
|
||||
.card-4
|
||||
box-shadow: 0 14px 28px rgba(0,0,0,0.25), 0 10px 10px rgba(0,0,0,0.22)
|
||||
|
||||
.card-5
|
||||
box-shadow: 0 19px 38px rgba(0,0,0,0.30), 0 15px 12px rgba(0,0,0,0.22)
|
||||
|
||||
.container
|
||||
max-width: 1200px
|
||||
|
||||
#main-nav
|
||||
position: fixed
|
||||
top: 0
|
||||
left: 0
|
||||
width: 100%
|
||||
height: 64px
|
||||
background: teal
|
||||
color: white
|
||||
z-index: 20
|
||||
|
||||
ul
|
||||
list-style: none
|
||||
display: inline-block
|
||||
|
||||
li
|
||||
display: inline-block
|
||||
margin-left: 15px
|
||||
|
||||
h4
|
||||
display: inline-block
|
||||
margin-left: 25px
|
||||
line-height: 64px
|
||||
|
||||
a
|
||||
color: white
|
||||
font-size: 2.25rem
|
||||
line-height: 64px
|
||||
transition: all 200ms ease-in-out
|
||||
&:hover
|
||||
color: #eee
|
||||
font-size: 2.5rem
|
||||
|
||||
#main-content
|
||||
padding: 15px 25px
|
||||
background: white
|
||||
border-radius: 8px
|
||||
z-index: 10
|
||||
|
||||
#main-footer
|
||||
position: fixed
|
||||
bottom: 0
|
||||
left: 0
|
||||
width: 100%
|
||||
height: 64px
|
||||
|
||||
p
|
||||
margin-bottom: 5px
|
||||
text-align: center
|
@ -1,65 +0,0 @@
|
||||
$primary-color: navy;
|
||||
$primary-color-highlight: lighten($primary-color, 10%);
|
||||
|
||||
$nav-height: 65px;
|
||||
|
||||
body{
|
||||
margin: 0;
|
||||
padding: $nav-height 0 0;
|
||||
background: white;
|
||||
}
|
||||
|
||||
a{
|
||||
color: $primary-color;
|
||||
transition: all 230ms ease-in-out;
|
||||
&:hover{
|
||||
color: $primary-color-highlight;
|
||||
}
|
||||
}
|
||||
|
||||
#main-nav{
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: $nav-height;
|
||||
background: $primary-color;
|
||||
color: #eee;
|
||||
font-size: 2rem;
|
||||
|
||||
ul{
|
||||
list-style: none;
|
||||
li{
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
|
||||
.nav-left{
|
||||
float: left;
|
||||
}
|
||||
.nav-right{
|
||||
float: right;
|
||||
}
|
||||
|
||||
a{
|
||||
display: inline-block;
|
||||
padding: 15px 10px;
|
||||
color: #eee;
|
||||
text-decoration: none;
|
||||
&:hover{
|
||||
color: white;
|
||||
}
|
||||
}
|
||||
|
||||
.site-logo{
|
||||
margin-left: 25px;
|
||||
margin-right: 25px;
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
|
||||
#main-wrapper{
|
||||
max-width: 1180px;
|
||||
margin-top: 15px;
|
||||
padding: 15px 20px;
|
||||
}
|
35
go.mod
Normal file
35
go.mod
Normal file
@ -0,0 +1,35 @@
|
||||
module git.metaunix.net/bitgoblin/blt
|
||||
|
||||
go 1.18
|
||||
|
||||
require (
|
||||
github.com/flamego/flamego v1.9.4
|
||||
github.com/flamego/template v1.2.2
|
||||
gorm.io/driver/sqlite v1.5.4
|
||||
gorm.io/gorm v1.25.5
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/alecthomas/participle/v2 v2.0.0 // indirect
|
||||
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
|
||||
github.com/charmbracelet/lipgloss v0.7.1 // indirect
|
||||
github.com/charmbracelet/log v0.2.3 // indirect
|
||||
github.com/flamego/binding v1.3.0 // indirect
|
||||
github.com/flamego/validator v1.0.0 // indirect
|
||||
github.com/go-logfmt/logfmt v0.6.0 // indirect
|
||||
github.com/jinzhu/inflection v1.0.0 // indirect
|
||||
github.com/jinzhu/now v1.1.5 // indirect
|
||||
github.com/leodido/go-urn v1.2.1 // indirect
|
||||
github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
|
||||
github.com/mattn/go-isatty v0.0.18 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.14 // indirect
|
||||
github.com/mattn/go-sqlite3 v1.14.18 // indirect
|
||||
github.com/muesli/reflow v0.3.0 // indirect
|
||||
github.com/muesli/termenv v0.15.2 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/rivo/uniseg v0.2.0 // indirect
|
||||
golang.org/x/crypto v0.0.0-20210920023735-84f357641f63 // indirect
|
||||
golang.org/x/sys v0.7.0 // indirect
|
||||
golang.org/x/text v0.3.7 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
92
go.sum
Normal file
92
go.sum
Normal file
@ -0,0 +1,92 @@
|
||||
github.com/alecthomas/assert/v2 v2.2.2/go.mod h1:pXcQ2Asjp247dahGEmsZ6ru0UVwnkhktn7S0bBDLxvQ=
|
||||
github.com/alecthomas/participle/v2 v2.0.0 h1:Fgrq+MbuSsJwIkw3fEj9h75vDP0Er5JzepJ0/HNHv0g=
|
||||
github.com/alecthomas/participle/v2 v2.0.0/go.mod h1:rAKZdJldHu8084ojcWevWAL8KmEU+AT+Olodb+WoN2Y=
|
||||
github.com/alecthomas/repr v0.2.0/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4=
|
||||
github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k=
|
||||
github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8=
|
||||
github.com/charmbracelet/lipgloss v0.7.1 h1:17WMwi7N1b1rVWOjMT+rCh7sQkvDU75B2hbZpc5Kc1E=
|
||||
github.com/charmbracelet/lipgloss v0.7.1/go.mod h1:yG0k3giv8Qj8edTCbbg6AlQ5e8KNWpFujkNawKNhE2c=
|
||||
github.com/charmbracelet/log v0.2.1/go.mod h1:GwFfjewhcVDWLrpAbY5A0Hin9YOlEn40eWT4PNaxFT4=
|
||||
github.com/charmbracelet/log v0.2.2/go.mod h1:Zs11hKpb8l+UyX4y1srwZIGW+MPCXJHIty3MB9l/sno=
|
||||
github.com/charmbracelet/log v0.2.3 h1:YVmBhJtpGL7nW/nlf5u+SEloU8XYljxozGzZpgwIvhs=
|
||||
github.com/charmbracelet/log v0.2.3/go.mod h1:ZApwwzDbbETVTIRTk7724yQRJAXIktt98yGVMMaa3y8=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/flamego/binding v1.3.0 h1:CPbnSuP0SxT50JR7lK2khTjcQi1oOECqRK7kbOYw91U=
|
||||
github.com/flamego/binding v1.3.0/go.mod h1:xgm6FEpEKKkF8CQilK2X3MJ5kTjOTnYdz/ooFctDTdc=
|
||||
github.com/flamego/flamego v1.9.1/go.mod h1:WjaZO8GM/EGvIIGXlOiwp3oPuyy1fAdjWqEgEJWovJo=
|
||||
github.com/flamego/flamego v1.9.4 h1:SNsooIfNa6ljQM1rBmfg4cFcXPIhQdG/uvNHqXxPvD8=
|
||||
github.com/flamego/flamego v1.9.4/go.mod h1:2tAVbugA3fgX8xOBoqR2jmJSSvZDLBFGXTFCR5h5eAU=
|
||||
github.com/flamego/template v1.2.2 h1:aMpt8RzXBb2ZGuABf9p/q8oBBpXrurUV8rgBbz7mj2o=
|
||||
github.com/flamego/template v1.2.2/go.mod h1:xTAmwCCPaOuxN5t4CpzOP7WZN5WkLRiJfJCpsiB0aUg=
|
||||
github.com/flamego/validator v1.0.0 h1:ixuWHVgiVGp4pVGtUn/0d6HBjZJbbXfJHDNkxW+rZoY=
|
||||
github.com/flamego/validator v1.0.0/go.mod h1:POYn0/5iW4sdamdPAYPrzqN6DFC4YaczY0gYY+Pyx5E=
|
||||
github.com/go-logfmt/logfmt v0.6.0 h1:wGYYu3uicYdqXVgoYbvnkrPVXkuLM1p1ifugDMEdRi4=
|
||||
github.com/go-logfmt/logfmt v0.6.0/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs=
|
||||
github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
|
||||
github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg=
|
||||
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
|
||||
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
|
||||
github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
|
||||
github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
|
||||
github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w=
|
||||
github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY=
|
||||
github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY=
|
||||
github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
|
||||
github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||
github.com/mattn/go-isatty v0.0.18 h1:DOKFKCQ7FNG2L1rbrmstDN4QVRdS89Nkh85u68Uwp98=
|
||||
github.com/mattn/go-isatty v0.0.18/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/mattn/go-runewidth v0.0.12/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk=
|
||||
github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU=
|
||||
github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||
github.com/mattn/go-sqlite3 v1.14.17/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
|
||||
github.com/mattn/go-sqlite3 v1.14.18 h1:JL0eqdCOq6DJVNPSvArO/bIV9/P7fbGrV00LZHc+5aI=
|
||||
github.com/mattn/go-sqlite3 v1.14.18/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
|
||||
github.com/muesli/reflow v0.3.0 h1:IFsN6K9NfGtjeggFP+68I4chLZV2yIKsXJFNZ+eWh6s=
|
||||
github.com/muesli/reflow v0.3.0/go.mod h1:pbwTDkVPibjO2kyvBQRBxTWEEGDGq0FlB1BIKtnHY/8=
|
||||
github.com/muesli/termenv v0.15.1/go.mod h1:HeAQPTzpfs016yGtA4g00CsdYnVLJvxsS4ANqrZs2sQ=
|
||||
github.com/muesli/termenv v0.15.2 h1:GohcuySI0QmI3wN8Ok9PtKGkgkFIk7y6Vpb5PvrY+Wo=
|
||||
github.com/muesli/termenv v0.15.2/go.mod h1:Epx+iuz8sNs7mNKhxzH4fWXGNpZwUaJKRS1noLXviQ8=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||
github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
|
||||
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20210920023735-84f357641f63 h1:kETrAMYZq6WVGPa8IIixL0CaEcIUNi+1WX7grUoi3y8=
|
||||
golang.org/x/crypto v0.0.0-20210920023735-84f357641f63/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU=
|
||||
golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gorm.io/driver/sqlite v1.5.4 h1:IqXwXi8M/ZlPzH/947tn5uik3aYQslP9BVveoax0nV0=
|
||||
gorm.io/driver/sqlite v1.5.4/go.mod h1:qxAuCol+2r6PannQDpOP1FP6ag3mKi4esLnB/jHed+4=
|
||||
gorm.io/gorm v1.25.2-0.20230530020048-26663ab9bf55/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k=
|
||||
gorm.io/gorm v1.25.5 h1:zR9lOiiYf09VNh5Q1gphfyia1JpiClIWG9hQaxB/mls=
|
||||
gorm.io/gorm v1.25.5/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8=
|
22
index.js
22
index.js
@ -1,22 +0,0 @@
|
||||
const express = require('express');
|
||||
const Twig = require("twig");
|
||||
|
||||
const app = express();
|
||||
const port = 3000;
|
||||
|
||||
// serve static files
|
||||
app.use(express.static('public'));
|
||||
|
||||
// configure Twig templating
|
||||
app.set("twig options", {
|
||||
allowAsync: true, // Allow asynchronous compiling
|
||||
strict_variables: false
|
||||
});
|
||||
|
||||
// register routes
|
||||
const routes = require('./src/routes');
|
||||
routes.registerRoutes(app);
|
||||
|
||||
app.listen(port, () => {
|
||||
console.log(`Example app listening on port ${port}`);
|
||||
});
|
36
main.go
Normal file
36
main.go
Normal file
@ -0,0 +1,36 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"log"
|
||||
"net/http"
|
||||
|
||||
"github.com/flamego/flamego"
|
||||
"github.com/flamego/template"
|
||||
|
||||
"git.metaunix.net/bitgoblin/blt/models"
|
||||
"git.metaunix.net/bitgoblin/blt/web"
|
||||
"git.metaunix.net/bitgoblin/blt/web/middleware"
|
||||
)
|
||||
|
||||
var Version string = "N/a"
|
||||
|
||||
func main() {
|
||||
// initial Flamego server object
|
||||
f := flamego.Classic()
|
||||
|
||||
// initialize database
|
||||
models.Open()
|
||||
|
||||
// initialize templating engine
|
||||
f.Use(template.Templater())
|
||||
|
||||
// inject custom middleware
|
||||
f.Use(middleware.CustomVars)
|
||||
|
||||
// register routes to server (moved to separate file for cleanliness)
|
||||
web.RegisterRoutes(f)
|
||||
|
||||
// alert the user and start the server
|
||||
log.Println("Server is running...")
|
||||
log.Println(http.ListenAndServe("0.0.0.0:2830", f))
|
||||
}
|
18
models/benchmark.go
Normal file
18
models/benchmark.go
Normal file
@ -0,0 +1,18 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type Benchmark struct {
|
||||
gorm.Model
|
||||
Name string
|
||||
ScoringType string
|
||||
Description string
|
||||
|
||||
// many-to-many test
|
||||
Tests []Test `gorm:"many2many:tests_benchmarks;"`
|
||||
|
||||
// has many results
|
||||
Results []Result
|
||||
}
|
17
models/hardware.go
Normal file
17
models/hardware.go
Normal file
@ -0,0 +1,17 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type Hardware struct {
|
||||
gorm.Model
|
||||
Name string
|
||||
Type string
|
||||
|
||||
// has many tests
|
||||
Tests []Test
|
||||
|
||||
// has many results
|
||||
Results []Result
|
||||
}
|
26
models/init.go
Normal file
26
models/init.go
Normal file
@ -0,0 +1,26 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"log"
|
||||
|
||||
"gorm.io/gorm"
|
||||
"gorm.io/driver/sqlite"
|
||||
)
|
||||
|
||||
var (
|
||||
DB *gorm.DB
|
||||
)
|
||||
|
||||
// Initializes the Gorm database object
|
||||
func Open() {
|
||||
// Initialize database object
|
||||
var err error
|
||||
DB, err = gorm.Open(sqlite.Open("data/blt.db"), &gorm.Config{})
|
||||
if err != nil {
|
||||
panic("Failed to connect database")
|
||||
}
|
||||
|
||||
// Migrate the schema
|
||||
DB.AutoMigrate(&Test{}, &Hardware{}, &Benchmark{}, &Result{})
|
||||
log.Println("Database migrations complete.")
|
||||
}
|
24
models/result.go
Normal file
24
models/result.go
Normal file
@ -0,0 +1,24 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type Result struct {
|
||||
gorm.Model
|
||||
AverageScore float32
|
||||
MinimumScore float32
|
||||
MaximumScore float32
|
||||
|
||||
// belongs to Hardware
|
||||
HardwareID int
|
||||
Hardware Hardware
|
||||
|
||||
// belongs to Benchmark
|
||||
BenchmarkID int
|
||||
Benchmark Benchmark
|
||||
|
||||
// belongs to Test
|
||||
TestID int
|
||||
Test Test
|
||||
}
|
21
models/test.go
Normal file
21
models/test.go
Normal file
@ -0,0 +1,21 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type Test struct {
|
||||
gorm.Model
|
||||
Name string
|
||||
Description string
|
||||
|
||||
// belongs to hardware
|
||||
HardwareID int
|
||||
Hardware Hardware
|
||||
|
||||
// many-to-many benchmarks
|
||||
Benchmarks []Benchmark `gorm:"many2many:tests_benchmarks;"`
|
||||
|
||||
// has many results
|
||||
Results []Result
|
||||
}
|
12
nodemon.json
12
nodemon.json
@ -1,12 +0,0 @@
|
||||
{
|
||||
"verbose": true,
|
||||
"watch": [
|
||||
"src/",
|
||||
"views/",
|
||||
"./index.js"
|
||||
],
|
||||
"env": {
|
||||
"NODE_ENV": "development"
|
||||
},
|
||||
"ext": "js,json,twig"
|
||||
}
|
1287
package-lock.json
generated
1287
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
33
package.json
33
package.json
@ -1,34 +1,35 @@
|
||||
{
|
||||
"name": "benchmark-logging-tool",
|
||||
"name": "blt",
|
||||
"version": "0.1.0",
|
||||
"description": "Bit Goblin PC hardware benchmarking logging tool",
|
||||
"description": "Self-hosted PC hardware benchmark logging tool",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1",
|
||||
"nodemon": "nodemon",
|
||||
"grunt": "grunt"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://git.metaunix.net/BitGoblin/blt"
|
||||
"url": "gitea@git.metaunix.net:BitGoblin/blt.git"
|
||||
},
|
||||
"keywords": [
|
||||
"hardware",
|
||||
"benchmarking",
|
||||
"gaming"
|
||||
"benchmark",
|
||||
"testing",
|
||||
"PC"
|
||||
],
|
||||
"author": "Gregory Ballanine <gballantine@bitgoblin.tech>",
|
||||
"uploaders": [
|
||||
{
|
||||
"name": "Gregory Ballantine",
|
||||
"email": "gballantine@bitgoblin.tech"
|
||||
}
|
||||
],
|
||||
"author": "Gregory Ballantine <gballantine@bitgoblin.tech>",
|
||||
"license": "BSD-2-Clause",
|
||||
"dependencies": {
|
||||
"express": "^4.18.2",
|
||||
"twig": "^1.16.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"grunt": "^1.6.1",
|
||||
"grunt": "^1.5.3",
|
||||
"grunt-cli": "^1.4.3",
|
||||
"grunt-contrib-sass": "^2.0.0",
|
||||
"grunt-contrib-uglify": "^5.2.2",
|
||||
"grunt-contrib-coffee": "^2.1.0",
|
||||
"grunt-contrib-watch": "^1.1.0",
|
||||
"nodemon": "^3.0.1",
|
||||
"sass": "^1.68.0"
|
||||
"sass": "^1.55.0"
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +0,0 @@
|
||||
const getIndex = (req, res) => {
|
||||
res.render('index/dashboard.twig');
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
getIndex
|
||||
};
|
@ -1,7 +0,0 @@
|
||||
// load controllers
|
||||
const indexController = require('./controllers/indexController');
|
||||
|
||||
// index routes
|
||||
exports.registerRoutes = (app) => {
|
||||
app.get('/', indexController.getIndex);
|
||||
};
|
38
templates/benchmark/create.tmpl
Normal file
38
templates/benchmark/create.tmpl
Normal file
@ -0,0 +1,38 @@
|
||||
{{ template "header" . }}
|
||||
|
||||
<div class="row">
|
||||
<h2>Add new benchmark</h2>
|
||||
|
||||
<form class="twelve columns" action="/benchmark/create" method="POST">
|
||||
<div class="row">
|
||||
<div class="nine columns">
|
||||
<label for="benchmark_name">
|
||||
Benchmark name:
|
||||
<input id="benchmark_name" class="u-full-width" type="text" name="benchmark_name" placeholder="Unigine Heaven">
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="three columns">
|
||||
<label for="benchmark_scoring">
|
||||
Benchmark type:
|
||||
<select id="benchmark_scoring" class="u-full-width" name="benchmark_scoring">
|
||||
<option value="fps">Frames per second</option>
|
||||
<option value="ms">Frame time</option>
|
||||
<option value="pts">Total points</option>
|
||||
</select>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<label for="benchmark_description">
|
||||
Benchmark description:
|
||||
<textarea id="benchmark_description" class="twelve columns" cols="30" rows="10" name="benchmark_description"></textarea>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<input class="button-primary u-full-width" type="submit" value="Submit">
|
||||
</form>
|
||||
</div>
|
||||
|
||||
{{ template "footer" . }}
|
27
templates/benchmark/list.tmpl
Normal file
27
templates/benchmark/list.tmpl
Normal file
@ -0,0 +1,27 @@
|
||||
{{ template "header" . }}
|
||||
|
||||
<div class="row">
|
||||
<h2>Benchmark</h2>
|
||||
<a href="/benchmark/create">Add new benchmark</a>
|
||||
|
||||
<table class="twelve columns card-2">
|
||||
<thead>
|
||||
<tr>
|
||||
<td>Name</td>
|
||||
<td>Created at</td>
|
||||
<td>Last updated</td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{ range $b := .benchmarks }}
|
||||
<tr>
|
||||
<td><a href="/benchmark/{{ $b.ID }}">{{ $b.Name }}</a></td>
|
||||
<td>{{ $b.CreatedAt.Format "01/02/2006 15:04am" }}</td>
|
||||
<td>{{ $b.UpdatedAt.Format "01/02/2006 15:04am" }}</td>
|
||||
</tr>
|
||||
{{ end }}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
{{ template "footer" . }}
|
19
templates/benchmark/view.tmpl
Normal file
19
templates/benchmark/view.tmpl
Normal file
@ -0,0 +1,19 @@
|
||||
{{ template "header" . }}
|
||||
|
||||
<div class="row">
|
||||
<h2>{{ .benchmark.Name }}</h2>
|
||||
|
||||
<p>{{ .benchmark.ScoringType }}</p>
|
||||
|
||||
<hr>
|
||||
|
||||
<h4>Latest Benchmark Results:</h4>
|
||||
|
||||
<p>There are currently no results recorded using this benchmark.</p>
|
||||
|
||||
<hr>
|
||||
|
||||
<p><a href="/benchmark">Back</a></p>
|
||||
</div>
|
||||
|
||||
{{ template "footer" . }}
|
34
templates/hardware/create.tmpl
Normal file
34
templates/hardware/create.tmpl
Normal file
@ -0,0 +1,34 @@
|
||||
{{ template "header" . }}
|
||||
|
||||
<div class="row">
|
||||
<h2>Add new hardware</h2>
|
||||
|
||||
<form class="twelve columns" action="/hardware/create" method="POST">
|
||||
<div class="row">
|
||||
<div class="nine columns">
|
||||
<label for="hardware_name">
|
||||
Hardware name:
|
||||
<input id="hardware_name" class="u-full-width" type="text" name="hardware_name" placeholder="EVGA RTX 3080 Ti">
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="three columns">
|
||||
<label for="hardware_type">
|
||||
Hardware type:
|
||||
<select id="hardware_type" class="u-full-width" name="hardware_type">
|
||||
<option value="cpu">Processor</option>
|
||||
<option value="mem">Memory</option>
|
||||
<option value="gpu">Graphics Card</option>
|
||||
<option value="ssd">Solid State Drive</option>
|
||||
<option value="hdd">Hard Drive</option>
|
||||
<option value="nic">Network Card</option>
|
||||
</select>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<input class="button-primary u-full-width" type="submit" value="Submit">
|
||||
</form>
|
||||
</div>
|
||||
|
||||
{{ template "footer" . }}
|
27
templates/hardware/list.tmpl
Normal file
27
templates/hardware/list.tmpl
Normal file
@ -0,0 +1,27 @@
|
||||
{{ template "header" . }}
|
||||
|
||||
<div class="row">
|
||||
<h2>Hardware</h2>
|
||||
<a href="/hardware/create">Add new hardware</a>
|
||||
|
||||
<table class="twelve columns card-2">
|
||||
<thead>
|
||||
<tr>
|
||||
<td>Name</td>
|
||||
<td>Created at</td>
|
||||
<td>Last updated</td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{ range $h := .hardware }}
|
||||
<tr>
|
||||
<td><a href="/hardware/{{ $h.ID }}">{{ $h.Name }}</a></td>
|
||||
<td>{{ $h.CreatedAt.Format "01/02/2006 15:04am" }}</td>
|
||||
<td>{{ $h.UpdatedAt.Format "01/02/2006 15:04am" }}</td>
|
||||
</tr>
|
||||
{{ end }}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
{{ template "footer" . }}
|
40
templates/hardware/view.tmpl
Normal file
40
templates/hardware/view.tmpl
Normal file
@ -0,0 +1,40 @@
|
||||
{{ template "header" . }}
|
||||
|
||||
<div class="row">
|
||||
<h2>{{ .hardware.Name }}</h2>
|
||||
|
||||
<p>{{ .hardware.Type }}</p>
|
||||
|
||||
<hr>
|
||||
|
||||
<h4>Tests Using This Component:</h4>
|
||||
|
||||
{{ $length := len .hardware.Tests }} {{ if eq $length 0 }}
|
||||
<p>There are currently no tests using this hardware component.</p>
|
||||
{{ else }}
|
||||
<table class="u-full-width card-2">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Test</th>
|
||||
<th># of Benchmarks</th>
|
||||
<th>Last Updated</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{ range $test := .hardware.Tests }}
|
||||
<tr>
|
||||
<td><a href="/test/{{ $test.ID }}">{{ $test.Name }}</a></td>
|
||||
<td>{{ len $test.Benchmarks }}</td>
|
||||
<td>{{ $test.CreatedAt.Format "01/02/2006 15:04am" }}</td>
|
||||
</tr>
|
||||
{{ end }}
|
||||
</tbody>
|
||||
</table>
|
||||
{{ end }}
|
||||
|
||||
<hr>
|
||||
|
||||
<p><a href="/hardware">Back</a></p>
|
||||
</div>
|
||||
|
||||
{{ template "footer" . }}
|
5
templates/index/dashboard.tmpl
Normal file
5
templates/index/dashboard.tmpl
Normal file
@ -0,0 +1,5 @@
|
||||
{{ template "header" . }}
|
||||
|
||||
<p>This is the BLT dashboard.</p>
|
||||
|
||||
{{ template "footer" . }}
|
11
templates/layout/footer.tmpl
Normal file
11
templates/layout/footer.tmpl
Normal file
@ -0,0 +1,11 @@
|
||||
{{ define "footer" }}
|
||||
</div>
|
||||
|
||||
<!-- footer -->
|
||||
<nav id="main-footer">
|
||||
<p>BLT version {{ .app_version }} | Built with Go {{ .runtime_version }}</p>
|
||||
</nav>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
{{ end }}
|
21
templates/layout/header.tmpl
Normal file
21
templates/layout/header.tmpl
Normal file
@ -0,0 +1,21 @@
|
||||
{{ define "header" }}
|
||||
<!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>{{ .title }} | BLT</title>
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/skeleton/2.0.4/skeleton.min.css">
|
||||
<link rel="stylesheet" href="/css/kourend.css">
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js" charset="utf-8"></script>
|
||||
<script src="/js/kebos.js" charset="utf-8"></script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<!-- navbar -->
|
||||
{{ template "navbar" . }}
|
||||
|
||||
<!-- main content -->
|
||||
<div id="main-content" class="container card-5">
|
||||
{{ end }}
|
13
templates/layout/navbar.tmpl
Normal file
13
templates/layout/navbar.tmpl
Normal file
@ -0,0 +1,13 @@
|
||||
{{ define "navbar" }}
|
||||
<nav id="main-nav" class="card-2">
|
||||
<div class="nav-left">
|
||||
<h4>BLT</h4>
|
||||
<ul>
|
||||
<li><a href="/">Dashboard</a></li>
|
||||
<li><a href="/test">Tests</a></li>
|
||||
<li><a href="/hardware">Hardware</a></li>
|
||||
<li><a href="/benchmark">Benchmarks</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
{{ end }}
|
51
templates/test/create.tmpl
Normal file
51
templates/test/create.tmpl
Normal file
@ -0,0 +1,51 @@
|
||||
{{ template "header" . }}
|
||||
|
||||
<div class="row">
|
||||
<h2>Create a test</h2>
|
||||
|
||||
<form class="twelve columns" action="/test/create" method="POST">
|
||||
<div class="row">
|
||||
<div class="columns four">
|
||||
<label for="test_hardware">
|
||||
Hardware Component:
|
||||
<select id="test_hardware" class="u-full-width" name="test_hardware">
|
||||
{{ range $hw := .hardware }}
|
||||
<option value="{{ $hw.ID }}">{{ $hw.Name }}</option>
|
||||
{{ end }}
|
||||
</select>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="columns eight">
|
||||
<label for="test_name">
|
||||
Test name:
|
||||
<input id="test_name" class="u-full-width" type="text" name="test_name" placeholder="My hardware benchmarking test">
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="columns twelve">
|
||||
<label for="test_benchmarks">
|
||||
Benchmarks to Test:
|
||||
<select id="test_benchmarks" class="u-full-width" name="test_benchmarks" multiple>
|
||||
{{ range $bm := .benchmarks }}
|
||||
<option value="{{ $bm.ID }}">{{ $bm.Name }}</option>
|
||||
{{ end }}
|
||||
</select>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<label for="test_description">
|
||||
Test description:
|
||||
<textarea id="test_description" class="twelve columns" cols="30" rows="10" name="test_description"></textarea>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<input class="button-primary u-full-width" type="submit" value="Submit">
|
||||
</form>
|
||||
</div>
|
||||
|
||||
{{ template "footer" . }}
|
27
templates/test/list.tmpl
Normal file
27
templates/test/list.tmpl
Normal file
@ -0,0 +1,27 @@
|
||||
{{ template "header" . }}
|
||||
|
||||
<div class="row">
|
||||
<h2>Tests</h2>
|
||||
<a href="/test/create">Create a new test</a>
|
||||
|
||||
<table class="twelve columns card-2">
|
||||
<thead>
|
||||
<tr>
|
||||
<td>Title</td>
|
||||
<td>Created at</td>
|
||||
<td>Last updated</td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{ range $p := .tests }}
|
||||
<tr>
|
||||
<td><a href="/test/{{ $p.ID }}">{{ $p.Name }}</a></td>
|
||||
<td>{{ $p.CreatedAt.Format "01/02/2006 15:04am" }}</td>
|
||||
<td>{{ $p.UpdatedAt.Format "01/02/2006 15:04am" }}</td>
|
||||
</tr>
|
||||
{{ end }}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
{{ template "footer" . }}
|
99
templates/test/view.tmpl
Normal file
99
templates/test/view.tmpl
Normal file
@ -0,0 +1,99 @@
|
||||
{{ template "header" . }}
|
||||
|
||||
<div class="row">
|
||||
<h2>{{ .test.Name }}</h2>
|
||||
|
||||
<p><a href="/hardware/{{ .test.Hardware.ID }}">link to hardware tested.</a></p>
|
||||
|
||||
<p>{{ .test.Description }}</p>
|
||||
|
||||
<h4>Benchmarks used:</h4>
|
||||
|
||||
<ul>
|
||||
{{ range $bm := .test.Benchmarks }}
|
||||
<li><a href="/benchmark/{{ $bm.ID }}">{{ $bm.Name }}</a></li>
|
||||
{{ end }}
|
||||
</ul>
|
||||
|
||||
<hr>
|
||||
|
||||
<h4>Add new result:</h4>
|
||||
|
||||
<form class="u-full-width" action="/result/add" method="POST">
|
||||
<div class="row">
|
||||
<div class="columns four">
|
||||
<label for="result_benchmark">
|
||||
Benchmark:
|
||||
<select id="result_benchmark" class="u-full-width" name="result_benchmark">
|
||||
{{ range $bm := .test.Benchmarks }}
|
||||
<option value="{{ $bm.ID }}">{{ $bm.Name }}</option>
|
||||
{{ end }}
|
||||
</select>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="columns two">
|
||||
<label for="result_avg">
|
||||
Average score:
|
||||
<input id="result_avg" class="u-full-width" type="number" name="result_avg" value="0">
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="columns two">
|
||||
<label for="result_min">
|
||||
Minimum score:
|
||||
<input id="result_min" class="u-full-width" type="number" name="result_min" value="0">
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="columns two">
|
||||
<label for="result_max">
|
||||
Maximum score:
|
||||
<input id="result_max" class="u-full-width" type="number" name="result_max" value="0">
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="columns two">
|
||||
<button class="button-primary u-full-width" type="submit" name="button">Submit</button>
|
||||
</div>
|
||||
|
||||
<input type="hidden" name="result_test" value="{{ .test.ID }}">
|
||||
<input type="hidden" name="result_hardware" value="{{ .test.Hardware.ID }}">
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<hr>
|
||||
|
||||
<h4>Latest Benchmark Results:</h4>
|
||||
|
||||
{{ $length := len .test.Results }} {{ if eq $length 0 }}
|
||||
<p>There are currently no benchmarks recorded in this test.</p>
|
||||
{{ else }}
|
||||
<table class="u-full-width card-2">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Benchmark</th>
|
||||
<th>Average</th>
|
||||
<th>Minimum</th>
|
||||
<th>Maximum</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{ range $res := .test.Results }}
|
||||
<tr>
|
||||
<td>{{ $res.Benchmark.Name }}</td>
|
||||
<td>{{ $res.AverageScore }}</td>
|
||||
<td>{{ if eq $res.MinimumScore 0.0 }}N/a{{ else }}{{ $res.MinimumScore }}{{ end }}</td>
|
||||
<td>{{ if eq $res.MaximumScore 0.0 }}N/a{{ else }}{{ $res.MaximumScore }}{{ end }}</td>
|
||||
</tr>
|
||||
{{ end }}
|
||||
</tbody>
|
||||
</table>
|
||||
{{ end }}
|
||||
|
||||
<hr>
|
||||
|
||||
<p><a href="/test">Back</a></p>
|
||||
</div>
|
||||
|
||||
{{ template "footer" . }}
|
@ -1,9 +0,0 @@
|
||||
{% extends 'layout/default.twig' %}
|
||||
|
||||
{% block title %}Dashboard{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<p>This is a test.</p>
|
||||
|
||||
{% endblock %}
|
@ -1,19 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>{% block title %}{% endblock %} | BLT</title>
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/skeleton/2.0.4/skeleton.min.css">
|
||||
<link rel="stylesheet" href="/css/nardah.css">
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
|
||||
<script src="/js/bedabin.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
{% include 'partials/navbar.twig' %}
|
||||
|
||||
<div class="container">
|
||||
{% block content %}{% endblock %}
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
@ -1,10 +0,0 @@
|
||||
<nav id="main-nav">
|
||||
|
||||
<ul class="nav-left">
|
||||
<li class="site-logo">BLT</li>
|
||||
<li><a href="/">Dashboard</a></li>
|
||||
<li><a href="/test">Test</a></li>
|
||||
<li><a href="/result">Results</a></li>
|
||||
</ul>
|
||||
|
||||
</nav>
|
7
web/forms/benchmark.go
Normal file
7
web/forms/benchmark.go
Normal file
@ -0,0 +1,7 @@
|
||||
package forms
|
||||
|
||||
type BenchmarkForm struct {
|
||||
Name string `form:"benchmark_name" validate:"required"`
|
||||
ScoringType string `form:"benchmark_scoring" validate:"required"`
|
||||
Description string `form:"benchmark_description"`
|
||||
}
|
6
web/forms/hardware.go
Normal file
6
web/forms/hardware.go
Normal file
@ -0,0 +1,6 @@
|
||||
package forms
|
||||
|
||||
type HardwareForm struct {
|
||||
Name string `form:"hardware_name" validate:"required"`
|
||||
Type string `form:"hardware_type" validate:"required"`
|
||||
}
|
10
web/forms/result.go
Normal file
10
web/forms/result.go
Normal file
@ -0,0 +1,10 @@
|
||||
package forms
|
||||
|
||||
type ResultForm struct {
|
||||
Test int `form:"result_test" validate:"required"`
|
||||
Hardware int `form:"result_hardware" validate:"required"`
|
||||
Benchmark int `form:"result_benchmark" validate:"required"`
|
||||
AverageScore float32 `form:"result_avg" validate:"required"`
|
||||
MinimumScore float32 `form:"result_min"`
|
||||
MaximumScore float32 `form:"result_max"`
|
||||
}
|
8
web/forms/test.go
Normal file
8
web/forms/test.go
Normal file
@ -0,0 +1,8 @@
|
||||
package forms
|
||||
|
||||
type TestForm struct {
|
||||
Name string `form:"test_name" validate:"required"`
|
||||
Description string `form:"test_description"`
|
||||
Hardware int `form:"test_hardware" validate:"required"`
|
||||
Benchmarks []string `form:"test_benchmarks" validate:"required"`
|
||||
}
|
12
web/middleware/vars.go
Normal file
12
web/middleware/vars.go
Normal file
@ -0,0 +1,12 @@
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"github.com/flamego/template"
|
||||
|
||||
"git.metaunix.net/bitgoblin/blt/app"
|
||||
)
|
||||
|
||||
func CustomVars(data template.Data) {
|
||||
data["app_version"] = app.AppVersion
|
||||
data["runtime_version"] = app.RuntimeVersion
|
||||
}
|
61
web/routes.go
Normal file
61
web/routes.go
Normal file
@ -0,0 +1,61 @@
|
||||
package web
|
||||
|
||||
import (
|
||||
"github.com/flamego/binding"
|
||||
"github.com/flamego/flamego"
|
||||
|
||||
"git.metaunix.net/bitgoblin/blt/web/forms"
|
||||
"git.metaunix.net/bitgoblin/blt/web/routes"
|
||||
)
|
||||
|
||||
func RegisterRoutes(f *flamego.Flame) {
|
||||
// index routes
|
||||
f.Get("/", routes.GetDashboard)
|
||||
|
||||
// hardware routes
|
||||
f.Group("/hardware", func() {
|
||||
f.Get("", func(c flamego.Context) {
|
||||
c.Redirect("/hardware/list")
|
||||
})
|
||||
|
||||
f.Get("/list", routes.HardwareGetList)
|
||||
|
||||
f.Get("/create", routes.HardwareGetCreate)
|
||||
f.Post("/create", binding.Form(forms.HardwareForm{}), routes.HardwarePostCreate)
|
||||
|
||||
f.Get("/{hardware_id}", routes.HardwareGetView)
|
||||
})
|
||||
|
||||
// benchmark routes
|
||||
f.Group("/benchmark", func() {
|
||||
f.Get("", func(c flamego.Context) {
|
||||
c.Redirect("/benchmark/list")
|
||||
})
|
||||
|
||||
f.Get("/list", routes.BenchmarkGetList)
|
||||
|
||||
f.Get("/create", routes.BenchmarkGetCreate)
|
||||
f.Post("/create", binding.Form(forms.BenchmarkForm{}), routes.BenchmarkPostCreate)
|
||||
|
||||
f.Get("/{benchmark_id}", routes.BenchmarkGetView)
|
||||
})
|
||||
|
||||
// test routes
|
||||
f.Group("/test", func() {
|
||||
f.Get("", func(c flamego.Context) {
|
||||
c.Redirect("/test/list")
|
||||
})
|
||||
|
||||
f.Get("/list", routes.TestGetList)
|
||||
|
||||
f.Get("/create", routes.TestGetCreate)
|
||||
f.Post("/create", binding.Form(forms.TestForm{}), routes.TestPostCreate)
|
||||
|
||||
f.Get("/{test_id}", routes.TestGetView)
|
||||
})
|
||||
|
||||
// result routes
|
||||
f.Group("/result", func() {
|
||||
f.Post("/add", binding.Form(forms.ResultForm{}), routes.ResultPostCreate)
|
||||
})
|
||||
}
|
66
web/routes/benchmark.go
Normal file
66
web/routes/benchmark.go
Normal file
@ -0,0 +1,66 @@
|
||||
package routes
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
|
||||
"github.com/flamego/binding"
|
||||
"github.com/flamego/flamego"
|
||||
"github.com/flamego/template"
|
||||
"github.com/flamego/validator"
|
||||
|
||||
"git.metaunix.net/bitgoblin/blt/models"
|
||||
"git.metaunix.net/bitgoblin/blt/web/forms"
|
||||
)
|
||||
|
||||
func BenchmarkGetList(t template.Template, data template.Data) {
|
||||
// add benchmarks to template
|
||||
var benchmarks []models.Benchmark
|
||||
models.DB.Find(&benchmarks)
|
||||
data["benchmarks"] = benchmarks
|
||||
|
||||
data["title"] = "List of Benchmarks"
|
||||
t.HTML(http.StatusOK, "benchmark/list")
|
||||
}
|
||||
|
||||
func BenchmarkGetView(c flamego.Context, t template.Template, data template.Data) {
|
||||
// find benchmark ID from request
|
||||
benchmarkID := c.Param("benchmark_id")
|
||||
|
||||
// find benchmark from DB
|
||||
var benchmark models.Benchmark
|
||||
models.DB.First(&benchmark, benchmarkID)
|
||||
data["benchmark"] = benchmark
|
||||
|
||||
data["title"] = benchmark.Name
|
||||
t.HTML(http.StatusOK, "benchmark/view")
|
||||
}
|
||||
|
||||
func BenchmarkGetCreate(t template.Template, data template.Data) {
|
||||
data["title"] = "Add New Benchmark"
|
||||
t.HTML(http.StatusOK, "benchmark/create")
|
||||
}
|
||||
|
||||
func BenchmarkPostCreate(c flamego.Context, form forms.BenchmarkForm, errs binding.Errors) {
|
||||
if len(errs) > 0 {
|
||||
var err error
|
||||
switch errs[0].Category {
|
||||
case binding.ErrorCategoryValidation:
|
||||
err = errs[0].Err.(validator.ValidationErrors)[0]
|
||||
default:
|
||||
err = errs[0].Err
|
||||
}
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
benchmark := models.Benchmark{
|
||||
Name: form.Name,
|
||||
ScoringType: form.ScoringType,
|
||||
Description: form.Description,
|
||||
}
|
||||
|
||||
_ = models.DB.Create(&benchmark)
|
||||
|
||||
c.Redirect(fmt.Sprintf("/benchmark/%d", benchmark.ID))
|
||||
}
|
65
web/routes/hardware.go
Normal file
65
web/routes/hardware.go
Normal file
@ -0,0 +1,65 @@
|
||||
package routes
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
|
||||
"github.com/flamego/binding"
|
||||
"github.com/flamego/flamego"
|
||||
"github.com/flamego/template"
|
||||
"github.com/flamego/validator"
|
||||
|
||||
"git.metaunix.net/bitgoblin/blt/models"
|
||||
"git.metaunix.net/bitgoblin/blt/web/forms"
|
||||
)
|
||||
|
||||
func HardwareGetList(t template.Template, data template.Data) {
|
||||
// add hardwares to template
|
||||
var hardware []models.Hardware
|
||||
models.DB.Find(&hardware)
|
||||
data["hardware"] = hardware
|
||||
|
||||
data["title"] = "List of Hardware"
|
||||
t.HTML(http.StatusOK, "hardware/list")
|
||||
}
|
||||
|
||||
func HardwareGetView(c flamego.Context, t template.Template, data template.Data) {
|
||||
// find hardware ID from request
|
||||
hardwareID := c.Param("hardware_id")
|
||||
|
||||
// find hardware from DB
|
||||
var hardware models.Hardware
|
||||
models.DB.Preload("Tests.Benchmarks").First(&hardware, hardwareID)
|
||||
data["hardware"] = hardware
|
||||
|
||||
data["title"] = hardware.Name
|
||||
t.HTML(http.StatusOK, "hardware/view")
|
||||
}
|
||||
|
||||
func HardwareGetCreate(t template.Template, data template.Data) {
|
||||
data["title"] = "Add New Hardware"
|
||||
t.HTML(http.StatusOK, "hardware/create")
|
||||
}
|
||||
|
||||
func HardwarePostCreate(c flamego.Context, form forms.HardwareForm, errs binding.Errors) {
|
||||
if len(errs) > 0 {
|
||||
var err error
|
||||
switch errs[0].Category {
|
||||
case binding.ErrorCategoryValidation:
|
||||
err = errs[0].Err.(validator.ValidationErrors)[0]
|
||||
default:
|
||||
err = errs[0].Err
|
||||
}
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
hardware := models.Hardware{
|
||||
Name: form.Name,
|
||||
Type: form.Type,
|
||||
}
|
||||
|
||||
_ = models.DB.Create(&hardware)
|
||||
|
||||
c.Redirect(fmt.Sprintf("/hardware/%d", hardware.ID))
|
||||
}
|
12
web/routes/index.go
Normal file
12
web/routes/index.go
Normal file
@ -0,0 +1,12 @@
|
||||
package routes
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/flamego/template"
|
||||
)
|
||||
|
||||
func GetDashboard(t template.Template, data template.Data) {
|
||||
data["title"] = "Dashboard"
|
||||
t.HTML(http.StatusOK, "index/dashboard")
|
||||
}
|
39
web/routes/result.go
Normal file
39
web/routes/result.go
Normal file
@ -0,0 +1,39 @@
|
||||
package routes
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"github.com/flamego/binding"
|
||||
"github.com/flamego/flamego"
|
||||
"github.com/flamego/validator"
|
||||
|
||||
"git.metaunix.net/bitgoblin/blt/models"
|
||||
"git.metaunix.net/bitgoblin/blt/web/forms"
|
||||
)
|
||||
|
||||
func ResultPostCreate(c flamego.Context, form forms.ResultForm, errs binding.Errors) {
|
||||
if len(errs) > 0 {
|
||||
var err error
|
||||
switch errs[0].Category {
|
||||
case binding.ErrorCategoryValidation:
|
||||
err = errs[0].Err.(validator.ValidationErrors)[0]
|
||||
default:
|
||||
err = errs[0].Err
|
||||
}
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
result := models.Result{
|
||||
TestID: form.Test,
|
||||
HardwareID: form.Hardware,
|
||||
BenchmarkID: form.Benchmark,
|
||||
AverageScore: form.AverageScore,
|
||||
MinimumScore: form.MinimumScore,
|
||||
MaximumScore: form.MaximumScore,
|
||||
}
|
||||
|
||||
_ = models.DB.Create(&result)
|
||||
|
||||
c.Redirect(fmt.Sprintf("/test/%d", result.TestID))
|
||||
}
|
83
web/routes/test.go
Normal file
83
web/routes/test.go
Normal file
@ -0,0 +1,83 @@
|
||||
package routes
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
|
||||
"github.com/flamego/binding"
|
||||
"github.com/flamego/flamego"
|
||||
"github.com/flamego/template"
|
||||
"github.com/flamego/validator"
|
||||
|
||||
"git.metaunix.net/bitgoblin/blt/models"
|
||||
"git.metaunix.net/bitgoblin/blt/web/forms"
|
||||
)
|
||||
|
||||
func TestGetList(t template.Template, data template.Data) {
|
||||
// add tests to template
|
||||
var tests []models.Test
|
||||
models.DB.Find(&tests)
|
||||
data["tests"] = tests
|
||||
|
||||
data["title"] = "List of Tests"
|
||||
t.HTML(http.StatusOK, "test/list")
|
||||
}
|
||||
|
||||
func TestGetView(c flamego.Context, t template.Template, data template.Data) {
|
||||
// find test ID from request
|
||||
testID := c.Param("test_id")
|
||||
|
||||
// find hardware from DB
|
||||
var test models.Test
|
||||
models.DB.Preload("Hardware").Preload("Benchmarks").Preload("Results.Benchmark").First(&test, testID)
|
||||
data["test"] = test
|
||||
|
||||
data["title"] = test.Name
|
||||
t.HTML(http.StatusOK, "test/view")
|
||||
}
|
||||
|
||||
func TestGetCreate(t template.Template, data template.Data) {
|
||||
// add hardware components to template
|
||||
var hardware []models.Hardware
|
||||
models.DB.Find(&hardware)
|
||||
data["hardware"] = hardware
|
||||
|
||||
// add benchmarks to template
|
||||
var benchmarks []models.Benchmark
|
||||
models.DB.Find(&benchmarks)
|
||||
data["benchmarks"] = benchmarks
|
||||
|
||||
data["title"] = "Create a Test"
|
||||
t.HTML(http.StatusOK, "test/create")
|
||||
}
|
||||
|
||||
func TestPostCreate(c flamego.Context, form forms.TestForm, errs binding.Errors) {
|
||||
if len(errs) > 0 {
|
||||
var err error
|
||||
switch errs[0].Category {
|
||||
case binding.ErrorCategoryValidation:
|
||||
err = errs[0].Err.(validator.ValidationErrors)[0]
|
||||
default:
|
||||
err = errs[0].Err
|
||||
}
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
test := models.Test{
|
||||
Name: form.Name,
|
||||
Description: form.Description,
|
||||
HardwareID: form.Hardware,
|
||||
}
|
||||
|
||||
_ = models.DB.Create(&test)
|
||||
|
||||
// bind benchmarks to test
|
||||
for _, v := range form.Benchmarks {
|
||||
var benchmark models.Benchmark
|
||||
models.DB.First(&benchmark, v) // find benchmark
|
||||
models.DB.Model(&test).Association("Benchmarks").Append(&benchmark)
|
||||
}
|
||||
|
||||
c.Redirect(fmt.Sprintf("/test/%d", test.ID))
|
||||
}
|
Loading…
Reference in New Issue
Block a user