Skip to content

Commit

Permalink
feat: saved configs for generators
Browse files Browse the repository at this point in the history
  • Loading branch information
BigJk committed Sep 8, 2024
1 parent be89d17 commit f85f99b
Show file tree
Hide file tree
Showing 10 changed files with 219 additions and 9 deletions.
21 changes: 21 additions & 0 deletions database/badger/badger.go
Original file line number Diff line number Diff line change
Expand Up @@ -211,3 +211,24 @@ func (b *Badger) GetSources() ([]database.DataSourceEntry, error) {

return sources, nil
}

func (b *Badger) GetKey(key string) (string, error) {
var value string
err := b.db.View(func(txn *badger.Txn) error {
item, err := txn.Get([]byte("KV_" + key))
if err != nil {
return err
}
return item.Value(func(val []byte) error {
value = string(val)
return nil
})
})
return value, err
}

func (b *Badger) SetKey(key string, value string) error {
return b.db.Update(func(txn *badger.Txn) error {
return txn.Set([]byte("KV_"+key), []byte(value))
})
}
15 changes: 12 additions & 3 deletions database/cloud/cloud.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,14 @@ 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"

"github.com/BigJk/snd"
"github.com/BigJk/snd/database"
"github.com/BigJk/snd/log"
)

type Cloud struct {
Expand Down Expand Up @@ -217,3 +218,11 @@ func (c *Cloud) GetSources() ([]database.DataSourceEntry, error) {
_, err := c.request(http.MethodGet, "/api/sources", nil, &sources)
return sources, err
}

func (c *Cloud) GetKey(key string) (string, error) {
return "", errors.New("not implemented")
}

func (c *Cloud) SetKey(key string, value string) error {
return errors.New("not implemented")
}
3 changes: 3 additions & 0 deletions database/database.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,4 +50,7 @@ type Database interface {
DeleteSource(id string) error
GetSource(id string) (snd.DataSource, error)
GetSources() ([]DataSourceEntry, error)

GetKey(key string) (string, error)
SetKey(key string, value string) error
}
10 changes: 10 additions & 0 deletions database/memory/memory.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ type Memory struct {
entries map[string]map[string]snd.Entry
generators map[string]snd.Generator
sources map[string]snd.DataSource
kv map[string]string
}

func New() *Memory {
Expand Down Expand Up @@ -159,3 +160,12 @@ func (m *Memory) GetSources() ([]database.DataSourceEntry, error) {
}
return sources, nil
}

func (m *Memory) GetKey(key string) (string, error) {
return m.kv[key], nil
}

func (m *Memory) SetKey(key string, value string) error {
m.kv[key] = value
return nil
}
9 changes: 9 additions & 0 deletions database/storm/storm.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package storm

import (
"bytes"
"errors"
"time"

"github.com/BigJk/snd"
Expand Down Expand Up @@ -185,3 +186,11 @@ func (s *Storm) GetSources() ([]database.DataSourceEntry, error) {

return sources, nil
}

func (s *Storm) GetKey(key string) (string, error) {
return "", errors.New("not implemented")
}

func (s *Storm) SetKey(key, value string) error {
return errors.New("not implemented")
}
4 changes: 4 additions & 0 deletions frontend/src/js/core/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ export const SAVE_SETTINGS = 'saveSettings';
export const GET_VERSION = 'getVersion';
export const NEW_VERSION = 'newVersion';

// Key Value functions
export const GET_KEY = 'getKey';
export const SET_KEY = 'setKey';

// Entries functions
export const GET_ENTRIES = 'getEntries';
export const SAVE_ENTRY = 'saveEntry';
Expand Down
57 changes: 57 additions & 0 deletions frontend/src/js/ui/components/modals/prompt.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import m from 'mithril';

import Button from 'js/ui/shoelace/button';
import Input from 'js/ui/shoelace/input';
import Modal from 'js/ui/shoelace/modal';

import HorizontalProperty from 'js/ui/components/horizontal-property';

import { popPortal, pushPortal } from 'js/ui/portal';

type PromptProps = {
title: string;
label: string;
description: string;
buttonText?: string;
onSuccess: (answer: string) => void;
};

const promptModal = (props: PromptProps) => (): m.Component => {
let state = '';

return {
view: () =>
m(
Modal,
{ title: props.title, onClose: () => popPortal() },
m('div', [
m(
HorizontalProperty,
{
label: props.label,
description: props.description,
bottomBorder: false,
centered: true,
},
m(Input, { value: state, placeholder: '', onChange: (val: string) => (state = val) }),
),
m(
Button,
{
intend: 'success',
className: '.mt2',
onClick: () => {
props.onSuccess(state);
popPortal();
},
},
props.buttonText || 'Submit',
),
]),
),
};
};

export function openPromptModal(props: PromptProps) {
pushPortal(promptModal(props));
}
93 changes: 88 additions & 5 deletions frontend/src/js/ui/views/generator/single.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
import m from 'mithril';
import { cloneDeep, map } from 'lodash-es';

import HorizontalProperty from '../../components/horizontal-property';
import { openPromptModal } from '../../components/modals/prompt';

import { buildId } from 'js/types/basic-info';
import Generator, { sanitizeConfig } from 'js/types/generator';
Expand Down Expand Up @@ -34,6 +38,7 @@ type SingleGeneratorState = {
printCount: number;
lastRendered: string;
hidePreview: boolean;
savedConfigs: Record<string, any[]>;
};

export default (): m.Component<SingleGeneratorProps> => {
Expand All @@ -43,6 +48,7 @@ export default (): m.Component<SingleGeneratorProps> => {
printCount: 1,
lastRendered: '',
hidePreview: false,
savedConfigs: {},
};

const print = () => {
Expand Down Expand Up @@ -95,12 +101,51 @@ export default (): m.Component<SingleGeneratorProps> => {
});
};

const saveConfigs = () => {
if (!state.generator) {
return;
}
return API.exec<void>(API.SET_KEY, `${buildId('generator', state.generator)}_saved_configs`, JSON.stringify(state.savedConfigs));
};

const saveConfig = () => {
openPromptModal({
title: 'Save Config',
label: 'Name',
description: 'Enter a name for the config',
onSuccess: (name) => {
if (!state.generator) return;
state.savedConfigs[name] = cloneDeep(state.config);
saveConfigs()?.catch(error);
success('Saved config');
},
});
};

const deleteSavedConfig = (name: string) => {
dialogWarning('Are you sure you want to delete this config?').then(() => {
if (!state.generator) return;
delete state.savedConfigs[name];
saveConfigs()?.catch(error);
});
};

const loadSavedConfig = (name: string) => {
if (!state.generator) return;
state.config = cloneDeep(state.savedConfigs[name]);
};

return {
oninit({ attrs }) {
API.exec<Generator>(API.GET_GENERATOR, attrs.id).then((generator) => {
state.generator = generator;
state.config = sanitizeConfig(generator, {});
});
API.exec<string>(API.GET_KEY, `${attrs.id}_saved_configs`)
.then((configs) => {
state.savedConfigs = JSON.parse(configs);
})
.catch(console.error);
},
onupdate({ attrs }) {},
view({ attrs }) {
Expand Down Expand Up @@ -187,7 +232,7 @@ export default (): m.Component<SingleGeneratorProps> => {
m.redraw();
},
}),
m(Flex, { className: '.bt.b--black-10.pv2.ph3', justify: 'end', items: 'center', gap: 2 }, [
m(Flex, { className: '.bt.b--black-10.pv2.ph3', justify: 'between', items: 'center', gap: 2 }, [
/*
Disabled for now!
Expand All @@ -203,9 +248,18 @@ export default (): m.Component<SingleGeneratorProps> => {
}),
),
*/
m(Tooltip, { content: 'Hide Preview' }, m(Checkbox, { checked: state.hidePreview, onChange: (val) => (state.hidePreview = val) })),
m(IconButton, { icon: 'camera', intend: 'primary', onClick: screenshot }, 'Screenshot'),
m(IconButton, { icon: 'print', intend: 'success', onClick: print }, 'Print'),
m(Flex, { gap: 2 }, [
m(IconButton, { icon: 'save', intend: 'primary', onClick: saveConfig }, 'Save Config'),
m(IconButton, { icon: 'camera', intend: 'primary', onClick: screenshot }, 'Screenshot'),
]),
m(Flex, { gap: 2, items: 'center' }, [
m(
Tooltip,
{ content: 'Hide Preview' },
m(Checkbox, { checked: state.hidePreview, onChange: (val) => (state.hidePreview = val) }),
),
m(IconButton, { icon: 'print', intend: 'success', onClick: print }, 'Print'),
]),
]),
]),
Information: () =>
Expand All @@ -216,7 +270,36 @@ export default (): m.Component<SingleGeneratorProps> => {
? [m('div.f5.mb2.b.mt3', 'Copyright Notice'), m('div', { style: { whiteSpace: 'break-spaces' } }, state.generator.copyrightNotice)]
: []),
]),
Saved: () => m('div.ph3.pv2', 'coming soon...'),
Saved: () =>
m('div.ph3.pv2.lh-copy', [
m('div.f5.b', 'Saved Configs'),
Object.keys(state.savedConfigs).length
? m(Flex, { direction: 'column' }, [
...map(state.savedConfigs, (config, key) =>
m(
HorizontalProperty,
{
label: key,
description: '',
bottomBorder: true,
centered: true,
},
m(
Flex,
{
gap: 2,
justify: 'end',
},
[
m(IconButton, { icon: 'trash', intend: 'error', onClick: () => deleteSavedConfig(key) }),
m(IconButton, { icon: 'edit', intend: 'primary', onClick: () => loadSavedConfig(key) }, 'Load'),
],
),
),
),
])
: m('div.pv2.text-muted', 'No saved configs yet...'),
]),
},
}),
);
Expand Down
12 changes: 12 additions & 0 deletions rpc/kv.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package rpc

import (
"github.com/BigJk/snd/database"
"github.com/BigJk/snd/rpc/bind"
"github.com/labstack/echo/v4"
)

func RegisterKeyValue(route *echo.Group, db database.Database) {
bind.MustBind(route, "/getKey", db.GetKey)
bind.MustBind(route, "/setKey", db.SetKey)
}
4 changes: 3 additions & 1 deletion server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import (
"context"
"errors"
"fmt"
"github.com/BigJk/snd/rpc/bind"
"io/ioutil"
"mime"
"net/http"
Expand All @@ -14,6 +13,8 @@ import (
"sync"
"time"

"github.com/BigJk/snd/rpc/bind"

"github.com/BigJk/snd/database"
"github.com/labstack/echo/v4/middleware"
"github.com/patrickmn/go-cache"
Expand Down Expand Up @@ -142,6 +143,7 @@ func (s *Server) Start(bindAddr string) error {
extern := api.Group("/extern")

rpc.RegisterVersion(api)
rpc.RegisterKeyValue(api, s.db)
rpc.RegisterImageUtilities(api)
rpc.RegisterSettings(api, s.db)
rpc.RegisterTemplate(api, extern, s.db)
Expand Down

0 comments on commit f85f99b

Please sign in to comment.