Skip to content

Commit

Permalink
v1.0.0: rewrite of ui with typescript (#51)
Browse files Browse the repository at this point in the history
  • Loading branch information
BigJk authored Nov 17, 2023
1 parent 66be3ac commit e9fa6b4
Show file tree
Hide file tree
Showing 258 changed files with 15,488 additions and 12,556 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ vendor/
templates/
!src/**/templates/**
userdata*/
frontend_old/

.idea/
.cache/
Expand All @@ -33,4 +34,4 @@ build/
*.png

!data/*.png
!data/*.svg
!data/*.svg
7 changes: 6 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,13 @@ or a letter that the group found to little character sheets of your players to u
- CSV
- [FoundryVTT](https://foundryvtt.com/) Modules
- Fight Club 5e XML Format
- 5eTools
- Access Community Templates, Generators & Data Sources from within the App
- Edit templates in your favorite editor (e.g. Visual Studio Code) and get live preview
- AI LLM Support (OpenAI, OpenRouter)
- Generate entries by prompt using the power of AI
- Translate entries by prompt
- Execute AI prompts in your templates and generators
- Cloud sync for templates, generators and data sources

## Download 📁

Expand Down
4 changes: 2 additions & 2 deletions cmd/app/electron.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ func startElectron(db database.Database, debug bool) {
time.Sleep(time.Millisecond * 500)
log.Info("If no window is opening please wait a few seconds for the dependencies to download...")

var a, err = astilectron.New(stdlog.New(targetWriter, "", 0), astilectron.Options{
a, err := astilectron.New(stdlog.New(targetWriter, "", 0), astilectron.Options{
AppName: "SND",
BaseDirectoryPath: "./data",
DataDirectoryPath: "./data",
Expand All @@ -78,7 +78,7 @@ func startElectron(db database.Database, debug bool) {
panic(err)
}

var w, _ = a.NewWindow("http://127.0.0.1:7123", &astilectron.WindowOptions{
w, _ := a.NewWindow("http://127.0.0.1:7123", &astilectron.WindowOptions{
Center: astikit.BoolPtr(true),
Height: astikit.IntPtr(920),
Width: astikit.IntPtr(1600),
Expand Down
68 changes: 20 additions & 48 deletions cmd/app/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package main
import (
"flag"
"fmt"
"github.com/BigJk/snd/database/cloud"
"math/rand"
"os"
"path/filepath"
Expand All @@ -12,7 +13,6 @@ import (
"github.com/BigJk/snd"
"github.com/BigJk/snd/database"
"github.com/BigJk/snd/database/badger"
"github.com/BigJk/snd/database/storm"
"github.com/BigJk/snd/printing/cups"
"github.com/BigJk/snd/printing/dump"
"github.com/BigJk/snd/printing/remote"
Expand All @@ -25,60 +25,32 @@ import (
var serverOptions []server.Option
var startFunc = startServer

func syncBaseUrl() string {
override := os.Getenv("SND_SYNC_BASE_URL")
if override != "" {
fmt.Println("INFO: overriding sync base url with", override)
return override
}
// TODO: Set default sync base url
return ""
}

func openDatabase() database.Database {
db, err := badger.New("./userdata/")
if err != nil {
panic(err)
}

// Migrate old db to new one
if _, err := os.Stat("./data.db"); err == nil {
oldDb, err := storm.New("./data.db")
if err == nil {
fmt.Println("Old database detected. Migrating...")

templates, _ := oldDb.GetTemplates()
for i := range templates {
fmt.Println("Copying", templates[i].ID())

_ = db.SaveTemplate(templates[i].Template)

entries, _ := oldDb.GetEntries(templates[i].ID())
for j := range entries {
_ = db.SaveEntry(templates[i].ID(), entries[j])
}
}

sources, _ := oldDb.GetSources()
for i := range sources {
fmt.Println("Copying", sources[i].ID())

_ = db.SaveSource(sources[i].DataSource)

entries, _ := oldDb.GetEntries(sources[i].ID())
for j := range entries {
_ = db.SaveEntry(sources[i].ID(), entries[j])
}
if settings, err := db.GetSettings(); err == nil {
if settings.SyncEnabled {
if err := cloud.CheckKey(syncBaseUrl(), settings.SyncKey); err != nil {
fmt.Println("ERROR: could not validate sync key!", err, "=> disabling sync")
settings.SyncEnabled = false
_ = db.SaveSettings(settings)
} else {
fmt.Println("INFO: enabling sync")
return cloud.New(syncBaseUrl(), settings.SyncKey, db)
}

generators, _ := oldDb.GetGenerators()
for i := range generators {
fmt.Println("Copying", generators[i].ID())

_ = db.SaveGenerator(generators[i])
}

if err := oldDb.Close(); err != nil {
fmt.Println("Could not close old database:", err)
}

if err := os.Rename("./data.db", "/data_old.db"); err != nil {
fmt.Println("Could not rename old database:", err)
}

_ = db.Sync()

fmt.Println("Migration done!")
}
}

Expand Down
Binary file modified data/readme_header.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified data/screenshot.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified data/screenshot_gen.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
9 changes: 9 additions & 0 deletions database/badger/badger.go
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,15 @@ func (b *Badger) SaveEntry(id string, entry snd.Entry) error {
return setSingle[snd.Entry](b.db, id+EntryConnector+entry.ID, entry)
}

func (b *Badger) SaveEntries(id string, entries []snd.Entry) error {
for i := range entries {
if err := setSingle[snd.Entry](b.db, id+EntryConnector+entries[i].ID, entries[i]); err != nil {
return err
}
}
return nil
}

func (b *Badger) DeleteEntry(id string, eid string) error {
return dropSingle(b.db, id+EntryConnector+eid)
}
Expand Down
219 changes: 219 additions & 0 deletions database/cloud/cloud.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,219 @@
package cloud

import (
"bytes"
"encoding/json"
"errors"
"github.com/BigJk/snd"
"github.com/BigJk/snd/database"
"github.com/BigJk/snd/log"
"io"
"net/http"
"net/url"
"time"
)

type Cloud struct {
client http.Client
baseUrl string
key string
localDb database.Database
}

func CheckKey(baseUrl string, key string) error {
client := http.Client{
Timeout: time.Second * 10,
}

resp, err := client.Get(baseUrl + "/key/" + key)
if err != nil {
return err
}
defer resp.Body.Close()

if resp.StatusCode != http.StatusOK {
return errors.New("invalid key")
}

return nil
}

func New(baseUrl string, key string, localDb database.Database) *Cloud {
return &Cloud{
client: http.Client{
Timeout: time.Second * 10,
},
baseUrl: baseUrl,
key: key,
localDb: localDb,
}
}

func (c *Cloud) CopyFromLocal() error {
return database.Migrate(c.localDb, c)
}

func (c *Cloud) CopyToLocal() error {
return database.Migrate(c, c.localDb)
}

func (c *Cloud) request(method string, path string, body interface{}, result interface{}) (int, error) {
route, err := url.Parse(c.baseUrl + path)
if err != nil {
return -1, err
}

req := http.Request{
Method: method,
URL: route,
Header: http.Header{
"Authorization": []string{c.key},
"Content-Type": []string{"application/json"},
},
}

if body != nil {
jsonData, err := json.Marshal(body)
if err != nil {
return -1, err
}
req.Body = io.NopCloser(bytes.NewBuffer(jsonData))
}

resp, err := c.client.Do(&req)
if err != nil {
return -1, err
}

if resp.StatusCode != http.StatusOK {
return resp.StatusCode, nil
}

if result != nil {
err = json.NewDecoder(resp.Body).Decode(result)
if err != nil {
return resp.StatusCode, err
}
}

return resp.StatusCode, nil
}

func (c *Cloud) requestNoStatus(method string, path string, body interface{}, result interface{}) error {
_, err := c.request(method, path, body, result)
return err
}

func (c *Cloud) Close() error {
return c.localDb.Close()
}

func (c *Cloud) GetSettings() (snd.Settings, error) {
return c.localDb.GetSettings()
}

func (c *Cloud) SaveSettings(settings snd.Settings) error {
return c.localDb.SaveSettings(settings)
}

func (c *Cloud) GetLogs(hours int) ([]log.Entry, error) {
return c.localDb.GetLogs(hours)
}

func (c *Cloud) AddLog(e log.Entry) error {
return c.localDb.AddLog(e)
}

func (c *Cloud) GetTemplate(id string) (snd.Template, error) {
var template snd.Template
_, err := c.request(http.MethodGet, "/api/template/"+id, nil, &template)
return template, err
}

func (c *Cloud) SaveTemplate(template snd.Template) error {
return c.requestNoStatus(http.MethodPost, "/api/template", template, nil)
}

func (c *Cloud) DeleteTemplate(id string) error {
return c.requestNoStatus(http.MethodDelete, "/api/template/"+id, nil, nil)
}

func (c *Cloud) GetTemplates() ([]database.TemplateEntry, error) {
var templates []database.TemplateEntry
_, err := c.request(http.MethodGet, "/api/templates", nil, &templates)
return templates, err
}

func (c *Cloud) GetEntries(id string) ([]snd.Entry, error) {
var entries []snd.Entry
_, err := c.request(http.MethodGet, "/api/entries/"+id, nil, &entries)
return entries, err
}

func (c *Cloud) GetEntry(id string, eid string) (snd.Entry, error) {
var entry snd.Entry
_, err := c.request(http.MethodGet, "/api/entry/"+id+"/"+eid, nil, &entry)
return entry, err
}

func (c *Cloud) CountEntries(id string) (int, error) {
var count int
_, err := c.request(http.MethodGet, "/api/entries/"+id+"/count", nil, &count)
return count, err
}

func (c *Cloud) SaveEntry(id string, entry snd.Entry) error {
return c.requestNoStatus(http.MethodPost, "/api/entry/"+id, entry, nil)
}

func (c *Cloud) SaveEntries(id string, entries []snd.Entry) error {
return c.requestNoStatus(http.MethodPost, "/api/entries/"+id, entries, nil)
}

func (c *Cloud) DeleteEntry(id string, eid string) error {
return c.requestNoStatus(http.MethodDelete, "/api/entry/"+id+"/"+eid, nil, nil)
}

func (c *Cloud) DeleteEntries(id string) error {
return c.requestNoStatus(http.MethodDelete, "/api/entries/"+id, nil, nil)
}

func (c *Cloud) GetGenerator(id string) (snd.Generator, error) {
var generator snd.Generator
_, err := c.request(http.MethodGet, "/api/generator/"+id, nil, &generator)
return generator, err
}

func (c *Cloud) SaveGenerator(generator snd.Generator) error {
return c.requestNoStatus(http.MethodPost, "/api/generator", generator, nil)
}

func (c *Cloud) DeleteGenerator(id string) error {
return c.requestNoStatus(http.MethodDelete, "/api/generator/"+id, nil, nil)
}

func (c *Cloud) GetGenerators() ([]snd.Generator, error) {
var generators []snd.Generator
_, err := c.request(http.MethodGet, "/api/generators", nil, &generators)
return generators, err
}

func (c *Cloud) SaveSource(ds snd.DataSource) error {
return c.requestNoStatus(http.MethodPost, "/api/source/", ds, nil)
}

func (c *Cloud) DeleteSource(id string) error {
return c.requestNoStatus(http.MethodDelete, "/api/source/"+id, nil, nil)
}

func (c *Cloud) GetSource(id string) (snd.DataSource, error) {
var ds snd.DataSource
_, err := c.request(http.MethodGet, "/api/source/"+id, nil, &ds)
return ds, err
}

func (c *Cloud) GetSources() ([]database.DataSourceEntry, error) {
var sources []database.DataSourceEntry
_, err := c.request(http.MethodGet, "/api/sources", nil, &sources)
return sources, err
}
1 change: 1 addition & 0 deletions database/database.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ type Database interface {
GetEntry(id string, eid string) (snd.Entry, error)
CountEntries(id string) (int, error)
SaveEntry(id string, entry snd.Entry) error
SaveEntries(id string, entry []snd.Entry) error
DeleteEntry(id string, eid string) error
DeleteEntries(id string) error

Expand Down
Loading

0 comments on commit e9fa6b4

Please sign in to comment.