Added initial Settings
This commit is contained in:
@@ -14,4 +14,10 @@ create table if not exists Chapter (
|
|||||||
Number integer not null,
|
Number integer not null,
|
||||||
TimeStampUnixEpoch integer not null,
|
TimeStampUnixEpoch integer not null,
|
||||||
foreign key(MangaID) references Manga(ID)
|
foreign key(MangaID) references Manga(ID)
|
||||||
|
);
|
||||||
|
|
||||||
|
create table if not exists Setting (
|
||||||
|
Name text not null primary key,
|
||||||
|
Value text,
|
||||||
|
DefaultValue text not null
|
||||||
);
|
);
|
||||||
@@ -11,6 +11,7 @@ type Manager struct {
|
|||||||
db *sql.DB
|
db *sql.DB
|
||||||
Mangas DbTable[int, Manga]
|
Mangas DbTable[int, Manga]
|
||||||
Chapters DbTable[int, Chapter]
|
Chapters DbTable[int, Chapter]
|
||||||
|
Settings DbTable[string, Setting]
|
||||||
CreateIfNotExists bool
|
CreateIfNotExists bool
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -18,8 +19,9 @@ func NewDatabase(connectionString string, createIfNotExists bool) Manager {
|
|||||||
return Manager{
|
return Manager{
|
||||||
ConnectionString: connectionString,
|
ConnectionString: connectionString,
|
||||||
db: nil,
|
db: nil,
|
||||||
Mangas: NewDbTable[int, Manga](updateManga, insertManga, loadMangas, deleteManga),
|
Mangas: NewDbTable(updateManga, insertManga, loadMangas, deleteManga),
|
||||||
Chapters: NewDbTable[int, Chapter](updateChapter, insertChapter, loadChapters, deleteChapter),
|
Chapters: NewDbTable(updateChapter, insertChapter, loadChapters, deleteChapter),
|
||||||
|
Settings: NewDbTable(updateSetting, insertSetting, loadSettings, deleteSetting),
|
||||||
CreateIfNotExists: createIfNotExists,
|
CreateIfNotExists: createIfNotExists,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -75,8 +77,12 @@ func (dbMgr *Manager) Save() error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
err = dbMgr.Chapters.Save(dbMgr.db)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
return dbMgr.Chapters.Save(dbMgr.db)
|
return dbMgr.Settings.Save(dbMgr.db)
|
||||||
}
|
}
|
||||||
|
|
||||||
//go:embed createDb.sql
|
//go:embed createDb.sql
|
||||||
@@ -98,5 +104,11 @@ func (dbMgr *Manager) load() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
err = dbMgr.Settings.Load(dbMgr.db)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
initSettings(&dbMgr.Settings)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
65
internal/database/setting.go
Normal file
65
internal/database/setting.go
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
package database
|
||||||
|
|
||||||
|
import (
|
||||||
|
"database/sql"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Setting struct {
|
||||||
|
Name string
|
||||||
|
Value string
|
||||||
|
Default string
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewSetting(name string, defaultValue string) Setting {
|
||||||
|
return Setting{
|
||||||
|
Name: name,
|
||||||
|
Value: defaultValue,
|
||||||
|
Default: defaultValue,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func initSettings(settings *DbTable[string, Setting]) {
|
||||||
|
addSettingIfNotExists(NewSetting("theme", "white"), settings)
|
||||||
|
addSettingIfNotExists(NewSetting("order", "title"), settings)
|
||||||
|
}
|
||||||
|
|
||||||
|
func addSettingIfNotExists(setting Setting, settings *DbTable[string, Setting]) {
|
||||||
|
_, exists := settings.Get(setting.Name)
|
||||||
|
if !exists {
|
||||||
|
settings.Set(setting.Name, setting)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func updateSetting(db *sql.DB, s *Setting) error {
|
||||||
|
const cmd = "UPDATE Setting set Value = ? WHERE Name = ?"
|
||||||
|
_, err := db.Exec(cmd, s.Value, s.Name)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func insertSetting(db *sql.DB, s *Setting) error {
|
||||||
|
const cmd = "INSERT INTO Setting(Name, Value, DefaultValue) VALUES(?, ?, ?)"
|
||||||
|
_, err := db.Exec(cmd, s.Name, s.Value, s.Default)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func loadSettings(db *sql.DB) (map[string]Setting, error) {
|
||||||
|
const cmd = "SELECT Name, Value, DefaultValue from Setting"
|
||||||
|
rows, err := db.Query(cmd)
|
||||||
|
|
||||||
|
res := make(map[string]Setting)
|
||||||
|
|
||||||
|
for rows.Next() {
|
||||||
|
setting := Setting{}
|
||||||
|
if err = rows.Scan(&setting.Name, &setting.Value, &setting.Default); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
res[setting.Name] = setting
|
||||||
|
}
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func deleteSetting(db *sql.DB, key string) error {
|
||||||
|
const cmd = "UPDATE Setting set Value = DefaultValue WHERE Name = ?"
|
||||||
|
_, err := db.Exec(cmd, key)
|
||||||
|
return err
|
||||||
|
}
|
||||||
@@ -88,6 +88,16 @@ func (d *DbTable[K, T]) All() []T {
|
|||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (d *DbTable[K, T]) Map() map[K]T {
|
||||||
|
d.mutex.Lock()
|
||||||
|
defer d.mutex.Unlock()
|
||||||
|
res := make(map[K]T, len(d.items))
|
||||||
|
for k, manga := range d.items {
|
||||||
|
res[k] = manga
|
||||||
|
}
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
func (d *DbTable[K, T]) Delete(db *sql.DB, key K) error {
|
func (d *DbTable[K, T]) Delete(db *sql.DB, key K) error {
|
||||||
d.mutex.Lock()
|
d.mutex.Lock()
|
||||||
defer d.mutex.Unlock()
|
defer d.mutex.Unlock()
|
||||||
|
|||||||
@@ -136,7 +136,8 @@ func (s *Server) HandleMenu(w http.ResponseWriter, r *http.Request) {
|
|||||||
fmt.Printf("Sorting took %d ms\n", (nex-n)/1000000)
|
fmt.Printf("Sorting took %d ms\n", (nex-n)/1000000)
|
||||||
|
|
||||||
menuViewModel := view.MenuViewModel{
|
menuViewModel := view.MenuViewModel{
|
||||||
Mangas: mangaViewModels,
|
Settings: s.DbMgr.Settings.Map(),
|
||||||
|
Mangas: mangaViewModels,
|
||||||
}
|
}
|
||||||
|
|
||||||
err := tmpl.Execute(w, menuViewModel)
|
err := tmpl.Execute(w, menuViewModel)
|
||||||
@@ -336,6 +337,23 @@ func (s *Server) HandlePrev(w http.ResponseWriter, r *http.Request) {
|
|||||||
http.Redirect(w, r, "/current/", http.StatusTemporaryRedirect)
|
http.Redirect(w, r, "/current/", http.StatusTemporaryRedirect)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Server) HandleSetting(w http.ResponseWriter, r *http.Request) {
|
||||||
|
settingName := r.PostFormValue("setting")
|
||||||
|
settingValue := r.PostFormValue(settingName)
|
||||||
|
|
||||||
|
setting, ok := s.DbMgr.Settings.Get(settingName)
|
||||||
|
if !ok {
|
||||||
|
s.DbMgr.Settings.Set(settingName, database.NewSetting(settingName, settingValue))
|
||||||
|
} else {
|
||||||
|
if setting.Value != settingValue {
|
||||||
|
setting.Value = settingValue
|
||||||
|
s.DbMgr.Settings.Set(settingName, setting)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
http.Redirect(w, r, "/", http.StatusTemporaryRedirect)
|
||||||
|
}
|
||||||
|
|
||||||
func (s *Server) HandleNewQuery(w http.ResponseWriter, r *http.Request) {
|
func (s *Server) HandleNewQuery(w http.ResponseWriter, r *http.Request) {
|
||||||
sub := r.PostFormValue("subUrl")
|
sub := r.PostFormValue("subUrl")
|
||||||
|
|
||||||
|
|||||||
@@ -58,6 +58,7 @@ func (s *Server) Start(port int) error {
|
|||||||
http.HandleFunc("POST /exit", s.HandleExit)
|
http.HandleFunc("POST /exit", s.HandleExit)
|
||||||
http.HandleFunc("POST /delete", s.HandleDelete)
|
http.HandleFunc("POST /delete", s.HandleDelete)
|
||||||
http.HandleFunc("/favicon.ico", s.HandleFavicon)
|
http.HandleFunc("/favicon.ico", s.HandleFavicon)
|
||||||
|
http.HandleFunc("POST /setting/", s.HandleSetting)
|
||||||
|
|
||||||
// Update Latest Chapter every 5 Minutes
|
// Update Latest Chapter every 5 Minutes
|
||||||
go func(s *Server) {
|
go func(s *Server) {
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
font-size: 25px;
|
font-size: 25px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dark-mode {
|
.dark {
|
||||||
background-color: #171717;
|
background-color: #171717;
|
||||||
color: white;
|
color: white;
|
||||||
}
|
}
|
||||||
@@ -101,17 +101,31 @@
|
|||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
label {
|
||||||
|
display: flex;
|
||||||
|
align-content: center;
|
||||||
|
justify-content: center;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
select {
|
||||||
|
width: 10em;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
<script>
|
<script>
|
||||||
function myFunction() {
|
function myFunction(theme) {
|
||||||
var element = document.body;
|
if (theme !== "white") {
|
||||||
element.classList.toggle("dark-mode");
|
var element = document.body;
|
||||||
|
element.classList.toggle(theme);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body onload="myFunction({{(index .Settings "theme").Value}})">
|
||||||
<form method="post" action="/new/">
|
<form method="post" action="/new/">
|
||||||
<label>
|
<label>
|
||||||
New Sub Url
|
New Sub Url
|
||||||
@@ -119,7 +133,15 @@
|
|||||||
</label>
|
</label>
|
||||||
<input type="submit" value="Open" class="button-36">
|
<input type="submit" value="Open" class="button-36">
|
||||||
</form>
|
</form>
|
||||||
<button onclick="myFunction()">Toggle dark mode</button>
|
|
||||||
|
<form method="post" action="/setting/">
|
||||||
|
<label for="theme">Theme</label>
|
||||||
|
<select onchange="this.form.submit()" id="theme" name="theme">
|
||||||
|
<option value="white">White</option>
|
||||||
|
<option value="dark">Dark</option>
|
||||||
|
</select>
|
||||||
|
<input type="hidden" name="setting" value="theme">
|
||||||
|
</form>
|
||||||
|
|
||||||
<table class="table">
|
<table class="table">
|
||||||
<tr>
|
<tr>
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
package view
|
package view
|
||||||
|
|
||||||
|
import "mangaGetter/internal/database"
|
||||||
|
|
||||||
type Image struct {
|
type Image struct {
|
||||||
Path string
|
Path string
|
||||||
Index int
|
Index int
|
||||||
@@ -21,5 +23,6 @@ type MangaViewModel struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type MenuViewModel struct {
|
type MenuViewModel struct {
|
||||||
Mangas []MangaViewModel
|
Settings map[string]database.Setting
|
||||||
|
Mangas []MangaViewModel
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user