Add themes
This commit is contained in:
parent
806822a9a8
commit
bfee129443
12 changed files with 139 additions and 25 deletions
|
@ -1,6 +1,12 @@
|
||||||
# Changelog
|
# Changelog
|
||||||
This file keeps track of changes in more human-readable fashion
|
This file keeps track of changes in more human-readable fashion
|
||||||
|
|
||||||
|
## v0.3.0
|
||||||
|
* Added themes
|
||||||
|
* Picked theme is set by `theme` key in config. Default is ...`default`
|
||||||
|
* Themes are defined in `/public/themes/<name>.css` and modify colours (or, theoretically, do more)
|
||||||
|
* Current pre-made themes are `default`, `gruvbox` and `high-contrast`
|
||||||
|
|
||||||
## v0.2.0
|
## v0.2.0
|
||||||
* Added config reload
|
* Added config reload
|
||||||
* Can be reloaded in info page
|
* Can be reloaded in info page
|
||||||
|
|
|
@ -48,7 +48,8 @@ password=admin # Your password
|
||||||
port=7101 # What port to run on (probably leave on 7101 if using docker)
|
port=7101 # What port to run on (probably leave on 7101 if using docker)
|
||||||
timezone=Local # IANA Time zone database identifier ("UTC", Local", "Europe/Moscow" etc.), Defaults to Local if can't parse.
|
timezone=Local # IANA Time zone database identifier ("UTC", Local", "Europe/Moscow" etc.), Defaults to Local if can't parse.
|
||||||
grace_period=0s # Time after a new day begins, but before the switch to next day's file. e.g. 2h30m - files will change at 2:30am
|
grace_period=0s # Time after a new day begins, but before the switch to next day's file. e.g. 2h30m - files will change at 2:30am
|
||||||
language=en # ISO-639 language code (currently supported - en, ru)
|
language=en # ISO-639 language code (pre-installed - en, ru)
|
||||||
|
theme=default # Picked theme (pre-installed - default, gruvbox, high-contrast)
|
||||||
log_to_file=false # Whether to write logs to a file
|
log_to_file=false # Whether to write logs to a file
|
||||||
log_file=config/log.txt # Where to store the log file if it is enabled
|
log_file=config/log.txt # Where to store the log file if it is enabled
|
||||||
enable_scram=false # Whether the app should shut down if there are 3 or more failed login attempts within 100 seconds
|
enable_scram=false # Whether the app should shut down if there are 3 or more failed login attempts within 100 seconds
|
||||||
|
|
21
TODO.md
21
TODO.md
|
@ -1,21 +1,32 @@
|
||||||
# TODO
|
# TODO
|
||||||
List of things to add to this project
|
List of things to add to this project
|
||||||
|
|
||||||
## Agenda
|
## v1.0.0
|
||||||
* a 512x logo so I can enable PWA
|
* a logo so I can enable PWA (and look cool)
|
||||||
* CI/CD pipeline
|
* Themes
|
||||||
* Better docs in case others want to use this for some reason
|
* Theme in config [X]
|
||||||
* Check export function for improvements
|
* Themes
|
||||||
|
* Default [X]
|
||||||
|
* Gruvbox [X]
|
||||||
|
* High contrast [ ]
|
||||||
|
* Seasons?
|
||||||
|
* Check for bugs
|
||||||
|
* Versioned containers via `ghcr.io` or `dockerhub`,
|
||||||
|
with automatic CI/CD build on release
|
||||||
|
* Test test test !!!!
|
||||||
|
|
||||||
## Brainstorming
|
## Brainstorming
|
||||||
Don't expect any of this, these are ideas floating inside my head
|
Don't expect any of this, these are ideas floating inside my head
|
||||||
* Further info page functionality
|
* Further info page functionality
|
||||||
* Edit config
|
* Edit config
|
||||||
* Statistics e.g. mb taken, number of day pages/notes
|
* Statistics e.g. mb taken, number of day pages/notes
|
||||||
|
* Test telegram link
|
||||||
* Multi-user support through several username-pass keys
|
* Multi-user support through several username-pass keys
|
||||||
* `/data/<user>/...`
|
* `/data/<user>/...`
|
||||||
* This would be an *extremely* breaking change
|
* This would be an *extremely* breaking change
|
||||||
* How to handle exporting *all*? Admin account?
|
* How to handle exporting *all*? Admin account?
|
||||||
* I don't need this, unless Hibiscus.txt somehow gets popular why bother?
|
* I don't need this, unless Hibiscus.txt somehow gets popular why bother?
|
||||||
Is this even a feature that fits the vision?
|
Is this even a feature that fits the vision?
|
||||||
|
* Better, *multi-page* docs in case others want to use this for some reason
|
||||||
|
* Check export function for improvements
|
||||||
* *Go* dependency-less? <-- this is a terrible idea
|
* *Go* dependency-less? <-- this is a terrible idea
|
||||||
|
|
|
@ -22,6 +22,7 @@ type Config struct {
|
||||||
Timezone *time.Location `config:"timezone" type:"location"`
|
Timezone *time.Location `config:"timezone" type:"location"`
|
||||||
GraceTime time.Duration `config:"grace_period" type:"duration"`
|
GraceTime time.Duration `config:"grace_period" type:"duration"`
|
||||||
Language string `config:"language" type:"string"`
|
Language string `config:"language" type:"string"`
|
||||||
|
Theme string `config:"theme" type:"string"`
|
||||||
LogToFile bool `config:"log_to_file" type:"bool"`
|
LogToFile bool `config:"log_to_file" type:"bool"`
|
||||||
LogFile string `config:"log_file" type:"string"`
|
LogFile string `config:"log_file" type:"string"`
|
||||||
Scram bool `config:"enable_scram" type:"bool"`
|
Scram bool `config:"enable_scram" type:"bool"`
|
||||||
|
@ -141,6 +142,7 @@ func ConfigInit() Config {
|
||||||
Password: "admin",
|
Password: "admin",
|
||||||
Timezone: time.Local,
|
Timezone: time.Local,
|
||||||
Language: "en",
|
Language: "en",
|
||||||
|
Theme: "default",
|
||||||
LogFile: "config/log.txt",
|
LogFile: "config/log.txt",
|
||||||
GraceTime: 0,
|
GraceTime: 0,
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ port=7101
|
||||||
timezone=Local
|
timezone=Local
|
||||||
grace_period=0s
|
grace_period=0s
|
||||||
language=en
|
language=en
|
||||||
|
theme=default
|
||||||
log_to_file=false
|
log_to_file=false
|
||||||
log_file=config/log.txt
|
log_file=config/log.txt
|
||||||
enable_scram=false
|
enable_scram=false
|
||||||
|
|
2
info.go
2
info.go
|
@ -15,7 +15,7 @@ type HibiscusInfo struct {
|
||||||
|
|
||||||
// Info contains app information
|
// Info contains app information
|
||||||
var Info = HibiscusInfo{
|
var Info = HibiscusInfo{
|
||||||
Version: "0.2.0",
|
Version: "0.3.0",
|
||||||
SourceLink: "https://git.a71.su/Andrew71/hibiscus",
|
SourceLink: "https://git.a71.su/Andrew71/hibiscus",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
<link rel="manifest" href="/public/manifest.json" />
|
<link rel="manifest" href="/public/manifest.json" />
|
||||||
<link rel="icon" type="image/x-icon" href="/public/favicon.ico">
|
<link rel="icon" type="image/x-icon" href="/public/favicon.ico">
|
||||||
<link rel="stylesheet" href="/public/main.css">
|
<link rel="stylesheet" href="/public/main.css">
|
||||||
|
<link rel="stylesheet" href="/public/themes/{{ hibiscusTheme }}.css">
|
||||||
<script src="/public/date.js"></script>
|
<script src="/public/date.js"></script>
|
||||||
<title>Hibiscus.txt</title>
|
<title>Hibiscus.txt</title>
|
||||||
</head>
|
</head>
|
||||||
|
|
|
@ -1,6 +1,33 @@
|
||||||
|
/* Default theme */
|
||||||
|
:root {
|
||||||
|
/* Light theme */
|
||||||
|
--text-light: #454545;
|
||||||
|
--bg-light: #f5f0e1;
|
||||||
|
|
||||||
|
--clickable-light: #f85552;
|
||||||
|
--clickable-hover-light: #e66868;
|
||||||
|
--clickable-label-light: #f5f2ee;
|
||||||
|
--text-hover-light: #656565;
|
||||||
|
|
||||||
|
--textarea-bg-light: #f5f2ee;
|
||||||
|
--textarea-border-light: #454545;
|
||||||
|
|
||||||
|
/* Dark theme */
|
||||||
|
--text-dark: #f5f0e1;
|
||||||
|
--bg-dark: #2c2825;
|
||||||
|
|
||||||
|
--clickable-dark: #f85552;
|
||||||
|
--clickable-hover-dark: #e66868;
|
||||||
|
--clickable-label-dark: #f5f2ee;
|
||||||
|
--text-hover-dark: #656565;
|
||||||
|
|
||||||
|
--textarea-bg-dark: #383030;
|
||||||
|
--textarea-border-dark: #454545;
|
||||||
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
color: #454545;
|
color: var(--text-light);
|
||||||
background-color: #f5f0e1;
|
background-color: var(--bg-light);
|
||||||
margin: 2em auto;
|
margin: 2em auto;
|
||||||
max-width: 640px;
|
max-width: 640px;
|
||||||
padding: 1em;
|
padding: 1em;
|
||||||
|
@ -11,33 +38,33 @@ body {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
a, a:visited { color: #f85552; }
|
a, a:visited { color: var(--clickable-light); }
|
||||||
a:hover, a:visited:hover { color: #e66868; }
|
a:hover, a:visited:hover { color: var(--clickable-hover-light); }
|
||||||
a.no-accent, a.no-accent:visited { color: #454545; }
|
a.no-accent, a.no-accent:visited { color: var(--text-light); }
|
||||||
a.no-accent:hover, a.no-accent:visited:hover { color: #656565; }
|
a.no-accent:hover, a.no-accent:visited:hover { color: var(--text-hover-light); }
|
||||||
|
|
||||||
h2 { margin-bottom:12px; }
|
h2 { margin-bottom:12px; }
|
||||||
.list-title { margin-bottom: 0}
|
.list-title { margin-bottom: 0}
|
||||||
.list-desc { margin-top: 0 }
|
.list-desc { margin-top: 0 }
|
||||||
|
|
||||||
textarea, input {
|
textarea, input {
|
||||||
background: #f5f2ee;
|
background: var(--textarea-bg-light);
|
||||||
max-width: 640px;
|
max-width: 640px;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
display: block;
|
display: block;
|
||||||
resize: vertical;
|
resize: vertical;
|
||||||
outline: 0;
|
outline: 0;
|
||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
border: 0.0625em solid #454545;
|
border: 0.0625em solid var(--textarea-border-light);
|
||||||
margin-bottom: 1em;
|
margin-bottom: 1em;
|
||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
}
|
}
|
||||||
input { height: 2.5em; }
|
input { height: 2.5em; }
|
||||||
|
|
||||||
button {
|
button {
|
||||||
background-color: #f85552;
|
background-color: var(--clickable-light);
|
||||||
border: none;
|
border: none;
|
||||||
color: #f5f2ee;
|
color: var(--clickable-label-light);
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
|
@ -49,7 +76,7 @@ button {
|
||||||
max-width: 640px;
|
max-width: 640px;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
button:hover { background-color: #e66868; }
|
button:hover { background-color: var(--clickable-hover-light); }
|
||||||
|
|
||||||
footer { margin-top: auto; }
|
footer { margin-top: auto; }
|
||||||
header > h1, header > p {
|
header > h1, header > p {
|
||||||
|
@ -60,13 +87,23 @@ header > h1, header > p {
|
||||||
/* Dark theme */
|
/* Dark theme */
|
||||||
@media (prefers-color-scheme: dark) {
|
@media (prefers-color-scheme: dark) {
|
||||||
body {
|
body {
|
||||||
color: #f5f0e1;
|
color: var(--text-dark);
|
||||||
background-color: #2c2825;
|
background-color: var(--bg-dark);
|
||||||
}
|
}
|
||||||
textarea, input {
|
textarea, input {
|
||||||
color: #f5f0e1;
|
color: var(--text-dark);
|
||||||
background-color: #383030;
|
background-color: var(--textarea-bg-dark);
|
||||||
|
border-color: var(--textarea-border-dark)
|
||||||
}
|
}
|
||||||
a.no-accent, a.no-accent:visited { color: #f5f0e1; }
|
|
||||||
a.no-accent:hover, a.no-accent:visited:hover { color: #a9a8a4; }
|
a, a:visited { color: var(--clickable-dark); }
|
||||||
|
a:hover, a:visited:hover { color: var(--clickable-hover-dark); }
|
||||||
|
a.no-accent, a.no-accent:visited { color: var(--text-dark); }
|
||||||
|
a.no-accent:hover, a.no-accent:visited:hover { color: var(--text-hover-dark); }
|
||||||
|
|
||||||
|
button {
|
||||||
|
background-color: var(--clickable-dark);
|
||||||
|
color: var(--clickable-label-dark);
|
||||||
|
}
|
||||||
|
button:hover { background-color: var(--clickable-hover-dark); }
|
||||||
}
|
}
|
1
public/themes/default.css
Normal file
1
public/themes/default.css
Normal file
|
@ -0,0 +1 @@
|
||||||
|
/* Default theme is defined in main.css */
|
26
public/themes/gruvbox.css
Normal file
26
public/themes/gruvbox.css
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
/* Based on https://github.com/morhetz/gruvbox, MIT licensed colorscheme for vim */
|
||||||
|
:root {
|
||||||
|
/* Light theme */
|
||||||
|
--text-light: #3c3836;
|
||||||
|
--bg-light: #fbf1c7;
|
||||||
|
|
||||||
|
--clickable-light: #cc241d;
|
||||||
|
--clickable-hover-light: #9d0006;
|
||||||
|
--clickable-label-light: #f9f5d7;
|
||||||
|
--text-hover-light: #665c54;
|
||||||
|
|
||||||
|
--textarea-bg-light: #f9f5d7;
|
||||||
|
--textarea-border-light: #282828;
|
||||||
|
|
||||||
|
/* Dark theme */
|
||||||
|
--text-dark: #ebdbb2;
|
||||||
|
--bg-dark: #282828;
|
||||||
|
|
||||||
|
--clickable-dark: #cc241d;
|
||||||
|
--clickable-hover-dark: #fb4934;
|
||||||
|
--clickable-label-dark: #fbf1c7;
|
||||||
|
--text-hover-dark: #fbf1c7;
|
||||||
|
|
||||||
|
--textarea-bg-dark: #32302f;
|
||||||
|
--textarea-border-dark: #3c3836;
|
||||||
|
}
|
26
public/themes/high-contrast.css
Normal file
26
public/themes/high-contrast.css
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
/* High contrast theme. It ain't pretty, but it passes WCAG AA and mostly even AAA */
|
||||||
|
:root {
|
||||||
|
/* Light theme */
|
||||||
|
--text-light: #000000;
|
||||||
|
--bg-light: #FFFFFF;
|
||||||
|
|
||||||
|
--clickable-light: #CC0000;
|
||||||
|
--clickable-hover-light: #CC3333;
|
||||||
|
--clickable-label-light: #FFFFFF;
|
||||||
|
--text-hover-light: #666666;
|
||||||
|
|
||||||
|
--textarea-bg-light: #FFFFFF;
|
||||||
|
--textarea-border-light: #000000;
|
||||||
|
|
||||||
|
/* Dark theme */
|
||||||
|
--text-dark: #FFFFFF;
|
||||||
|
--bg-dark: #000000;
|
||||||
|
|
||||||
|
--clickable-dark: #FF3333;
|
||||||
|
--clickable-hover-dark: #FF6666;
|
||||||
|
--clickable-label-dark: #000000;
|
||||||
|
--text-hover-dark: #e7e7e7;
|
||||||
|
|
||||||
|
--textarea-bg-dark: #000000;
|
||||||
|
--textarea-border-dark: #666666;
|
||||||
|
}
|
|
@ -7,6 +7,7 @@ import (
|
||||||
"log/slog"
|
"log/slog"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
|
"path"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
@ -27,7 +28,8 @@ type formatEntries func([]string) []Entry
|
||||||
|
|
||||||
var templateFuncs = map[string]interface{}{
|
var templateFuncs = map[string]interface{}{
|
||||||
"translatableText": TranslatableText,
|
"translatableText": TranslatableText,
|
||||||
"hibiscusVersion": func() string { return "v" + Info.Version }}
|
"hibiscusVersion": func() string { return "v" + Info.Version },
|
||||||
|
"hibiscusTheme": func() string { return path.Clean(Cfg.Theme) }}
|
||||||
var editTemplate = template.Must(template.New("").Funcs(templateFuncs).ParseFiles("./pages/base.html", "./pages/edit.html"))
|
var editTemplate = template.Must(template.New("").Funcs(templateFuncs).ParseFiles("./pages/base.html", "./pages/edit.html"))
|
||||||
var viewTemplate = template.Must(template.New("").Funcs(templateFuncs).ParseFiles("./pages/base.html", "./pages/entry.html"))
|
var viewTemplate = template.Must(template.New("").Funcs(templateFuncs).ParseFiles("./pages/base.html", "./pages/entry.html"))
|
||||||
var listTemplate = template.Must(template.New("").Funcs(templateFuncs).ParseFiles("./pages/base.html", "./pages/list.html"))
|
var listTemplate = template.Must(template.New("").Funcs(templateFuncs).ParseFiles("./pages/base.html", "./pages/list.html"))
|
||||||
|
|
Loading…
Reference in a new issue