Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

v1.0.0: rewrite of ui with typescript #51

Merged
merged 65 commits into from
Nov 17, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
65 commits
Select commit Hold shift + click to select a range
4a27ad2
Prototyping.
BigJk Jun 1, 2023
0ed06cc
Store base.
BigJk Jun 1, 2023
cda3c15
Dashboard prototyping.
BigJk Jun 1, 2023
0958187
Added select dropdown.
BigJk Jun 2, 2023
35be8f6
More spectre components.
BigJk Jun 2, 2023
3244d11
Added more components.
BigJk Jun 6, 2023
4b8cc81
Added comments.
BigJk Jun 6, 2023
be66efa
Added sync key and version simplification.
BigJk Jun 6, 2023
02afe72
More components.
BigJk Jun 6, 2023
41310bf
Added spotlight.
BigJk Jun 6, 2023
2c2c990
Spotlight operations.
BigJk Jun 6, 2023
9030cb8
Device page update.
BigJk Jun 13, 2023
77b7f7d
Better devices layout.
BigJk Jun 13, 2023
f82ccf4
Added base for monaco editor.
BigJk Jun 16, 2023
32fd16a
Basic info and images editor page.
BigJk Jun 17, 2023
f0ce5b5
Better basic information.
BigJk Jun 17, 2023
9731018
Restructure.
BigJk Jun 17, 2023
19e4727
Base of settings page.
BigJk Jun 19, 2023
5c4db04
Refactored RPC routes.
BigJk Jun 20, 2023
15f6570
Added cloud sync routes and db.
BigJk Jun 22, 2023
0338bd9
Cloud sync ui, settings page and monaco fix.
BigJk Jun 22, 2023
1738170
Fullscreen loader fix.
BigJk Jun 22, 2023
234f46b
Base for template edit pages.
BigJk Jun 22, 2023
38e1d2b
Template editing.
BigJk Jun 22, 2023
be02b68
Template page and other improvements.
BigJk Jul 11, 2023
784e54a
CSS cleanup.
BigJk Jul 11, 2023
26fe2a4
Template page navigation.
BigJk Jul 11, 2023
7f651bc
Added "Open Templates" to spotlight and templates search.
BigJk Jul 11, 2023
3eb59d8
Template entries listing.
BigJk Aug 16, 2023
a63d3dd
Better layout of dashboard.
BigJk Aug 16, 2023
dfed97e
Prototype AI features and some layout changes.
BigJk Sep 23, 2023
ee7840b
Missing changes.
BigJk Sep 23, 2023
2e6b104
Config editing and furhter AI improvements.
BigJk Sep 26, 2023
ee87dbd
Cache AI prompts based on token.
BigJk Sep 26, 2023
77e3562
AI caching.
BigJk Sep 26, 2023
01287ca
AI template generator.
BigJk Sep 29, 2023
09cc45d
Dynamic data source import.
BigJk Oct 1, 2023
74877e9
RPC im and export.
BigJk Oct 3, 2023
f10cdcc
Layout changes.
BigJk Oct 3, 2023
b7fe19a
Single source page.
BigJk Oct 5, 2023
39e31be
Added credits.
BigJk Oct 5, 2023
d9f2757
Finish up data source page.
BigJk Oct 5, 2023
c3ac83a
Added name editing for data sources
BigJk Oct 5, 2023
bb9cb82
Fixing monaco suggestion problems.
BigJk Oct 6, 2023
8dac132
Consistent comment style.
BigJk Oct 6, 2023
acecd02
Consistent arrow function usage.
BigJk Oct 6, 2023
2b8437e
Removed easydropdown.
BigJk Oct 11, 2023
f7c4488
AI max token and base for config creation.
BigJk Oct 12, 2023
9e6c739
AI translation and internal file-browser prototype
BigJk Oct 21, 2023
980fd87
File browser and config creator.
BigJk Oct 22, 2023
ee1986d
Finished config editor.
BigJk Oct 24, 2023
b9690aa
Additional info modals.
BigJk Oct 24, 2023
3549f5e
Fix missing config in additional info modal.
BigJk Oct 25, 2023
6151a64
Don't allow edit of author and slug.
BigJk Oct 25, 2023
ca9bb0a
Removed wrong prop.
BigJk Oct 25, 2023
46b8071
Duplicate template and generator.
BigJk Oct 25, 2023
73837ca
Template screenshot and print.
BigJk Oct 25, 2023
78afd8f
Entry managment and skeleton data helper.
BigJk Nov 6, 2023
87c3230
Workshop and imexport.
BigJk Nov 17, 2023
5b0a01a
Data source creation.
BigJk Nov 17, 2023
667f6b5
Smaller bug fixes.
BigJk Nov 17, 2023
4a33124
Wrong type.
BigJk Nov 17, 2023
65ffe5e
Fixed null problem.
BigJk Nov 17, 2023
35476ba
Fix wrong button being hidden.
BigJk Nov 17, 2023
bd27b0f
Merge branch 'master' into v2
BigJk Nov 17, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading