mirror of
https://github.com/onsonr/sonr.git
synced 2025-03-10 13:07:09 +00:00
feature/implement vault allocation (#11)
* feat: add authentication middleware * feat: add REST API endpoints for database interactions * refactor: move DiscoveryDocument Pkl schema to oidc module * fix: replace sonrd with test_node.sh * feat: use NFT keeper to mint DID namespace NFT * refactor: move NFT class configuration to types * feat: add GlobalIntegrity genesis state * fix: ensure GlobalIntegrity is initialized in genesis * refactor: update all references to transactions module * refactor: improve genesis state struct * chore(did): update discovery endpoint to reflect base url * feat: remove unused context cache and client code * refactor: remove middleware dependency from keeper * feat: Add new query handlers for DID module * feat: Implement unimplemented params queries * feat: add support for first-party caveats * refactor: move motr command to cmd directory * feat: add support for GitHub releases * fix(motr): build app.wasm for motr package * feat: add card component * feat: add IndexedDB support for persistent storage * feat: Add Row and Column components * feat: add and components * refactor: improve button component * refactor: remove unnecessary button parameter in renderButton * feat: add vault service endpoint * feat: add input component
This commit is contained in:
parent
bbfe2a2329
commit
b593245fe6
2
.github/workflows/run-goreleaser.yml
vendored
2
.github/workflows/run-goreleaser.yml
vendored
@ -4,6 +4,8 @@ name: "Release Binary"
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
tags:
|
||||
- v*
|
||||
|
||||
|
3
.gitignore
vendored
3
.gitignore
vendored
@ -76,3 +76,6 @@ sonr
|
||||
deploy/**/data
|
||||
x/.DS_Store
|
||||
.aider*
|
||||
|
||||
|
||||
!motr/build
|
||||
|
@ -2,7 +2,7 @@ project_name: core
|
||||
|
||||
release:
|
||||
github:
|
||||
owner: di-dao
|
||||
owner: onsonr
|
||||
name: core
|
||||
name_template: "{{.Tag}}"
|
||||
|
||||
@ -13,44 +13,22 @@ builds:
|
||||
goos:
|
||||
- linux
|
||||
- darwin
|
||||
# - windows
|
||||
goarch:
|
||||
- amd64
|
||||
# - arm64
|
||||
# - "386"
|
||||
goarm:
|
||||
- "6"
|
||||
gomips:
|
||||
- hardfloat
|
||||
goamd64:
|
||||
- v1
|
||||
targets:
|
||||
- linux_amd64_v1
|
||||
# - darwin_amd64_v1
|
||||
# - linux_arm64
|
||||
# - linux_386
|
||||
# - darwin_arm64
|
||||
# - windows_amd64_v1
|
||||
# - windows_arm64
|
||||
# - windows_386
|
||||
dir: .
|
||||
main: ./cmd/sonrd
|
||||
binary: sonrd
|
||||
builder: go
|
||||
gobinary: go
|
||||
command: build
|
||||
ldflags:
|
||||
- -s -w -X main.version={{.Version}} -X main.commit={{.Commit}} -X main.date={{.Date}} -X main.builtBy=goreleaser
|
||||
- -s -w -X main.version={{.Version}} -X main.commit={{.Commit}} -X main.date={{.Date}}
|
||||
archives:
|
||||
- id: default
|
||||
name_template: '{{ .ProjectName }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}{{ with .Arm }}v{{ . }}{{ end }}{{ with .Mips }}_{{ . }}{{ end }}{{ if not (eq .Amd64 "v1") }}{{ .Amd64 }}{{ end }}'
|
||||
format: tar.gz
|
||||
files:
|
||||
- src: license*
|
||||
- src: LICENSE*
|
||||
- src: readme*
|
||||
- src: README*
|
||||
- src: changelog*
|
||||
- src: CHANGELOG*
|
||||
snapshot:
|
||||
name_template: "{{ .Version }}-SNAPSHOT-{{ .ShortCommit }}"
|
||||
@ -76,28 +54,11 @@ announce:
|
||||
reddit:
|
||||
title_template: "{{ .ProjectName }} {{ .Tag }} is out!"
|
||||
url_template: "{{ .ReleaseURL }}"
|
||||
slack:
|
||||
message_template: "{{ .ProjectName }} {{ .Tag }} is out! Check it out at {{ .ReleaseURL }}"
|
||||
username: GoReleaser
|
||||
discord:
|
||||
message_template: "{{ .ProjectName }} {{ .Tag }} is out! Check it out at {{ .ReleaseURL }}"
|
||||
author: GoReleaser
|
||||
color: "3888754"
|
||||
icon_url: https://goreleaser.com/static/avatar.png
|
||||
teams:
|
||||
title_template: "{{ .ProjectName }} {{ .Tag }} is out!"
|
||||
message_template: "{{ .ProjectName }} {{ .Tag }} is out! Check it out at {{ .ReleaseURL }}"
|
||||
color: "#2D313E"
|
||||
icon_url: https://goreleaser.com/static/avatar.png
|
||||
smtp:
|
||||
subject_template: "{{ .ProjectName }} {{ .Tag }} is out!"
|
||||
body_template: "You can view details from: {{ .ReleaseURL }}"
|
||||
mattermost:
|
||||
message_template: "{{ .ProjectName }} {{ .Tag }} is out! Check it out at {{ .ReleaseURL }}"
|
||||
title_template: "{{ .ProjectName }} {{ .Tag }} is out!"
|
||||
username: GoReleaser
|
||||
linkedin:
|
||||
message_template: "{{ .ProjectName }} {{ .Tag }} is out! Check it out at {{ .ReleaseURL }}"
|
||||
telegram:
|
||||
message_template: "{{ .ProjectName }} {{ .Tag }} is out! Check it out at {{ .ReleaseURL }}"
|
||||
webhook:
|
||||
|
@ -86,4 +86,4 @@ WORKDIR /opt
|
||||
# rest server, tendermint p2p, tendermint rpc
|
||||
EXPOSE 1317 26656 26657
|
||||
|
||||
ENTRYPOINT ["/usr/bin/sonrd"]
|
||||
CMD ["test_node.sh"]
|
||||
|
2
Makefile
2
Makefile
@ -307,7 +307,7 @@ dwn:
|
||||
|
||||
motr:
|
||||
@echo "(motr) Building app.wasm -> Deploy to Cloudflare Workers"
|
||||
GOOS=js GOARCH=wasm go build -o ./motr/build/app.wasm ./motr
|
||||
GOOS=js GOARCH=wasm go build -o ./cmd/motr/build/app.wasm ./cmd/motr/main.go
|
||||
|
||||
###############################################################################
|
||||
### help ###
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -19,9 +19,14 @@ import (
|
||||
const _ = grpc.SupportPackageIsVersion7
|
||||
|
||||
const (
|
||||
Query_Params_FullMethodName = "/did.v1.Query/Params"
|
||||
Query_Resolve_FullMethodName = "/did.v1.Query/Resolve"
|
||||
Query_Service_FullMethodName = "/did.v1.Query/Service"
|
||||
Query_Params_FullMethodName = "/did.v1.Query/Params"
|
||||
Query_ParamsAssets_FullMethodName = "/did.v1.Query/ParamsAssets"
|
||||
Query_ParamsByAsset_FullMethodName = "/did.v1.Query/ParamsByAsset"
|
||||
Query_ParamsKeys_FullMethodName = "/did.v1.Query/ParamsKeys"
|
||||
Query_ParamsByKey_FullMethodName = "/did.v1.Query/ParamsByKey"
|
||||
Query_RegistrationOptionsByKey_FullMethodName = "/did.v1.Query/RegistrationOptionsByKey"
|
||||
Query_Resolve_FullMethodName = "/did.v1.Query/Resolve"
|
||||
Query_Service_FullMethodName = "/did.v1.Query/Service"
|
||||
)
|
||||
|
||||
// QueryClient is the client API for Query service.
|
||||
@ -29,7 +34,17 @@ const (
|
||||
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
|
||||
type QueryClient interface {
|
||||
// Params queries all parameters of the module.
|
||||
Params(ctx context.Context, in *QueryRequest, opts ...grpc.CallOption) (*QueryResponse, error)
|
||||
Params(ctx context.Context, in *QueryRequest, opts ...grpc.CallOption) (*QueryParamsResponse, error)
|
||||
// ParamsAssets queries all parameters of the module.
|
||||
ParamsAssets(ctx context.Context, in *QueryRequest, opts ...grpc.CallOption) (*QueryResponse, error)
|
||||
// Params queries all parameters of the module.
|
||||
ParamsByAsset(ctx context.Context, in *QueryRequest, opts ...grpc.CallOption) (*QueryResponse, error)
|
||||
// ParamsKeys queries all parameters of the module.
|
||||
ParamsKeys(ctx context.Context, in *QueryRequest, opts ...grpc.CallOption) (*QueryResponse, error)
|
||||
// Params queries all parameters of the module.
|
||||
ParamsByKey(ctx context.Context, in *QueryRequest, opts ...grpc.CallOption) (*QueryResponse, error)
|
||||
// Params queries all parameters of the module.
|
||||
RegistrationOptionsByKey(ctx context.Context, in *QueryRequest, opts ...grpc.CallOption) (*QueryResponse, error)
|
||||
// Resolve queries the DID document by its id.
|
||||
Resolve(ctx context.Context, in *QueryRequest, opts ...grpc.CallOption) (*QueryResponse, error)
|
||||
// Service returns associated ServiceInfo for a given Origin
|
||||
@ -46,8 +61,8 @@ func NewQueryClient(cc grpc.ClientConnInterface) QueryClient {
|
||||
return &queryClient{cc}
|
||||
}
|
||||
|
||||
func (c *queryClient) Params(ctx context.Context, in *QueryRequest, opts ...grpc.CallOption) (*QueryResponse, error) {
|
||||
out := new(QueryResponse)
|
||||
func (c *queryClient) Params(ctx context.Context, in *QueryRequest, opts ...grpc.CallOption) (*QueryParamsResponse, error) {
|
||||
out := new(QueryParamsResponse)
|
||||
err := c.cc.Invoke(ctx, Query_Params_FullMethodName, in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -55,6 +70,51 @@ func (c *queryClient) Params(ctx context.Context, in *QueryRequest, opts ...grpc
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *queryClient) ParamsAssets(ctx context.Context, in *QueryRequest, opts ...grpc.CallOption) (*QueryResponse, error) {
|
||||
out := new(QueryResponse)
|
||||
err := c.cc.Invoke(ctx, Query_ParamsAssets_FullMethodName, in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *queryClient) ParamsByAsset(ctx context.Context, in *QueryRequest, opts ...grpc.CallOption) (*QueryResponse, error) {
|
||||
out := new(QueryResponse)
|
||||
err := c.cc.Invoke(ctx, Query_ParamsByAsset_FullMethodName, in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *queryClient) ParamsKeys(ctx context.Context, in *QueryRequest, opts ...grpc.CallOption) (*QueryResponse, error) {
|
||||
out := new(QueryResponse)
|
||||
err := c.cc.Invoke(ctx, Query_ParamsKeys_FullMethodName, in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *queryClient) ParamsByKey(ctx context.Context, in *QueryRequest, opts ...grpc.CallOption) (*QueryResponse, error) {
|
||||
out := new(QueryResponse)
|
||||
err := c.cc.Invoke(ctx, Query_ParamsByKey_FullMethodName, in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *queryClient) RegistrationOptionsByKey(ctx context.Context, in *QueryRequest, opts ...grpc.CallOption) (*QueryResponse, error) {
|
||||
out := new(QueryResponse)
|
||||
err := c.cc.Invoke(ctx, Query_RegistrationOptionsByKey_FullMethodName, in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *queryClient) Resolve(ctx context.Context, in *QueryRequest, opts ...grpc.CallOption) (*QueryResponse, error) {
|
||||
out := new(QueryResponse)
|
||||
err := c.cc.Invoke(ctx, Query_Resolve_FullMethodName, in, out, opts...)
|
||||
@ -78,7 +138,17 @@ func (c *queryClient) Service(ctx context.Context, in *QueryRequest, opts ...grp
|
||||
// for forward compatibility
|
||||
type QueryServer interface {
|
||||
// Params queries all parameters of the module.
|
||||
Params(context.Context, *QueryRequest) (*QueryResponse, error)
|
||||
Params(context.Context, *QueryRequest) (*QueryParamsResponse, error)
|
||||
// ParamsAssets queries all parameters of the module.
|
||||
ParamsAssets(context.Context, *QueryRequest) (*QueryResponse, error)
|
||||
// Params queries all parameters of the module.
|
||||
ParamsByAsset(context.Context, *QueryRequest) (*QueryResponse, error)
|
||||
// ParamsKeys queries all parameters of the module.
|
||||
ParamsKeys(context.Context, *QueryRequest) (*QueryResponse, error)
|
||||
// Params queries all parameters of the module.
|
||||
ParamsByKey(context.Context, *QueryRequest) (*QueryResponse, error)
|
||||
// Params queries all parameters of the module.
|
||||
RegistrationOptionsByKey(context.Context, *QueryRequest) (*QueryResponse, error)
|
||||
// Resolve queries the DID document by its id.
|
||||
Resolve(context.Context, *QueryRequest) (*QueryResponse, error)
|
||||
// Service returns associated ServiceInfo for a given Origin
|
||||
@ -92,9 +162,24 @@ type QueryServer interface {
|
||||
type UnimplementedQueryServer struct {
|
||||
}
|
||||
|
||||
func (UnimplementedQueryServer) Params(context.Context, *QueryRequest) (*QueryResponse, error) {
|
||||
func (UnimplementedQueryServer) Params(context.Context, *QueryRequest) (*QueryParamsResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method Params not implemented")
|
||||
}
|
||||
func (UnimplementedQueryServer) ParamsAssets(context.Context, *QueryRequest) (*QueryResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ParamsAssets not implemented")
|
||||
}
|
||||
func (UnimplementedQueryServer) ParamsByAsset(context.Context, *QueryRequest) (*QueryResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ParamsByAsset not implemented")
|
||||
}
|
||||
func (UnimplementedQueryServer) ParamsKeys(context.Context, *QueryRequest) (*QueryResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ParamsKeys not implemented")
|
||||
}
|
||||
func (UnimplementedQueryServer) ParamsByKey(context.Context, *QueryRequest) (*QueryResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ParamsByKey not implemented")
|
||||
}
|
||||
func (UnimplementedQueryServer) RegistrationOptionsByKey(context.Context, *QueryRequest) (*QueryResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method RegistrationOptionsByKey not implemented")
|
||||
}
|
||||
func (UnimplementedQueryServer) Resolve(context.Context, *QueryRequest) (*QueryResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method Resolve not implemented")
|
||||
}
|
||||
@ -132,6 +217,96 @@ func _Query_Params_Handler(srv interface{}, ctx context.Context, dec func(interf
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _Query_ParamsAssets_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(QueryRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(QueryServer).ParamsAssets(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: Query_ParamsAssets_FullMethodName,
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(QueryServer).ParamsAssets(ctx, req.(*QueryRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _Query_ParamsByAsset_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(QueryRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(QueryServer).ParamsByAsset(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: Query_ParamsByAsset_FullMethodName,
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(QueryServer).ParamsByAsset(ctx, req.(*QueryRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _Query_ParamsKeys_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(QueryRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(QueryServer).ParamsKeys(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: Query_ParamsKeys_FullMethodName,
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(QueryServer).ParamsKeys(ctx, req.(*QueryRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _Query_ParamsByKey_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(QueryRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(QueryServer).ParamsByKey(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: Query_ParamsByKey_FullMethodName,
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(QueryServer).ParamsByKey(ctx, req.(*QueryRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _Query_RegistrationOptionsByKey_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(QueryRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(QueryServer).RegistrationOptionsByKey(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: Query_RegistrationOptionsByKey_FullMethodName,
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(QueryServer).RegistrationOptionsByKey(ctx, req.(*QueryRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _Query_Resolve_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(QueryRequest)
|
||||
if err := dec(in); err != nil {
|
||||
@ -179,6 +354,26 @@ var Query_ServiceDesc = grpc.ServiceDesc{
|
||||
MethodName: "Params",
|
||||
Handler: _Query_Params_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "ParamsAssets",
|
||||
Handler: _Query_ParamsAssets_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "ParamsByAsset",
|
||||
Handler: _Query_ParamsByAsset_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "ParamsKeys",
|
||||
Handler: _Query_ParamsKeys_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "ParamsByKey",
|
||||
Handler: _Query_ParamsByKey_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "RegistrationOptionsByKey",
|
||||
Handler: _Query_RegistrationOptionsByKey_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "Resolve",
|
||||
Handler: _Query_Resolve_Handler,
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -611,6 +611,7 @@ func NewChainApp(
|
||||
appCodec,
|
||||
sdkruntime.NewKVStoreService(keys[didtypes.StoreKey]),
|
||||
app.AccountKeeper,
|
||||
app.NFTKeeper,
|
||||
app.StakingKeeper,
|
||||
logger,
|
||||
authtypes.NewModuleAddress(govtypes.ModuleName).String(),
|
||||
@ -872,7 +873,7 @@ func NewChainApp(
|
||||
app.GetSubspace(packetforwardtypes.ModuleName),
|
||||
),
|
||||
|
||||
did.NewAppModule(appCodec, app.DidKeeper),
|
||||
did.NewAppModule(appCodec, app.DidKeeper, app.NFTKeeper),
|
||||
)
|
||||
|
||||
// BasicModuleManager defines the module BasicManager is in charge of setting up basic,
|
||||
|
@ -4,12 +4,9 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/labstack/echo/v4"
|
||||
"github.com/onsonr/sonr/internal/vfs/wasm"
|
||||
|
||||
"github.com/donseba/go-htmx"
|
||||
"github.com/onsonr/sonr/internal/db"
|
||||
)
|
||||
|
||||
@ -17,102 +14,27 @@ var dwn *DWN
|
||||
|
||||
type DWN struct {
|
||||
*echo.Echo
|
||||
DB *db.DB
|
||||
Htmx *htmx.HTMX
|
||||
DB *db.DB
|
||||
}
|
||||
|
||||
func main() {
|
||||
dwn = initRails()
|
||||
|
||||
dwn.GET("/", htmxHandler)
|
||||
dwn.POST("/accounts", accountsHandler)
|
||||
|
||||
wasm.Serve(dwn.Echo)
|
||||
}
|
||||
|
||||
// initRails initializes the Rails application
|
||||
func initRails() *DWN {
|
||||
// Open the database
|
||||
cnfg := db.New()
|
||||
db, err := cnfg.Open()
|
||||
e := echo.New()
|
||||
db, err := db.New()
|
||||
if err != nil {
|
||||
panic(err.Error())
|
||||
}
|
||||
db.ServeEcho(e.Group("/dwn"))
|
||||
|
||||
// Initialize the htmx handler
|
||||
return &DWN{
|
||||
Echo: echo.New(),
|
||||
Echo: e,
|
||||
DB: db,
|
||||
Htmx: htmx.New(),
|
||||
}
|
||||
}
|
||||
|
||||
func accountsHandler(e echo.Context) error {
|
||||
switch e.Request().Method {
|
||||
case "GET":
|
||||
case "PUT":
|
||||
// dwn.DB.AddAccount(e.Param("account"), e.Param("address"))
|
||||
default:
|
||||
e.Error(errors.New("Method not allowed"))
|
||||
}
|
||||
return e.JSON(200, "OK")
|
||||
}
|
||||
|
||||
func htmxHandler(e echo.Context) error {
|
||||
// initiate a new htmx handler
|
||||
h := dwn.Htmx.NewHandler(e.Response(), e.Request())
|
||||
|
||||
// check if the request is a htmx request
|
||||
if h.IsHxRequest() {
|
||||
// do something
|
||||
}
|
||||
|
||||
// check if the request is boosted
|
||||
if h.IsHxBoosted() {
|
||||
// do something
|
||||
}
|
||||
|
||||
// check if the request is a history restore request
|
||||
if h.IsHxHistoryRestoreRequest() {
|
||||
// do something
|
||||
}
|
||||
|
||||
// check if the request is a prompt request
|
||||
if h.RenderPartial() {
|
||||
// do something
|
||||
}
|
||||
|
||||
// set the headers for the response, see docs for more options
|
||||
h.PushURL("http://push.url")
|
||||
h.ReTarget("#ReTarged")
|
||||
|
||||
// write the output like you normally do.
|
||||
// check the inspector tool in the browser to see that the headers are set.
|
||||
_, err := h.Write([]byte("OK"))
|
||||
return err
|
||||
}
|
||||
|
||||
//
|
||||
// func credentialsHandler(e echo.Context) error {
|
||||
// switch e.Request().Method {
|
||||
// case "GET":
|
||||
// dwn.DB.GetCredentials(e.Param("account"))
|
||||
// case "PUT":
|
||||
// dwn.DB.AddCredentials(e.Param("account"), e.Param("address"))
|
||||
// default:
|
||||
// e.Error(errors.New("Method not allowed"))
|
||||
// }
|
||||
// return e.JSON(200, "OK")
|
||||
// }
|
||||
//
|
||||
// func keysharesHandler(e echo.Context) error {
|
||||
// switch e.Request().Method {
|
||||
// case "GET":
|
||||
// dwn.DB.GetKeyshares(e.Param("account"))
|
||||
// case "PUT":
|
||||
// dwn.DB.AddKeyshares(e.Param("account"), e.Param("address"))
|
||||
// default:
|
||||
// e.Error(errors.New("Method not allowed"))
|
||||
// }
|
||||
// return e.JSON(200, "OK")
|
||||
// }
|
||||
|
@ -6,6 +6,8 @@ import (
|
||||
"github.com/labstack/echo/v4"
|
||||
"github.com/syumai/workers"
|
||||
|
||||
"github.com/onsonr/sonr/internal/db"
|
||||
|
||||
"github.com/onsonr/sonr/internal/gui/views"
|
||||
"github.com/onsonr/sonr/internal/mdw"
|
||||
"github.com/onsonr/sonr/internal/svc"
|
||||
@ -19,13 +21,15 @@ func main() {
|
||||
e.Use(mdw.UseSession)
|
||||
|
||||
// Setup routes
|
||||
registerRoutes(e)
|
||||
registerFrontend(e)
|
||||
registerOpenID(e.Group("/authorize"))
|
||||
registerVault(e.Group("/vault"))
|
||||
|
||||
// Serve Worker
|
||||
workers.Serve(e)
|
||||
}
|
||||
|
||||
func registerRoutes(e *echo.Echo) {
|
||||
func registerFrontend(e *echo.Echo) {
|
||||
// Add Public Pages
|
||||
e.GET("/", views.HomeView)
|
||||
e.GET("/login", views.LoginView)
|
||||
@ -33,11 +37,25 @@ func registerRoutes(e *echo.Echo) {
|
||||
e.GET("/register", views.RegisterView)
|
||||
e.POST("/register/:subject", svc.HandleCredentialCreation)
|
||||
e.POST("/register/:subject/check", svc.CheckSubjectIsValid)
|
||||
|
||||
// Add Authenticated Pages
|
||||
e.GET("/authorize", views.AuthorizeView)
|
||||
e.GET("/authorize/discovery", svc.GetDiscovery)
|
||||
e.GET("/authorize/jwks", svc.GetJWKS)
|
||||
e.GET("/authorize/token", svc.GetToken)
|
||||
e.POST("/authorize/:origin/grant/:subject", svc.GrantAuthorization)
|
||||
e.GET("/profile", views.ProfileView)
|
||||
}
|
||||
|
||||
func registerOpenID(g *echo.Group) {
|
||||
// Add Authenticated Pages
|
||||
g.Use(mdw.MacaroonMiddleware("test", "test"))
|
||||
g.GET("/", views.AuthorizeView)
|
||||
g.GET("/discovery", svc.GetDiscovery)
|
||||
g.GET("/jwks", svc.GetJWKS)
|
||||
g.GET("/token", svc.GetToken)
|
||||
g.POST("/:origin/grant/:subject", svc.GrantAuthorization)
|
||||
}
|
||||
|
||||
func registerVault(g *echo.Group) {
|
||||
// Add Authenticated Pages
|
||||
g.Use(mdw.MacaroonMiddleware("test", "test"))
|
||||
vault, err := db.New(db.WitDir("vault"))
|
||||
if err != nil {
|
||||
// panic(err)
|
||||
}
|
||||
vault.ServeEcho(g)
|
||||
}
|
@ -13,8 +13,7 @@ import (
|
||||
|
||||
func main() {
|
||||
rootCmd := NewRootCmd()
|
||||
rootCmd.AddCommand(tui.NewTUIDashboardCmd())
|
||||
// rootCmd.AddCommand(tui.NewExplorerCmd())
|
||||
tui.AddTUICmds(rootCmd)
|
||||
|
||||
if err := svrcmd.Execute(rootCmd, "", app.DefaultNodeHome); err != nil {
|
||||
log.NewLogger(rootCmd.OutOrStderr()).Error("failure when running app", "err", err)
|
||||
|
@ -15,8 +15,7 @@
|
||||
"CHAIN_ID": "sonr-testnet-1",
|
||||
"DENOM": "usnr",
|
||||
"KEYRING": "test",
|
||||
"MONIKER": "florence",
|
||||
"MIN_GAS_PRICES": "0.0001usnr"
|
||||
"MONIKER": "florence"
|
||||
},
|
||||
"shell": {
|
||||
"scripts": {
|
||||
@ -39,6 +38,7 @@
|
||||
"make proto-gen"
|
||||
],
|
||||
"gen:pkl": [
|
||||
"go run github.com/apple/pkl-go/cmd/pkl-gen-go ./pkl/oidc.pkl",
|
||||
"go run github.com/apple/pkl-go/cmd/pkl-gen-go ./pkl/orm.pkl",
|
||||
"go run github.com/apple/pkl-go/cmd/pkl-gen-go ./pkl/txns.pkl"
|
||||
],
|
||||
|
15
go.mod
15
go.mod
@ -2,8 +2,6 @@ module github.com/onsonr/sonr
|
||||
|
||||
go 1.22.5
|
||||
|
||||
toolchain go1.23.0
|
||||
|
||||
// overrides
|
||||
replace (
|
||||
cosmossdk.io/core => cosmossdk.io/core v0.11.0
|
||||
@ -65,20 +63,20 @@ require (
|
||||
github.com/cosmos/ibc-go/modules/capability v1.0.0
|
||||
github.com/cosmos/ibc-go/v8 v8.2.0
|
||||
github.com/donseba/go-htmx v1.10.0
|
||||
github.com/ethereum/go-ethereum v1.14.6
|
||||
github.com/go-webauthn/webauthn v0.10.2
|
||||
github.com/golang/protobuf v1.5.4
|
||||
github.com/gorilla/mux v1.8.1
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.16.0
|
||||
github.com/hack-pad/go-indexeddb v0.3.2
|
||||
github.com/ipfs/boxo v0.21.0
|
||||
github.com/ipfs/kubo v0.29.0
|
||||
github.com/joho/godotenv v1.5.1
|
||||
github.com/labstack/echo-jwt/v4 v4.2.0
|
||||
github.com/labstack/echo/v4 v4.10.2
|
||||
github.com/mr-tron/base58 v1.2.0
|
||||
github.com/ncruces/go-sqlite3 v0.18.2
|
||||
github.com/ncruces/go-sqlite3/gormlite v0.18.0
|
||||
github.com/nlepage/go-js-promise v1.0.0
|
||||
github.com/onsonr/crypto v1.28.0
|
||||
github.com/onsonr/crypto v1.29.0
|
||||
github.com/segmentio/ksuid v1.0.4
|
||||
github.com/spf13/cast v1.6.0
|
||||
github.com/spf13/cobra v1.8.0
|
||||
@ -97,6 +95,7 @@ require (
|
||||
gopkg.in/macaroon.v2 v2.1.0
|
||||
gorm.io/gorm v1.25.11
|
||||
lukechampine.com/adiantum v1.1.1
|
||||
lukechampine.com/blake3 v1.3.0
|
||||
)
|
||||
|
||||
require (
|
||||
@ -110,7 +109,6 @@ require (
|
||||
github.com/99designs/keyring v1.2.1 // indirect
|
||||
github.com/DataDog/datadog-go v3.2.0+incompatible // indirect
|
||||
github.com/DataDog/zstd v1.5.5 // indirect
|
||||
github.com/Microsoft/go-winio v0.6.2 // indirect
|
||||
github.com/alecthomas/units v0.0.0-20231202071711-9a357b53e9c9 // indirect
|
||||
github.com/atotto/clipboard v0.1.4 // indirect
|
||||
github.com/aws/aws-sdk-go v1.44.224 // indirect
|
||||
@ -176,7 +174,6 @@ require (
|
||||
github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 // indirect
|
||||
github.com/gogo/googleapis v1.4.1 // indirect
|
||||
github.com/gogo/protobuf v1.3.2 // indirect
|
||||
github.com/golang-jwt/jwt v3.2.2+incompatible // indirect
|
||||
github.com/golang-jwt/jwt/v5 v5.2.1 // indirect
|
||||
github.com/golang/glog v1.2.0 // indirect
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
||||
@ -192,10 +189,12 @@ require (
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect
|
||||
github.com/googleapis/gax-go/v2 v2.12.2 // indirect
|
||||
github.com/gorilla/handlers v1.5.2 // indirect
|
||||
github.com/gorilla/mux v1.8.1 // indirect
|
||||
github.com/gorilla/websocket v1.5.3 // indirect
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 // indirect
|
||||
github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c // indirect
|
||||
github.com/gtank/merlin v0.1.1 // indirect
|
||||
github.com/hack-pad/safejs v0.1.0 // indirect
|
||||
github.com/hashicorp/errwrap v1.1.0 // indirect
|
||||
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
|
||||
github.com/hashicorp/go-getter v1.7.5 // indirect
|
||||
@ -211,6 +210,7 @@ require (
|
||||
github.com/hashicorp/hcl v1.0.0 // indirect
|
||||
github.com/hashicorp/yamux v0.1.1 // indirect
|
||||
github.com/hdevalence/ed25519consensus v0.1.0 // indirect
|
||||
github.com/holiman/uint256 v1.2.4 // indirect
|
||||
github.com/huandu/skiplist v1.2.0 // indirect
|
||||
github.com/iancoleman/orderedmap v0.3.0 // indirect
|
||||
github.com/iancoleman/strcase v0.3.0 // indirect
|
||||
@ -362,7 +362,6 @@ require (
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
gotest.tools/v3 v3.5.1 // indirect
|
||||
lukechampine.com/blake3 v1.3.0 // indirect
|
||||
nhooyr.io/websocket v1.8.10 // indirect
|
||||
pgregory.net/rapid v1.1.0 // indirect
|
||||
rsc.io/tmplfunc v0.0.3 // indirect
|
||||
|
16
go.sum
16
go.sum
@ -1129,6 +1129,8 @@ github.com/envoyproxy/protoc-gen-validate v1.0.1/go.mod h1:0vj8bNkYbSTNS2PIyH87K
|
||||
github.com/envoyproxy/protoc-gen-validate v1.0.2/go.mod h1:GpiZQP3dDbg4JouG/NNS7QWXpgx6x8QiMKdmN72jogE=
|
||||
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f h1:Y/CXytFA4m6baUTXGLOoWe4PQhGxaX0KpnayAqC48p4=
|
||||
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f/go.mod h1:vw97MGsxSvLiUE2X8qFplwetxpGLQrlU1Q9AUEIzCaM=
|
||||
github.com/ethereum/go-ethereum v1.14.6 h1:ZTxnErSopkDyxdvB8zW/KcK+/AVrdil/TzoWXVKaaC8=
|
||||
github.com/ethereum/go-ethereum v1.14.6/go.mod h1:hglUZo/5pVIYXNyYjWzsAUDpT/zI+WbWo/Nih7ot+G0=
|
||||
github.com/facebookgo/atomicfile v0.0.0-20151019160806-2de1f203e7d5 h1:BBso6MBKW8ncyZLv37o+KNyy0HrrHgfnOaGQC2qvN+A=
|
||||
github.com/facebookgo/atomicfile v0.0.0-20151019160806-2de1f203e7d5/go.mod h1:JpoxHjuQauoxiFMl1ie8Xc/7TfLuMZ5eOCONd1sUBHg=
|
||||
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
||||
@ -1228,8 +1230,6 @@ github.com/gofrs/uuid v4.4.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRx
|
||||
github.com/gogo/googleapis v1.4.1-0.20201022092350-68b0159b7869/go.mod h1:5YRNX2z1oM5gXdAkurHa942MDgEJyk02w4OecKY87+c=
|
||||
github.com/gogo/googleapis v1.4.1 h1:1Yx4Myt7BxzvUr5ldGSbwYiZG6t9wGBZ+8/fX3Wvtq0=
|
||||
github.com/gogo/googleapis v1.4.1/go.mod h1:2lpHqI5OcWCtVElxXnPt+s8oJvMpySlOyM6xDCrzib4=
|
||||
github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY=
|
||||
github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
|
||||
github.com/golang-jwt/jwt/v5 v5.2.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17wHk=
|
||||
github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
|
||||
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k=
|
||||
@ -1403,6 +1403,10 @@ github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c h1:6rhixN/i8
|
||||
github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c/go.mod h1:NMPJylDgVpX0MLRlPy15sqSwOFv/U1GZ2m21JhFfek0=
|
||||
github.com/gtank/merlin v0.1.1 h1:eQ90iG7K9pOhtereWsmyRJ6RAwcP4tHTDBHXNg+u5is=
|
||||
github.com/gtank/merlin v0.1.1/go.mod h1:T86dnYJhcGOh5BjZFCJWTDeTK7XW8uE+E21Cy/bIQ+s=
|
||||
github.com/hack-pad/go-indexeddb v0.3.2 h1:DTqeJJYc1usa45Q5r52t01KhvlSN02+Oq+tQbSBI91A=
|
||||
github.com/hack-pad/go-indexeddb v0.3.2/go.mod h1:QvfTevpDVlkfomY498LhstjwbPW6QC4VC/lxYb0Kom0=
|
||||
github.com/hack-pad/safejs v0.1.0 h1:qPS6vjreAqh2amUqj4WNG1zIw7qlRQJ9K10eDKMCnE8=
|
||||
github.com/hack-pad/safejs v0.1.0/go.mod h1:HdS+bKF1NrE72VoXZeWzxFOVQVUSqZJAG0xNCnb+Tio=
|
||||
github.com/hashicorp/consul/api v1.25.1/go.mod h1:iiLVwR/htV7mas/sy0O+XSuEnrdBUUydemjxcUrAt4g=
|
||||
github.com/hashicorp/consul/sdk v0.14.1/go.mod h1:vFt03juSzocLRFo59NkeQHHmQa6+g7oU0pfzdI1mUhg=
|
||||
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||
@ -1459,6 +1463,8 @@ github.com/hashicorp/yamux v0.1.1 h1:yrQxtgseBDrq9Y652vSRDvsKCJKOUD+GzTS4Y0Y8pvE
|
||||
github.com/hashicorp/yamux v0.1.1/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ=
|
||||
github.com/hdevalence/ed25519consensus v0.1.0 h1:jtBwzzcHuTmFrQN6xQZn6CQEO/V9f7HsjsjeEZ6auqU=
|
||||
github.com/hdevalence/ed25519consensus v0.1.0/go.mod h1:w3BHWjwJbFU29IRHL1Iqkw3sus+7FctEyM4RqDxYNzo=
|
||||
github.com/holiman/uint256 v1.2.4 h1:jUc4Nk8fm9jZabQuqr2JzednajVmBpC+oiTiXZJEApU=
|
||||
github.com/holiman/uint256 v1.2.4/go.mod h1:EOMSn4q6Nyt9P6efbI3bueV4e1b3dGlUCXeiRV4ng7E=
|
||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
github.com/huandu/go-assert v1.1.5 h1:fjemmA7sSfYHJD7CUqs9qTwwfdNAx7/j2/ZlHXzNB3c=
|
||||
github.com/huandu/go-assert v1.1.5/go.mod h1:yOLvuqZwmcHIC5rIzrBhT7D3Q9c3GFnd0JrPVhn/06U=
|
||||
@ -1645,8 +1651,6 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/labstack/echo-jwt/v4 v4.2.0 h1:odSISV9JgcSCuhgQSV/6Io3i7nUmfM/QkBeR5GVJj5c=
|
||||
github.com/labstack/echo-jwt/v4 v4.2.0/go.mod h1:MA2RqdXdEn4/uEglx0HcUOgQSyBaTh5JcaHIan3biwU=
|
||||
github.com/labstack/echo/v4 v4.10.2 h1:n1jAhnq/elIFTHr1EYpiYtyKgx4RW9ccVgkqByZaN2M=
|
||||
github.com/labstack/echo/v4 v4.10.2/go.mod h1:OEyqf2//K1DFdE57vw2DRgWY0M7s65IVQO2FzvI4J5k=
|
||||
github.com/labstack/gommon v0.4.0 h1:y7cvthEAEbU0yHOf4axH8ZG2NH8knB9iNSoTO8dyIk8=
|
||||
@ -1857,8 +1861,8 @@ github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7J
|
||||
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
|
||||
github.com/onsi/gomega v1.33.1 h1:dsYjIxxSR755MDmKVsaFQTE22ChNBcuuTWgkUDSubOk=
|
||||
github.com/onsi/gomega v1.33.1/go.mod h1:U4R44UsT+9eLIaYRB2a5qajjtQYn0hauxvRm16AVYg0=
|
||||
github.com/onsonr/crypto v1.28.0 h1:IZnWipcqtehohvau065NJSEgS2a2iMeTv2S0KlQ22ns=
|
||||
github.com/onsonr/crypto v1.28.0/go.mod h1:2Ew7gRDlysE9+UXN904nUaJ9bqn6OlpKFMtk/LuTYoc=
|
||||
github.com/onsonr/crypto v1.29.0 h1:ontCN/XNNmpWv23N8VB6vsirLXcjxZaA67lLX9RNj0c=
|
||||
github.com/onsonr/crypto v1.29.0/go.mod h1:NSfeCO6XoyQeSDEp6Jy42UGG5047GvzG6lW9lRnjrR0=
|
||||
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
|
||||
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
|
||||
github.com/opencontainers/image-spec v1.1.0-rc5 h1:Ygwkfw9bpDvs+c9E34SdgGOj41dX/cbdlwvlWt0pnFI=
|
||||
|
@ -12,11 +12,11 @@ func createInitialTables(db *gorm.DB) (*DB, error) {
|
||||
err := db.AutoMigrate(
|
||||
&orm.Account{},
|
||||
&orm.Asset{},
|
||||
&orm.Keyshare{},
|
||||
&orm.Credential{},
|
||||
&orm.Keyshare{},
|
||||
&orm.Permission{},
|
||||
&orm.Profile{},
|
||||
&orm.Property{},
|
||||
&orm.Permission{},
|
||||
)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create table: %w", err)
|
||||
@ -35,12 +35,75 @@ func (db *DB) AddAccount(account *orm.Account) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// AddKeyshare adds a new keyshare to the database
|
||||
func (db *DB) AddKeyshare(keyshare *orm.Keyshare) error {
|
||||
tx := db.Create(keyshare)
|
||||
// GetAccount gets an account from the database
|
||||
func (db *DB) GetAccount(account *orm.Account) error {
|
||||
tx := db.First(account)
|
||||
if tx.Error != nil {
|
||||
return fmt.Errorf("failed to get account: %w", tx.Error)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// UpdateAccount updates an existing account in the database
|
||||
func (db *DB) UpdateAccount(account *orm.Account) error {
|
||||
tx := db.Save(account)
|
||||
if tx.Error != nil {
|
||||
return fmt.Errorf("failed to update account: %w", tx.Error)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// DeleteAccount deletes an existing account from the database
|
||||
func (db *DB) DeleteAccount(account *orm.Account) error {
|
||||
tx := db.Delete(account)
|
||||
if tx.Error != nil {
|
||||
return fmt.Errorf("failed to delete account: %w", tx.Error)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// AddAsset adds a new asset to the database
|
||||
func (db *DB) AddAsset(asset *orm.Asset) error {
|
||||
tx := db.Create(asset)
|
||||
|
||||
if tx.Error != nil {
|
||||
return fmt.Errorf("failed to add keyshare: %w", tx.Error)
|
||||
return fmt.Errorf("failed to add asset: %w", tx.Error)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetAsset gets an asset from the database
|
||||
func (db *DB) GetAsset(asset *orm.Asset) error {
|
||||
tx := db.First(asset)
|
||||
|
||||
if tx.Error != nil {
|
||||
return fmt.Errorf("failed to get asset: %w", tx.Error)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// UpdateAsset updates an existing asset in the database
|
||||
func (db *DB) UpdateAsset(asset *orm.Asset) error {
|
||||
tx := db.Save(asset)
|
||||
|
||||
if tx.Error != nil {
|
||||
return fmt.Errorf("failed to update asset: %w", tx.Error)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// DeleteAsset deletes an existing asset from the database
|
||||
func (db *DB) DeleteAsset(asset *orm.Asset) error {
|
||||
tx := db.Delete(asset)
|
||||
|
||||
if tx.Error != nil {
|
||||
return fmt.Errorf("failed to delete asset: %w", tx.Error)
|
||||
}
|
||||
|
||||
return nil
|
||||
@ -57,6 +120,127 @@ func (db *DB) AddCredential(credential *orm.Credential) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetCredential gets an credential from the database
|
||||
func (db *DB) GetCredential(credential *orm.Credential) error {
|
||||
tx := db.First(credential)
|
||||
|
||||
if tx.Error != nil {
|
||||
return fmt.Errorf("failed to get credential: %w", tx.Error)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// UpdateCredential updates an existing credential in the database
|
||||
func (db *DB) UpdateCredential(credential *orm.Credential) error {
|
||||
tx := db.Save(credential)
|
||||
|
||||
if tx.Error != nil {
|
||||
return fmt.Errorf("failed to update credential: %w", tx.Error)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// DeleteCredential deletes an existing credential from the database
|
||||
func (db *DB) DeleteCredential(credential *orm.Credential) error {
|
||||
tx := db.Delete(credential)
|
||||
|
||||
if tx.Error != nil {
|
||||
return fmt.Errorf("failed to delete credential: %w", tx.Error)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// AddKeyshare adds a new keyshare to the database
|
||||
func (db *DB) AddKeyshare(keyshare *orm.Keyshare) error {
|
||||
tx := db.Create(keyshare)
|
||||
|
||||
if tx.Error != nil {
|
||||
return fmt.Errorf("failed to add keyshare: %w", tx.Error)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetKeyshare gets an keyshare from the database
|
||||
func (db *DB) GetKeyshare(keyshare *orm.Keyshare) error {
|
||||
tx := db.First(keyshare)
|
||||
|
||||
if tx.Error != nil {
|
||||
return fmt.Errorf("failed to get keyshare: %w", tx.Error)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// UpdateKeyshare updates an existing keyshare in the database
|
||||
func (db *DB) UpdateKeyshare(keyshare *orm.Keyshare) error {
|
||||
tx := db.Save(keyshare)
|
||||
|
||||
if tx.Error != nil {
|
||||
return fmt.Errorf("failed to update keyshare: %w", tx.Error)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// DeleteKeyshare deletes an existing keyshare from the database
|
||||
func (db *DB) DeleteKeyshare(keyshare *orm.Keyshare) error {
|
||||
tx := db.Delete(keyshare)
|
||||
|
||||
if tx.Error != nil {
|
||||
return fmt.Errorf("failed to delete keyshare: %w", tx.Error)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// AddPermission adds a new permission to the database
|
||||
func (db *DB) AddPermission(permission *orm.Permission) error {
|
||||
tx := db.Create(permission)
|
||||
|
||||
if tx.Error != nil {
|
||||
return fmt.Errorf("failed to add permission: %w", tx.Error)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetPermission gets an permission from the database
|
||||
func (db *DB) GetPermission(permission *orm.Permission) error {
|
||||
tx := db.First(permission)
|
||||
|
||||
if tx.Error != nil {
|
||||
return fmt.Errorf("failed to get permission: %w", tx.Error)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// UpdatePermission updates an existing permission in the database
|
||||
func (db *DB) UpdatePermission(permission *orm.Permission) error {
|
||||
tx := db.Save(permission)
|
||||
|
||||
if tx.Error != nil {
|
||||
return fmt.Errorf("failed to update permission: %w", tx.Error)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// DeletePermission deletes an existing permission from the database
|
||||
func (db *DB) DeletePermission(permission *orm.Permission) error {
|
||||
tx := db.Delete(permission)
|
||||
|
||||
if tx.Error != nil {
|
||||
return fmt.Errorf("failed to delete permission: %w", tx.Error)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// AddProfile adds a new profile to the database
|
||||
func (db *DB) AddProfile(profile *orm.Profile) error {
|
||||
tx := db.Create(profile)
|
||||
@ -68,6 +252,39 @@ func (db *DB) AddProfile(profile *orm.Profile) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetProfile gets an profile from the database
|
||||
func (db *DB) GetProfile(profile *orm.Profile) error {
|
||||
tx := db.First(profile)
|
||||
|
||||
if tx.Error != nil {
|
||||
return fmt.Errorf("failed to get profile: %w", tx.Error)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// UpdateProfile updates an existing profile in the database
|
||||
func (db *DB) UpdateProfile(profile *orm.Profile) error {
|
||||
tx := db.Save(profile)
|
||||
|
||||
if tx.Error != nil {
|
||||
return fmt.Errorf("failed to update profile: %w", tx.Error)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// DeleteProfile deletes an existing profile from the database
|
||||
func (db *DB) DeleteProfile(profile *orm.Profile) error {
|
||||
tx := db.Delete(profile)
|
||||
|
||||
if tx.Error != nil {
|
||||
return fmt.Errorf("failed to delete profile: %w", tx.Error)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// AddProperty adds a new property to the database
|
||||
func (db *DB) AddProperty(property *orm.Property) error {
|
||||
tx := db.Create(property)
|
||||
@ -79,12 +296,34 @@ func (db *DB) AddProperty(property *orm.Property) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// AddPermission adds a new permission to the database
|
||||
func (db *DB) AddPermission(permission *orm.Permission) error {
|
||||
tx := db.Create(permission)
|
||||
// GetProperty gets an property from the database
|
||||
func (db *DB) GetProperty(property *orm.Property) error {
|
||||
tx := db.First(property)
|
||||
|
||||
if tx.Error != nil {
|
||||
return fmt.Errorf("failed to add permission: %w", tx.Error)
|
||||
return fmt.Errorf("failed to get property: %w", tx.Error)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// UpdateProperty updates an existing property in the database
|
||||
func (db *DB) UpdateProperty(property *orm.Property) error {
|
||||
tx := db.Save(property)
|
||||
|
||||
if tx.Error != nil {
|
||||
return fmt.Errorf("failed to update property: %w", tx.Error)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// DeleteProperty deletes an existing property from the database
|
||||
func (db *DB) DeleteProperty(property *orm.Property) error {
|
||||
tx := db.Delete(property)
|
||||
|
||||
if tx.Error != nil {
|
||||
return fmt.Errorf("failed to delete property: %w", tx.Error)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -1,17 +1,54 @@
|
||||
package db
|
||||
|
||||
import "gorm.io/gorm"
|
||||
import (
|
||||
"crypto/rand"
|
||||
|
||||
"github.com/ncruces/go-sqlite3/gormlite"
|
||||
"golang.org/x/crypto/argon2"
|
||||
"gorm.io/gorm"
|
||||
"lukechampine.com/adiantum/hbsh"
|
||||
"lukechampine.com/adiantum/hpolyc"
|
||||
)
|
||||
|
||||
type DB struct {
|
||||
*gorm.DB
|
||||
}
|
||||
|
||||
func New(opts ...DBOption) *DBConfig {
|
||||
func New(opts ...DBOption) (*DB, error) {
|
||||
config := &DBConfig{
|
||||
fileName: "vault.db",
|
||||
}
|
||||
for _, opt := range opts {
|
||||
opt(config)
|
||||
}
|
||||
return config
|
||||
gormdb, err := gorm.Open(gormlite.Open(config.ConnectionString()))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
db, err := createInitialTables(gormdb)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return db, nil
|
||||
}
|
||||
|
||||
// HBSH creates an HBSH cipher given a key.
|
||||
func (c *DB) HBSH(key []byte) *hbsh.HBSH {
|
||||
if len(key) != 32 {
|
||||
// Key is not appropriate, return nil.
|
||||
return nil
|
||||
}
|
||||
return hpolyc.New(key)
|
||||
}
|
||||
|
||||
// KDF gets a key from a secret.
|
||||
func (c *DB) KDF(secret string) []byte {
|
||||
if secret == "" {
|
||||
// No secret is given, generate a random key.
|
||||
key := make([]byte, 32)
|
||||
n, _ := rand.Read(key)
|
||||
return key[:n]
|
||||
}
|
||||
// Hash the secret with a KDF.
|
||||
return argon2.IDKey([]byte(secret), []byte("hpolyc"), 3, 64*1024, 4, 32)
|
||||
}
|
||||
|
195
internal/db/handlers.go
Normal file
195
internal/db/handlers.go
Normal file
@ -0,0 +1,195 @@
|
||||
package db
|
||||
|
||||
import (
|
||||
"github.com/labstack/echo/v4"
|
||||
"github.com/onsonr/sonr/internal/db/orm"
|
||||
)
|
||||
|
||||
func (db *DB) ServeEcho(e *echo.Group) {
|
||||
e.GET("/accounts", db.HandleAccount)
|
||||
e.GET("/assets", db.HandleAsset)
|
||||
e.GET("/credentials", db.HandleCredential)
|
||||
e.GET("/keyshares", db.HandleKeyshare)
|
||||
e.GET("/permissions", db.HandlePermission)
|
||||
e.GET("/profiles", db.HandleProfile)
|
||||
e.GET("/properties", db.HandleProperty)
|
||||
}
|
||||
|
||||
func (db *DB) HandleAccount(c echo.Context) error {
|
||||
data := new(orm.Account)
|
||||
if err := c.Bind(data); err != nil {
|
||||
return err
|
||||
}
|
||||
// Check the method for GET, POST, PUT, DELETE
|
||||
switch c.Request().Method {
|
||||
case echo.POST:
|
||||
|
||||
if err := db.AddAccount(data); err != nil {
|
||||
return err
|
||||
}
|
||||
return c.JSON(200, "OK")
|
||||
case echo.PUT:
|
||||
|
||||
if err := db.UpdateAccount(data); err != nil {
|
||||
return err
|
||||
}
|
||||
return c.JSON(200, "OK")
|
||||
case echo.DELETE:
|
||||
if err := db.DeleteAccount(data); err != nil {
|
||||
return err
|
||||
}
|
||||
return c.JSON(200, nil)
|
||||
}
|
||||
return c.JSON(200, data)
|
||||
}
|
||||
|
||||
func (db *DB) HandleAsset(c echo.Context) error {
|
||||
data := new(orm.Asset)
|
||||
if err := c.Bind(data); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
switch c.Request().Method {
|
||||
case echo.POST:
|
||||
if err := db.AddAsset(data); err != nil {
|
||||
return err
|
||||
}
|
||||
return c.JSON(200, "OK")
|
||||
case echo.PUT:
|
||||
if err := db.UpdateAsset(data); err != nil {
|
||||
return err
|
||||
}
|
||||
return c.JSON(200, "OK")
|
||||
case echo.DELETE:
|
||||
if err := db.DeleteAsset(data); err != nil {
|
||||
return err
|
||||
}
|
||||
return c.JSON(200, "OK")
|
||||
}
|
||||
return c.JSON(200, data)
|
||||
}
|
||||
|
||||
func (db *DB) HandleCredential(c echo.Context) error {
|
||||
data := new(orm.Credential)
|
||||
if err := c.Bind(data); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
switch c.Request().Method {
|
||||
case echo.POST:
|
||||
if err := db.AddCredential(data); err != nil {
|
||||
return err
|
||||
}
|
||||
return c.JSON(200, "OK")
|
||||
case echo.PUT:
|
||||
if err := db.UpdateCredential(data); err != nil {
|
||||
return err
|
||||
}
|
||||
return c.JSON(200, "OK")
|
||||
case echo.DELETE:
|
||||
if err := db.DeleteCredential(data); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return c.JSON(200, data)
|
||||
}
|
||||
|
||||
func (db *DB) HandleKeyshare(c echo.Context) error {
|
||||
data := new(orm.Keyshare)
|
||||
if err := c.Bind(data); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
switch c.Request().Method {
|
||||
case echo.POST:
|
||||
if err := db.AddKeyshare(data); err != nil {
|
||||
return err
|
||||
}
|
||||
return c.JSON(200, "OK")
|
||||
case echo.PUT:
|
||||
if err := db.UpdateKeyshare(data); err != nil {
|
||||
return err
|
||||
}
|
||||
return c.JSON(200, "OK")
|
||||
case echo.DELETE:
|
||||
if err := db.DeleteKeyshare(data); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return c.JSON(200, data)
|
||||
}
|
||||
|
||||
func (db *DB) HandlePermission(c echo.Context) error {
|
||||
data := new(orm.Permission)
|
||||
if err := c.Bind(data); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
switch c.Request().Method {
|
||||
case echo.POST:
|
||||
if err := db.AddPermission(data); err != nil {
|
||||
return err
|
||||
}
|
||||
return c.JSON(200, "OK")
|
||||
case echo.PUT:
|
||||
if err := db.UpdatePermission(data); err != nil {
|
||||
return err
|
||||
}
|
||||
return c.JSON(200, "OK")
|
||||
case echo.DELETE:
|
||||
if err := db.DeletePermission(data); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return c.JSON(200, data)
|
||||
}
|
||||
|
||||
func (db *DB) HandleProfile(c echo.Context) error {
|
||||
data := new(orm.Profile)
|
||||
if err := c.Bind(data); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
switch c.Request().Method {
|
||||
case echo.POST:
|
||||
if err := db.AddProfile(data); err != nil {
|
||||
return err
|
||||
}
|
||||
return c.JSON(200, "OK")
|
||||
case echo.PUT:
|
||||
if err := db.UpdateProfile(data); err != nil {
|
||||
return err
|
||||
}
|
||||
return c.JSON(200, "OK")
|
||||
case echo.DELETE:
|
||||
if err := db.DeleteProfile(data); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return c.JSON(200, data)
|
||||
}
|
||||
|
||||
func (db *DB) HandleProperty(c echo.Context) error {
|
||||
data := new(orm.Property)
|
||||
if err := c.Bind(data); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
switch c.Request().Method {
|
||||
case echo.POST:
|
||||
if err := db.AddProperty(data); err != nil {
|
||||
return err
|
||||
}
|
||||
return c.JSON(200, "OK")
|
||||
case echo.PUT:
|
||||
if err := db.UpdateProperty(data); err != nil {
|
||||
return err
|
||||
}
|
||||
return c.JSON(200, "OK")
|
||||
case echo.DELETE:
|
||||
if err := db.DeleteProperty(data); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return c.JSON(200, data)
|
||||
}
|
131
internal/db/idb/idb.go
Normal file
131
internal/db/idb/idb.go
Normal file
@ -0,0 +1,131 @@
|
||||
//go:build js && wasm
|
||||
// +build js,wasm
|
||||
|
||||
package idb
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"syscall/js"
|
||||
|
||||
"github.com/hack-pad/go-indexeddb/idb"
|
||||
)
|
||||
|
||||
// Model is an interface that must be implemented by types used with Table
|
||||
type Model interface {
|
||||
Table() string
|
||||
}
|
||||
|
||||
// Table is a generic wrapper around IDB for easier database operations on a specific table
|
||||
type Table[T Model] struct {
|
||||
db *idb.Database
|
||||
dbName string
|
||||
keyPath string
|
||||
}
|
||||
|
||||
// NewTable creates a new Table instance
|
||||
func NewTable[T Model](dbName string, version uint, keyPath string) (*Table[T], error) {
|
||||
ctx := context.Background()
|
||||
factory := idb.Global()
|
||||
|
||||
var model T
|
||||
tableName := model.Table()
|
||||
|
||||
openRequest, err := factory.Open(ctx, dbName, version, func(db *idb.Database, oldVersion, newVersion uint) error {
|
||||
_, err := db.CreateObjectStore(tableName, idb.ObjectStoreOptions{
|
||||
KeyPath: js.ValueOf(keyPath),
|
||||
})
|
||||
return err
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
db, err := openRequest.Await(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &Table[T]{
|
||||
db: db,
|
||||
dbName: dbName,
|
||||
keyPath: keyPath,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Insert adds a new record to the table
|
||||
func (t *Table[T]) Insert(data T) error {
|
||||
tx, err := t.db.Transaction(idb.TransactionReadWrite, data.Table())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer tx.Commit()
|
||||
|
||||
objectStore, err := tx.ObjectStore(data.Table())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
jsonData, err := json.Marshal(data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = objectStore.Add(js.ValueOf(string(jsonData)))
|
||||
return err
|
||||
}
|
||||
|
||||
// Query retrieves a record from the table based on a key
|
||||
func (t *Table[T]) Query(key interface{}) (T, error) {
|
||||
var result T
|
||||
|
||||
tx, err := t.db.Transaction(idb.TransactionReadOnly, result.Table())
|
||||
if err != nil {
|
||||
return result, err
|
||||
}
|
||||
defer tx.Commit()
|
||||
|
||||
objectStore, err := tx.ObjectStore(result.Table())
|
||||
if err != nil {
|
||||
return result, err
|
||||
}
|
||||
|
||||
request, err := objectStore.Get(js.ValueOf(key))
|
||||
if err != nil {
|
||||
return result, err
|
||||
}
|
||||
|
||||
value, err := request.Await(context.Background())
|
||||
if err != nil {
|
||||
return result, err
|
||||
}
|
||||
|
||||
if value.IsUndefined() || value.IsNull() {
|
||||
return result, errors.New("record not found")
|
||||
}
|
||||
|
||||
err = json.Unmarshal([]byte(value.String()), &result)
|
||||
return result, err
|
||||
}
|
||||
|
||||
// Delete removes a record from the table based on a key
|
||||
func (t *Table[T]) Delete(key interface{}) error {
|
||||
var model T
|
||||
tx, err := t.db.Transaction(idb.TransactionReadWrite, model.Table())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer tx.Commit()
|
||||
|
||||
objectStore, err := tx.ObjectStore(model.Table())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = objectStore.Delete(js.ValueOf(key))
|
||||
return err
|
||||
}
|
||||
|
||||
// Close closes the database connection
|
||||
func (t *Table[T]) Close() error {
|
||||
return t.db.Close()
|
||||
}
|
@ -1,20 +1,13 @@
|
||||
package db
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
|
||||
"github.com/ncruces/go-sqlite3/gormlite"
|
||||
"golang.org/x/crypto/argon2"
|
||||
"gorm.io/gorm"
|
||||
"lukechampine.com/adiantum/hbsh"
|
||||
"lukechampine.com/adiantum/hpolyc"
|
||||
|
||||
_ "github.com/ncruces/go-sqlite3/embed"
|
||||
"github.com/onsonr/sonr/internal/db/orm"
|
||||
)
|
||||
|
||||
type DBOption func(config *DBConfig)
|
||||
|
||||
func WithDir(dir string) DBOption {
|
||||
func WitDir(dir string) DBOption {
|
||||
return func(config *DBConfig) {
|
||||
config.Dir = dir
|
||||
}
|
||||
@ -30,41 +23,18 @@ type DBConfig struct {
|
||||
Dir string
|
||||
SecretKey string
|
||||
|
||||
fileName string
|
||||
fileName string
|
||||
initialAccounts []*orm.Account
|
||||
initialAssets []*orm.Asset
|
||||
initialCredentials []*orm.Credential
|
||||
initialKeyshares []*orm.Keyshare
|
||||
initialPermissions []*orm.Permission
|
||||
initialProfiles []*orm.Profile
|
||||
initialProperties []*orm.Property
|
||||
}
|
||||
|
||||
func (config *DBConfig) ConnectionString() string {
|
||||
connStr := "file:"
|
||||
connStr += config.Dir + "/" + config.fileName
|
||||
connStr += config.fileName
|
||||
return connStr
|
||||
}
|
||||
|
||||
// GormDialector creates a gorm dialector for the database.
|
||||
func (config *DBConfig) Open() (*DB, error) {
|
||||
db, err := gorm.Open(gormlite.Open(config.ConnectionString()))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return createInitialTables(db)
|
||||
}
|
||||
|
||||
// HBSH creates an HBSH cipher given a key.
|
||||
func (c *DBConfig) HBSH(key []byte) *hbsh.HBSH {
|
||||
if len(key) != 32 {
|
||||
// Key is not appropriate, return nil.
|
||||
return nil
|
||||
}
|
||||
return hpolyc.New(key)
|
||||
}
|
||||
|
||||
// KDF gets a key from a secret.
|
||||
func (c *DBConfig) KDF(secret string) []byte {
|
||||
if secret == "" {
|
||||
// No secret is given, generate a random key.
|
||||
key := make([]byte, 32)
|
||||
n, _ := rand.Read(key)
|
||||
return key[:n]
|
||||
}
|
||||
// Hash the secret with a KDF.
|
||||
return argon2.IDKey([]byte(secret), []byte("hpolyc"), 3, 64*1024, 4, 32)
|
||||
}
|
||||
|
@ -4,17 +4,9 @@ package orm
|
||||
type Keyshare struct {
|
||||
Id uint `pkl:"id" gorm:"primaryKey,autoIncrement" json:"id,omitempty" query:"id"`
|
||||
|
||||
Metadata string `pkl:"metadata" json:"metadata,omitempty" param:"metadata"`
|
||||
|
||||
Payloads string `pkl:"payloads" json:"payloads,omitempty" param:"payloads"`
|
||||
|
||||
Protocol string `pkl:"protocol" json:"protocol,omitempty" param:"protocol"`
|
||||
|
||||
PublicKey string `pkl:"publicKey" json:"publicKey,omitempty" param:"publicKey"`
|
||||
Data string `pkl:"data" json:"data,omitempty" param:"data"`
|
||||
|
||||
Role int `pkl:"role" json:"role,omitempty" param:"role"`
|
||||
|
||||
Version int `pkl:"version" json:"version,omitempty" param:"version"`
|
||||
|
||||
CreatedAt *string `pkl:"createdAt" json:"createdAt,omitempty" param:"createdAt"`
|
||||
}
|
||||
|
@ -1,16 +0,0 @@
|
||||
// Code generated from Pkl module `orm`. DO NOT EDIT.
|
||||
package orm
|
||||
|
||||
type PublicKey struct {
|
||||
Id uint `pkl:"id" gorm:"primaryKey,autoIncrement" json:"id,omitempty" query:"id"`
|
||||
|
||||
Role int `pkl:"role" json:"role,omitempty" param:"role"`
|
||||
|
||||
Algorithm int `pkl:"algorithm" json:"algorithm,omitempty" param:"algorithm"`
|
||||
|
||||
Encoding int `pkl:"encoding" json:"encoding,omitempty" param:"encoding"`
|
||||
|
||||
Jwk string `pkl:"jwk" json:"jwk,omitempty" param:"jwk"`
|
||||
|
||||
CreatedAt *string `pkl:"createdAt" json:"createdAt,omitempty" param:"createdAt"`
|
||||
}
|
@ -12,7 +12,5 @@ func init() {
|
||||
pkl.RegisterMapping("orm#Profile", Profile{})
|
||||
pkl.RegisterMapping("orm#Property", Property{})
|
||||
pkl.RegisterMapping("orm#Keyshare", Keyshare{})
|
||||
pkl.RegisterMapping("orm#PublicKey", PublicKey{})
|
||||
pkl.RegisterMapping("orm#Permission", Permission{})
|
||||
pkl.RegisterMapping("orm#DiscoveryDocument", DiscoveryDocument{})
|
||||
}
|
||||
|
29
internal/db/orm/orm.go
Normal file
29
internal/db/orm/orm.go
Normal file
@ -0,0 +1,29 @@
|
||||
package orm
|
||||
|
||||
func (a *Account) Table() string {
|
||||
return "accounts"
|
||||
}
|
||||
|
||||
func (a *Asset) Table() string {
|
||||
return "assets"
|
||||
}
|
||||
|
||||
func (a *Credential) Table() string {
|
||||
return "credentials"
|
||||
}
|
||||
|
||||
func (a *Keyshare) Table() string {
|
||||
return "keyshares"
|
||||
}
|
||||
|
||||
func (a *Permission) Table() string {
|
||||
return "permissions"
|
||||
}
|
||||
|
||||
func (a *Profile) Table() string {
|
||||
return "profiles"
|
||||
}
|
||||
|
||||
func (a *Property) Table() string {
|
||||
return "properties"
|
||||
}
|
59
internal/gui/elements/badge.templ
Normal file
59
internal/gui/elements/badge.templ
Normal file
@ -0,0 +1,59 @@
|
||||
package elements
|
||||
|
||||
templ PoweredBySonr() {
|
||||
<div class="mx-auto w-fit pt-8">
|
||||
<div class="pt-2 pb-3 pl-4 pr-4 gap-x-3 text-sm text-gray-500 border-t border-neutral-200/70">
|
||||
<div
|
||||
x-data="{
|
||||
hoverCardHovered: false,
|
||||
hoverCardDelay: 600,
|
||||
hoverCardLeaveDelay: 500,
|
||||
hoverCardTimout: null,
|
||||
hoverCardLeaveTimeout: null,
|
||||
hoverCardEnter () {
|
||||
clearTimeout(this.hoverCardLeaveTimeout);
|
||||
if(this.hoverCardHovered) return;
|
||||
clearTimeout(this.hoverCardTimout);
|
||||
this.hoverCardTimout = setTimeout(() => {
|
||||
this.hoverCardHovered = true;
|
||||
}, this.hoverCardDelay);
|
||||
},
|
||||
hoverCardLeave () {
|
||||
clearTimeout(this.hoverCardTimout);
|
||||
if(!this.hoverCardHovered) return;
|
||||
clearTimeout(this.hoverCardLeaveTimeout);
|
||||
this.hoverCardLeaveTimeout = setTimeout(() => {
|
||||
this.hoverCardHovered = false;
|
||||
}, this.hoverCardLeaveDelay);
|
||||
}
|
||||
}"
|
||||
class="relative"
|
||||
@mouseover="hoverCardEnter()"
|
||||
@mouseleave="hoverCardLeave()"
|
||||
>
|
||||
<span class="bg-transparent text-gray-500 border border-neutral-300 flex items-center text-xs font-semibold px-2.5 py-0.5 rounded-full">
|
||||
<span class="mr-1">Powered by </span>
|
||||
<svg class="w-3 h-3" width="164" height="164" viewBox="0 0 164 164" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M71.8077 133.231C74.5054 135.928 78.1636 137.443 81.978 137.443C85.7924 137.443 89.4506 135.928 92.1483 133.231L133.219 92.1638C135.909 89.4654 137.42 85.8102 137.42 81.9998C137.42 78.1895 135.909 74.5345 133.219 71.8361L112.886 51.5272L131.665 32.7499L152.031 53.1143C159.696 60.7963 164 71.2046 164 82.0559C164 92.9072 159.696 103.315 152.031 110.997L110.95 152.065C107.154 155.869 102.642 158.883 97.6739 160.931C92.7059 162.98 87.3809 164.023 82.0071 164L82.0052 164C76.622 164.019 71.2886 162.969 66.3145 160.91C61.3405 158.852 56.8247 155.826 53.0294 152.009L53.0289 152.008L48.7187 147.699L67.4974 128.921L71.8077 133.231Z" fill="currentColor"></path>
|
||||
<path d="M110.95 11.9912L115.26 16.3011L96.481 35.0785L92.1707 30.7685C89.4731 28.072 85.8148 26.5572 82.0004 26.5572C78.186 26.5572 74.5277 28.072 71.8301 30.7685L30.7597 71.8359C29.4247 73.1706 28.3658 74.7552 27.6433 76.4991C26.9208 78.2431 26.549 80.1122 26.549 81.9999C26.549 83.8876 26.9208 85.7567 27.6433 87.5007C28.3658 89.2446 29.4247 90.8292 30.7597 92.1639L51.1256 112.528L32.3138 131.306L11.9923 110.941C8.19043 107.141 5.17433 102.629 3.1167 97.6635C1.05907 92.6976 0 87.3751 0 81.9999C0 76.6247 1.05907 71.3022 3.1167 66.3363C5.17433 61.3705 8.19021 56.8587 11.9921 53.0586L53.0625 11.9912C56.8629 8.18964 61.3751 5.17395 66.3413 3.11647C71.3075 1.05899 76.6304 0 82.006 0C87.3816 0 92.7045 1.05899 97.6707 3.11647C102.637 5.17395 107.149 8.18964 110.95 11.9912Z" fill="currentColor"></path>
|
||||
<path d="M55.603 76.6744L76.6993 55.5798C79.6327 52.6465 84.3888 52.6465 87.3223 55.5797L108.419 76.6744C111.352 79.6077 111.352 84.3634 108.419 87.2966L87.3223 108.391C84.3888 111.325 79.6327 111.325 76.6993 108.391L55.603 87.2966C52.6696 84.3634 52.6696 79.6077 55.603 76.6744Z" fill="currentColor"></path>
|
||||
</svg>
|
||||
</span>
|
||||
<div x-show="hoverCardHovered" class="absolute top-0 w-[365px] max-w-lg mt-5 z-30 -translate-x-1/2 translate-y-3 left-1/2" x-cloak>
|
||||
<div x-show="hoverCardHovered" class="w-[full] h-auto bg-white space-x-3 p-5 flex items-start rounded-md shadow-sm border border-neutral-200/70" x-transition>
|
||||
<img src="https://cdn.sonr.io/logo.svg" alt="sonr image" class="rounded-full w-14 h-14"/>
|
||||
<div class="relative">
|
||||
<p class="mb-1 text-sm text-gray-600">The creative platform for developers. Community, tools, products, and more</p>
|
||||
<p class="flex items-center space-x-1 text-xs text-gray-400">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-5 h-5">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M6.75 3v2.25M17.25 3v2.25M3 18.75V7.5a2.25 2.25 0 012.25-2.25h13.5A2.25 2.25 0 0121 7.5v11.25m-18 0A2.25 2.25 0 005.25 21h13.5A2.25 2.25 0 0021 18.75m-18 0v-7.5A2.25 2.25 0 015.25 9h13.5A2.25 2.25 0 0121 11.25v7.5m-9-6h.008v.008H12v-.008zM12 15h.008v.008H12V15zm0 2.25h.008v.008H12v-.008zM9.75 15h.008v.008H9.75V15zm0 2.25h.008v.008H9.75v-.008zM7.5 15h.008v.008H7.5V15zm0 2.25h.008v.008H7.5v-.008zm6.75-4.5h.008v.008h-.008v-.008zm0 2.25h.008v.008h-.008V15zm0 2.25h.008v.008h-.008v-.008zm2.25-4.5h.008v.008H16.5v-.008zm0 2.25h.008v.008H16.5V15z"></path>
|
||||
</svg>
|
||||
<span>Joined June 2020</span>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
37
internal/gui/elements/badge_templ.go
Normal file
37
internal/gui/elements/badge_templ.go
Normal file
@ -0,0 +1,37 @@
|
||||
// Code generated by templ - DO NOT EDIT.
|
||||
|
||||
// templ: version: v0.2.771
|
||||
package elements
|
||||
|
||||
//lint:file-ignore SA4006 This context is only used if a nested component is present.
|
||||
|
||||
import "github.com/a-h/templ"
|
||||
import templruntime "github.com/a-h/templ/runtime"
|
||||
|
||||
func PoweredBySonr() templ.Component {
|
||||
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
||||
if !templ_7745c5c3_IsBuffer {
|
||||
defer func() {
|
||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err == nil {
|
||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
||||
}
|
||||
}()
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var1 == nil {
|
||||
templ_7745c5c3_Var1 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div class=\"mx-auto w-fit pt-8\"><div class=\"pt-2 pb-3 pl-4 pr-4 gap-x-3 text-sm text-gray-500 border-t border-neutral-200/70\"><div x-data=\"{ \n hoverCardHovered: false,\n hoverCardDelay: 600,\n hoverCardLeaveDelay: 500,\n hoverCardTimout: null,\n hoverCardLeaveTimeout: null,\n hoverCardEnter () {\n clearTimeout(this.hoverCardLeaveTimeout);\n if(this.hoverCardHovered) return;\n clearTimeout(this.hoverCardTimout);\n this.hoverCardTimout = setTimeout(() => {\n this.hoverCardHovered = true;\n }, this.hoverCardDelay);\n },\n hoverCardLeave () {\n clearTimeout(this.hoverCardTimout);\n if(!this.hoverCardHovered) return;\n clearTimeout(this.hoverCardLeaveTimeout);\n this.hoverCardLeaveTimeout = setTimeout(() => {\n this.hoverCardHovered = false;\n }, this.hoverCardLeaveDelay);\n }\n }\" class=\"relative\" @mouseover=\"hoverCardEnter()\" @mouseleave=\"hoverCardLeave()\"><span class=\"bg-transparent text-gray-500 border border-neutral-300 flex items-center text-xs font-semibold px-2.5 py-0.5 rounded-full\"><span class=\"mr-1\">Powered by </span> <svg class=\"w-3 h-3\" width=\"164\" height=\"164\" viewBox=\"0 0 164 164\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M71.8077 133.231C74.5054 135.928 78.1636 137.443 81.978 137.443C85.7924 137.443 89.4506 135.928 92.1483 133.231L133.219 92.1638C135.909 89.4654 137.42 85.8102 137.42 81.9998C137.42 78.1895 135.909 74.5345 133.219 71.8361L112.886 51.5272L131.665 32.7499L152.031 53.1143C159.696 60.7963 164 71.2046 164 82.0559C164 92.9072 159.696 103.315 152.031 110.997L110.95 152.065C107.154 155.869 102.642 158.883 97.6739 160.931C92.7059 162.98 87.3809 164.023 82.0071 164L82.0052 164C76.622 164.019 71.2886 162.969 66.3145 160.91C61.3405 158.852 56.8247 155.826 53.0294 152.009L53.0289 152.008L48.7187 147.699L67.4974 128.921L71.8077 133.231Z\" fill=\"currentColor\"></path> <path d=\"M110.95 11.9912L115.26 16.3011L96.481 35.0785L92.1707 30.7685C89.4731 28.072 85.8148 26.5572 82.0004 26.5572C78.186 26.5572 74.5277 28.072 71.8301 30.7685L30.7597 71.8359C29.4247 73.1706 28.3658 74.7552 27.6433 76.4991C26.9208 78.2431 26.549 80.1122 26.549 81.9999C26.549 83.8876 26.9208 85.7567 27.6433 87.5007C28.3658 89.2446 29.4247 90.8292 30.7597 92.1639L51.1256 112.528L32.3138 131.306L11.9923 110.941C8.19043 107.141 5.17433 102.629 3.1167 97.6635C1.05907 92.6976 0 87.3751 0 81.9999C0 76.6247 1.05907 71.3022 3.1167 66.3363C5.17433 61.3705 8.19021 56.8587 11.9921 53.0586L53.0625 11.9912C56.8629 8.18964 61.3751 5.17395 66.3413 3.11647C71.3075 1.05899 76.6304 0 82.006 0C87.3816 0 92.7045 1.05899 97.6707 3.11647C102.637 5.17395 107.149 8.18964 110.95 11.9912Z\" fill=\"currentColor\"></path> <path d=\"M55.603 76.6744L76.6993 55.5798C79.6327 52.6465 84.3888 52.6465 87.3223 55.5797L108.419 76.6744C111.352 79.6077 111.352 84.3634 108.419 87.2966L87.3223 108.391C84.3888 111.325 79.6327 111.325 76.6993 108.391L55.603 87.2966C52.6696 84.3634 52.6696 79.6077 55.603 76.6744Z\" fill=\"currentColor\"></path></svg></span><div x-show=\"hoverCardHovered\" class=\"absolute top-0 w-[365px] max-w-lg mt-5 z-30 -translate-x-1/2 translate-y-3 left-1/2\" x-cloak><div x-show=\"hoverCardHovered\" class=\"w-[full] h-auto bg-white space-x-3 p-5 flex items-start rounded-md shadow-sm border border-neutral-200/70\" x-transition><img src=\"https://cdn.sonr.io/logo.svg\" alt=\"sonr image\" class=\"rounded-full w-14 h-14\"><div class=\"relative\"><p class=\"mb-1 text-sm text-gray-600\">The creative platform for developers. Community, tools, products, and more</p><p class=\"flex items-center space-x-1 text-xs text-gray-400\"><svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\" stroke-width=\"1.5\" stroke=\"currentColor\" class=\"w-5 h-5\"><path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M6.75 3v2.25M17.25 3v2.25M3 18.75V7.5a2.25 2.25 0 012.25-2.25h13.5A2.25 2.25 0 0121 7.5v11.25m-18 0A2.25 2.25 0 005.25 21h13.5A2.25 2.25 0 0021 18.75m-18 0v-7.5A2.25 2.25 0 015.25 9h13.5A2.25 2.25 0 0121 11.25v7.5m-9-6h.008v.008H12v-.008zM12 15h.008v.008H12V15zm0 2.25h.008v.008H12v-.008zM9.75 15h.008v.008H9.75V15zm0 2.25h.008v.008H9.75v-.008zM7.5 15h.008v.008H7.5V15zm0 2.25h.008v.008H7.5v-.008zm6.75-4.5h.008v.008h-.008v-.008zm0 2.25h.008v.008h-.008V15zm0 2.25h.008v.008h-.008v-.008zm2.25-4.5h.008v.008H16.5v-.008zm0 2.25h.008v.008H16.5V15z\"></path></svg> <span>Joined June 2020</span></p></div></div></div></div></div></div>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
}
|
||||
|
||||
var _ = templruntime.GeneratedTemplate
|
35
internal/gui/elements/breadcrumbs.templ
Normal file
35
internal/gui/elements/breadcrumbs.templ
Normal file
@ -0,0 +1,35 @@
|
||||
package elements
|
||||
|
||||
templ Breadcrumbs() {
|
||||
<nav class="flex justify-between px-3.5 py-1 rounded-md pb-3">
|
||||
<ol class="inline-flex items-center mb-3 space-x-1 text-xs text-neutral-500 [&_.active-breadcrumb]:text-neutral-600 [&_.active-breadcrumb]:font-medium sm:mb-0">
|
||||
<li class="flex items-center h-full">
|
||||
<a href="#_" class="py-1 hover:text-neutral-900">
|
||||
@breadcrumbIcon()
|
||||
</a>
|
||||
</li>
|
||||
<svg class="w-5 h-5 text-gray-400/70" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><g fill="none" stroke="none"><path d="M10 8.013l4 4-4 4" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path></g></svg>
|
||||
@breadcrumbItem("Policy", false)
|
||||
<svg class="w-5 h-5 text-gray-400/70" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><g fill="none" stroke="none"><path d="M10 8.013l4 4-4 4" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path></g></svg>
|
||||
@breadcrumbItem("About You", true)
|
||||
<svg class="w-5 h-5 text-gray-400/70" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><g fill="none" stroke="none"><path d="M10 8.013l4 4-4 4" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path></g></svg>
|
||||
@breadcrumbItem("Generate", false)
|
||||
</ol>
|
||||
</nav>
|
||||
}
|
||||
|
||||
templ breadcrumbItem(title string, active bool) {
|
||||
if (active) {
|
||||
<li><a class="inline-flex items-center py-1 font-normal rounded cursor-default active-breadcrumb focus:outline-none">{ title }</a></li>
|
||||
} else {
|
||||
<li><a href="#_" class="inline-flex items-center py-1 font-normal hover:text-neutral-900 focus:outline-none">{ title }</a></li>
|
||||
}
|
||||
}
|
||||
|
||||
templ breadcrumbIcon() {
|
||||
<svg class="w-4 w-4" viewBox="0 0 164 164" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M71.8077 133.231C74.5054 135.928 78.1636 137.443 81.978 137.443C85.7924 137.443 89.4506 135.928 92.1483 133.231L133.219 92.1638C135.909 89.4654 137.42 85.8102 137.42 81.9998C137.42 78.1895 135.909 74.5345 133.219 71.8361L112.886 51.5272L131.665 32.7499L152.031 53.1143C159.696 60.7963 164 71.2046 164 82.0559C164 92.9072 159.696 103.315 152.031 110.997L110.95 152.065C107.154 155.869 102.642 158.883 97.6739 160.931C92.7059 162.98 87.3809 164.023 82.0071 164L82.0052 164C76.622 164.019 71.2886 162.969 66.3145 160.91C61.3405 158.852 56.8247 155.826 53.0294 152.009L53.0289 152.008L48.7187 147.699L67.4974 128.921L71.8077 133.231Z" fill="currentColor"></path>
|
||||
<path d="M110.95 11.9912L115.26 16.3011L96.481 35.0785L92.1707 30.7685C89.4731 28.072 85.8148 26.5572 82.0004 26.5572C78.186 26.5572 74.5277 28.072 71.8301 30.7685L30.7597 71.8359C29.4247 73.1706 28.3658 74.7552 27.6433 76.4991C26.9208 78.2431 26.549 80.1122 26.549 81.9999C26.549 83.8876 26.9208 85.7567 27.6433 87.5007C28.3658 89.2446 29.4247 90.8292 30.7597 92.1639L51.1256 112.528L32.3138 131.306L11.9923 110.941C8.19043 107.141 5.17433 102.629 3.1167 97.6635C1.05907 92.6976 0 87.3751 0 81.9999C0 76.6247 1.05907 71.3022 3.1167 66.3363C5.17433 61.3705 8.19021 56.8587 11.9921 53.0586L53.0625 11.9912C56.8629 8.18964 61.3751 5.17395 66.3413 3.11647C71.3075 1.05899 76.6304 0 82.006 0C87.3816 0 92.7045 1.05899 97.6707 3.11647C102.637 5.17395 107.149 8.18964 110.95 11.9912Z" fill="currentColor"></path>
|
||||
<path d="M55.603 76.6744L76.6993 55.5798C79.6327 52.6465 84.3888 52.6465 87.3223 55.5797L108.419 76.6744C111.352 79.6077 111.352 84.3634 108.419 87.2966L87.3223 108.391C84.3888 111.325 79.6327 111.325 76.6993 108.391L55.603 87.2966C52.6696 84.3634 52.6696 79.6077 55.603 76.6744Z" fill="currentColor"></path>
|
||||
</svg>
|
||||
}
|
154
internal/gui/elements/breadcrumbs_templ.go
Normal file
154
internal/gui/elements/breadcrumbs_templ.go
Normal file
@ -0,0 +1,154 @@
|
||||
// Code generated by templ - DO NOT EDIT.
|
||||
|
||||
// templ: version: v0.2.771
|
||||
package elements
|
||||
|
||||
//lint:file-ignore SA4006 This context is only used if a nested component is present.
|
||||
|
||||
import "github.com/a-h/templ"
|
||||
import templruntime "github.com/a-h/templ/runtime"
|
||||
|
||||
func Breadcrumbs() templ.Component {
|
||||
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
||||
if !templ_7745c5c3_IsBuffer {
|
||||
defer func() {
|
||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err == nil {
|
||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
||||
}
|
||||
}()
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var1 == nil {
|
||||
templ_7745c5c3_Var1 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<nav class=\"flex justify-between px-3.5 py-1 rounded-md pb-3\"><ol class=\"inline-flex items-center mb-3 space-x-1 text-xs text-neutral-500 [&_.active-breadcrumb]:text-neutral-600 [&_.active-breadcrumb]:font-medium sm:mb-0\"><li class=\"flex items-center h-full\"><a href=\"#_\" class=\"py-1 hover:text-neutral-900\">")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = breadcrumbIcon().Render(ctx, templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</a></li><svg class=\"w-5 h-5 text-gray-400/70\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\"><g fill=\"none\" stroke=\"none\"><path d=\"M10 8.013l4 4-4 4\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></path></g></svg>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = breadcrumbItem("Policy", false).Render(ctx, templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<svg class=\"w-5 h-5 text-gray-400/70\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\"><g fill=\"none\" stroke=\"none\"><path d=\"M10 8.013l4 4-4 4\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></path></g></svg>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = breadcrumbItem("About You", true).Render(ctx, templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<svg class=\"w-5 h-5 text-gray-400/70\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\"><g fill=\"none\" stroke=\"none\"><path d=\"M10 8.013l4 4-4 4\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></path></g></svg>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = breadcrumbItem("Generate", false).Render(ctx, templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</ol></nav>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
}
|
||||
|
||||
func breadcrumbItem(title string, active bool) templ.Component {
|
||||
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
||||
if !templ_7745c5c3_IsBuffer {
|
||||
defer func() {
|
||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err == nil {
|
||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
||||
}
|
||||
}()
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
templ_7745c5c3_Var2 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var2 == nil {
|
||||
templ_7745c5c3_Var2 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
if active {
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<li><a class=\"inline-flex items-center py-1 font-normal rounded cursor-default active-breadcrumb focus:outline-none\">")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var3 string
|
||||
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(title)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/gui/elements/breadcrumbs.templ`, Line: 23, Col: 126}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</a></li>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
} else {
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<li><a href=\"#_\" class=\"inline-flex items-center py-1 font-normal hover:text-neutral-900 focus:outline-none\">")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var4 string
|
||||
templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(title)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/gui/elements/breadcrumbs.templ`, Line: 25, Col: 118}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</a></li>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
}
|
||||
|
||||
func breadcrumbIcon() templ.Component {
|
||||
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
||||
if !templ_7745c5c3_IsBuffer {
|
||||
defer func() {
|
||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err == nil {
|
||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
||||
}
|
||||
}()
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
templ_7745c5c3_Var5 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var5 == nil {
|
||||
templ_7745c5c3_Var5 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<svg class=\"w-4 w-4\" viewBox=\"0 0 164 164\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M71.8077 133.231C74.5054 135.928 78.1636 137.443 81.978 137.443C85.7924 137.443 89.4506 135.928 92.1483 133.231L133.219 92.1638C135.909 89.4654 137.42 85.8102 137.42 81.9998C137.42 78.1895 135.909 74.5345 133.219 71.8361L112.886 51.5272L131.665 32.7499L152.031 53.1143C159.696 60.7963 164 71.2046 164 82.0559C164 92.9072 159.696 103.315 152.031 110.997L110.95 152.065C107.154 155.869 102.642 158.883 97.6739 160.931C92.7059 162.98 87.3809 164.023 82.0071 164L82.0052 164C76.622 164.019 71.2886 162.969 66.3145 160.91C61.3405 158.852 56.8247 155.826 53.0294 152.009L53.0289 152.008L48.7187 147.699L67.4974 128.921L71.8077 133.231Z\" fill=\"currentColor\"></path> <path d=\"M110.95 11.9912L115.26 16.3011L96.481 35.0785L92.1707 30.7685C89.4731 28.072 85.8148 26.5572 82.0004 26.5572C78.186 26.5572 74.5277 28.072 71.8301 30.7685L30.7597 71.8359C29.4247 73.1706 28.3658 74.7552 27.6433 76.4991C26.9208 78.2431 26.549 80.1122 26.549 81.9999C26.549 83.8876 26.9208 85.7567 27.6433 87.5007C28.3658 89.2446 29.4247 90.8292 30.7597 92.1639L51.1256 112.528L32.3138 131.306L11.9923 110.941C8.19043 107.141 5.17433 102.629 3.1167 97.6635C1.05907 92.6976 0 87.3751 0 81.9999C0 76.6247 1.05907 71.3022 3.1167 66.3363C5.17433 61.3705 8.19021 56.8587 11.9921 53.0586L53.0625 11.9912C56.8629 8.18964 61.3751 5.17395 66.3413 3.11647C71.3075 1.05899 76.6304 0 82.006 0C87.3816 0 92.7045 1.05899 97.6707 3.11647C102.637 5.17395 107.149 8.18964 110.95 11.9912Z\" fill=\"currentColor\"></path> <path d=\"M55.603 76.6744L76.6993 55.5798C79.6327 52.6465 84.3888 52.6465 87.3223 55.5797L108.419 76.6744C111.352 79.6077 111.352 84.3634 108.419 87.2966L87.3223 108.391C84.3888 111.325 79.6327 111.325 76.6993 108.391L55.603 87.2966C52.6696 84.3634 52.6696 79.6077 55.603 76.6744Z\" fill=\"currentColor\"></path></svg>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
}
|
||||
|
||||
var _ = templruntime.GeneratedTemplate
|
@ -1,7 +1,79 @@
|
||||
package elements
|
||||
|
||||
func Button(variant Variant) templ.Component {
|
||||
return renderButton(variant.Attributes())
|
||||
type button struct {
|
||||
variant Variant
|
||||
hxGet string
|
||||
hxPost string
|
||||
hxTarget string
|
||||
hxTrigger string
|
||||
hxSwap string
|
||||
}
|
||||
|
||||
type ButtonOpt func(button *button)
|
||||
|
||||
func PrimaryButtonStyle() ButtonOpt {
|
||||
return func(button *button) {
|
||||
button.variant = ButtonVariantPrimary
|
||||
}
|
||||
}
|
||||
|
||||
func InfoButtonStyle() ButtonOpt {
|
||||
return func(button *button) {
|
||||
button.variant = ButtonVariantInfo
|
||||
}
|
||||
}
|
||||
|
||||
func ErrorButtonStyle() ButtonOpt {
|
||||
return func(button *button) {
|
||||
button.variant = ButtonVariantError
|
||||
}
|
||||
}
|
||||
|
||||
func SuccessButtonStyle() ButtonOpt {
|
||||
return func(button *button) {
|
||||
button.variant = ButtonVariantSuccess
|
||||
}
|
||||
}
|
||||
|
||||
func WarningButtonStyle() ButtonOpt {
|
||||
return func(button *button) {
|
||||
button.variant = ButtonVariantWarning
|
||||
}
|
||||
}
|
||||
|
||||
func GET(action string, target string) ButtonOpt {
|
||||
return func(button *button) {
|
||||
button.hxGet = action
|
||||
button.hxTarget = target
|
||||
button.hxTrigger = "click"
|
||||
button.hxSwap = "outerHTML"
|
||||
}
|
||||
}
|
||||
|
||||
func POST(action string, target string) ButtonOpt {
|
||||
return func(button *button) {
|
||||
button.hxPost = action
|
||||
button.hxTarget = target
|
||||
button.hxTrigger = "click"
|
||||
button.hxSwap = "outerHTML"
|
||||
}
|
||||
}
|
||||
|
||||
func Button(opts ...ButtonOpt) templ.Component {
|
||||
button := button{
|
||||
variant: ButtonVariantDefault,
|
||||
}
|
||||
for _, opt := range opts {
|
||||
opt(&button)
|
||||
}
|
||||
if button.hxGet != "" {
|
||||
return renderHxGetButton(&button, button.variant.Attributes())
|
||||
}
|
||||
|
||||
if button.hxPost != "" {
|
||||
return renderHxPostButton(&button, button.variant.Attributes())
|
||||
}
|
||||
return renderButton(button.variant.Attributes())
|
||||
}
|
||||
|
||||
templ renderButton(attrs templ.Attributes) {
|
||||
@ -10,6 +82,18 @@ templ renderButton(attrs templ.Attributes) {
|
||||
</button>
|
||||
}
|
||||
|
||||
templ renderHxGetButton(c *button, attrs templ.Attributes) {
|
||||
<button hx-get={ c.hxGet } hx-push-url="true" hx-target={ c.hxTarget } hx-trigger={ c.hxTrigger } hx-swap={ c.hxSwap } { attrs... }>
|
||||
{ children... }
|
||||
</button>
|
||||
}
|
||||
|
||||
templ renderHxPostButton(c *button, attrs templ.Attributes) {
|
||||
<button hx-post={ c.hxPost } hx-target={ c.hxTarget } hx-trigger={ c.hxTrigger } hx-swap={ c.hxSwap } { attrs... }>
|
||||
{ children... }
|
||||
</button>
|
||||
}
|
||||
|
||||
type ButtonVariant int
|
||||
|
||||
const (
|
||||
|
@ -8,8 +8,80 @@ package elements
|
||||
import "github.com/a-h/templ"
|
||||
import templruntime "github.com/a-h/templ/runtime"
|
||||
|
||||
func Button(variant Variant) templ.Component {
|
||||
return renderButton(variant.Attributes())
|
||||
type button struct {
|
||||
variant Variant
|
||||
hxGet string
|
||||
hxPost string
|
||||
hxTarget string
|
||||
hxTrigger string
|
||||
hxSwap string
|
||||
}
|
||||
|
||||
type ButtonOpt func(button *button)
|
||||
|
||||
func PrimaryButtonStyle() ButtonOpt {
|
||||
return func(button *button) {
|
||||
button.variant = ButtonVariantPrimary
|
||||
}
|
||||
}
|
||||
|
||||
func InfoButtonStyle() ButtonOpt {
|
||||
return func(button *button) {
|
||||
button.variant = ButtonVariantInfo
|
||||
}
|
||||
}
|
||||
|
||||
func ErrorButtonStyle() ButtonOpt {
|
||||
return func(button *button) {
|
||||
button.variant = ButtonVariantError
|
||||
}
|
||||
}
|
||||
|
||||
func SuccessButtonStyle() ButtonOpt {
|
||||
return func(button *button) {
|
||||
button.variant = ButtonVariantSuccess
|
||||
}
|
||||
}
|
||||
|
||||
func WarningButtonStyle() ButtonOpt {
|
||||
return func(button *button) {
|
||||
button.variant = ButtonVariantWarning
|
||||
}
|
||||
}
|
||||
|
||||
func GET(action string, target string) ButtonOpt {
|
||||
return func(button *button) {
|
||||
button.hxGet = action
|
||||
button.hxTarget = target
|
||||
button.hxTrigger = "click"
|
||||
button.hxSwap = "outerHTML"
|
||||
}
|
||||
}
|
||||
|
||||
func POST(action string, target string) ButtonOpt {
|
||||
return func(button *button) {
|
||||
button.hxPost = action
|
||||
button.hxTarget = target
|
||||
button.hxTrigger = "click"
|
||||
button.hxSwap = "outerHTML"
|
||||
}
|
||||
}
|
||||
|
||||
func Button(opts ...ButtonOpt) templ.Component {
|
||||
button := button{
|
||||
variant: ButtonVariantDefault,
|
||||
}
|
||||
for _, opt := range opts {
|
||||
opt(&button)
|
||||
}
|
||||
if button.hxGet != "" {
|
||||
return renderHxGetButton(&button, button.variant.Attributes())
|
||||
}
|
||||
|
||||
if button.hxPost != "" {
|
||||
return renderHxPostButton(&button, button.variant.Attributes())
|
||||
}
|
||||
return renderButton(button.variant.Attributes())
|
||||
}
|
||||
|
||||
func renderButton(attrs templ.Attributes) templ.Component {
|
||||
@ -54,6 +126,194 @@ func renderButton(attrs templ.Attributes) templ.Component {
|
||||
})
|
||||
}
|
||||
|
||||
func renderHxGetButton(c *button, attrs templ.Attributes) templ.Component {
|
||||
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
||||
if !templ_7745c5c3_IsBuffer {
|
||||
defer func() {
|
||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err == nil {
|
||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
||||
}
|
||||
}()
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
templ_7745c5c3_Var2 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var2 == nil {
|
||||
templ_7745c5c3_Var2 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<button hx-get=\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var3 string
|
||||
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(c.hxGet)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/gui/elements/button.templ`, Line: 86, Col: 25}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\" hx-push-url=\"true\" hx-target=\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var4 string
|
||||
templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(c.hxTarget)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/gui/elements/button.templ`, Line: 86, Col: 69}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\" hx-trigger=\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var5 string
|
||||
templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(c.hxTrigger)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/gui/elements/button.templ`, Line: 86, Col: 96}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\" hx-swap=\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var6 string
|
||||
templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(c.hxSwap)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/gui/elements/button.templ`, Line: 86, Col: 117}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templ.RenderAttributes(ctx, templ_7745c5c3_Buffer, attrs)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(">")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templ_7745c5c3_Var2.Render(ctx, templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</button>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
}
|
||||
|
||||
func renderHxPostButton(c *button, attrs templ.Attributes) templ.Component {
|
||||
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
||||
if !templ_7745c5c3_IsBuffer {
|
||||
defer func() {
|
||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err == nil {
|
||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
||||
}
|
||||
}()
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
templ_7745c5c3_Var7 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var7 == nil {
|
||||
templ_7745c5c3_Var7 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<button hx-post=\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var8 string
|
||||
templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(c.hxPost)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/gui/elements/button.templ`, Line: 92, Col: 27}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\" hx-target=\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var9 string
|
||||
templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinStringErrs(c.hxTarget)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/gui/elements/button.templ`, Line: 92, Col: 52}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var9))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\" hx-trigger=\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var10 string
|
||||
templ_7745c5c3_Var10, templ_7745c5c3_Err = templ.JoinStringErrs(c.hxTrigger)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/gui/elements/button.templ`, Line: 92, Col: 79}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var10))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\" hx-swap=\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var11 string
|
||||
templ_7745c5c3_Var11, templ_7745c5c3_Err = templ.JoinStringErrs(c.hxSwap)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/gui/elements/button.templ`, Line: 92, Col: 100}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var11))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templ.RenderAttributes(ctx, templ_7745c5c3_Buffer, attrs)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(">")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templ_7745c5c3_Var7.Render(ctx, templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</button>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
}
|
||||
|
||||
type ButtonVariant int
|
||||
|
||||
const (
|
||||
|
@ -1,12 +1,12 @@
|
||||
package elements
|
||||
|
||||
func Card(size Size) templ.Component {
|
||||
return renderCard(size.CardAttributes())
|
||||
func Card(id string, size Size) templ.Component {
|
||||
return renderCard(id, size.CardAttributes())
|
||||
}
|
||||
|
||||
templ renderCard(attrs templ.Attributes) {
|
||||
<div { attrs... }>
|
||||
<div class="container">
|
||||
templ renderCard(id string, attrs templ.Attributes) {
|
||||
<div id={ id } { attrs... }>
|
||||
<div class="w-full h-full">
|
||||
<div class="row">
|
||||
<div class="col-md-12 space-3">
|
||||
{ children... }
|
||||
@ -15,3 +15,33 @@ templ renderCard(attrs templ.Attributes) {
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
templ ProfileCard() {
|
||||
<div class="relative max-w-sm overflow-hidden bg-white border rounded-lg shadow-sm border-neutral-200/60">
|
||||
<img src="https://cdn.devdojo.com/images/august2023/wallpaper.jpeg" class="relative z-20 object-cover w-full h-32"/>
|
||||
<div class="absolute top-0 z-50 flex items-center w-full mt-2 translate-y-24 px-7 -translate-x-0">
|
||||
<div class="w-20 h-20 p-1 bg-white rounded-full">
|
||||
<img src="https://cdn.devdojo.com/images/august2023/adam.jpeg" class="w-full h-full rounded-full"/>
|
||||
</div>
|
||||
<a href="https://twitter.com/adamwathan" target="_blank" class="block mt-6 ml-2">
|
||||
<h5 class="text-lg font-bold leading-none tracking-tight text-neutral-900">Adam Wathan</h5>
|
||||
<small class="block mt-1 text-sm font-medium leading-none text-neutral-500">adamwathan</small>
|
||||
</a>
|
||||
<button class="absolute right-0 inline-flex items-center justify-center w-auto px-5 mt-6 text-sm font-medium transition-colors duration-100 rounded-full h-9 mr-7 hover:text-white focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:opacity-50 bg-neutral-900 disabled:pointer-events-none hover:bg-neutral-800 text-neutral-100">
|
||||
<span>Follow</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="relative pb-6 p-7">
|
||||
<p class="mt-12 mb-6 text-neutral-500 text-">Creator of @tailwindcss. Listener of Slayer. Austin 3:16. BTW, Pines UI is super cool!</p>
|
||||
<div class="flex items-center justify-between pr-2 text-neutral-500">
|
||||
<div class="relative flex w-16">
|
||||
<img src="https://cdn.devdojo.com/images/august2023/caleb.jpeg" class="relative z-30 w-8 h-8 border-2 border-white rounded-full"/>
|
||||
<img src="https://cdn.devdojo.com/images/august2023/taylor.jpeg" class="z-20 w-8 h-8 -translate-x-4 border-2 border-white rounded-full"/>
|
||||
<img src="https://cdn.devdojo.com/images/august2023/adam.jpeg" class="z-10 w-8 h-8 border-2 border-white rounded-full -translate-x-7"/>
|
||||
</div>
|
||||
<a href="https://twitter.com/adamwathan/following" target="_blank" class="text-sm hover:underline"><strong class="text-neutral-800">673</strong> Following</a>
|
||||
<a href="https://twitter.com/adamwathan/followers" target="_blank" class="text-sm hover:underline"><strong class="text-neutral-800">168.6K</strong> Followers</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
@ -8,11 +8,11 @@ package elements
|
||||
import "github.com/a-h/templ"
|
||||
import templruntime "github.com/a-h/templ/runtime"
|
||||
|
||||
func Card(size Size) templ.Component {
|
||||
return renderCard(size.CardAttributes())
|
||||
func Card(id string, size Size) templ.Component {
|
||||
return renderCard(id, size.CardAttributes())
|
||||
}
|
||||
|
||||
func renderCard(attrs templ.Attributes) templ.Component {
|
||||
func renderCard(id string, attrs templ.Attributes) templ.Component {
|
||||
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
||||
@ -30,7 +30,20 @@ func renderCard(attrs templ.Attributes) templ.Component {
|
||||
templ_7745c5c3_Var1 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div")
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div id=\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var2 string
|
||||
templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs(id)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/gui/elements/card.templ`, Line: 8, Col: 13}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var2))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
@ -38,7 +51,7 @@ func renderCard(attrs templ.Attributes) templ.Component {
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("><div class=\"container\"><div class=\"row\"><div class=\"col-md-12 space-3\">")
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("><div class=\"w-full h-full\"><div class=\"row\"><div class=\"col-md-12 space-3\">")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
@ -54,4 +67,30 @@ func renderCard(attrs templ.Attributes) templ.Component {
|
||||
})
|
||||
}
|
||||
|
||||
func ProfileCard() templ.Component {
|
||||
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
||||
if !templ_7745c5c3_IsBuffer {
|
||||
defer func() {
|
||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err == nil {
|
||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
||||
}
|
||||
}()
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
templ_7745c5c3_Var3 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var3 == nil {
|
||||
templ_7745c5c3_Var3 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div class=\"relative max-w-sm overflow-hidden bg-white border rounded-lg shadow-sm border-neutral-200/60\"><img src=\"https://cdn.devdojo.com/images/august2023/wallpaper.jpeg\" class=\"relative z-20 object-cover w-full h-32\"><div class=\"absolute top-0 z-50 flex items-center w-full mt-2 translate-y-24 px-7 -translate-x-0\"><div class=\"w-20 h-20 p-1 bg-white rounded-full\"><img src=\"https://cdn.devdojo.com/images/august2023/adam.jpeg\" class=\"w-full h-full rounded-full\"></div><a href=\"https://twitter.com/adamwathan\" target=\"_blank\" class=\"block mt-6 ml-2\"><h5 class=\"text-lg font-bold leading-none tracking-tight text-neutral-900\">Adam Wathan</h5><small class=\"block mt-1 text-sm font-medium leading-none text-neutral-500\">adamwathan</small></a> <button class=\"absolute right-0 inline-flex items-center justify-center w-auto px-5 mt-6 text-sm font-medium transition-colors duration-100 rounded-full h-9 mr-7 hover:text-white focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:opacity-50 bg-neutral-900 disabled:pointer-events-none hover:bg-neutral-800 text-neutral-100\"><span>Follow</span></button></div><div class=\"relative pb-6 p-7\"><p class=\"mt-12 mb-6 text-neutral-500 text-\">Creator of @tailwindcss. Listener of Slayer. Austin 3:16. BTW, Pines UI is super cool!</p><div class=\"flex items-center justify-between pr-2 text-neutral-500\"><div class=\"relative flex w-16\"><img src=\"https://cdn.devdojo.com/images/august2023/caleb.jpeg\" class=\"relative z-30 w-8 h-8 border-2 border-white rounded-full\"> <img src=\"https://cdn.devdojo.com/images/august2023/taylor.jpeg\" class=\"z-20 w-8 h-8 -translate-x-4 border-2 border-white rounded-full\"> <img src=\"https://cdn.devdojo.com/images/august2023/adam.jpeg\" class=\"z-10 w-8 h-8 border-2 border-white rounded-full -translate-x-7\"></div><a href=\"https://twitter.com/adamwathan/following\" target=\"_blank\" class=\"text-sm hover:underline\"><strong class=\"text-neutral-800\">673</strong> Following</a> <a href=\"https://twitter.com/adamwathan/followers\" target=\"_blank\" class=\"text-sm hover:underline\"><strong class=\"text-neutral-800\">168.6K</strong> Followers</a></div></div></div>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
}
|
||||
|
||||
var _ = templruntime.GeneratedTemplate
|
||||
|
@ -35,3 +35,13 @@ func clsxMerge(variants ...Variant) templ.Attributes {
|
||||
}
|
||||
return combinedAttrs
|
||||
}
|
||||
|
||||
func clsxBuilder(classes ...string) templ.Attributes {
|
||||
if len(classes) == 0 {
|
||||
return templ.Attributes{}
|
||||
}
|
||||
class := strings.Join(classes, " ")
|
||||
return templ.Attributes{
|
||||
"class": class,
|
||||
}
|
||||
}
|
62
internal/gui/elements/fonts.templ
Normal file
62
internal/gui/elements/fonts.templ
Normal file
@ -0,0 +1,62 @@
|
||||
package elements
|
||||
|
||||
func H1(content string) templ.Component {
|
||||
return renderText(1, content)
|
||||
}
|
||||
|
||||
func H2(content string) templ.Component {
|
||||
return renderText(2, content)
|
||||
}
|
||||
|
||||
func H3(content string) templ.Component {
|
||||
return renderText(3, content)
|
||||
}
|
||||
|
||||
func Text(content string) templ.Component {
|
||||
return renderText(0, content)
|
||||
}
|
||||
|
||||
templ renderText(level int, text string) {
|
||||
switch level {
|
||||
case 1:
|
||||
<h1 class="text-2xl lg:text-3xl font-bold">
|
||||
{ text }
|
||||
</h1>
|
||||
case 2:
|
||||
<h2 class="text-xl lg:text-2xl font-bold">
|
||||
{ text }
|
||||
</h2>
|
||||
case 3:
|
||||
<h3 class="text-md lg:text-xl font-semibold">
|
||||
{ text }
|
||||
</h3>
|
||||
default:
|
||||
<p class="text-base font-normal">
|
||||
{ text }
|
||||
</p>
|
||||
}
|
||||
}
|
||||
|
||||
templ renderLink(attrs templ.Attributes, text string) {
|
||||
<a { attrs... }>
|
||||
{ text }
|
||||
</a>
|
||||
}
|
||||
|
||||
templ renderStrong(attrs templ.Attributes, text string) {
|
||||
<strong { attrs... }>
|
||||
{ text }
|
||||
</strong>
|
||||
}
|
||||
|
||||
templ renderEmphasis(attrs templ.Attributes, text string) {
|
||||
<em { attrs... }>
|
||||
{ text }
|
||||
</em>
|
||||
}
|
||||
|
||||
templ renderCode(attrs templ.Attributes, text string) {
|
||||
<code { attrs... }>
|
||||
{ text }
|
||||
</code>
|
||||
}
|
@ -8,28 +8,23 @@ package elements
|
||||
import "github.com/a-h/templ"
|
||||
import templruntime "github.com/a-h/templ/runtime"
|
||||
|
||||
import "fmt"
|
||||
|
||||
func Text(content string, options ...Variant) templ.Component {
|
||||
if err := ValidTextVariants(options...); err != nil {
|
||||
return renderParagraph(clsxMerge(TextSizeDefault, TextStyleDefault), content)
|
||||
}
|
||||
return renderParagraph(clsxMerge(options...), content)
|
||||
func H1(content string) templ.Component {
|
||||
return renderText(1, content)
|
||||
}
|
||||
|
||||
func ValidTextVariants(variants ...Variant) error {
|
||||
for _, v := range variants {
|
||||
switch v.(type) {
|
||||
case TextSize:
|
||||
case TextStyle:
|
||||
default:
|
||||
return fmt.Errorf("invalid text variant: %v", v)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
func H2(content string) templ.Component {
|
||||
return renderText(2, content)
|
||||
}
|
||||
|
||||
func renderHeading(attrs templ.Attributes, text string) templ.Component {
|
||||
func H3(content string) templ.Component {
|
||||
return renderText(3, content)
|
||||
}
|
||||
|
||||
func Text(content string) templ.Component {
|
||||
return renderText(0, content)
|
||||
}
|
||||
|
||||
func renderText(level int, text string) templ.Component {
|
||||
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
||||
@ -47,77 +42,79 @@ func renderHeading(attrs templ.Attributes, text string) templ.Component {
|
||||
templ_7745c5c3_Var1 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<h1")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templ.RenderAttributes(ctx, templ_7745c5c3_Buffer, attrs)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(">")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var2 string
|
||||
templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs(text)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/gui/elements/text.templ`, Line: 26, Col: 8}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var2))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</h1>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
}
|
||||
|
||||
func renderParagraph(attrs templ.Attributes, text string) templ.Component {
|
||||
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
||||
if !templ_7745c5c3_IsBuffer {
|
||||
defer func() {
|
||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err == nil {
|
||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
||||
}
|
||||
}()
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
templ_7745c5c3_Var3 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var3 == nil {
|
||||
templ_7745c5c3_Var3 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<p")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templ.RenderAttributes(ctx, templ_7745c5c3_Buffer, attrs)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(">")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var4 string
|
||||
templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(text)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/gui/elements/text.templ`, Line: 32, Col: 8}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</p>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
switch level {
|
||||
case 1:
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<h1 class=\"text-2xl lg:text-3xl font-bold\">")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var2 string
|
||||
templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs(text)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/gui/elements/fonts.templ`, Line: 23, Col: 10}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var2))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</h1>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
case 2:
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<h2 class=\"text-xl lg:text-2xl font-bold\">")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var3 string
|
||||
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(text)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/gui/elements/fonts.templ`, Line: 27, Col: 10}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</h2>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
case 3:
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<h3 class=\"text-md lg:text-xl font-semibold\">")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var4 string
|
||||
templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(text)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/gui/elements/fonts.templ`, Line: 31, Col: 10}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</h3>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
default:
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<p class=\"text-base font-normal\">")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var5 string
|
||||
templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(text)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/gui/elements/fonts.templ`, Line: 35, Col: 10}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</p>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
@ -136,9 +133,9 @@ func renderLink(attrs templ.Attributes, text string) templ.Component {
|
||||
}()
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
templ_7745c5c3_Var5 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var5 == nil {
|
||||
templ_7745c5c3_Var5 = templ.NopComponent
|
||||
templ_7745c5c3_Var6 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var6 == nil {
|
||||
templ_7745c5c3_Var6 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<a")
|
||||
@ -153,12 +150,12 @@ func renderLink(attrs templ.Attributes, text string) templ.Component {
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var6 string
|
||||
templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(text)
|
||||
var templ_7745c5c3_Var7 string
|
||||
templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(text)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/gui/elements/text.templ`, Line: 38, Col: 8}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/gui/elements/fonts.templ`, Line: 42, Col: 8}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6))
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
@ -183,9 +180,9 @@ func renderStrong(attrs templ.Attributes, text string) templ.Component {
|
||||
}()
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
templ_7745c5c3_Var7 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var7 == nil {
|
||||
templ_7745c5c3_Var7 = templ.NopComponent
|
||||
templ_7745c5c3_Var8 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var8 == nil {
|
||||
templ_7745c5c3_Var8 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<strong")
|
||||
@ -200,12 +197,12 @@ func renderStrong(attrs templ.Attributes, text string) templ.Component {
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var8 string
|
||||
templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(text)
|
||||
var templ_7745c5c3_Var9 string
|
||||
templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinStringErrs(text)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/gui/elements/text.templ`, Line: 44, Col: 8}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/gui/elements/fonts.templ`, Line: 48, Col: 8}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8))
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var9))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
@ -230,9 +227,9 @@ func renderEmphasis(attrs templ.Attributes, text string) templ.Component {
|
||||
}()
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
templ_7745c5c3_Var9 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var9 == nil {
|
||||
templ_7745c5c3_Var9 = templ.NopComponent
|
||||
templ_7745c5c3_Var10 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var10 == nil {
|
||||
templ_7745c5c3_Var10 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<em")
|
||||
@ -247,12 +244,12 @@ func renderEmphasis(attrs templ.Attributes, text string) templ.Component {
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var10 string
|
||||
templ_7745c5c3_Var10, templ_7745c5c3_Err = templ.JoinStringErrs(text)
|
||||
var templ_7745c5c3_Var11 string
|
||||
templ_7745c5c3_Var11, templ_7745c5c3_Err = templ.JoinStringErrs(text)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/gui/elements/text.templ`, Line: 50, Col: 8}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/gui/elements/fonts.templ`, Line: 54, Col: 8}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var10))
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var11))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
@ -277,9 +274,9 @@ func renderCode(attrs templ.Attributes, text string) templ.Component {
|
||||
}()
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
templ_7745c5c3_Var11 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var11 == nil {
|
||||
templ_7745c5c3_Var11 = templ.NopComponent
|
||||
templ_7745c5c3_Var12 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var12 == nil {
|
||||
templ_7745c5c3_Var12 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<code")
|
||||
@ -294,12 +291,12 @@ func renderCode(attrs templ.Attributes, text string) templ.Component {
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var12 string
|
||||
templ_7745c5c3_Var12, templ_7745c5c3_Err = templ.JoinStringErrs(text)
|
||||
var templ_7745c5c3_Var13 string
|
||||
templ_7745c5c3_Var13, templ_7745c5c3_Err = templ.JoinStringErrs(text)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/gui/elements/text.templ`, Line: 56, Col: 8}
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/gui/elements/fonts.templ`, Line: 60, Col: 8}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var12))
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var13))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
@ -311,70 +308,4 @@ func renderCode(attrs templ.Attributes, text string) templ.Component {
|
||||
})
|
||||
}
|
||||
|
||||
type TextSize int
|
||||
|
||||
const (
|
||||
TextSizeDefault TextSize = iota
|
||||
TextSizeSmall
|
||||
TextSizeMedium
|
||||
TextSizeLarge
|
||||
)
|
||||
|
||||
func (s TextSize) Attributes() templ.Attributes {
|
||||
switch s {
|
||||
case TextSizeSmall:
|
||||
return templ.Attributes{
|
||||
"class": "text-sm",
|
||||
}
|
||||
case TextSizeLarge:
|
||||
return templ.Attributes{
|
||||
"class": "text-xl",
|
||||
}
|
||||
}
|
||||
return templ.Attributes{
|
||||
"class": "text-md",
|
||||
}
|
||||
}
|
||||
|
||||
type TextStyle int
|
||||
|
||||
const (
|
||||
TextStyleDefault TextStyle = iota
|
||||
TextStyleHeading
|
||||
TextStyleParagraph
|
||||
TextStyleLink
|
||||
TextStyleStrong
|
||||
TextStyleEmphasis
|
||||
TextStyleCode
|
||||
)
|
||||
|
||||
func (s TextStyle) Attributes() templ.Attributes {
|
||||
switch s {
|
||||
case TextStyleHeading:
|
||||
return templ.Attributes{
|
||||
"class": "text-xl font-bold text-xl",
|
||||
}
|
||||
case TextStyleParagraph:
|
||||
return templ.Attributes{
|
||||
"class": "text-base font-normal",
|
||||
}
|
||||
case TextStyleLink:
|
||||
return templ.Attributes{
|
||||
"class": "text-blue-600 font-medium underline",
|
||||
}
|
||||
case TextStyleStrong:
|
||||
return templ.Attributes{
|
||||
"class": "font-semibold text-md",
|
||||
}
|
||||
case TextStyleCode:
|
||||
return templ.Attributes{
|
||||
"class": "text-stone-800 font-mono",
|
||||
}
|
||||
default:
|
||||
return templ.Attributes{
|
||||
"class": "text-base font-normal text-md",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var _ = templruntime.GeneratedTemplate
|
@ -7,11 +7,9 @@ templ Layout(title string) {
|
||||
@defaultStyles()
|
||||
<title>{ title }</title>
|
||||
</head>
|
||||
<body class="flex items-center justify-center h-full bg-gray-50 lg:p-24">
|
||||
<main class="flex items-center justify-center w-full max-w-full">
|
||||
<div id="view">
|
||||
{ children... }
|
||||
</div>
|
||||
<body class="flex items-center justify-center h-full bg-neutral-50 lg:p-24 md:16 p-4">
|
||||
<main class="flex-row items-center justify-center mx-auto w-fit max-w-screen-sm gap-y-3">
|
||||
{ children... }
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
@ -31,7 +29,26 @@ templ defaultStyles() {
|
||||
<meta charset="UTF-8"/>
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
||||
<style>[x-cloak]{display:none}</style>
|
||||
<script src="https://unpkg.com/alpinejs" defer></script>
|
||||
<script src="https://cdn.sonr.io/js/htmx.min.js"></script>
|
||||
<link href="https://cdn.sonr.io/stylesheet.css" rel="stylesheet"/>
|
||||
<script src="https://cdn.tailwindcss.com"></script>
|
||||
<script src="https://unpkg.com/alpinejs" defer></script>
|
||||
<style>[x-cloak]{display:none}</style>
|
||||
<style>font-family: R-Flex, system-ui, Inter, Helvetica, Arial, sans-serif;</style>
|
||||
}
|
||||
|
||||
templ Rows() {
|
||||
<div class="flex flex-row w-full gap-2 md:gap-4">
|
||||
{ children... }
|
||||
</div>
|
||||
}
|
||||
|
||||
templ Columns() {
|
||||
<div class="flex flex-col h-full w-full gap-3 md:gap-6 md:flex-row">
|
||||
{ children... }
|
||||
</div>
|
||||
}
|
||||
|
||||
css main() {
|
||||
font-family: R-Flex, system-ui, Avenir, Helvetica, Arial, sans-serif;
|
||||
}
|
||||
|
@ -47,7 +47,7 @@ func Layout(title string) templ.Component {
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</title></head><body class=\"flex items-center justify-center h-full bg-gray-50 lg:p-24\"><main class=\"flex items-center justify-center w-full max-w-full\"><div id=\"view\">")
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</title></head><body class=\"flex items-center justify-center h-full bg-neutral-50 lg:p-24 md:16 p-4\"><main class=\"flex-row items-center justify-center mx-auto w-fit max-w-screen-sm gap-y-3\">")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
@ -55,7 +55,7 @@ func Layout(title string) templ.Component {
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div></main></body></html>")
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</main></body></html>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
@ -133,7 +133,7 @@ func defaultStyles() templ.Component {
|
||||
templ_7745c5c3_Var5 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<meta charset=\"UTF-8\"><meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\"><meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"><style>[x-cloak]{display:none}</style><script src=\"https://unpkg.com/alpinejs\" defer></script><script src=\"https://cdn.tailwindcss.com\"></script>")
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<meta charset=\"UTF-8\"><meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\"><meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"><script src=\"https://cdn.sonr.io/js/htmx.min.js\"></script><link href=\"https://cdn.sonr.io/stylesheet.css\" rel=\"stylesheet\"><script src=\"https://cdn.tailwindcss.com\"></script><script src=\"https://unpkg.com/alpinejs\" defer></script><style>[x-cloak]{display:none}</style><style>font-family: R-Flex, system-ui, Inter, Helvetica, Arial, sans-serif;</style>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
@ -141,4 +141,82 @@ func defaultStyles() templ.Component {
|
||||
})
|
||||
}
|
||||
|
||||
func Rows() templ.Component {
|
||||
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
||||
if !templ_7745c5c3_IsBuffer {
|
||||
defer func() {
|
||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err == nil {
|
||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
||||
}
|
||||
}()
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
templ_7745c5c3_Var6 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var6 == nil {
|
||||
templ_7745c5c3_Var6 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div class=\"flex flex-row w-full gap-2 md:gap-4\">")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templ_7745c5c3_Var6.Render(ctx, templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
}
|
||||
|
||||
func Columns() templ.Component {
|
||||
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
||||
if !templ_7745c5c3_IsBuffer {
|
||||
defer func() {
|
||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err == nil {
|
||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
||||
}
|
||||
}()
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
templ_7745c5c3_Var7 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var7 == nil {
|
||||
templ_7745c5c3_Var7 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div class=\"flex flex-col h-full w-full gap-3 md:gap-6 md:flex-row\">")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templ_7745c5c3_Var7.Render(ctx, templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
}
|
||||
|
||||
func main() templ.CSSClass {
|
||||
templ_7745c5c3_CSSBuilder := templruntime.GetBuilder()
|
||||
templ_7745c5c3_CSSBuilder.WriteString(`font-family:R-Flex, system-ui, Avenir, Helvetica, Arial, sans-serif;`)
|
||||
templ_7745c5c3_CSSID := templ.CSSID(`main`, templ_7745c5c3_CSSBuilder.String())
|
||||
return templ.ComponentCSSClass{
|
||||
ID: templ_7745c5c3_CSSID,
|
||||
Class: templ.SafeCSS(`.` + templ_7745c5c3_CSSID + `{` + templ_7745c5c3_CSSBuilder.String() + `}`),
|
||||
}
|
||||
}
|
||||
|
||||
var _ = templruntime.GeneratedTemplate
|
||||
|
@ -26,3 +26,6 @@ templ renderIconVariant(v Icons) {
|
||||
}
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-chevron-right"><polyline points="9 18 15 12 9 6"></polyline></svg>
|
||||
}
|
||||
|
||||
templ SonrIcon() {
|
||||
}
|
||||
|
@ -69,4 +69,26 @@ func renderIconVariant(v Icons) templ.Component {
|
||||
})
|
||||
}
|
||||
|
||||
func SonrIcon() templ.Component {
|
||||
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
||||
if !templ_7745c5c3_IsBuffer {
|
||||
defer func() {
|
||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err == nil {
|
||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
||||
}
|
||||
}()
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
templ_7745c5c3_Var2 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var2 == nil {
|
||||
templ_7745c5c3_Var2 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
}
|
||||
|
||||
var _ = templruntime.GeneratedTemplate
|
||||
|
29
internal/gui/elements/inputs.templ
Normal file
29
internal/gui/elements/inputs.templ
Normal file
@ -0,0 +1,29 @@
|
||||
package elements
|
||||
|
||||
type InputState int
|
||||
|
||||
const (
|
||||
InputStateDefault InputState = iota
|
||||
InputStateError
|
||||
InputStateSuccess
|
||||
)
|
||||
|
||||
templ TextInput(state InputState, label string, placeholder string) {
|
||||
switch (state) {
|
||||
case InputStateDefault:
|
||||
<div class="flex flex-col space-y-1.5 p-6">
|
||||
<label class="text-xs font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70" for="name">{ label }</label>
|
||||
<input type="text" placeholder="{label}" id="name" value="{value}" class="flex w-full h-10 px-3 py-2 text-sm bg-white border rounded-md peer border-neutral-300 ring-offset-background placeholder:text-neutral-400 focus:border-neutral-300 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-neutral-400 disabled:cursor-not-allowed disabled:opacity-50"/>
|
||||
</div>
|
||||
case InputStateError:
|
||||
<div class="flex flex-col space-y-1.5 p-6">
|
||||
<label class="text-xs font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70" for="name">{ label }</label>
|
||||
<input type="text" placeholder="{label}" id="name" value="{value}" class="flex w-full h-10 px-3 py-2 text-sm bg-white border rounded-md peer border-neutral-300 ring-offset-background placeholder:text-neutral-400 focus:border-neutral-300 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-neutral-400 disabled:cursor-not-allowed disabled:opacity-50"/>
|
||||
</div>
|
||||
case InputStateSuccess:
|
||||
<div class="flex flex-col space-y-1.5 p-6">
|
||||
<label class="text-xs font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70" for="name">{ label }</label>
|
||||
<input type="text" placeholder="{label}" id="name" value="{value}" class="flex w-full h-10 px-3 py-2 text-sm bg-white border rounded-md peer border-neutral-300 ring-offset-background placeholder:text-neutral-400 focus:border-neutral-300 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-neutral-400 disabled:cursor-not-allowed disabled:opacity-50"/>
|
||||
</div>
|
||||
}
|
||||
}
|
97
internal/gui/elements/inputs_templ.go
Normal file
97
internal/gui/elements/inputs_templ.go
Normal file
@ -0,0 +1,97 @@
|
||||
// Code generated by templ - DO NOT EDIT.
|
||||
|
||||
// templ: version: v0.2.771
|
||||
package elements
|
||||
|
||||
//lint:file-ignore SA4006 This context is only used if a nested component is present.
|
||||
|
||||
import "github.com/a-h/templ"
|
||||
import templruntime "github.com/a-h/templ/runtime"
|
||||
|
||||
type InputState int
|
||||
|
||||
const (
|
||||
InputStateDefault InputState = iota
|
||||
InputStateError
|
||||
InputStateSuccess
|
||||
)
|
||||
|
||||
func TextInput(state InputState, label string, placeholder string) templ.Component {
|
||||
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
||||
if !templ_7745c5c3_IsBuffer {
|
||||
defer func() {
|
||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err == nil {
|
||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
||||
}
|
||||
}()
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var1 == nil {
|
||||
templ_7745c5c3_Var1 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
switch state {
|
||||
case InputStateDefault:
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div class=\"flex flex-col space-y-1.5 p-6\"><label class=\"text-xs font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70\" for=\"name\">")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var2 string
|
||||
templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs(label)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/gui/elements/inputs.templ`, Line: 15, Col: 128}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var2))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</label> <input type=\"text\" placeholder=\"{label}\" id=\"name\" value=\"{value}\" class=\"flex w-full h-10 px-3 py-2 text-sm bg-white border rounded-md peer border-neutral-300 ring-offset-background placeholder:text-neutral-400 focus:border-neutral-300 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-neutral-400 disabled:cursor-not-allowed disabled:opacity-50\"></div>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
case InputStateError:
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div class=\"flex flex-col space-y-1.5 p-6\"><label class=\"text-xs font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70\" for=\"name\">")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var3 string
|
||||
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(label)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/gui/elements/inputs.templ`, Line: 20, Col: 128}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</label> <input type=\"text\" placeholder=\"{label}\" id=\"name\" value=\"{value}\" class=\"flex w-full h-10 px-3 py-2 text-sm bg-white border rounded-md peer border-neutral-300 ring-offset-background placeholder:text-neutral-400 focus:border-neutral-300 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-neutral-400 disabled:cursor-not-allowed disabled:opacity-50\"></div>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
case InputStateSuccess:
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div class=\"flex flex-col space-y-1.5 p-6\"><label class=\"text-xs font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70\" for=\"name\">")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var4 string
|
||||
templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(label)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/gui/elements/inputs.templ`, Line: 25, Col: 128}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</label> <input type=\"text\" placeholder=\"{label}\" id=\"name\" value=\"{value}\" class=\"flex w-full h-10 px-3 py-2 text-sm bg-white border rounded-md peer border-neutral-300 ring-offset-background placeholder:text-neutral-400 focus:border-neutral-300 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-neutral-400 disabled:cursor-not-allowed disabled:opacity-50\"></div>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
}
|
||||
|
||||
var _ = templruntime.GeneratedTemplate
|
37
internal/gui/elements/radios.templ
Normal file
37
internal/gui/elements/radios.templ
Normal file
@ -0,0 +1,37 @@
|
||||
package elements
|
||||
|
||||
templ RadioGroup() {
|
||||
<div
|
||||
x-data="{
|
||||
radioGroupSelectedValue: null,
|
||||
radioGroupOptions: [
|
||||
{
|
||||
title: 'Email Address',
|
||||
description: 'Get a login code to your email address.',
|
||||
value: 'email'
|
||||
},
|
||||
{
|
||||
title: 'Phone Number',
|
||||
description: 'Get a login code to your phone number.',
|
||||
value: 'phone'
|
||||
},
|
||||
{
|
||||
title: 'Passkey',
|
||||
description: 'Sign in with your passkey.',
|
||||
value: 'passkey'
|
||||
}
|
||||
]
|
||||
}"
|
||||
class="space-y-3"
|
||||
>
|
||||
<template x-for="(option, index) in radioGroupOptions" :key="index">
|
||||
<label @click="radioGroupSelectedValue=option.value" class="flex items-start p-5 space-x-3 bg-white border rounded-md shadow-sm hover:bg-gray-50 border-neutral-200/70">
|
||||
<input type="radio" name="radio-group" :value="option.value" class="text-gray-900 translate-y-px focus:ring-gray-700"/>
|
||||
<span class="relative flex flex-col text-left space-y-1.5 leading-none">
|
||||
<span x-text="option.title" class="font-semibold"></span>
|
||||
<span x-text="option.description" class="text-sm opacity-50"></span>
|
||||
</span>
|
||||
</label>
|
||||
</template>
|
||||
</div>
|
||||
}
|
37
internal/gui/elements/radios_templ.go
Normal file
37
internal/gui/elements/radios_templ.go
Normal file
@ -0,0 +1,37 @@
|
||||
// Code generated by templ - DO NOT EDIT.
|
||||
|
||||
// templ: version: v0.2.771
|
||||
package elements
|
||||
|
||||
//lint:file-ignore SA4006 This context is only used if a nested component is present.
|
||||
|
||||
import "github.com/a-h/templ"
|
||||
import templruntime "github.com/a-h/templ/runtime"
|
||||
|
||||
func RadioGroup() templ.Component {
|
||||
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
||||
if !templ_7745c5c3_IsBuffer {
|
||||
defer func() {
|
||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err == nil {
|
||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
||||
}
|
||||
}()
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var1 == nil {
|
||||
templ_7745c5c3_Var1 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div x-data=\"{\n radioGroupSelectedValue: null,\n radioGroupOptions: [\n {\n title: 'Email Address',\n description: 'Get a login code to your email address.',\n value: 'email'\n },\n {\n title: 'Phone Number',\n description: 'Get a login code to your phone number.',\n value: 'phone'\n },\n {\n title: 'Passkey',\n description: 'Sign in with your passkey.',\n value: 'passkey'\n }\n ]\n}\" class=\"space-y-3\"><template x-for=\"(option, index) in radioGroupOptions\" :key=\"index\"><label @click=\"radioGroupSelectedValue=option.value\" class=\"flex items-start p-5 space-x-3 bg-white border rounded-md shadow-sm hover:bg-gray-50 border-neutral-200/70\"><input type=\"radio\" name=\"radio-group\" :value=\"option.value\" class=\"text-gray-900 translate-y-px focus:ring-gray-700\"> <span class=\"relative flex flex-col text-left space-y-1.5 leading-none\"><span x-text=\"option.title\" class=\"font-semibold\"></span> <span x-text=\"option.description\" class=\"text-sm opacity-50\"></span></span></label></template></div>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
}
|
||||
|
||||
var _ = templruntime.GeneratedTemplate
|
@ -13,15 +13,15 @@ func (s Size) CardAttributes() templ.Attributes {
|
||||
switch s {
|
||||
case SizeSmall:
|
||||
return templ.Attributes{
|
||||
"class": "max-w-md bg-white border rounded-lg shadow-sm p-7 border-neutral-200/60",
|
||||
"class": "max-w-lg bg-white border rounded-lg shadow-sm p-7 border-neutral-200/60",
|
||||
}
|
||||
case SizeLarge:
|
||||
return templ.Attributes{
|
||||
"class": "max-w-xl bg-white border rounded-lg shadow-sm p-7 border-neutral-200/60",
|
||||
"class": "max-w-2xl bg-white border rounded-lg shadow-sm p-7 border-neutral-200/60",
|
||||
}
|
||||
}
|
||||
return templ.Attributes{
|
||||
"class": "max-w-lg bg-white border rounded-lg shadow-sm p-7 border-neutral-200/60",
|
||||
"class": "max-w-xl bg-white border rounded-lg shadow-sm p-7 border-neutral-200/60",
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -21,15 +21,15 @@ func (s Size) CardAttributes() templ.Attributes {
|
||||
switch s {
|
||||
case SizeSmall:
|
||||
return templ.Attributes{
|
||||
"class": "max-w-md bg-white border rounded-lg shadow-sm p-7 border-neutral-200/60",
|
||||
"class": "max-w-lg bg-white border rounded-lg shadow-sm p-7 border-neutral-200/60",
|
||||
}
|
||||
case SizeLarge:
|
||||
return templ.Attributes{
|
||||
"class": "max-w-xl bg-white border rounded-lg shadow-sm p-7 border-neutral-200/60",
|
||||
"class": "max-w-2xl bg-white border rounded-lg shadow-sm p-7 border-neutral-200/60",
|
||||
}
|
||||
}
|
||||
return templ.Attributes{
|
||||
"class": "max-w-lg bg-white border rounded-lg shadow-sm p-7 border-neutral-200/60",
|
||||
"class": "max-w-xl bg-white border rounded-lg shadow-sm p-7 border-neutral-200/60",
|
||||
}
|
||||
}
|
||||
|
||||
|
109
internal/gui/elements/tabs.templ
Normal file
109
internal/gui/elements/tabs.templ
Normal file
@ -0,0 +1,109 @@
|
||||
package elements
|
||||
|
||||
templ Tabs() {
|
||||
<div
|
||||
x-data="{
|
||||
tabSelected: 1,
|
||||
tabId: $id('tabs'),
|
||||
tabButtonClicked(tabButton){
|
||||
this.tabSelected = tabButton.id.replace(this.tabId + '-', '');
|
||||
this.tabRepositionMarker(tabButton);
|
||||
},
|
||||
tabRepositionMarker(tabButton){
|
||||
this.$refs.tabMarker.style.width=tabButton.offsetWidth + 'px';
|
||||
this.$refs.tabMarker.style.height=tabButton.offsetHeight + 'px';
|
||||
this.$refs.tabMarker.style.left=tabButton.offsetLeft + 'px';
|
||||
},
|
||||
tabContentActive(tabContent){
|
||||
return this.tabSelected == tabContent.id.replace(this.tabId + '-content-', '');
|
||||
},
|
||||
tabButtonActive(tabContent){
|
||||
const tabId = tabContent.id.split('-').slice(-1);
|
||||
return this.tabSelected == tabId;
|
||||
}
|
||||
}"
|
||||
x-init="tabRepositionMarker($refs.tabButtons.firstElementChild);"
|
||||
class="relative w-full max-w-sm"
|
||||
>
|
||||
<div x-ref="tabButtons" class="relative inline-grid items-center justify-center w-full h-10 grid-cols-3 p-1 text-gray-500 bg-white border border-gray-100 rounded-lg select-none">
|
||||
<button :id="$id(tabId)" @click="tabButtonClicked($el);" type="button" :class="{ 'bg-gray-100 text-gray-700' : tabButtonActive($el) }" class="relative z-20 inline-flex items-center justify-center w-full h-8 px-3 text-sm font-medium transition-all rounded-md cursor-pointer whitespace-nowrap">Tab1</button>
|
||||
<button :id="$id(tabId)" @click="tabButtonClicked($el);" type="button" :class="{ 'bg-gray-100 text-gray-700' : tabButtonActive($el) }" class="relative z-20 inline-flex items-center justify-center w-full h-8 px-3 text-sm font-medium transition-all rounded-md cursor-pointer whitespace-nowrap">Tab2</button>
|
||||
<button :id="$id(tabId)" @click="tabButtonClicked($el);" type="button" :class="{ 'bg-gray-100 text-gray-700' : tabButtonActive($el) }" class="relative z-20 inline-flex items-center justify-center w-full h-8 px-3 text-sm font-medium transition-all rounded-md cursor-pointer whitespace-nowrap">Tab3</button>
|
||||
<div x-ref="tabMarker" class="absolute left-0 z-10 w-1/2 h-full duration-300 ease-out" x-cloak><div class="w-full h-full bg-gray-100 rounded-md shadow-sm"></div></div>
|
||||
</div>
|
||||
<div class="relative flex items-center justify-center w-full p-5 mt-2 text-xs text-gray-400 border rounded-md content border-gray-200/70">
|
||||
<div :id="$id(tabId + '-content')" x-show="tabContentActive($el)" class="relative">
|
||||
@Table()
|
||||
</div>
|
||||
<div :id="$id(tabId + '-content')" x-show="tabContentActive($el)" class="relative" x-cloak>
|
||||
And, this is the content for Tab2
|
||||
</div>
|
||||
<div :id="$id(tabId + '-content')" x-show="tabContentActive($el)" class="relative" x-cloak>
|
||||
Finally, this is the content for Tab3
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
templ Table() {
|
||||
<div class="flex flex-col">
|
||||
<div class="overflow-x-auto">
|
||||
<div class="inline-block min-w-full">
|
||||
<div class="overflow-hidden">
|
||||
<table class="min-w-full divide-y divide-neutral-200">
|
||||
<thead>
|
||||
<tr class="text-neutral-500">
|
||||
<th class="px-5 py-3 text-xs font-medium text-left uppercase">Name</th>
|
||||
<th class="px-5 py-3 text-xs font-medium text-left uppercase">Age</th>
|
||||
<th class="px-5 py-3 text-xs font-medium text-left uppercase">Address</th>
|
||||
<th class="px-5 py-3 text-xs font-medium text-right uppercase">Action</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="divide-y divide-neutral-200">
|
||||
<tr class="text-neutral-800">
|
||||
<td class="px-5 py-4 text-sm font-medium whitespace-nowrap">Richard Hendricks</td>
|
||||
<td class="px-5 py-4 text-sm whitespace-nowrap">30</td>
|
||||
<td class="px-5 py-4 text-sm whitespace-nowrap">Pied Piper HQ, Palo Alto</td>
|
||||
<td class="px-5 py-4 text-sm font-medium text-right whitespace-nowrap">
|
||||
<a class="text-blue-600 hover:text-blue-700" href="#">Edit</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="text-neutral-800">
|
||||
<td class="px-5 py-4 text-sm font-medium whitespace-nowrap">Erlich Bachman</td>
|
||||
<td class="px-5 py-4 text-sm whitespace-nowrap">40</td>
|
||||
<td class="px-5 py-4 text-sm whitespace-nowrap">5230 Penfield Ave, Woodland Hills</td>
|
||||
<td class="px-5 py-4 text-sm font-medium text-right whitespace-nowrap">
|
||||
<a class="text-blue-600 hover:text-blue-700" href="#">Edit</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="text-neutral-800">
|
||||
<td class="px-5 py-4 text-sm font-medium whitespace-nowrap">Monica Hall</td>
|
||||
<td class="px-5 py-4 text-sm whitespace-nowrap">35</td>
|
||||
<td class="px-5 py-4 text-sm whitespace-nowrap">2030 Stewart Drive, Sunnyvale</td>
|
||||
<td class="px-5 py-4 text-sm font-medium text-right whitespace-nowrap">
|
||||
<a class="text-blue-600 hover:text-blue-700" href="#">Edit</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="text-neutral-800">
|
||||
<td class="px-5 py-4 text-sm font-medium whitespace-nowrap">Dinesh Chugtai</td>
|
||||
<td class="px-5 py-4 text-sm whitespace-nowrap">28</td>
|
||||
<td class="px-5 py-4 text-sm whitespace-nowrap">Pied Piper HQ, Palo Alto</td>
|
||||
<td class="px-5 py-4 text-sm font-medium text-right whitespace-nowrap">
|
||||
<a class="text-blue-600 hover:text-blue-700" href="#">Edit</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="text-neutral-800">
|
||||
<td class="px-5 py-4 text-sm font-medium whitespace-nowrap">Gilfoyle</td>
|
||||
<td class="px-5 py-4 text-sm whitespace-nowrap">32</td>
|
||||
<td class="px-5 py-4 text-sm whitespace-nowrap">Pied Piper HQ, Palo Alto</td>
|
||||
<td class="px-5 py-4 text-sm font-medium text-right whitespace-nowrap">
|
||||
<a class="text-blue-600 hover:text-blue-700" href="#">Edit</a>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
71
internal/gui/elements/tabs_templ.go
Normal file
71
internal/gui/elements/tabs_templ.go
Normal file
@ -0,0 +1,71 @@
|
||||
// Code generated by templ - DO NOT EDIT.
|
||||
|
||||
// templ: version: v0.2.771
|
||||
package elements
|
||||
|
||||
//lint:file-ignore SA4006 This context is only used if a nested component is present.
|
||||
|
||||
import "github.com/a-h/templ"
|
||||
import templruntime "github.com/a-h/templ/runtime"
|
||||
|
||||
func Tabs() templ.Component {
|
||||
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
||||
if !templ_7745c5c3_IsBuffer {
|
||||
defer func() {
|
||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err == nil {
|
||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
||||
}
|
||||
}()
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var1 == nil {
|
||||
templ_7745c5c3_Var1 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div x-data=\"{\n tabSelected: 1,\n tabId: $id('tabs'),\n tabButtonClicked(tabButton){\n this.tabSelected = tabButton.id.replace(this.tabId + '-', '');\n this.tabRepositionMarker(tabButton);\n },\n tabRepositionMarker(tabButton){\n this.$refs.tabMarker.style.width=tabButton.offsetWidth + 'px';\n this.$refs.tabMarker.style.height=tabButton.offsetHeight + 'px';\n this.$refs.tabMarker.style.left=tabButton.offsetLeft + 'px';\n },\n tabContentActive(tabContent){\n return this.tabSelected == tabContent.id.replace(this.tabId + '-content-', '');\n },\n tabButtonActive(tabContent){\n const tabId = tabContent.id.split('-').slice(-1);\n return this.tabSelected == tabId;\n }\n }\" x-init=\"tabRepositionMarker($refs.tabButtons.firstElementChild);\" class=\"relative w-full max-w-sm\"><div x-ref=\"tabButtons\" class=\"relative inline-grid items-center justify-center w-full h-10 grid-cols-3 p-1 text-gray-500 bg-white border border-gray-100 rounded-lg select-none\"><button :id=\"$id(tabId)\" @click=\"tabButtonClicked($el);\" type=\"button\" :class=\"{ 'bg-gray-100 text-gray-700' : tabButtonActive($el) }\" class=\"relative z-20 inline-flex items-center justify-center w-full h-8 px-3 text-sm font-medium transition-all rounded-md cursor-pointer whitespace-nowrap\">Tab1</button> <button :id=\"$id(tabId)\" @click=\"tabButtonClicked($el);\" type=\"button\" :class=\"{ 'bg-gray-100 text-gray-700' : tabButtonActive($el) }\" class=\"relative z-20 inline-flex items-center justify-center w-full h-8 px-3 text-sm font-medium transition-all rounded-md cursor-pointer whitespace-nowrap\">Tab2</button> <button :id=\"$id(tabId)\" @click=\"tabButtonClicked($el);\" type=\"button\" :class=\"{ 'bg-gray-100 text-gray-700' : tabButtonActive($el) }\" class=\"relative z-20 inline-flex items-center justify-center w-full h-8 px-3 text-sm font-medium transition-all rounded-md cursor-pointer whitespace-nowrap\">Tab3</button><div x-ref=\"tabMarker\" class=\"absolute left-0 z-10 w-1/2 h-full duration-300 ease-out\" x-cloak><div class=\"w-full h-full bg-gray-100 rounded-md shadow-sm\"></div></div></div><div class=\"relative flex items-center justify-center w-full p-5 mt-2 text-xs text-gray-400 border rounded-md content border-gray-200/70\"><div :id=\"$id(tabId + '-content')\" x-show=\"tabContentActive($el)\" class=\"relative\">")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = Table().Render(ctx, templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div><div :id=\"$id(tabId + '-content')\" x-show=\"tabContentActive($el)\" class=\"relative\" x-cloak>And, this is the content for Tab2</div><div :id=\"$id(tabId + '-content')\" x-show=\"tabContentActive($el)\" class=\"relative\" x-cloak>Finally, this is the content for Tab3</div></div></div>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
}
|
||||
|
||||
func Table() templ.Component {
|
||||
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
||||
if !templ_7745c5c3_IsBuffer {
|
||||
defer func() {
|
||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err == nil {
|
||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
||||
}
|
||||
}()
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
templ_7745c5c3_Var2 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var2 == nil {
|
||||
templ_7745c5c3_Var2 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div class=\"flex flex-col\"><div class=\"overflow-x-auto\"><div class=\"inline-block min-w-full\"><div class=\"overflow-hidden\"><table class=\"min-w-full divide-y divide-neutral-200\"><thead><tr class=\"text-neutral-500\"><th class=\"px-5 py-3 text-xs font-medium text-left uppercase\">Name</th><th class=\"px-5 py-3 text-xs font-medium text-left uppercase\">Age</th><th class=\"px-5 py-3 text-xs font-medium text-left uppercase\">Address</th><th class=\"px-5 py-3 text-xs font-medium text-right uppercase\">Action</th></tr></thead> <tbody class=\"divide-y divide-neutral-200\"><tr class=\"text-neutral-800\"><td class=\"px-5 py-4 text-sm font-medium whitespace-nowrap\">Richard Hendricks</td><td class=\"px-5 py-4 text-sm whitespace-nowrap\">30</td><td class=\"px-5 py-4 text-sm whitespace-nowrap\">Pied Piper HQ, Palo Alto</td><td class=\"px-5 py-4 text-sm font-medium text-right whitespace-nowrap\"><a class=\"text-blue-600 hover:text-blue-700\" href=\"#\">Edit</a></td></tr><tr class=\"text-neutral-800\"><td class=\"px-5 py-4 text-sm font-medium whitespace-nowrap\">Erlich Bachman</td><td class=\"px-5 py-4 text-sm whitespace-nowrap\">40</td><td class=\"px-5 py-4 text-sm whitespace-nowrap\">5230 Penfield Ave, Woodland Hills</td><td class=\"px-5 py-4 text-sm font-medium text-right whitespace-nowrap\"><a class=\"text-blue-600 hover:text-blue-700\" href=\"#\">Edit</a></td></tr><tr class=\"text-neutral-800\"><td class=\"px-5 py-4 text-sm font-medium whitespace-nowrap\">Monica Hall</td><td class=\"px-5 py-4 text-sm whitespace-nowrap\">35</td><td class=\"px-5 py-4 text-sm whitespace-nowrap\">2030 Stewart Drive, Sunnyvale</td><td class=\"px-5 py-4 text-sm font-medium text-right whitespace-nowrap\"><a class=\"text-blue-600 hover:text-blue-700\" href=\"#\">Edit</a></td></tr><tr class=\"text-neutral-800\"><td class=\"px-5 py-4 text-sm font-medium whitespace-nowrap\">Dinesh Chugtai</td><td class=\"px-5 py-4 text-sm whitespace-nowrap\">28</td><td class=\"px-5 py-4 text-sm whitespace-nowrap\">Pied Piper HQ, Palo Alto</td><td class=\"px-5 py-4 text-sm font-medium text-right whitespace-nowrap\"><a class=\"text-blue-600 hover:text-blue-700\" href=\"#\">Edit</a></td></tr><tr class=\"text-neutral-800\"><td class=\"px-5 py-4 text-sm font-medium whitespace-nowrap\">Gilfoyle</td><td class=\"px-5 py-4 text-sm whitespace-nowrap\">32</td><td class=\"px-5 py-4 text-sm whitespace-nowrap\">Pied Piper HQ, Palo Alto</td><td class=\"px-5 py-4 text-sm font-medium text-right whitespace-nowrap\"><a class=\"text-blue-600 hover:text-blue-700\" href=\"#\">Edit</a></td></tr></tbody></table></div></div></div></div>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
}
|
||||
|
||||
var _ = templruntime.GeneratedTemplate
|
@ -1,124 +0,0 @@
|
||||
package elements
|
||||
|
||||
import "fmt"
|
||||
|
||||
func Text(content string, options ...Variant) templ.Component {
|
||||
if err := ValidTextVariants(options...); err != nil {
|
||||
return renderParagraph(clsxMerge(TextSizeDefault, TextStyleDefault), content)
|
||||
}
|
||||
return renderParagraph(clsxMerge(options...), content)
|
||||
}
|
||||
|
||||
func ValidTextVariants(variants ...Variant) error {
|
||||
for _, v := range variants {
|
||||
switch v.(type) {
|
||||
case TextSize:
|
||||
case TextStyle:
|
||||
default:
|
||||
return fmt.Errorf("invalid text variant: %v", v)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
templ renderHeading(attrs templ.Attributes, text string) {
|
||||
<h1 { attrs... }>
|
||||
{ text }
|
||||
</h1>
|
||||
}
|
||||
|
||||
templ renderParagraph(attrs templ.Attributes, text string) {
|
||||
<p { attrs... }>
|
||||
{ text }
|
||||
</p>
|
||||
}
|
||||
|
||||
templ renderLink(attrs templ.Attributes, text string) {
|
||||
<a { attrs... }>
|
||||
{ text }
|
||||
</a>
|
||||
}
|
||||
|
||||
templ renderStrong(attrs templ.Attributes, text string) {
|
||||
<strong { attrs... }>
|
||||
{ text }
|
||||
</strong>
|
||||
}
|
||||
|
||||
templ renderEmphasis(attrs templ.Attributes, text string) {
|
||||
<em { attrs... }>
|
||||
{ text }
|
||||
</em>
|
||||
}
|
||||
|
||||
templ renderCode(attrs templ.Attributes, text string) {
|
||||
<code { attrs... }>
|
||||
{ text }
|
||||
</code>
|
||||
}
|
||||
|
||||
type TextSize int
|
||||
|
||||
const (
|
||||
TextSizeDefault TextSize = iota
|
||||
TextSizeSmall
|
||||
TextSizeMedium
|
||||
TextSizeLarge
|
||||
)
|
||||
|
||||
func (s TextSize) Attributes() templ.Attributes {
|
||||
switch s {
|
||||
case TextSizeSmall:
|
||||
return templ.Attributes{
|
||||
"class": "text-sm",
|
||||
}
|
||||
case TextSizeLarge:
|
||||
return templ.Attributes{
|
||||
"class": "text-xl",
|
||||
}
|
||||
}
|
||||
return templ.Attributes{
|
||||
"class": "text-md",
|
||||
}
|
||||
}
|
||||
|
||||
type TextStyle int
|
||||
|
||||
const (
|
||||
TextStyleDefault TextStyle = iota
|
||||
TextStyleHeading
|
||||
TextStyleParagraph
|
||||
TextStyleLink
|
||||
TextStyleStrong
|
||||
TextStyleEmphasis
|
||||
TextStyleCode
|
||||
)
|
||||
|
||||
func (s TextStyle) Attributes() templ.Attributes {
|
||||
switch s {
|
||||
case TextStyleHeading:
|
||||
return templ.Attributes{
|
||||
"class": "text-xl font-bold text-xl",
|
||||
}
|
||||
case TextStyleParagraph:
|
||||
return templ.Attributes{
|
||||
"class": "text-base font-normal",
|
||||
}
|
||||
case TextStyleLink:
|
||||
return templ.Attributes{
|
||||
"class": "text-blue-600 font-medium underline",
|
||||
}
|
||||
case TextStyleStrong:
|
||||
return templ.Attributes{
|
||||
"class": "font-semibold text-md",
|
||||
}
|
||||
case TextStyleCode:
|
||||
return templ.Attributes{
|
||||
"class": "text-stone-800 font-mono",
|
||||
}
|
||||
default:
|
||||
return templ.Attributes{
|
||||
"class": "text-base font-normal text-md",
|
||||
}
|
||||
}
|
||||
}
|
41
internal/gui/forms/forms.go
Normal file
41
internal/gui/forms/forms.go
Normal file
@ -0,0 +1,41 @@
|
||||
package forms
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
|
||||
"github.com/a-h/templ"
|
||||
"github.com/labstack/echo/v4"
|
||||
)
|
||||
|
||||
func echoFormResponse(c echo.Context, cmp templ.Component, state FormState) error {
|
||||
// Create a buffer to store the rendered HTML
|
||||
buf := &bytes.Buffer{}
|
||||
// Render the component to the buffer
|
||||
err := cmp.Render(c.Request().Context(), buf)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Set the content type
|
||||
c.Response().Header().Set(echo.HeaderContentType, echo.MIMETextHTML)
|
||||
c.Response().Header().Set("X-Status", string(state))
|
||||
|
||||
// Write the buffered content to the response
|
||||
_, err = c.Response().Write(buf.Bytes())
|
||||
return err
|
||||
}
|
||||
|
||||
type FormState string
|
||||
|
||||
const (
|
||||
InitialForm FormState = "initial"
|
||||
ErrorForm FormState = "error"
|
||||
SuccessForm FormState = "success"
|
||||
WarningForm FormState = "warning"
|
||||
)
|
||||
|
||||
type Form struct {
|
||||
State FormState
|
||||
Title string
|
||||
Description string
|
||||
}
|
25
internal/gui/forms/register.templ
Normal file
25
internal/gui/forms/register.templ
Normal file
@ -0,0 +1,25 @@
|
||||
package forms
|
||||
|
||||
import "github.com/labstack/echo/v4"
|
||||
|
||||
templ BasicInfo(c echo.Context, state FormState) {
|
||||
switch (state) {
|
||||
default:
|
||||
<div class="border rounded-lg shadow-sm bg-card text-neutral-900">
|
||||
<div class="flex flex-col space-y-1.5 p-6">
|
||||
<h3 class="text-lg font-semibold leading-none tracking-tight">Account</h3>
|
||||
<p class="text-sm text-neutral-500">Make changes to your account here. Click save when you're done.</p>
|
||||
</div>
|
||||
<div class="p-6 pt-0 space-y-2">
|
||||
<div class="space-y-1"><label class="text-xs font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70" for="name">Name</label><input type="text" id="name" placeholder="Adam Wathan" class="flex w-full h-10 px-3 py-2 text-sm bg-white border rounded-md peer border-neutral-300 ring-offset-background placeholder:text-neutral-400 focus:border-neutral-300 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-neutral-400 disabled:cursor-not-allowed disabled:opacity-50"/></div>
|
||||
<div class="space-y-1"><label class="text-xs font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70" for="username">Handle</label><input type="text" id="handle" placeholder="angelo.snr" class="flex w-full h-10 px-3 py-2 text-sm bg-white border rounded-md peer border-neutral-300 ring-offset-background placeholder:text-neutral-400 focus:border-neutral-300 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-neutral-400 disabled:cursor-not-allowed disabled:opacity-50"/></div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
|
||||
templ CreateCredentials(state FormState) {
|
||||
}
|
||||
|
||||
templ PrivacyTerms(state FormState) {
|
||||
}
|
86
internal/gui/forms/register_templ.go
Normal file
86
internal/gui/forms/register_templ.go
Normal file
@ -0,0 +1,86 @@
|
||||
// Code generated by templ - DO NOT EDIT.
|
||||
|
||||
// templ: version: v0.2.771
|
||||
package forms
|
||||
|
||||
//lint:file-ignore SA4006 This context is only used if a nested component is present.
|
||||
|
||||
import "github.com/a-h/templ"
|
||||
import templruntime "github.com/a-h/templ/runtime"
|
||||
|
||||
import "github.com/labstack/echo/v4"
|
||||
|
||||
func BasicInfo(c echo.Context, state FormState) templ.Component {
|
||||
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
||||
if !templ_7745c5c3_IsBuffer {
|
||||
defer func() {
|
||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err == nil {
|
||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
||||
}
|
||||
}()
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var1 == nil {
|
||||
templ_7745c5c3_Var1 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
switch state {
|
||||
default:
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div class=\"border rounded-lg shadow-sm bg-card text-neutral-900\"><div class=\"flex flex-col space-y-1.5 p-6\"><h3 class=\"text-lg font-semibold leading-none tracking-tight\">Account</h3><p class=\"text-sm text-neutral-500\">Make changes to your account here. Click save when you're done.</p></div><div class=\"p-6 pt-0 space-y-2\"><div class=\"space-y-1\"><label class=\"text-xs font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70\" for=\"name\">Name</label><input type=\"text\" id=\"name\" placeholder=\"Adam Wathan\" class=\"flex w-full h-10 px-3 py-2 text-sm bg-white border rounded-md peer border-neutral-300 ring-offset-background placeholder:text-neutral-400 focus:border-neutral-300 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-neutral-400 disabled:cursor-not-allowed disabled:opacity-50\"></div><div class=\"space-y-1\"><label class=\"text-xs font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70\" for=\"username\">Handle</label><input type=\"text\" id=\"handle\" placeholder=\"angelo.snr\" class=\"flex w-full h-10 px-3 py-2 text-sm bg-white border rounded-md peer border-neutral-300 ring-offset-background placeholder:text-neutral-400 focus:border-neutral-300 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-neutral-400 disabled:cursor-not-allowed disabled:opacity-50\"></div></div></div>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
}
|
||||
|
||||
func CreateCredentials(state FormState) templ.Component {
|
||||
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
||||
if !templ_7745c5c3_IsBuffer {
|
||||
defer func() {
|
||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err == nil {
|
||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
||||
}
|
||||
}()
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
templ_7745c5c3_Var2 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var2 == nil {
|
||||
templ_7745c5c3_Var2 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
}
|
||||
|
||||
func PrivacyTerms(state FormState) templ.Component {
|
||||
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
||||
if !templ_7745c5c3_IsBuffer {
|
||||
defer func() {
|
||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err == nil {
|
||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
||||
}
|
||||
}()
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
templ_7745c5c3_Var3 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var3 == nil {
|
||||
templ_7745c5c3_Var3 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
}
|
||||
|
||||
var _ = templruntime.GeneratedTemplate
|
@ -11,13 +11,19 @@ func HomeView(c echo.Context) error {
|
||||
|
||||
templ renderHomeView() {
|
||||
@elements.Layout("Sonr.ID") {
|
||||
@elements.Card(elements.SizeMedium) {
|
||||
@elements.Text("Sonr.ID", elements.TextSizeLarge, elements.TextStyleHeading)
|
||||
@elements.Text("Neo-tree is a file manager for NeoFS.", elements.TextSizeMedium, elements.TextStyleParagraph)
|
||||
@elements.Card("home-view", elements.SizeLarge) {
|
||||
@elements.H1("Sonr.ID")
|
||||
@elements.Text("A Decentralized Web Node Client for the Sonr Network.")
|
||||
@elements.Spacer()
|
||||
@elements.Button(elements.ButtonVariantPrimary) {
|
||||
@elements.Text("Get Started", elements.TextSizeMedium, elements.TextStyleParagraph)
|
||||
}
|
||||
<div class="flex flex-col gap-3">
|
||||
@elements.Button(elements.GET("/register", "#home-view"), elements.PrimaryButtonStyle()) {
|
||||
@elements.Text("Get Started")
|
||||
}
|
||||
@elements.Button(elements.GET("/login", "#home-view")) {
|
||||
@elements.Text("Login")
|
||||
}
|
||||
</div>
|
||||
@elements.PoweredBySonr()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -59,7 +59,7 @@ func renderHomeView() templ.Component {
|
||||
}()
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
templ_7745c5c3_Err = elements.Text("Sonr.ID", elements.TextSizeLarge, elements.TextStyleHeading).Render(ctx, templ_7745c5c3_Buffer)
|
||||
templ_7745c5c3_Err = elements.H1("Sonr.ID").Render(ctx, templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
@ -67,7 +67,7 @@ func renderHomeView() templ.Component {
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = elements.Text("Neo-tree is a file manager for NeoFS.", elements.TextSizeMedium, elements.TextStyleParagraph).Render(ctx, templ_7745c5c3_Buffer)
|
||||
templ_7745c5c3_Err = elements.Text("A Decentralized Web Node Client for the Sonr Network.").Render(ctx, templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
@ -79,7 +79,7 @@ func renderHomeView() templ.Component {
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" ")
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" <div class=\"flex flex-col gap-3\">")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
@ -95,19 +95,49 @@ func renderHomeView() templ.Component {
|
||||
}()
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
templ_7745c5c3_Err = elements.Text("Get Started", elements.TextSizeMedium, elements.TextStyleParagraph).Render(ctx, templ_7745c5c3_Buffer)
|
||||
templ_7745c5c3_Err = elements.Text("Get Started").Render(ctx, templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
templ_7745c5c3_Err = elements.Button(elements.ButtonVariantPrimary).Render(templ.WithChildren(ctx, templ_7745c5c3_Var4), templ_7745c5c3_Buffer)
|
||||
templ_7745c5c3_Err = elements.Button(elements.GET("/register", "#home-view"), elements.PrimaryButtonStyle()).Render(templ.WithChildren(ctx, templ_7745c5c3_Var4), templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Var5 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
||||
if !templ_7745c5c3_IsBuffer {
|
||||
defer func() {
|
||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err == nil {
|
||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
||||
}
|
||||
}()
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
templ_7745c5c3_Err = elements.Text("Login").Render(ctx, templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
templ_7745c5c3_Err = elements.Button(elements.GET("/login", "#home-view")).Render(templ.WithChildren(ctx, templ_7745c5c3_Var5), templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = elements.PoweredBySonr().Render(ctx, templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
templ_7745c5c3_Err = elements.Card(elements.SizeMedium).Render(templ.WithChildren(ctx, templ_7745c5c3_Var3), templ_7745c5c3_Buffer)
|
||||
templ_7745c5c3_Err = elements.Card("home-view", elements.SizeLarge).Render(templ.WithChildren(ctx, templ_7745c5c3_Var3), templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
|
@ -10,13 +10,15 @@ func LoginView(c echo.Context) error {
|
||||
}
|
||||
|
||||
templ renderLoginView() {
|
||||
@elements.Layout("Sonr.ID") {
|
||||
@elements.Card(elements.SizeMedium) {
|
||||
@elements.Text("Sonr.ID", elements.TextSizeLarge, elements.TextStyleHeading)
|
||||
@elements.Text("Neo-tree is a file manager for NeoFS.", elements.TextSizeMedium, elements.TextStyleParagraph)
|
||||
@elements.Layout("Login | Sonr.ID") {
|
||||
@elements.Card("login-view", elements.SizeLarge) {
|
||||
@elements.H1("Sonr.ID")
|
||||
@elements.Text("Neo-tree is a file manager for NeoFS.")
|
||||
@elements.Spacer()
|
||||
@elements.Button(elements.ButtonVariantPrimary) {
|
||||
@elements.Text("Login", elements.TextSizeMedium, elements.TextStyleParagraph)
|
||||
@elements.RadioGroup()
|
||||
@elements.Spacer()
|
||||
@elements.Button(elements.GET("/", "#login-view")) {
|
||||
@elements.Text("Cancel")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -59,7 +59,7 @@ func renderLoginView() templ.Component {
|
||||
}()
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
templ_7745c5c3_Err = elements.Text("Sonr.ID", elements.TextSizeLarge, elements.TextStyleHeading).Render(ctx, templ_7745c5c3_Buffer)
|
||||
templ_7745c5c3_Err = elements.H1("Sonr.ID").Render(ctx, templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
@ -67,7 +67,23 @@ func renderLoginView() templ.Component {
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = elements.Text("Neo-tree is a file manager for NeoFS.", elements.TextSizeMedium, elements.TextStyleParagraph).Render(ctx, templ_7745c5c3_Buffer)
|
||||
templ_7745c5c3_Err = elements.Text("Neo-tree is a file manager for NeoFS.").Render(ctx, templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" ")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = elements.Spacer().Render(ctx, templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" ")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = elements.RadioGroup().Render(ctx, templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
@ -95,25 +111,25 @@ func renderLoginView() templ.Component {
|
||||
}()
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
templ_7745c5c3_Err = elements.Text("Login", elements.TextSizeMedium, elements.TextStyleParagraph).Render(ctx, templ_7745c5c3_Buffer)
|
||||
templ_7745c5c3_Err = elements.Text("Cancel").Render(ctx, templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
templ_7745c5c3_Err = elements.Button(elements.ButtonVariantPrimary).Render(templ.WithChildren(ctx, templ_7745c5c3_Var4), templ_7745c5c3_Buffer)
|
||||
templ_7745c5c3_Err = elements.Button(elements.GET("/", "#login-view")).Render(templ.WithChildren(ctx, templ_7745c5c3_Var4), templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
templ_7745c5c3_Err = elements.Card(elements.SizeMedium).Render(templ.WithChildren(ctx, templ_7745c5c3_Var3), templ_7745c5c3_Buffer)
|
||||
templ_7745c5c3_Err = elements.Card("login-view", elements.SizeLarge).Render(templ.WithChildren(ctx, templ_7745c5c3_Var3), templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
templ_7745c5c3_Err = elements.Layout("Sonr.ID").Render(templ.WithChildren(ctx, templ_7745c5c3_Var2), templ_7745c5c3_Buffer)
|
||||
templ_7745c5c3_Err = elements.Layout("Login | Sonr.ID").Render(templ.WithChildren(ctx, templ_7745c5c3_Var2), templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
|
@ -11,9 +11,9 @@ func AuthorizeView(c echo.Context) error {
|
||||
|
||||
templ renderAuthorizeView() {
|
||||
@elements.Layout("Login | Sonr.ID") {
|
||||
@elements.Card(elements.SizeMedium) {
|
||||
@elements.Text("Sonr.ID", elements.TextSizeLarge, elements.TextStyleHeading)
|
||||
@elements.Text("Neo-tree is a file manager for NeoFS.", elements.TextSizeMedium, elements.TextStyleParagraph)
|
||||
@elements.Card("authorize-view", elements.SizeMedium) {
|
||||
@elements.H1("Sonr.ID")
|
||||
@elements.Text("Neo-tree is a file manager for NeoFS.")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -59,7 +59,7 @@ func renderAuthorizeView() templ.Component {
|
||||
}()
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
templ_7745c5c3_Err = elements.Text("Sonr.ID", elements.TextSizeLarge, elements.TextStyleHeading).Render(ctx, templ_7745c5c3_Buffer)
|
||||
templ_7745c5c3_Err = elements.H1("Sonr.ID").Render(ctx, templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
@ -67,13 +67,13 @@ func renderAuthorizeView() templ.Component {
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = elements.Text("Neo-tree is a file manager for NeoFS.", elements.TextSizeMedium, elements.TextStyleParagraph).Render(ctx, templ_7745c5c3_Buffer)
|
||||
templ_7745c5c3_Err = elements.Text("Neo-tree is a file manager for NeoFS.").Render(ctx, templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
templ_7745c5c3_Err = elements.Card(elements.SizeMedium).Render(templ.WithChildren(ctx, templ_7745c5c3_Var3), templ_7745c5c3_Buffer)
|
||||
templ_7745c5c3_Err = elements.Card("authorize-view", elements.SizeMedium).Render(templ.WithChildren(ctx, templ_7745c5c3_Var3), templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
|
19
internal/gui/views/profile.templ
Normal file
19
internal/gui/views/profile.templ
Normal file
@ -0,0 +1,19 @@
|
||||
package views
|
||||
|
||||
import (
|
||||
"github.com/labstack/echo/v4"
|
||||
"github.com/onsonr/sonr/internal/gui/elements"
|
||||
)
|
||||
|
||||
func ProfileView(c echo.Context) error {
|
||||
return echoComponentResponse(c, renderProfileView())
|
||||
}
|
||||
|
||||
templ renderProfileView() {
|
||||
@elements.Layout("Profile | Sonr.ID") {
|
||||
@elements.Card("profile-view", elements.SizeLarge) {
|
||||
@elements.ProfileCard()
|
||||
@elements.Tabs()
|
||||
}
|
||||
}
|
||||
}
|
90
internal/gui/views/profile_templ.go
Normal file
90
internal/gui/views/profile_templ.go
Normal file
@ -0,0 +1,90 @@
|
||||
// Code generated by templ - DO NOT EDIT.
|
||||
|
||||
// templ: version: v0.2.771
|
||||
package views
|
||||
|
||||
//lint:file-ignore SA4006 This context is only used if a nested component is present.
|
||||
|
||||
import "github.com/a-h/templ"
|
||||
import templruntime "github.com/a-h/templ/runtime"
|
||||
|
||||
import (
|
||||
"github.com/labstack/echo/v4"
|
||||
"github.com/onsonr/sonr/internal/gui/elements"
|
||||
)
|
||||
|
||||
func ProfileView(c echo.Context) error {
|
||||
return echoComponentResponse(c, renderProfileView())
|
||||
}
|
||||
|
||||
func renderProfileView() templ.Component {
|
||||
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
||||
if !templ_7745c5c3_IsBuffer {
|
||||
defer func() {
|
||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err == nil {
|
||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
||||
}
|
||||
}()
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var1 == nil {
|
||||
templ_7745c5c3_Var1 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
templ_7745c5c3_Var2 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
||||
if !templ_7745c5c3_IsBuffer {
|
||||
defer func() {
|
||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err == nil {
|
||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
||||
}
|
||||
}()
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
templ_7745c5c3_Var3 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
||||
if !templ_7745c5c3_IsBuffer {
|
||||
defer func() {
|
||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err == nil {
|
||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
||||
}
|
||||
}()
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
templ_7745c5c3_Err = elements.ProfileCard().Render(ctx, templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" ")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = elements.Tabs().Render(ctx, templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
templ_7745c5c3_Err = elements.Card("profile-view", elements.SizeLarge).Render(templ.WithChildren(ctx, templ_7745c5c3_Var3), templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
templ_7745c5c3_Err = elements.Layout("Profile | Sonr.ID").Render(templ.WithChildren(ctx, templ_7745c5c3_Var2), templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
}
|
||||
|
||||
var _ = templruntime.GeneratedTemplate
|
@ -3,31 +3,24 @@ package views
|
||||
import (
|
||||
"github.com/labstack/echo/v4"
|
||||
"github.com/onsonr/sonr/internal/gui/elements"
|
||||
"github.com/onsonr/sonr/internal/gui/forms"
|
||||
)
|
||||
|
||||
func RegisterView(c echo.Context) error {
|
||||
return echoComponentResponse(c, renderRegisterView())
|
||||
return echoComponentResponse(c, renderRegisterView(c))
|
||||
}
|
||||
|
||||
templ renderRegisterView() {
|
||||
templ renderRegisterView(c echo.Context) {
|
||||
@elements.Layout("Register | Sonr.ID") {
|
||||
@elements.Card(elements.SizeMedium) {
|
||||
@elements.Text("Sonr.ID", elements.TextSizeLarge, elements.TextStyleHeading)
|
||||
@elements.Text("Neo-tree is a file manager for NeoFS.", elements.TextSizeMedium, elements.TextStyleParagraph)
|
||||
}
|
||||
@elements.Card(elements.SizeMedium) {
|
||||
<h1>Welcome to Neo-tree</h1>
|
||||
<p>Neo-tree is a file manager for NeoFS.</p>
|
||||
}
|
||||
@elements.Card(elements.SizeMedium) {
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<h1>Welcome to Neo-tree</h1>
|
||||
<p>Neo-tree is a file manager for NeoFS.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@elements.Card("register-view", elements.SizeMedium) {
|
||||
@elements.H2("Account Registration")
|
||||
@elements.Spacer()
|
||||
@elements.Breadcrumbs()
|
||||
@forms.BasicInfo(c, forms.InitialForm)
|
||||
@elements.Spacer()
|
||||
@elements.Button(elements.GET("/", "#register-view")) {
|
||||
@elements.Text("Cancel")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -11,13 +11,14 @@ import templruntime "github.com/a-h/templ/runtime"
|
||||
import (
|
||||
"github.com/labstack/echo/v4"
|
||||
"github.com/onsonr/sonr/internal/gui/elements"
|
||||
"github.com/onsonr/sonr/internal/gui/forms"
|
||||
)
|
||||
|
||||
func RegisterView(c echo.Context) error {
|
||||
return echoComponentResponse(c, renderRegisterView())
|
||||
return echoComponentResponse(c, renderRegisterView(c))
|
||||
}
|
||||
|
||||
func renderRegisterView() templ.Component {
|
||||
func renderRegisterView(c echo.Context) templ.Component {
|
||||
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
||||
@ -59,7 +60,7 @@ func renderRegisterView() templ.Component {
|
||||
}()
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
templ_7745c5c3_Err = elements.Text("Sonr.ID", elements.TextSizeLarge, elements.TextStyleHeading).Render(ctx, templ_7745c5c3_Buffer)
|
||||
templ_7745c5c3_Err = elements.H2("Account Registration").Render(ctx, templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
@ -67,65 +68,63 @@ func renderRegisterView() templ.Component {
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = elements.Text("Neo-tree is a file manager for NeoFS.", elements.TextSizeMedium, elements.TextStyleParagraph).Render(ctx, templ_7745c5c3_Buffer)
|
||||
templ_7745c5c3_Err = elements.Spacer().Render(ctx, templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" ")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = elements.Breadcrumbs().Render(ctx, templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" ")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = forms.BasicInfo(c, forms.InitialForm).Render(ctx, templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" ")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = elements.Spacer().Render(ctx, templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" ")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Var4 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
||||
if !templ_7745c5c3_IsBuffer {
|
||||
defer func() {
|
||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err == nil {
|
||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
||||
}
|
||||
}()
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
templ_7745c5c3_Err = elements.Text("Cancel").Render(ctx, templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
templ_7745c5c3_Err = elements.Button(elements.GET("/", "#register-view")).Render(templ.WithChildren(ctx, templ_7745c5c3_Var4), templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
templ_7745c5c3_Err = elements.Card(elements.SizeMedium).Render(templ.WithChildren(ctx, templ_7745c5c3_Var3), templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" ")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Var4 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
||||
if !templ_7745c5c3_IsBuffer {
|
||||
defer func() {
|
||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err == nil {
|
||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
||||
}
|
||||
}()
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<h1>Welcome to Neo-tree</h1><p>Neo-tree is a file manager for NeoFS.</p>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
templ_7745c5c3_Err = elements.Card(elements.SizeMedium).Render(templ.WithChildren(ctx, templ_7745c5c3_Var4), templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" ")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Var5 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
||||
if !templ_7745c5c3_IsBuffer {
|
||||
defer func() {
|
||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err == nil {
|
||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
||||
}
|
||||
}()
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div class=\"container\"><div class=\"row\"><div class=\"col-md-12\"><h1>Welcome to Neo-tree</h1><p>Neo-tree is a file manager for NeoFS.</p></div></div></div>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
templ_7745c5c3_Err = elements.Card(elements.SizeMedium).Render(templ.WithChildren(ctx, templ_7745c5c3_Var5), templ_7745c5c3_Buffer)
|
||||
templ_7745c5c3_Err = elements.Card("register-view", elements.SizeMedium).Render(templ.WithChildren(ctx, templ_7745c5c3_Var3), templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
|
@ -1,41 +1,61 @@
|
||||
package mdw
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
echojwt "github.com/labstack/echo-jwt/v4"
|
||||
"github.com/labstack/echo/v4"
|
||||
"gopkg.in/macaroon.v2"
|
||||
)
|
||||
|
||||
type Authz struct {
|
||||
echo.Context
|
||||
echojwt.Config
|
||||
const (
|
||||
OriginMacroonCaveat MacroonCaveat = "origin"
|
||||
ScopesMacroonCaveat MacroonCaveat = "scopes"
|
||||
SubjectMacroonCaveat MacroonCaveat = "subject"
|
||||
ExpMacroonCaveat MacroonCaveat = "exp"
|
||||
TokenMacroonCaveat MacroonCaveat = "token"
|
||||
)
|
||||
|
||||
signKey []byte
|
||||
type MacroonCaveat string
|
||||
|
||||
func (c MacroonCaveat) Equal(other string) bool {
|
||||
return string(c) == other
|
||||
}
|
||||
|
||||
func newAuthz(c echo.Context, signKey []byte) *Authz {
|
||||
return &Authz{Context: c, signKey: signKey}
|
||||
func (c MacroonCaveat) String() string {
|
||||
return string(c)
|
||||
}
|
||||
|
||||
func (a *Authz) Accessible(route string, handler echo.HandlerFunc) echo.HandlerFunc {
|
||||
// Verify the macaroon
|
||||
// verified := a.Verify(a.signKey, func(caveat string) error {
|
||||
// Implement your caveat verification logic here
|
||||
// For example, you might check if the caveat is still valid (e.g., not expired)
|
||||
// return nil // Return nil if the caveat is valid
|
||||
// }, nil)
|
||||
// if !verified {
|
||||
// return func(c echo.Context) error {
|
||||
// return c.JSON(http.StatusUnauthorized, map[string]string{"error": "Invalid macaroon"})
|
||||
// }
|
||||
// }
|
||||
a.SetPath(route)
|
||||
return handler
|
||||
func (c MacroonCaveat) Verify(value string) error {
|
||||
switch c {
|
||||
case OriginMacroonCaveat:
|
||||
return nil
|
||||
case ScopesMacroonCaveat:
|
||||
return nil
|
||||
case SubjectMacroonCaveat:
|
||||
return nil
|
||||
case ExpMacroonCaveat:
|
||||
// Check if the expiration time is still valid
|
||||
exp, err := time.Parse(time.RFC3339, value)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if time.Now().After(exp) {
|
||||
return fmt.Errorf("expired")
|
||||
}
|
||||
return nil
|
||||
case TokenMacroonCaveat:
|
||||
return nil
|
||||
default:
|
||||
return fmt.Errorf("unknown caveat: %s", c)
|
||||
}
|
||||
}
|
||||
|
||||
func ValidateMacaroonMiddleware(secretKey []byte, location string) echo.MiddlewareFunc {
|
||||
var MacroonCaveats = []MacroonCaveat{OriginMacroonCaveat, ScopesMacroonCaveat, SubjectMacroonCaveat, ExpMacroonCaveat, TokenMacroonCaveat}
|
||||
|
||||
func MacaroonMiddleware(secretKeyStr string, location string) echo.MiddlewareFunc {
|
||||
secretKey := []byte(secretKeyStr)
|
||||
return func(next echo.HandlerFunc) echo.HandlerFunc {
|
||||
return func(c echo.Context) error {
|
||||
// Extract the macaroon from the Authorization header
|
||||
@ -57,8 +77,11 @@ func ValidateMacaroonMiddleware(secretKey []byte, location string) echo.Middlewa
|
||||
|
||||
// Verify the macaroon
|
||||
err = token.Verify(secretKey, func(caveat string) error {
|
||||
// Implement your caveat verification logic here
|
||||
// For example, you might check if the caveat is still valid (e.g., not expired)
|
||||
for _, c := range MacroonCaveats {
|
||||
if c.String() == caveat {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return nil // Return nil if the caveat is valid
|
||||
}, nil)
|
||||
if err != nil {
|
||||
|
3
internal/mdw/client.go
Normal file
3
internal/mdw/client.go
Normal file
@ -0,0 +1,3 @@
|
||||
package mdw
|
||||
|
||||
type AuthClient struct{}
|
@ -1,7 +1,5 @@
|
||||
package mdw
|
||||
|
||||
import "github.com/labstack/echo/v4"
|
||||
|
||||
type RequestHeaders struct {
|
||||
Authorization *string `header:"Authorization"`
|
||||
CacheControl *string `header:"Cache-Control"`
|
||||
@ -55,8 +53,3 @@ type ResponseHeaders struct {
|
||||
HXTriggerAfterSettle *string `header:"HX-Trigger-After-Settle"`
|
||||
HXTriggerAfterSwap *string `header:"HX-Trigger-After-Swap"`
|
||||
}
|
||||
|
||||
func bindRequestHeaders(c echo.Context) {
|
||||
headers := new(RequestHeaders)
|
||||
c.Bind(headers)
|
||||
}
|
||||
|
@ -10,13 +10,10 @@ import (
|
||||
"github.com/segmentio/ksuid"
|
||||
)
|
||||
|
||||
// UseSession establishes a Session Cookie.
|
||||
func UseSession(next echo.HandlerFunc) echo.HandlerFunc {
|
||||
return func(c echo.Context) error {
|
||||
sc := newSession(c)
|
||||
bindRequestHeaders(sc)
|
||||
return next(sc)
|
||||
}
|
||||
type Session struct {
|
||||
echo.Context
|
||||
htmx *htmx.HTMX
|
||||
dB *db.DB
|
||||
}
|
||||
|
||||
// GetSession returns the current Session
|
||||
@ -24,25 +21,29 @@ func GetSession(c echo.Context) *Session {
|
||||
return c.(*Session)
|
||||
}
|
||||
|
||||
type Session struct {
|
||||
echo.Context
|
||||
htmx *htmx.HTMX
|
||||
dB *db.DB
|
||||
}
|
||||
|
||||
func (c *Session) ID() string {
|
||||
return readCookie(c, "session")
|
||||
}
|
||||
|
||||
func (c *Session) Htmx() *htmx.HTMX {
|
||||
return c.htmx
|
||||
// UseSession establishes a Session Cookie.
|
||||
func UseSession(next echo.HandlerFunc) echo.HandlerFunc {
|
||||
return func(c echo.Context) error {
|
||||
sc := initSession(c)
|
||||
headers := new(RequestHeaders)
|
||||
sc.Bind(headers)
|
||||
return next(sc)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Session) DB() *db.DB {
|
||||
return c.dB
|
||||
}
|
||||
|
||||
func newSession(c echo.Context) *Session {
|
||||
func (c *Session) Htmx() *htmx.HTMX {
|
||||
return c.htmx
|
||||
}
|
||||
|
||||
func (c *Session) ID() string {
|
||||
return readCookie(c, "session")
|
||||
}
|
||||
|
||||
func initSession(c echo.Context) *Session {
|
||||
s := &Session{Context: c}
|
||||
if val := readCookie(c, "session"); val == "" {
|
||||
id := ksuid.New().String()
|
||||
|
@ -1 +0,0 @@
|
||||
package mdw
|
@ -1,8 +1,10 @@
|
||||
package svc
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/labstack/echo/v4"
|
||||
"github.com/onsonr/sonr/internal/db/orm"
|
||||
oidc "github.com/onsonr/sonr/x/did/types/oidc"
|
||||
)
|
||||
|
||||
func GrantAuthorization(e echo.Context) error {
|
||||
@ -25,13 +27,13 @@ func GetToken(e echo.Context) error {
|
||||
|
||||
func GetDiscovery(e echo.Context) error {
|
||||
baseURL := "https://" + e.Request().Host // Ensure this is the correct base URL for your service
|
||||
discoveryDoc := &orm.DiscoveryDocument{
|
||||
Issuer: "https://sonr.id",
|
||||
AuthorizationEndpoint: "https://api.sonr.id/auth",
|
||||
TokenEndpoint: "https://api.sonr.id/token",
|
||||
UserinfoEndpoint: "https://api.sonr.id/userinfo",
|
||||
JwksUri: baseURL + "/jwks", // You'll need to implement this endpoint
|
||||
RegistrationEndpoint: baseURL + "/register",
|
||||
discoveryDoc := &oidc.DiscoveryDocument{
|
||||
Issuer: baseURL,
|
||||
AuthorizationEndpoint: fmt.Sprintf("%s/auth", baseURL),
|
||||
TokenEndpoint: fmt.Sprintf("%s/token", baseURL),
|
||||
UserinfoEndpoint: fmt.Sprintf("%s/userinfo", baseURL),
|
||||
JwksUri: fmt.Sprintf("%s/jwks", baseURL),
|
||||
RegistrationEndpoint: fmt.Sprintf("%s/register", baseURL),
|
||||
ScopesSupported: []string{"openid", "profile", "email", "web3", "sonr"},
|
||||
ResponseTypesSupported: []string{"code"},
|
||||
ResponseModesSupported: []string{"query", "form_post"},
|
||||
|
@ -1,4 +1,4 @@
|
||||
package tui
|
||||
package txmodel
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
@ -12,7 +12,6 @@ import (
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/types/tx"
|
||||
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
const maxWidth = 100
|
||||
@ -321,28 +320,3 @@ func RunTUIForm() (*tx.TxBody, error) {
|
||||
|
||||
return finalM.message, nil
|
||||
}
|
||||
|
||||
func NewTUIDashboardCmd() *cobra.Command {
|
||||
return &cobra.Command{
|
||||
Use: "dash",
|
||||
Short: "TUI for managing the local Sonr validator node",
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
txBody, err := RunTUIForm()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
interfaceRegistry := codectypes.NewInterfaceRegistry()
|
||||
marshaler := codec.NewProtoCodec(interfaceRegistry)
|
||||
jsonBytes, err := marshaler.MarshalJSON(txBody)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to marshal tx body: %w", err)
|
||||
}
|
||||
|
||||
fmt.Println("Generated Protobuf Message (JSON format):")
|
||||
fmt.Println(string(jsonBytes))
|
||||
|
||||
return nil
|
||||
},
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package tui
|
||||
package dexmodel
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
@ -156,18 +156,10 @@ func tick() tea.Msg {
|
||||
return tickMsg{}
|
||||
}
|
||||
|
||||
func runExplorer(cmd *cobra.Command, args []string) error {
|
||||
func RunExplorerTUI(cmd *cobra.Command, args []string) error {
|
||||
p := tea.NewProgram(initialModel(), tea.WithAltScreen())
|
||||
if _, err := p.Run(); err != nil {
|
||||
return fmt.Errorf("error running explorer: %v", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func NewExplorerCmd() *cobra.Command {
|
||||
return &cobra.Command{
|
||||
Use: "cosmos-explorer",
|
||||
Short: "A terminal-based Cosmos blockchain explorer",
|
||||
RunE: runExplorer,
|
||||
}
|
||||
}
|
49
internal/tui/tui.go
Normal file
49
internal/tui/tui.go
Normal file
@ -0,0 +1,49 @@
|
||||
package tui
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
|
||||
"github.com/onsonr/sonr/internal/tui/dexmodel"
|
||||
"github.com/onsonr/sonr/internal/tui/txmodel"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
func AddTUICmds(rootCmd *cobra.Command) {
|
||||
rootCmd.AddCommand(newBuildTxnTUICmd())
|
||||
rootCmd.AddCommand(newExplorerTUICmd())
|
||||
}
|
||||
|
||||
func newBuildTxnTUICmd() *cobra.Command {
|
||||
return &cobra.Command{
|
||||
Use: "dash",
|
||||
Short: "TUI for managing the local Sonr validator node",
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
txBody, err := txmodel.RunBuildTxnTUI()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
interfaceRegistry := codectypes.NewInterfaceRegistry()
|
||||
marshaler := codec.NewProtoCodec(interfaceRegistry)
|
||||
jsonBytes, err := marshaler.MarshalJSON(txBody)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to marshal tx body: %w", err)
|
||||
}
|
||||
|
||||
fmt.Println("Generated Protobuf Message (JSON format):")
|
||||
fmt.Println(string(jsonBytes))
|
||||
|
||||
return nil
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func newExplorerTUICmd() *cobra.Command {
|
||||
return &cobra.Command{
|
||||
Use: "cosmos-explorer",
|
||||
Short: "A terminal-based Cosmos blockchain explorer",
|
||||
RunE: dexmodel.RunExplorerTUI,
|
||||
}
|
||||
}
|
322
internal/tui/txmodel/txmodel.go
Normal file
322
internal/tui/txmodel/txmodel.go
Normal file
@ -0,0 +1,322 @@
|
||||
package txmodel
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
tea "github.com/charmbracelet/bubbletea"
|
||||
"github.com/charmbracelet/huh"
|
||||
"github.com/charmbracelet/lipgloss"
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/types/tx"
|
||||
banktypes "github.com/cosmos/cosmos-sdk/x/bank/types"
|
||||
)
|
||||
|
||||
const maxWidth = 100
|
||||
|
||||
var (
|
||||
red = lipgloss.AdaptiveColor{Light: "#FE5F86", Dark: "#FE5F86"}
|
||||
indigo = lipgloss.AdaptiveColor{Light: "#5A56E0", Dark: "#7571F9"}
|
||||
green = lipgloss.AdaptiveColor{Light: "#02BA84", Dark: "#02BF87"}
|
||||
)
|
||||
|
||||
type Styles struct {
|
||||
Base,
|
||||
HeaderText,
|
||||
Status,
|
||||
StatusHeader,
|
||||
Highlight,
|
||||
ErrorHeaderText,
|
||||
Help lipgloss.Style
|
||||
}
|
||||
|
||||
func NewStyles(lg *lipgloss.Renderer) *Styles {
|
||||
s := Styles{}
|
||||
s.Base = lg.NewStyle().
|
||||
Padding(1, 2, 0, 1)
|
||||
s.HeaderText = lg.NewStyle().
|
||||
Foreground(indigo).
|
||||
Bold(true).
|
||||
Padding(0, 1, 0, 1)
|
||||
s.Status = lg.NewStyle().
|
||||
Border(lipgloss.RoundedBorder()).
|
||||
BorderForeground(indigo).
|
||||
PaddingLeft(1).
|
||||
MarginTop(1)
|
||||
s.StatusHeader = lg.NewStyle().
|
||||
Foreground(green).
|
||||
Bold(true)
|
||||
s.Highlight = lg.NewStyle().
|
||||
Foreground(lipgloss.Color("212"))
|
||||
s.ErrorHeaderText = s.HeaderText.
|
||||
Foreground(red)
|
||||
s.Help = lg.NewStyle().
|
||||
Foreground(lipgloss.Color("240"))
|
||||
return &s
|
||||
}
|
||||
|
||||
type state int
|
||||
|
||||
const (
|
||||
statusNormal state = iota
|
||||
stateDone
|
||||
)
|
||||
|
||||
type Model struct {
|
||||
state state
|
||||
lg *lipgloss.Renderer
|
||||
styles *Styles
|
||||
form *huh.Form
|
||||
width int
|
||||
message *tx.TxBody
|
||||
}
|
||||
|
||||
func NewModel() Model {
|
||||
m := Model{width: maxWidth}
|
||||
m.lg = lipgloss.DefaultRenderer()
|
||||
m.styles = NewStyles(m.lg)
|
||||
|
||||
m.form = huh.NewForm(
|
||||
huh.NewGroup(
|
||||
huh.NewInput().
|
||||
Key("from").
|
||||
Title("From Address").
|
||||
Placeholder("cosmos1...").
|
||||
Validate(func(s string) error {
|
||||
if !strings.HasPrefix(s, "cosmos1") {
|
||||
return fmt.Errorf("invalid address format")
|
||||
}
|
||||
return nil
|
||||
}),
|
||||
|
||||
huh.NewInput().
|
||||
Key("to").
|
||||
Title("To Address").
|
||||
Placeholder("cosmos1...").
|
||||
Validate(func(s string) error {
|
||||
if !strings.HasPrefix(s, "cosmos1") {
|
||||
return fmt.Errorf("invalid address format")
|
||||
}
|
||||
return nil
|
||||
}),
|
||||
|
||||
huh.NewInput().
|
||||
Key("amount").
|
||||
Title("Amount").
|
||||
Placeholder("100").
|
||||
Validate(func(s string) error {
|
||||
if _, err := sdk.ParseCoinNormalized(s + "atom"); err != nil {
|
||||
return fmt.Errorf("invalid coin amount")
|
||||
}
|
||||
return nil
|
||||
}),
|
||||
|
||||
huh.NewSelect[string]().
|
||||
Key("denom").
|
||||
Title("Denom").
|
||||
Options(huh.NewOptions("atom", "osmo", "usnr", "snr")...),
|
||||
|
||||
huh.NewInput().
|
||||
Key("memo").
|
||||
Title("Memo").
|
||||
Placeholder("Optional"),
|
||||
|
||||
huh.NewConfirm().
|
||||
Key("done").
|
||||
Title("Ready to convert?").
|
||||
Validate(func(v bool) error {
|
||||
if !v {
|
||||
return fmt.Errorf("Please confirm when you're ready to convert")
|
||||
}
|
||||
return nil
|
||||
}).
|
||||
Affirmative("Yes, convert!").
|
||||
Negative("Not yet"),
|
||||
),
|
||||
).
|
||||
WithWidth(60).
|
||||
WithShowHelp(false).
|
||||
WithShowErrors(false)
|
||||
|
||||
return m
|
||||
}
|
||||
|
||||
func (m Model) Init() tea.Cmd {
|
||||
return m.form.Init()
|
||||
}
|
||||
|
||||
func min(x, y int) int {
|
||||
if x > y {
|
||||
return y
|
||||
}
|
||||
return x
|
||||
}
|
||||
|
||||
func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||
switch msg := msg.(type) {
|
||||
case tea.WindowSizeMsg:
|
||||
m.width = min(msg.Width, maxWidth) - m.styles.Base.GetHorizontalFrameSize()
|
||||
case tea.KeyMsg:
|
||||
switch msg.String() {
|
||||
case "esc", "ctrl+c", "q":
|
||||
return m, tea.Quit
|
||||
}
|
||||
}
|
||||
|
||||
var cmds []tea.Cmd
|
||||
|
||||
form, cmd := m.form.Update(msg)
|
||||
if f, ok := form.(*huh.Form); ok {
|
||||
m.form = f
|
||||
cmds = append(cmds, cmd)
|
||||
}
|
||||
|
||||
if m.form.State == huh.StateCompleted {
|
||||
m.buildMessage()
|
||||
cmds = append(cmds, tea.Quit)
|
||||
}
|
||||
|
||||
return m, tea.Batch(cmds...)
|
||||
}
|
||||
|
||||
func (m Model) View() string {
|
||||
s := m.styles
|
||||
|
||||
switch m.form.State {
|
||||
case huh.StateCompleted:
|
||||
pklCode := m.generatePkl()
|
||||
messageView := m.getMessageView()
|
||||
var b strings.Builder
|
||||
fmt.Fprintf(&b, "Final Tx:\n\n%s\n\n%s", pklCode, messageView)
|
||||
return s.Status.Margin(0, 1).Padding(1, 2).Width(80).Render(b.String()) + "\n\n"
|
||||
default:
|
||||
var schemaType string
|
||||
if m.form.GetString("schemaType") != "" {
|
||||
schemaType = "Schema Type: " + m.form.GetString("schemaType")
|
||||
}
|
||||
|
||||
v := strings.TrimSuffix(m.form.View(), "\n\n")
|
||||
form := m.lg.NewStyle().Margin(1, 0).Render(v)
|
||||
|
||||
var status string
|
||||
{
|
||||
preview := "(Preview will appear here)"
|
||||
if m.form.GetString("schema") != "" {
|
||||
preview = m.generatePkl()
|
||||
}
|
||||
|
||||
const statusWidth = 40
|
||||
statusMarginLeft := m.width - statusWidth - lipgloss.Width(form) - s.Status.GetMarginRight()
|
||||
status = s.Status.
|
||||
Height(lipgloss.Height(form)).
|
||||
Width(statusWidth).
|
||||
MarginLeft(statusMarginLeft).
|
||||
Render(s.StatusHeader.Render("Pkl Preview") + "\n" +
|
||||
schemaType + "\n\n" +
|
||||
preview)
|
||||
}
|
||||
|
||||
errors := m.form.Errors()
|
||||
header := m.appBoundaryView("Sonr TX Builder")
|
||||
if len(errors) > 0 {
|
||||
header = m.appErrorBoundaryView(m.errorView())
|
||||
}
|
||||
body := lipgloss.JoinHorizontal(lipgloss.Top, form, status)
|
||||
|
||||
footer := m.appBoundaryView(m.form.Help().ShortHelpView(m.form.KeyBinds()))
|
||||
if len(errors) > 0 {
|
||||
footer = m.appErrorBoundaryView("")
|
||||
}
|
||||
|
||||
return s.Base.Render(header + "\n" + body + "\n\n" + footer)
|
||||
}
|
||||
}
|
||||
|
||||
func (m Model) errorView() string {
|
||||
var s string
|
||||
for _, err := range m.form.Errors() {
|
||||
s += err.Error()
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
func (m Model) appBoundaryView(text string) string {
|
||||
return lipgloss.PlaceHorizontal(
|
||||
m.width,
|
||||
lipgloss.Left,
|
||||
m.styles.HeaderText.Render(text),
|
||||
lipgloss.WithWhitespaceChars("="),
|
||||
lipgloss.WithWhitespaceForeground(indigo),
|
||||
)
|
||||
}
|
||||
|
||||
func (m Model) appErrorBoundaryView(text string) string {
|
||||
return lipgloss.PlaceHorizontal(
|
||||
m.width,
|
||||
lipgloss.Left,
|
||||
m.styles.ErrorHeaderText.Render(text),
|
||||
lipgloss.WithWhitespaceChars("="),
|
||||
lipgloss.WithWhitespaceForeground(red),
|
||||
)
|
||||
}
|
||||
|
||||
func (m Model) generatePkl() string {
|
||||
schemaType := m.form.GetString("schemaType")
|
||||
schema := m.form.GetString("schema")
|
||||
|
||||
// This is a placeholder for the actual conversion logic
|
||||
// In a real implementation, you would parse the schema and generate Pkl code
|
||||
return fmt.Sprintf("// Converted from %s\n\nclass ConvertedSchema {\n // TODO: Implement conversion from %s\n // Original schema:\n /*\n%s\n */\n}", schemaType, schemaType, schema)
|
||||
}
|
||||
|
||||
func (m *Model) buildMessage() {
|
||||
from := m.form.GetString("from")
|
||||
to := m.form.GetString("to")
|
||||
amount := m.form.GetString("amount")
|
||||
denom := m.form.GetString("denom")
|
||||
memo := m.form.GetString("memo")
|
||||
|
||||
coin, _ := sdk.ParseCoinNormalized(fmt.Sprintf("%s%s", amount, denom))
|
||||
sendMsg := &banktypes.MsgSend{
|
||||
FromAddress: from,
|
||||
ToAddress: to,
|
||||
Amount: sdk.NewCoins(coin),
|
||||
}
|
||||
|
||||
anyMsg, _ := codectypes.NewAnyWithValue(sendMsg)
|
||||
m.message = &tx.TxBody{
|
||||
Messages: []*codectypes.Any{anyMsg},
|
||||
Memo: memo,
|
||||
}
|
||||
}
|
||||
|
||||
func (m Model) getMessageView() string {
|
||||
if m.message == nil {
|
||||
return "Current Message: None"
|
||||
}
|
||||
|
||||
interfaceRegistry := codectypes.NewInterfaceRegistry()
|
||||
marshaler := codec.NewProtoCodec(interfaceRegistry)
|
||||
jsonBytes, _ := marshaler.MarshalJSON(m.message)
|
||||
|
||||
return fmt.Sprintf("Current Message:\n%s", string(jsonBytes))
|
||||
}
|
||||
|
||||
func RunBuildTxnTUI() (*tx.TxBody, error) {
|
||||
m := NewModel()
|
||||
p := tea.NewProgram(m)
|
||||
|
||||
finalModel, err := p.Run()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to run program: %w", err)
|
||||
}
|
||||
|
||||
finalM, ok := finalModel.(Model)
|
||||
if !ok || finalM.message == nil {
|
||||
return nil, fmt.Errorf("form not completed")
|
||||
}
|
||||
|
||||
return finalM.message, nil
|
||||
}
|
37
pkl/api.pkl
Normal file
37
pkl/api.pkl
Normal file
@ -0,0 +1,37 @@
|
||||
@go.Package { name = "github.com/onsonr/sonr/motr/api" }
|
||||
|
||||
module api
|
||||
|
||||
import "package://pkg.pkl-lang.org/pkl-go/pkl.golang@0.5.0#/go.pkl"
|
||||
|
||||
class JsonField extends go.Field {
|
||||
structTags {
|
||||
["json"] = "%{name},omitempty"
|
||||
}
|
||||
}
|
||||
|
||||
abstract class Request {
|
||||
route: String
|
||||
method: String
|
||||
headers: Map<String, String>
|
||||
origin: String?
|
||||
userAgent: String?
|
||||
body: Dynamic
|
||||
}
|
||||
|
||||
abstract class Response {
|
||||
statusCode: Int
|
||||
headers: Map<String, String>
|
||||
body: Dynamic
|
||||
}
|
||||
|
||||
class GetAccountsRequest extends Request {
|
||||
route = "/accounts"
|
||||
method = "GET"
|
||||
headers = {
|
||||
"Content-Type" = "application/json"
|
||||
}
|
||||
origin = null
|
||||
userAgent = null
|
||||
body = null
|
||||
}
|
30
pkl/bake.pkl
Normal file
30
pkl/bake.pkl
Normal file
@ -0,0 +1,30 @@
|
||||
@go.Package { name = "github.com/onsonr/sonr/motr/api/bake" }
|
||||
|
||||
module bake
|
||||
|
||||
import "package://pkg.pkl-lang.org/pkl-go/pkl.golang@0.5.0#/go.pkl"
|
||||
|
||||
class JsonField extends go.Field {
|
||||
structTags {
|
||||
["json"] = "%{name},omitempty"
|
||||
}
|
||||
}
|
||||
|
||||
abstract class Macroon {
|
||||
id: String
|
||||
location: String
|
||||
}
|
||||
|
||||
abstract class FirstPartyCaveats {
|
||||
scope: String
|
||||
exp: Int
|
||||
cnf: String
|
||||
aud: String
|
||||
}
|
||||
|
||||
abstract class ThirdPartyCaveats {
|
||||
scope: String
|
||||
exp: Int
|
||||
cnf: String
|
||||
aud: String
|
||||
}
|
59
pkl/oidc.pkl
Normal file
59
pkl/oidc.pkl
Normal file
@ -0,0 +1,59 @@
|
||||
@go.Package { name = "github.com/onsonr/sonr/x/did/types/oidc" }
|
||||
|
||||
module oidc
|
||||
|
||||
import "package://pkg.pkl-lang.org/pkl-go/pkl.golang@0.5.0#/go.pkl"
|
||||
|
||||
class JsonField extends go.Field {
|
||||
structTags {
|
||||
["json"] = "%{name},omitempty"
|
||||
["param"] = "%{name}"
|
||||
}
|
||||
}
|
||||
|
||||
class DiscoveryDocument {
|
||||
@JsonField
|
||||
issuer: String
|
||||
|
||||
@JsonField
|
||||
authorization_endpoint: String
|
||||
|
||||
@JsonField
|
||||
token_endpoint: String
|
||||
|
||||
@JsonField
|
||||
userinfo_endpoint: String
|
||||
|
||||
@JsonField
|
||||
jwks_uri: String
|
||||
|
||||
@JsonField
|
||||
registration_endpoint: String
|
||||
|
||||
@JsonField
|
||||
scopes_supported: List<String>
|
||||
|
||||
@JsonField
|
||||
response_types_supported: List<String>
|
||||
|
||||
@JsonField
|
||||
response_modes_supported: List<String>
|
||||
|
||||
@JsonField
|
||||
subject_types_supported: List<String>
|
||||
|
||||
@JsonField
|
||||
id_token_signing_alg_values_supported: List<String>
|
||||
|
||||
@JsonField
|
||||
claims_supported: List<String>
|
||||
|
||||
@JsonField
|
||||
grant_types_supported: List<String>
|
||||
|
||||
@JsonField
|
||||
acr_values_supported: List<String>
|
||||
|
||||
@JsonField
|
||||
token_endpoint_auth_methods_supported: List<String>
|
||||
}
|
84
pkl/orm.pkl
84
pkl/orm.pkl
@ -196,43 +196,11 @@ class Keyshare {
|
||||
id: UInt
|
||||
|
||||
@JsonField
|
||||
metadata: String
|
||||
|
||||
@JsonField
|
||||
payloads: String
|
||||
|
||||
@JsonField
|
||||
protocol: String
|
||||
|
||||
@JsonField
|
||||
publicKey: String
|
||||
data: String
|
||||
|
||||
@JsonField
|
||||
role: Int
|
||||
|
||||
@JsonField
|
||||
version: Int
|
||||
|
||||
@JsonField
|
||||
createdAt: String?
|
||||
}
|
||||
|
||||
class PublicKey {
|
||||
@PrimaryKey
|
||||
id: UInt
|
||||
|
||||
@JsonField
|
||||
role: Int
|
||||
|
||||
@JsonField
|
||||
algorithm: Int
|
||||
|
||||
@JsonField
|
||||
encoding: Int
|
||||
|
||||
@JsonField
|
||||
jwk: String
|
||||
|
||||
@JsonField
|
||||
createdAt: String?
|
||||
}
|
||||
@ -257,53 +225,3 @@ class Permission {
|
||||
updatedAt: String?
|
||||
}
|
||||
|
||||
//
|
||||
// OpenID Connect
|
||||
//
|
||||
|
||||
class DiscoveryDocument {
|
||||
@JsonField
|
||||
issuer: String
|
||||
|
||||
@JsonField
|
||||
authorization_endpoint: String
|
||||
|
||||
@JsonField
|
||||
token_endpoint: String
|
||||
|
||||
@JsonField
|
||||
userinfo_endpoint: String
|
||||
|
||||
@JsonField
|
||||
jwks_uri: String
|
||||
|
||||
@JsonField
|
||||
registration_endpoint: String
|
||||
|
||||
@JsonField
|
||||
scopes_supported: List<String>
|
||||
|
||||
@JsonField
|
||||
response_types_supported: List<String>
|
||||
|
||||
@JsonField
|
||||
response_modes_supported: List<String>
|
||||
|
||||
@JsonField
|
||||
subject_types_supported: List<String>
|
||||
|
||||
@JsonField
|
||||
id_token_signing_alg_values_supported: List<String>
|
||||
|
||||
@JsonField
|
||||
claims_supported: List<String>
|
||||
|
||||
@JsonField
|
||||
grant_types_supported: List<String>
|
||||
|
||||
@JsonField
|
||||
acr_values_supported: List<String>
|
||||
|
||||
@JsonField
|
||||
token_endpoint_auth_methods_supported: List<String>
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
@go.Package { name = "github.com/onsonr/sonr/txns" }
|
||||
@go.Package { name = "github.com/onsonr/sonr/x/did/types/txns" }
|
||||
|
||||
module transactions
|
||||
module txns
|
||||
|
||||
import "package://pkg.pkl-lang.org/pkl-go/pkl.golang@0.5.0#/go.pkl"
|
||||
|
||||
|
@ -10,6 +10,17 @@ option go_package = "github.com/onsonr/sonr/x/did/types";
|
||||
message GenesisState {
|
||||
// Params defines all the parameters of the module.
|
||||
Params params = 1 [(gogoproto.nullable) = false];
|
||||
|
||||
// GlobalIntegrity defines a zkp integrity proof for the entire DID namespace
|
||||
GlobalIntegrity global_integrity = 2;
|
||||
}
|
||||
|
||||
// GlobalIntegrity defines a zkp integrity proof for the entire DID namespace
|
||||
message GlobalIntegrity {
|
||||
string controller = 1;
|
||||
string seed = 2;
|
||||
bytes accumulator = 3;
|
||||
uint64 count = 4;
|
||||
}
|
||||
|
||||
// Params defines the set of module parameters.
|
||||
@ -21,23 +32,20 @@ message Params {
|
||||
// Whitelisted Assets
|
||||
repeated AssetInfo whitelisted_assets = 1;
|
||||
|
||||
// Whitelisted Blockchains
|
||||
repeated ChainInfo whitelisted_chains = 2;
|
||||
|
||||
// Whitelisted Key Types
|
||||
repeated KeyInfo allowed_public_keys = 3;
|
||||
map<string, KeyInfo> allowed_public_keys = 2;
|
||||
|
||||
// IpfsActive is a flag to enable/disable ipfs
|
||||
bool ipfs_active = 4;
|
||||
bool ipfs_active = 3;
|
||||
|
||||
// Localhost Registration Enabled
|
||||
bool localhost_registration_enabled = 5;
|
||||
bool localhost_registration_enabled = 4;
|
||||
|
||||
// ConveyancePreference defines the conveyance preference
|
||||
string conveyance_preference = 6;
|
||||
string conveyance_preference = 5;
|
||||
|
||||
// AttestationFormats defines the attestation formats
|
||||
repeated string attestation_formats = 7;
|
||||
repeated string attestation_formats = 6;
|
||||
}
|
||||
|
||||
// AssetInfo defines the asset info
|
||||
@ -57,20 +65,8 @@ message AssetInfo {
|
||||
// The name of the asset
|
||||
string name = 5;
|
||||
|
||||
// The Method of the did namespace
|
||||
string method = 6;
|
||||
|
||||
// The icon url
|
||||
string icon_url = 7;
|
||||
}
|
||||
|
||||
// ChainInfo defines the chain info
|
||||
message ChainInfo {
|
||||
string id = 1;
|
||||
string chain_id = 2;
|
||||
string name = 3;
|
||||
string symbol = 4;
|
||||
repeated ValidatorInfo validators = 5;
|
||||
string icon_url = 6;
|
||||
}
|
||||
|
||||
// KeyInfo defines information for accepted PubKey types
|
||||
|
@ -97,9 +97,18 @@ message ServiceInfo {
|
||||
Service service = 4;
|
||||
}
|
||||
|
||||
// Token defines a macron token
|
||||
message Token {
|
||||
string id = 1;
|
||||
string controller = 2;
|
||||
bytes macron = 3;
|
||||
// FirstPartyCaveat defines a first party caveat
|
||||
message FirstPartyCaveat {
|
||||
Permissions scope = 1;
|
||||
int64 exp = 2;
|
||||
string cnf = 3;
|
||||
string aud = 4;
|
||||
}
|
||||
|
||||
// ThirdPartyCaveat defines a third party caveat
|
||||
message ThirdPartyCaveat {
|
||||
Permissions scope = 1;
|
||||
int64 exp = 2;
|
||||
string cnf = 3;
|
||||
string aud = 4;
|
||||
}
|
||||
|
@ -10,8 +10,33 @@ option go_package = "github.com/onsonr/sonr/x/did/types";
|
||||
// Query provides defines the gRPC querier service.
|
||||
service Query {
|
||||
// Params queries all parameters of the module.
|
||||
rpc Params(QueryRequest) returns (QueryResponse) {
|
||||
option (google.api.http).get = "/did/params";
|
||||
rpc Params(QueryRequest) returns (QueryParamsResponse) {
|
||||
option (google.api.http).get = "/params";
|
||||
}
|
||||
|
||||
// ParamsAssets queries all parameters of the module.
|
||||
rpc ParamsAssets(QueryRequest) returns (QueryResponse) {
|
||||
option (google.api.http).get = "/params/assets";
|
||||
}
|
||||
|
||||
// Params queries all parameters of the module.
|
||||
rpc ParamsByAsset(QueryRequest) returns (QueryResponse) {
|
||||
option (google.api.http).get = "/params/assets/{asset}";
|
||||
}
|
||||
|
||||
// ParamsKeys queries all parameters of the module.
|
||||
rpc ParamsKeys(QueryRequest) returns (QueryResponse) {
|
||||
option (google.api.http).get = "/params/keys";
|
||||
}
|
||||
|
||||
// Params queries all parameters of the module.
|
||||
rpc ParamsByKey(QueryRequest) returns (QueryResponse) {
|
||||
option (google.api.http).get = "/params/keys/{key}";
|
||||
}
|
||||
|
||||
// Params queries all parameters of the module.
|
||||
rpc RegistrationOptionsByKey(QueryRequest) returns (QueryResponse) {
|
||||
option (google.api.http).get = "/params/keys/{key}/registration";
|
||||
}
|
||||
|
||||
// Resolve queries the DID document by its id.
|
||||
@ -31,6 +56,8 @@ service Query {
|
||||
message QueryRequest {
|
||||
string did = 1;
|
||||
string origin = 2;
|
||||
string key = 3;
|
||||
string asset = 4;
|
||||
}
|
||||
|
||||
// QueryResolveResponse is the response type for the Query/Resolve RPC method.
|
||||
@ -41,3 +68,28 @@ message QueryResponse {
|
||||
ServiceInfo service = 4;
|
||||
Params params = 5;
|
||||
}
|
||||
|
||||
// QueryParamsResponse is the response type for the Query/Params RPC method.
|
||||
message QueryParamsResponse {
|
||||
Params params = 1;
|
||||
}
|
||||
|
||||
message QueryParamsAssetsResponse {
|
||||
repeated AssetInfo assets = 1;
|
||||
}
|
||||
|
||||
message QueryParamsKeysResponse {
|
||||
map<string, KeyInfo> keys = 1;
|
||||
}
|
||||
|
||||
message QueryParamsByKeyResponse {
|
||||
KeyInfo key = 1;
|
||||
}
|
||||
|
||||
message QueryParamsByAssetResponse {
|
||||
AssetInfo asset = 1;
|
||||
}
|
||||
|
||||
message QueryRegistrationOptionsByKeyResponse {
|
||||
repeated string registration_options = 1;
|
||||
}
|
||||
|
@ -48,7 +48,7 @@ message MsgUpdateParams {
|
||||
Params params = 2 [(gogoproto.nullable) = false];
|
||||
|
||||
// token is the macron token to authenticate the operation.
|
||||
Token token = 3;
|
||||
string token = 3;
|
||||
}
|
||||
|
||||
// MsgUpdateParamsResponse defines the response structure for executing a
|
||||
@ -100,7 +100,7 @@ message MsgProveWitness {
|
||||
bytes witness = 3;
|
||||
|
||||
// token is the macron token to authenticate the operation.
|
||||
Token token = 4;
|
||||
string token = 4;
|
||||
}
|
||||
|
||||
// MsgProveWitnessResponse is the response type for the ProveWitness RPC.
|
||||
@ -117,7 +117,7 @@ message MsgSyncController {
|
||||
string controller = 1 [(cosmos_proto.scalar) = "cosmos.AddressString"];
|
||||
|
||||
// Token is the public token to authenticate the operation.
|
||||
Token token = 3;
|
||||
string token = 3;
|
||||
}
|
||||
|
||||
// MsgSyncControllerResponse is the response type for the SyncController RPC.
|
||||
@ -168,13 +168,13 @@ message MsgAuthorizeService {
|
||||
Permissions scopes = 3;
|
||||
|
||||
// token is the macron token to authenticate the operation.
|
||||
Token token = 4;
|
||||
string token = 4;
|
||||
}
|
||||
|
||||
// MsgAuthorizeServiceResponse is the response type for the AuthorizeService RPC.
|
||||
message MsgAuthorizeServiceResponse {
|
||||
bool success = 1;
|
||||
Token token = 2;
|
||||
string token = 2;
|
||||
}
|
||||
|
||||
// MsgRegisterService is the message type for the RegisterService RPC.
|
||||
@ -188,7 +188,7 @@ message MsgRegisterService {
|
||||
Service service = 2;
|
||||
|
||||
// token is the macron token to authenticate the operation.
|
||||
Token token = 3;
|
||||
string token = 3;
|
||||
}
|
||||
|
||||
// MsgRegisterServiceResponse is the response type for the RegisterService RPC.
|
||||
|
@ -1,6 +0,0 @@
|
||||
// Code generated from Pkl module `transactions`. DO NOT EDIT.
|
||||
package txns
|
||||
|
||||
type Msg interface {
|
||||
GetTypeUrl() string
|
||||
}
|
@ -1,27 +0,0 @@
|
||||
// Code generated from Pkl module `transactions`. DO NOT EDIT.
|
||||
package txns
|
||||
|
||||
import "github.com/apple/pkl-go/pkl"
|
||||
|
||||
func init() {
|
||||
pkl.RegisterMapping("transactions", Transactions{})
|
||||
pkl.RegisterMapping("transactions#Proposal", Proposal{})
|
||||
pkl.RegisterMapping("transactions#MsgGovSubmitProposal", MsgGovSubmitProposalImpl{})
|
||||
pkl.RegisterMapping("transactions#MsgGovVote", MsgGovVoteImpl{})
|
||||
pkl.RegisterMapping("transactions#MsgGovDeposit", MsgGovDepositImpl{})
|
||||
pkl.RegisterMapping("transactions#MsgGroupCreateGroup", MsgGroupCreateGroupImpl{})
|
||||
pkl.RegisterMapping("transactions#MsgGroupSubmitProposal", MsgGroupSubmitProposalImpl{})
|
||||
pkl.RegisterMapping("transactions#MsgGroupVote", MsgGroupVoteImpl{})
|
||||
pkl.RegisterMapping("transactions#MsgStakingCreateValidator", MsgStakingCreateValidatorImpl{})
|
||||
pkl.RegisterMapping("transactions#MsgStakingDelegate", MsgStakingDelegateImpl{})
|
||||
pkl.RegisterMapping("transactions#MsgStakingUndelegate", MsgStakingUndelegateImpl{})
|
||||
pkl.RegisterMapping("transactions#MsgStakingBeginRedelegate", MsgStakingBeginRedelegateImpl{})
|
||||
pkl.RegisterMapping("transactions#MsgDidUpdateParams", MsgDidUpdateParamsImpl{})
|
||||
pkl.RegisterMapping("transactions#MsgDidAllocateVault", MsgDidAllocateVaultImpl{})
|
||||
pkl.RegisterMapping("transactions#MsgDidProveWitness", MsgDidProveWitnessImpl{})
|
||||
pkl.RegisterMapping("transactions#MsgDidSyncVault", MsgDidSyncVaultImpl{})
|
||||
pkl.RegisterMapping("transactions#MsgDidRegisterController", MsgDidRegisterControllerImpl{})
|
||||
pkl.RegisterMapping("transactions#MsgDidAuthorize", MsgDidAuthorizeImpl{})
|
||||
pkl.RegisterMapping("transactions#MsgDidRegisterService", MsgDidRegisterServiceImpl{})
|
||||
pkl.RegisterMapping("transactions#TxBody", TxBody{})
|
||||
}
|
@ -24,7 +24,7 @@ func (am AppModule) AutoCLIOptions() *autocliv1.ModuleOptions {
|
||||
RpcCommandOptions: []*autocliv1.RpcCommandOptions{
|
||||
{
|
||||
RpcMethod: "UpdateParams",
|
||||
Skip: false, // set to true if authority gated
|
||||
Skip: true, // set to true if authority gated
|
||||
},
|
||||
},
|
||||
},
|
||||
|
27
x/did/builder/openid.go
Normal file
27
x/did/builder/openid.go
Normal file
@ -0,0 +1,27 @@
|
||||
package builder
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/onsonr/sonr/x/did/types/oidc"
|
||||
)
|
||||
|
||||
func GetDiscovery(origin string) *oidc.DiscoveryDocument {
|
||||
baseURL := "https://" + origin // Ensure this is the correct base URL for your service
|
||||
discoveryDoc := &oidc.DiscoveryDocument{
|
||||
Issuer: baseURL,
|
||||
AuthorizationEndpoint: fmt.Sprintf("%s/auth", baseURL),
|
||||
TokenEndpoint: fmt.Sprintf("%s/token", baseURL),
|
||||
UserinfoEndpoint: fmt.Sprintf("%s/userinfo", baseURL),
|
||||
JwksUri: fmt.Sprintf("%s/jwks", baseURL),
|
||||
RegistrationEndpoint: fmt.Sprintf("%s/register", baseURL),
|
||||
ScopesSupported: []string{"openid", "profile", "email", "web3", "sonr"},
|
||||
ResponseTypesSupported: []string{"code"},
|
||||
ResponseModesSupported: []string{"query", "form_post"},
|
||||
GrantTypesSupported: []string{"authorization_code", "refresh_token"},
|
||||
AcrValuesSupported: []string{"passkey"},
|
||||
SubjectTypesSupported: []string{"public"},
|
||||
ClaimsSupported: []string{"sub", "iss", "name", "email"},
|
||||
}
|
||||
return discoveryDoc
|
||||
}
|
@ -2,6 +2,7 @@ package builder
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"strings"
|
||||
|
||||
"github.com/onsonr/sonr/x/did/types"
|
||||
)
|
||||
@ -53,8 +54,8 @@ func NewCredentialParameter(ki *types.KeyInfo) CredentialParameter {
|
||||
|
||||
func ExtractCredentialParameters(p *types.Params) []CredentialParameter {
|
||||
var keys []*types.KeyInfo
|
||||
for _, v := range p.AllowedPublicKeys {
|
||||
if v.Role == types.KeyRole_KEY_ROLE_AUTHENTICATION {
|
||||
for k, v := range p.AllowedPublicKeys {
|
||||
if strings.Contains(k, "webauthn") {
|
||||
keys = append(keys, v)
|
||||
}
|
||||
}
|
||||
|
@ -1 +0,0 @@
|
||||
package context
|
@ -1,55 +0,0 @@
|
||||
package context
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net"
|
||||
"strings"
|
||||
|
||||
"google.golang.org/grpc/metadata"
|
||||
"google.golang.org/grpc/peer"
|
||||
)
|
||||
|
||||
type ClientInfo struct {
|
||||
Authority string
|
||||
ContentType string
|
||||
UserAgent string
|
||||
Hostname string
|
||||
IPAddress string
|
||||
}
|
||||
|
||||
func ExtractClientInfo(ctx context.Context) (*ClientInfo, error) {
|
||||
md, ok := metadata.FromIncomingContext(ctx)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("failed to get metadata from context")
|
||||
}
|
||||
|
||||
info := &ClientInfo{}
|
||||
|
||||
// Extract authority, content-type, and user-agent
|
||||
if authority := md.Get("authority"); len(authority) > 0 {
|
||||
info.Authority = authority[0]
|
||||
}
|
||||
if contentType := md.Get("content-type"); len(contentType) > 0 {
|
||||
info.ContentType = contentType[0]
|
||||
}
|
||||
if userAgent := md.Get("user-agent"); len(userAgent) > 0 {
|
||||
info.UserAgent = userAgent[0]
|
||||
}
|
||||
|
||||
// Extract hostname and IP address
|
||||
p, ok := peer.FromContext(ctx)
|
||||
if ok {
|
||||
if tcpAddr, ok := p.Addr.(*net.TCPAddr); ok {
|
||||
info.IPAddress = tcpAddr.IP.String()
|
||||
|
||||
// Try to get hostname
|
||||
names, err := net.LookupAddr(info.IPAddress)
|
||||
if err == nil && len(names) > 0 {
|
||||
info.Hostname = strings.TrimSuffix(names[0], ".")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return info, nil
|
||||
}
|
@ -8,10 +8,12 @@ import (
|
||||
"cosmossdk.io/core/store"
|
||||
"cosmossdk.io/depinject"
|
||||
"cosmossdk.io/log"
|
||||
nftkeeper "cosmossdk.io/x/nft/keeper"
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper"
|
||||
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||
govtypes "github.com/cosmos/cosmos-sdk/x/gov/types"
|
||||
|
||||
slashingkeeper "github.com/cosmos/cosmos-sdk/x/slashing/keeper"
|
||||
stakingkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper"
|
||||
|
||||
@ -42,6 +44,7 @@ type ModuleInputs struct {
|
||||
AddressCodec address.Codec
|
||||
|
||||
AccountKeeper authkeeper.AccountKeeper
|
||||
NFTKeeper nftkeeper.Keeper
|
||||
StakingKeeper stakingkeeper.Keeper
|
||||
SlashingKeeper slashingkeeper.Keeper
|
||||
}
|
||||
@ -56,8 +59,8 @@ type ModuleOutputs struct {
|
||||
func ProvideModule(in ModuleInputs) ModuleOutputs {
|
||||
govAddr := authtypes.NewModuleAddress(govtypes.ModuleName).String()
|
||||
|
||||
k := keeper.NewKeeper(in.Cdc, in.StoreService, in.AccountKeeper, &in.StakingKeeper, log.NewLogger(os.Stderr), govAddr)
|
||||
m := NewAppModule(in.Cdc, k)
|
||||
k := keeper.NewKeeper(in.Cdc, in.StoreService, in.AccountKeeper, in.NFTKeeper, &in.StakingKeeper, log.NewLogger(os.Stderr), govAddr)
|
||||
m := NewAppModule(in.Cdc, k, in.NFTKeeper)
|
||||
|
||||
return ModuleOutputs{Module: m, Keeper: k, Out: depinject.Out{}}
|
||||
}
|
||||
|
@ -5,16 +5,17 @@ import (
|
||||
storetypes "cosmossdk.io/core/store"
|
||||
"cosmossdk.io/log"
|
||||
"cosmossdk.io/orm/model/ormdb"
|
||||
nftkeeper "cosmossdk.io/x/nft/keeper"
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper"
|
||||
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
|
||||
|
||||
govtypes "github.com/cosmos/cosmos-sdk/x/gov/types"
|
||||
stakkeeper "github.com/cosmos/cosmos-sdk/x/staking/keeper"
|
||||
"github.com/ipfs/kubo/client/rpc"
|
||||
|
||||
apiv1 "github.com/onsonr/sonr/api/did/v1"
|
||||
middleware "github.com/onsonr/sonr/x/did/context"
|
||||
"github.com/onsonr/sonr/x/did/types"
|
||||
)
|
||||
|
||||
@ -30,6 +31,7 @@ type Keeper struct {
|
||||
Schema collections.Schema
|
||||
|
||||
AccountKeeper authkeeper.AccountKeeper
|
||||
NftKeeper nftkeeper.Keeper
|
||||
StakingKeeper *stakkeeper.Keeper
|
||||
|
||||
authority string
|
||||
@ -41,6 +43,7 @@ func NewKeeper(
|
||||
cdc codec.BinaryCodec,
|
||||
storeService storetypes.KVStoreService,
|
||||
accKeeper authkeeper.AccountKeeper,
|
||||
nftKeeper nftkeeper.Keeper,
|
||||
stkKeeper *stakkeeper.Keeper,
|
||||
logger log.Logger,
|
||||
authority string,
|
||||
@ -77,6 +80,7 @@ func NewKeeper(
|
||||
authority: authority,
|
||||
OrmDB: store,
|
||||
AccountKeeper: accKeeper,
|
||||
NftKeeper: nftKeeper,
|
||||
StakingKeeper: stkKeeper,
|
||||
}
|
||||
schema, err := sb.Build()
|
||||
@ -95,10 +99,7 @@ func (k Keeper) IsUnclaimedServiceOrigin(ctx sdk.Context, origin string) bool {
|
||||
}
|
||||
|
||||
// IsValidServiceOrigin checks if a service origin is valid
|
||||
func (k Keeper) IsValidServiceOrigin(ctx sdk.Context, origin string, clientInfo *middleware.ClientInfo) bool {
|
||||
if origin != clientInfo.Hostname {
|
||||
return false
|
||||
}
|
||||
func (k Keeper) IsValidServiceOrigin(ctx sdk.Context, origin string) bool {
|
||||
rec, err := k.OrmDB.ServiceRecordTable().GetByOrigin(ctx, origin)
|
||||
if err != nil {
|
||||
return false
|
||||
|
@ -6,6 +6,7 @@ import (
|
||||
"cosmossdk.io/core/store"
|
||||
"cosmossdk.io/log"
|
||||
storetypes "cosmossdk.io/store/types"
|
||||
nftkeeper "cosmossdk.io/x/nft/keeper"
|
||||
"github.com/cosmos/cosmos-sdk/runtime"
|
||||
"github.com/cosmos/cosmos-sdk/testutil"
|
||||
simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims"
|
||||
@ -48,6 +49,7 @@ type testFixture struct {
|
||||
|
||||
accountkeeper authkeeper.AccountKeeper
|
||||
bankkeeper bankkeeper.BaseKeeper
|
||||
nftKeeper nftkeeper.Keeper
|
||||
stakingKeeper *stakingkeeper.Keeper
|
||||
mintkeeper mintkeeper.Keeper
|
||||
|
||||
@ -77,10 +79,10 @@ func SetupTest(t *testing.T) *testFixture {
|
||||
registerBaseSDKModules(f, encCfg, storeService, logger, require)
|
||||
|
||||
// Setup POA Keeper.
|
||||
f.k = keeper.NewKeeper(encCfg.Codec, storeService, f.accountkeeper, f.stakingKeeper, logger, f.govModAddr)
|
||||
f.k = keeper.NewKeeper(encCfg.Codec, storeService, f.accountkeeper, f.nftKeeper, f.stakingKeeper, logger, f.govModAddr)
|
||||
f.msgServer = keeper.NewMsgServerImpl(f.k)
|
||||
f.queryServer = keeper.NewQuerier(f.k)
|
||||
f.appModule = module.NewAppModule(encCfg.Codec, f.k)
|
||||
f.appModule = module.NewAppModule(encCfg.Codec, f.k, f.nftKeeper)
|
||||
|
||||
return f
|
||||
}
|
||||
|
@ -20,9 +20,9 @@ func NewQuerier(keeper Keeper) Querier {
|
||||
func (k Querier) Params(
|
||||
goCtx context.Context,
|
||||
req *types.QueryRequest,
|
||||
) (*types.QueryResponse, error) {
|
||||
) (*types.QueryParamsResponse, error) {
|
||||
ctx := k.CurrentCtx(goCtx)
|
||||
return &types.QueryResponse{Params: k.GetParams(ctx.SDK())}, nil
|
||||
return &types.QueryParamsResponse{Params: k.GetParams(ctx.SDK())}, nil
|
||||
}
|
||||
|
||||
// Resolve implements types.QueryServer.
|
||||
@ -42,3 +42,38 @@ func (k Querier) Service(
|
||||
ctx := k.CurrentCtx(goCtx)
|
||||
return &types.QueryResponse{Service: ctx.GetServiceInfo(req.GetOrigin()), Params: ctx.Params()}, nil
|
||||
}
|
||||
|
||||
// ParamsAssets implements types.QueryServer.
|
||||
func (k Querier) ParamsAssets(goCtx context.Context, req *types.QueryRequest) (*types.QueryResponse, error) {
|
||||
// ctx := sdk.UnwrapSDKContext(goCtx)
|
||||
panic("ParamsAssets is unimplemented")
|
||||
return &types.QueryResponse{}, nil
|
||||
}
|
||||
|
||||
// ParamsByAsset implements types.QueryServer.
|
||||
func (k Querier) ParamsByAsset(goCtx context.Context, req *types.QueryRequest) (*types.QueryResponse, error) {
|
||||
// ctx := sdk.UnwrapSDKContext(goCtx)
|
||||
panic("ParamsByAsset is unimplemented")
|
||||
return &types.QueryResponse{}, nil
|
||||
}
|
||||
|
||||
// ParamsKeys implements types.QueryServer.
|
||||
func (k Querier) ParamsKeys(goCtx context.Context, req *types.QueryRequest) (*types.QueryResponse, error) {
|
||||
// ctx := sdk.UnwrapSDKContext(goCtx)
|
||||
panic("ParamsKeys is unimplemented")
|
||||
return &types.QueryResponse{}, nil
|
||||
}
|
||||
|
||||
// ParamsByKey implements types.QueryServer.
|
||||
func (k Querier) ParamsByKey(goCtx context.Context, req *types.QueryRequest) (*types.QueryResponse, error) {
|
||||
// ctx := sdk.UnwrapSDKContext(goCtx)
|
||||
panic("ParamsByKey is unimplemented")
|
||||
return &types.QueryResponse{}, nil
|
||||
}
|
||||
|
||||
// RegistrationOptionsByKey implements types.QueryServer.
|
||||
func (k Querier) RegistrationOptionsByKey(goCtx context.Context, req *types.QueryRequest) (*types.QueryResponse, error) {
|
||||
// ctx := sdk.UnwrapSDKContext(goCtx)
|
||||
panic("RegistrationOptionsByKey is unimplemented")
|
||||
return &types.QueryResponse{}, nil
|
||||
}
|
||||
|
@ -9,7 +9,6 @@ import (
|
||||
govtypes "github.com/cosmos/cosmos-sdk/x/gov/types"
|
||||
|
||||
"github.com/onsonr/sonr/x/did/builder"
|
||||
snrctx "github.com/onsonr/sonr/x/did/context"
|
||||
"github.com/onsonr/sonr/x/did/types"
|
||||
)
|
||||
|
||||
@ -24,6 +23,8 @@ func NewMsgServerImpl(keeper Keeper) types.MsgServer {
|
||||
return &msgServer{k: keeper}
|
||||
}
|
||||
|
||||
// # AuthorizeService
|
||||
//
|
||||
// AuthorizeService implements types.MsgServer.
|
||||
func (ms msgServer) AuthorizeService(goCtx context.Context, msg *types.MsgAuthorizeService) (*types.MsgAuthorizeServiceResponse, error) {
|
||||
if ms.k.authority != msg.Controller {
|
||||
@ -37,19 +38,16 @@ func (ms msgServer) AuthorizeService(goCtx context.Context, msg *types.MsgAuthor
|
||||
return &types.MsgAuthorizeServiceResponse{}, nil
|
||||
}
|
||||
|
||||
// # AllocateVault
|
||||
//
|
||||
// AllocateVault implements types.MsgServer.
|
||||
func (ms msgServer) AllocateVault(
|
||||
goCtx context.Context,
|
||||
msg *types.MsgAllocateVault,
|
||||
) (*types.MsgAllocateVaultResponse, error) {
|
||||
ctx := sdk.UnwrapSDKContext(goCtx)
|
||||
clientInfo, err := snrctx.ExtractClientInfo(goCtx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 1.Check if the service origin is valid
|
||||
if ms.k.IsValidServiceOrigin(ctx, msg.Origin, clientInfo) {
|
||||
if ms.k.IsValidServiceOrigin(ctx, msg.Origin) {
|
||||
return nil, types.ErrInvalidServiceOrigin
|
||||
}
|
||||
|
||||
@ -76,6 +74,8 @@ func (ms msgServer) AllocateVault(
|
||||
}, nil
|
||||
}
|
||||
|
||||
// # RegisterController
|
||||
//
|
||||
// RegisterController implements types.MsgServer.
|
||||
func (ms msgServer) RegisterController(
|
||||
goCtx context.Context,
|
||||
@ -85,6 +85,8 @@ func (ms msgServer) RegisterController(
|
||||
return &types.MsgRegisterControllerResponse{}, nil
|
||||
}
|
||||
|
||||
// # RegisterService
|
||||
//
|
||||
// RegisterService implements types.MsgServer.
|
||||
func (ms msgServer) RegisterService(
|
||||
goCtx context.Context,
|
||||
@ -92,24 +94,23 @@ func (ms msgServer) RegisterService(
|
||||
) (*types.MsgRegisterServiceResponse, error) {
|
||||
ctx := sdk.UnwrapSDKContext(goCtx)
|
||||
|
||||
clientInfo, err := snrctx.ExtractClientInfo(goCtx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 1.Check if the service origin is valid
|
||||
if !ms.k.IsValidServiceOrigin(ctx, msg.Service.Origin, clientInfo) {
|
||||
if !ms.k.IsValidServiceOrigin(ctx, msg.Service.Origin) {
|
||||
return nil, types.ErrInvalidServiceOrigin
|
||||
}
|
||||
return ms.k.insertService(ctx, msg.Service)
|
||||
}
|
||||
|
||||
// # SyncController
|
||||
//
|
||||
// SyncController implements types.MsgServer.
|
||||
func (ms msgServer) SyncController(ctx context.Context, msg *types.MsgSyncController) (*types.MsgSyncControllerResponse, error) {
|
||||
// ctx := sdk.UnwrapSDKContext(goCtx)
|
||||
return &types.MsgSyncControllerResponse{}, nil
|
||||
}
|
||||
|
||||
// # UpdateParams
|
||||
//
|
||||
// UpdateParams updates the x/did module parameters.
|
||||
func (ms msgServer) UpdateParams(
|
||||
ctx context.Context,
|
||||
|
@ -4,13 +4,14 @@ import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
"github.com/grpc-ecosystem/grpc-gateway/runtime"
|
||||
|
||||
abci "github.com/cometbft/cometbft/abci/types"
|
||||
|
||||
"cosmossdk.io/client/v2/autocli"
|
||||
errorsmod "cosmossdk.io/errors"
|
||||
"cosmossdk.io/x/nft"
|
||||
nftkeeper "cosmossdk.io/x/nft/keeper"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
@ -24,17 +25,15 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
// ConsensusVersion defines the current x/did module consensus version.
|
||||
ConsensusVersion = 1
|
||||
|
||||
// this line is used by starport scaffolding # simapp/module/const
|
||||
)
|
||||
|
||||
var (
|
||||
_ module.AppModuleBasic = AppModuleBasic{}
|
||||
_ module.AppModuleGenesis = AppModule{}
|
||||
_ module.AppModule = AppModule{}
|
||||
|
||||
_ module.AppModuleBasic = AppModuleBasic{}
|
||||
_ module.AppModuleGenesis = AppModule{}
|
||||
_ module.AppModule = AppModule{}
|
||||
_ autocli.HasAutoCLIConfig = AppModule{}
|
||||
)
|
||||
|
||||
@ -46,17 +45,20 @@ type AppModuleBasic struct {
|
||||
type AppModule struct {
|
||||
AppModuleBasic
|
||||
|
||||
keeper keeper.Keeper
|
||||
keeper keeper.Keeper
|
||||
nftKeeper nftkeeper.Keeper
|
||||
}
|
||||
|
||||
// NewAppModule constructor
|
||||
func NewAppModule(
|
||||
cdc codec.Codec,
|
||||
keeper keeper.Keeper,
|
||||
nftKeeper nftkeeper.Keeper,
|
||||
) *AppModule {
|
||||
return &AppModule{
|
||||
AppModuleBasic: AppModuleBasic{cdc: cdc},
|
||||
keeper: keeper,
|
||||
nftKeeper: nftKeeper,
|
||||
}
|
||||
}
|
||||
|
||||
@ -66,7 +68,8 @@ func (a AppModuleBasic) Name() string {
|
||||
|
||||
func (a AppModuleBasic) DefaultGenesis(cdc codec.JSONCodec) json.RawMessage {
|
||||
return cdc.MustMarshalJSON(&types.GenesisState{
|
||||
Params: types.DefaultParams(),
|
||||
GlobalIntegrity: types.DefaultGlobalIntegrity(),
|
||||
Params: types.DefaultParams(),
|
||||
})
|
||||
}
|
||||
|
||||
@ -82,28 +85,13 @@ func (a AppModuleBasic) ValidateGenesis(marshaler codec.JSONCodec, _ client.TxEn
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a AppModuleBasic) RegisterRESTRoutes(_ client.Context, _ *mux.Router) {
|
||||
}
|
||||
|
||||
func (a AppModuleBasic) RegisterGRPCGatewayRoutes(clientCtx client.Context, mux *runtime.ServeMux) {
|
||||
err := types.RegisterQueryHandlerClient(context.Background(), mux, types.NewQueryClient(clientCtx))
|
||||
if err != nil {
|
||||
// same behavior as in cosmos-sdk
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
// Disable in favor of autocli.go. If you wish to use these, it will override AutoCLI methods.
|
||||
/*
|
||||
func (a AppModuleBasic) GetTxCmd() *cobra.Command {
|
||||
return cli.NewTxCmd()
|
||||
}
|
||||
|
||||
func (a AppModuleBasic) GetQueryCmd() *cobra.Command {
|
||||
return cli.GetQueryCmd()
|
||||
}
|
||||
*/
|
||||
|
||||
func (AppModuleBasic) RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) {
|
||||
types.RegisterLegacyAminoCodec(cdc)
|
||||
}
|
||||
@ -113,11 +101,15 @@ func (a AppModuleBasic) RegisterInterfaces(r codectypes.InterfaceRegistry) {
|
||||
}
|
||||
|
||||
func (a AppModule) InitGenesis(ctx sdk.Context, marshaler codec.JSONCodec, message json.RawMessage) []abci.ValidatorUpdate {
|
||||
genesisState := types.DefaultGenesis()
|
||||
if err := a.keeper.Params.Set(ctx, genesisState.Params); err != nil {
|
||||
didGenesisState := types.DefaultGenesis()
|
||||
if err := a.keeper.Params.Set(ctx, didGenesisState.Params); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
nftGenesisState := nft.DefaultGenesisState()
|
||||
if err := types.DefaultNFTClasses(nftGenesisState); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
a.nftKeeper.InitGenesis(ctx, nftGenesisState)
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -1,10 +1,16 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
"crypto/ecdsa"
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"strings"
|
||||
|
||||
fmt "fmt"
|
||||
|
||||
ethcrypto "github.com/ethereum/go-ethereum/crypto"
|
||||
"golang.org/x/crypto/sha3"
|
||||
|
||||
"github.com/cosmos/btcutil/bech32"
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
"github.com/cosmos/cosmos-sdk/codec/types"
|
||||
@ -71,7 +77,11 @@ func (c ChainCode) FormatAddress(pubKey *PubKey) (string, error) {
|
||||
return bech32.Encode("bc", pubKey.Bytes())
|
||||
|
||||
case ChainCodeETH:
|
||||
return bech32.Encode("eth", pubKey.Bytes())
|
||||
epk, err := pubKey.ECDSA()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return ComputeEthAddress(*epk), nil
|
||||
|
||||
case ChainCodeSNR:
|
||||
return bech32.Encode("idx", pubKey.Bytes())
|
||||
@ -198,3 +208,30 @@ func ComputeOriginTXTRecord(origin string) string {
|
||||
h.Write([]byte(origin))
|
||||
return fmt.Sprintf("v=sonr,o=%s,p=%x", origin, h.Sum(nil))
|
||||
}
|
||||
|
||||
func ComputeEthAddress(pk ecdsa.PublicKey) string {
|
||||
// Generate Ethereum address
|
||||
address := ethcrypto.PubkeyToAddress(pk)
|
||||
|
||||
// Apply ERC-55 checksum encoding
|
||||
addr := address.Hex()
|
||||
addr = strings.ToLower(addr)
|
||||
addr = strings.TrimPrefix(addr, "0x")
|
||||
hash := sha3.NewLegacyKeccak256()
|
||||
hash.Write([]byte(addr))
|
||||
hashBytes := hash.Sum(nil)
|
||||
|
||||
result := "0x"
|
||||
for i, c := range addr {
|
||||
if c >= '0' && c <= '9' {
|
||||
result += string(c)
|
||||
} else {
|
||||
if hashBytes[i/2]>>(4-i%2*4)&0xf >= 8 {
|
||||
result += strings.ToUpper(string(c))
|
||||
} else {
|
||||
result += string(c)
|
||||
}
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
@ -2,10 +2,11 @@ package types
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"cosmossdk.io/collections"
|
||||
fmt "fmt"
|
||||
|
||||
ormv1alpha1 "cosmossdk.io/api/cosmos/orm/v1alpha1"
|
||||
"cosmossdk.io/collections"
|
||||
"cosmossdk.io/x/nft"
|
||||
)
|
||||
|
||||
// ParamsKey saves the current module params.
|
||||
@ -35,7 +36,8 @@ const DefaultIndex uint64 = 1
|
||||
func DefaultGenesis() *GenesisState {
|
||||
return &GenesisState{
|
||||
// this line is used by starport scaffolding # genesis/types/default
|
||||
Params: DefaultParams(),
|
||||
GlobalIntegrity: DefaultGlobalIntegrity(),
|
||||
Params: DefaultParams(),
|
||||
}
|
||||
}
|
||||
|
||||
@ -43,15 +45,24 @@ func DefaultGenesis() *GenesisState {
|
||||
// failure.
|
||||
func (gs GenesisState) Validate() error {
|
||||
// this line is used by starport scaffolding # genesis/types/validate
|
||||
|
||||
if gs.GlobalIntegrity == nil {
|
||||
return fmt.Errorf("global integrity proof is nil")
|
||||
}
|
||||
return gs.Params.Validate()
|
||||
}
|
||||
|
||||
// DefaultNFTClasses configures the Initial DIDNamespace NFT classes
|
||||
func DefaultNFTClasses(nftGenesis *nft.GenesisState) error {
|
||||
for _, n := range DIDNamespace_value {
|
||||
nftGenesis.Classes = append(nftGenesis.Classes, DIDNamespace(n).GetNFTClass())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// DefaultParams returns default module parameters.
|
||||
func DefaultParams() Params {
|
||||
return Params{
|
||||
WhitelistedAssets: DefaultAssets(),
|
||||
WhitelistedChains: DefaultChains(),
|
||||
AllowedPublicKeys: DefaultKeyInfos(),
|
||||
LocalhostRegistrationEnabled: true,
|
||||
ConveyancePreference: "direct",
|
||||
@ -59,6 +70,25 @@ func DefaultParams() Params {
|
||||
}
|
||||
}
|
||||
|
||||
// DefaultGlobalIntegrity returns the default global integrity proof
|
||||
func DefaultGlobalIntegrity() *GlobalIntegrity {
|
||||
return &GlobalIntegrity{
|
||||
Controller: "did:sonr:0x0",
|
||||
Seed: DefaultSeedMessage(),
|
||||
Accumulator: []byte{},
|
||||
Count: 0,
|
||||
}
|
||||
}
|
||||
|
||||
// DefaultSeedMessage returns the default seed message
|
||||
func DefaultSeedMessage() string {
|
||||
l1 := "The Sonr Network shall make no protocol that respects the establishment of centralized authority,"
|
||||
l2 := "or prohibits the free exercise of decentralized identity; or abridges the freedom of data sovereignty,"
|
||||
l3 := "or of encrypted communication; or the right of the users to peaceally interact and transact,"
|
||||
l4 := "and to petition the Network for the redress of vulnerabilities."
|
||||
return fmt.Sprintf("%s %s %s %s", l1, l2, l3, l4)
|
||||
}
|
||||
|
||||
// DefaultAssets returns the default asset infos: BTC, ETH, SNR, and USDC
|
||||
func DefaultAssets() []*AssetInfo {
|
||||
return []*AssetInfo{
|
||||
@ -89,17 +119,12 @@ func DefaultAssets() []*AssetInfo {
|
||||
}
|
||||
}
|
||||
|
||||
// DefaultChains returns the default chain infos: Bitcoin, Ethereum, and Sonr.
|
||||
func DefaultChains() []*ChainInfo {
|
||||
return []*ChainInfo{}
|
||||
}
|
||||
|
||||
// DefaultKeyInfos returns the default key infos: secp256k1, ed25519, keccak256, and bls12381.
|
||||
func DefaultKeyInfos() []*KeyInfo {
|
||||
return []*KeyInfo{
|
||||
func DefaultKeyInfos() map[string]*KeyInfo {
|
||||
return map[string]*KeyInfo{
|
||||
// Identity Key Info
|
||||
// Sonr Controller Key Info - From MPC
|
||||
{
|
||||
"auth.dwn": {
|
||||
Role: KeyRole_KEY_ROLE_INVOCATION,
|
||||
Curve: KeyCurve_KEY_CURVE_P256,
|
||||
Algorithm: KeyAlgorithm_KEY_ALGORITHM_ECDSA,
|
||||
@ -108,7 +133,7 @@ func DefaultKeyInfos() []*KeyInfo {
|
||||
},
|
||||
|
||||
// Sonr Vault Shared Key Info - From Registration
|
||||
{
|
||||
"auth.zk": {
|
||||
Role: KeyRole_KEY_ROLE_ASSERTION,
|
||||
Curve: KeyCurve_KEY_CURVE_BLS12381,
|
||||
Algorithm: KeyAlgorithm_KEY_ALGORITHM_UNSPECIFIED,
|
||||
@ -118,7 +143,7 @@ func DefaultKeyInfos() []*KeyInfo {
|
||||
|
||||
// Blockchain Key Info
|
||||
// Ethereum Key Info
|
||||
{
|
||||
"auth.ethereum": {
|
||||
Role: KeyRole_KEY_ROLE_DELEGATION,
|
||||
Curve: KeyCurve_KEY_CURVE_KECCAK256,
|
||||
Algorithm: KeyAlgorithm_KEY_ALGORITHM_ECDSA,
|
||||
@ -126,7 +151,7 @@ func DefaultKeyInfos() []*KeyInfo {
|
||||
Type: KeyType_KEY_TYPE_BIP32,
|
||||
},
|
||||
// Bitcoin/IBC Key Info
|
||||
{
|
||||
"auth.bitcoin": {
|
||||
Role: KeyRole_KEY_ROLE_DELEGATION,
|
||||
Curve: KeyCurve_KEY_CURVE_SECP256K1,
|
||||
Algorithm: KeyAlgorithm_KEY_ALGORITHM_ECDSA,
|
||||
@ -136,7 +161,7 @@ func DefaultKeyInfos() []*KeyInfo {
|
||||
|
||||
// Authentication Key Info
|
||||
// Browser based WebAuthn
|
||||
{
|
||||
"webauthn.browser": {
|
||||
Role: KeyRole_KEY_ROLE_AUTHENTICATION,
|
||||
Curve: KeyCurve_KEY_CURVE_P256,
|
||||
Algorithm: KeyAlgorithm_KEY_ALGORITHM_ES256,
|
||||
@ -144,7 +169,7 @@ func DefaultKeyInfos() []*KeyInfo {
|
||||
Type: KeyType_KEY_TYPE_WEBAUTHN,
|
||||
},
|
||||
// FIDO U2F
|
||||
{
|
||||
"webauthn.fido": {
|
||||
Role: KeyRole_KEY_ROLE_AUTHENTICATION,
|
||||
Curve: KeyCurve_KEY_CURVE_P256,
|
||||
Algorithm: KeyAlgorithm_KEY_ALGORITHM_ES256,
|
||||
@ -152,7 +177,7 @@ func DefaultKeyInfos() []*KeyInfo {
|
||||
Type: KeyType_KEY_TYPE_WEBAUTHN,
|
||||
},
|
||||
// Cross-Platform Passkeys
|
||||
{
|
||||
"webauthn.passkey": {
|
||||
Role: KeyRole_KEY_ROLE_AUTHENTICATION,
|
||||
Curve: KeyCurve_KEY_CURVE_ED25519,
|
||||
Algorithm: KeyAlgorithm_KEY_ALGORITHM_EDDSA,
|
||||
@ -195,14 +220,6 @@ func (a *AssetInfo) Equal(b *AssetInfo) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// Equal returns true if two chain infos are equal
|
||||
func (c *ChainInfo) Equal(b *ChainInfo) bool {
|
||||
if c == nil && b == nil {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Equal returns true if two key infos are equal
|
||||
func (k *KeyInfo) Equal(b *KeyInfo) bool {
|
||||
if k == nil && b == nil {
|
||||
|
File diff suppressed because it is too large
Load Diff
27
x/did/types/integrity.go
Normal file
27
x/did/types/integrity.go
Normal file
@ -0,0 +1,27 @@
|
||||
package types
|
||||
|
||||
import "lukechampine.com/blake3"
|
||||
|
||||
func (g *GlobalIntegrity) Update(address string) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (g *GlobalIntegrity) getProof() (*Proof, error) {
|
||||
if g.Accumulator == nil {
|
||||
return NewProof(g.Controller, g.proofProperty(), g.seedKdf())
|
||||
}
|
||||
return &Proof{
|
||||
Issuer: g.Controller,
|
||||
Property: g.proofProperty(),
|
||||
Accumulator: g.Accumulator,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (g *GlobalIntegrity) proofProperty() string {
|
||||
return "did:sonr:integrity"
|
||||
}
|
||||
|
||||
func (g *GlobalIntegrity) seedKdf() []byte {
|
||||
res := blake3.Sum256([]byte(g.Seed))
|
||||
return res[:]
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user