mirror of
https://github.com/sonr-io/sonr.git
synced 2026-08-02 17:31:39 +00:00
feature/refactor did state (#10)
* feat(did): remove account types * feat: Refactor Property to Proof in zkprop.go * feat: add ZKP proof mechanism for verifications * fix: return bool and error from pinInitialVault * feat: implement KeyshareSet for managing user and validator keyshares * feat: Update Credential type in protobuf * feat: update credential schema with sign count * feat: migrate and modules to middleware * refactor: rename vault module to ORM * chore(dwn): add service worker registration to index template * feat: integrate service worker for offline functionality * refactor(did): use DIDNamespace enum for verification method in proto reflection * refactor: update protobuf definitions to support Keyshare * feat: expose did keeper in app keepers * Add Motr Web App * refactor: rename motr/handlers/discovery.go to motr/handlers/openid.go * refactor: move session related code to middleware * feat: add database operations for managing assets, chains, and credentials * feat: add htmx support for UI updates * refactor: extract common helper scripts * chore: remove unused storage GUI components * refactor: Move frontend rendering to dedicated handlers * refactor: rename to * refactor: move alert implementation to templ * feat: add alert component with icon, title, and message * feat: add new RequestHeaders struct to store request headers * Feature/create home view (#9) * refactor: move view logic to new htmx handler * refactor: remove unnecessary dependencies * refactor: remove unused dependencies * feat(devbox): integrate air for local development * feat: implement openid connect discovery document * refactor: rename to * refactor(did): update service handling to support DNS discovery * feat: add support for user and validator keyshares * refactor: move keyshare signing logic to signer
This commit is contained in:
@@ -0,0 +1,91 @@
|
||||
package db
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/onsonr/sonr/internal/db/orm"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
// createInitialTables creates the initial tables in the database.
|
||||
func createInitialTables(db *gorm.DB) (*DB, error) {
|
||||
err := db.AutoMigrate(
|
||||
&orm.Account{},
|
||||
&orm.Asset{},
|
||||
&orm.Keyshare{},
|
||||
&orm.Credential{},
|
||||
&orm.Profile{},
|
||||
&orm.Property{},
|
||||
&orm.Permission{},
|
||||
)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create table: %w", err)
|
||||
}
|
||||
|
||||
return &DB{db}, nil
|
||||
}
|
||||
|
||||
// AddAccount adds a new account to the database
|
||||
func (db *DB) AddAccount(account *orm.Account) error {
|
||||
tx := db.Create(account)
|
||||
if tx.Error != nil {
|
||||
return fmt.Errorf("failed to add account: %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
|
||||
}
|
||||
|
||||
// AddCredential adds a new credential to the database
|
||||
func (db *DB) AddCredential(credential *orm.Credential) error {
|
||||
tx := db.Create(credential)
|
||||
|
||||
if tx.Error != nil {
|
||||
return fmt.Errorf("failed to add credential: %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)
|
||||
|
||||
if tx.Error != nil {
|
||||
return fmt.Errorf("failed to add 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)
|
||||
|
||||
if tx.Error != nil {
|
||||
return fmt.Errorf("failed to add property: %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
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package db
|
||||
|
||||
import "gorm.io/gorm"
|
||||
|
||||
type DB struct {
|
||||
*gorm.DB
|
||||
}
|
||||
|
||||
func New(opts ...DBOption) *DBConfig {
|
||||
config := &DBConfig{
|
||||
fileName: "vault.db",
|
||||
}
|
||||
for _, opt := range opts {
|
||||
opt(config)
|
||||
}
|
||||
return config
|
||||
}
|
||||
@@ -1,174 +0,0 @@
|
||||
package db
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/ncruces/go-sqlite3"
|
||||
_ "github.com/ncruces/go-sqlite3/embed"
|
||||
)
|
||||
|
||||
type DB struct {
|
||||
*sqlite3.Conn
|
||||
}
|
||||
|
||||
func New(opts ...DBOption) *DBConfig {
|
||||
config := &DBConfig{
|
||||
fileName: "vault.db",
|
||||
}
|
||||
for _, opt := range opts {
|
||||
opt(config)
|
||||
}
|
||||
return config
|
||||
}
|
||||
|
||||
func Open(config *DBConfig) (*DB, error) {
|
||||
conn, err := sqlite3.Open(config.ConnectionString())
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to open database: %w", err)
|
||||
}
|
||||
|
||||
db := &DB{
|
||||
Conn: conn,
|
||||
}
|
||||
|
||||
if err := createTables(db); err != nil {
|
||||
conn.Close()
|
||||
return nil, fmt.Errorf("failed to create tables: %w", err)
|
||||
}
|
||||
return db, nil
|
||||
}
|
||||
|
||||
func createTables(db *DB) error {
|
||||
tables := []string{
|
||||
createAccountsTable,
|
||||
createAssetsTable,
|
||||
createChainsTable,
|
||||
createCredentialsTable,
|
||||
createKeysharesTable,
|
||||
createProfilesTable,
|
||||
createPropertiesTable,
|
||||
createPermissionsTable,
|
||||
}
|
||||
|
||||
for _, table := range tables {
|
||||
err := db.Exec(table)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create table: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// AddAccount adds a new account to the database
|
||||
func (db *DB) AddAccount(name, address string) error {
|
||||
return db.Exec(insertAccountQuery(name, address))
|
||||
}
|
||||
|
||||
// AddAsset adds a new asset to the database
|
||||
func (db *DB) AddAsset(name, symbol string, decimals int, chainID int64) error {
|
||||
return db.Exec(insertAssetQuery(name, symbol, decimals, chainID))
|
||||
}
|
||||
|
||||
// AddChain adds a new chain to the database
|
||||
func (db *DB) AddChain(name, networkID string) error {
|
||||
return db.Exec(insertChainQuery(name, networkID))
|
||||
}
|
||||
|
||||
// AddCredential adds a new credential to the database
|
||||
func (db *DB) AddCredential(
|
||||
handle, controller, attestationType, origin string,
|
||||
credentialID, publicKey []byte,
|
||||
transport string,
|
||||
signCount uint32,
|
||||
userPresent, userVerified, backupEligible, backupState, cloneWarning bool,
|
||||
) error {
|
||||
return db.Exec(insertCredentialQuery(
|
||||
handle,
|
||||
controller,
|
||||
attestationType,
|
||||
origin,
|
||||
credentialID,
|
||||
publicKey,
|
||||
transport,
|
||||
signCount,
|
||||
userPresent,
|
||||
userVerified,
|
||||
backupEligible,
|
||||
backupState,
|
||||
cloneWarning,
|
||||
))
|
||||
}
|
||||
|
||||
//
|
||||
// // AddProfile adds a new profile to the database
|
||||
// func (db *DB) AddProfile(
|
||||
// id, subject, controller, originURI string,
|
||||
// publicMetadata, privateMetadata string,
|
||||
// ) error {
|
||||
// return db.statements["insertProfile"].Exec(
|
||||
// id,
|
||||
// subject,
|
||||
// controller,
|
||||
// originURI,
|
||||
// publicMetadata,
|
||||
// privateMetadata,
|
||||
// )
|
||||
// }
|
||||
//
|
||||
// // AddProperty adds a new property to the database
|
||||
// func (db *DB) AddProperty(profileID, key string, accumulator, propertyKey []byte) error {
|
||||
// return db.statements["insertProperty"].Exec(profileID, key, accumulator, propertyKey)
|
||||
// }
|
||||
//
|
||||
// // AddPermission adds a new permission to the database
|
||||
// func (db *DB) AddPermission(
|
||||
// serviceID string,
|
||||
// grants []DIDNamespace,
|
||||
// scopes []PermissionScope,
|
||||
// ) error {
|
||||
// grantsJSON, err := json.Marshal(grants)
|
||||
// if err != nil {
|
||||
// return fmt.Errorf("failed to marshal grants: %w", err)
|
||||
// }
|
||||
//
|
||||
// scopesJSON, err := json.Marshal(scopes)
|
||||
// if err != nil {
|
||||
// return fmt.Errorf("failed to marshal scopes: %w", err)
|
||||
// }
|
||||
//
|
||||
// return db.statements["insertPermission"].Exec(
|
||||
// serviceID,
|
||||
// string(grantsJSON),
|
||||
// string(scopesJSON),
|
||||
// )
|
||||
// }
|
||||
//
|
||||
// // GetPermission retrieves a permission from the database
|
||||
// func (db *DB) GetPermission(serviceID string) ([]DIDNamespace, []PermissionScope, error) {
|
||||
// stmt := db.statements["getPermission"]
|
||||
// if err := stmt.Exec(serviceID); err != nil {
|
||||
// return nil, nil, fmt.Errorf("failed to execute statement: %w", err)
|
||||
// }
|
||||
//
|
||||
// if !stmt.Step() {
|
||||
// return nil, nil, fmt.Errorf("permission not found")
|
||||
// }
|
||||
//
|
||||
// grantsJSON := stmt.ColumnText(0)
|
||||
// scopesJSON := stmt.ColumnText(1)
|
||||
//
|
||||
// var grants []DIDNamespace
|
||||
// err := json.Unmarshal([]byte(grantsJSON), &grants)
|
||||
// if err != nil {
|
||||
// return nil, nil, fmt.Errorf("failed to unmarshal grants: %w", err)
|
||||
// }
|
||||
//
|
||||
// var scopes []PermissionScope
|
||||
// err = json.Unmarshal([]byte(scopesJSON), &scopes)
|
||||
// if err != nil {
|
||||
// return nil, nil, fmt.Errorf("failed to unmarshal scopes: %w", err)
|
||||
// }
|
||||
//
|
||||
// return grants, scopes, nil
|
||||
// }
|
||||
@@ -1,36 +0,0 @@
|
||||
package db
|
||||
|
||||
// DIDNamespace defines the different namespaces of DID
|
||||
type DIDNamespace int
|
||||
|
||||
const (
|
||||
DIDNamespaceUnspecified DIDNamespace = iota
|
||||
DIDNamespaceIPFS
|
||||
DIDNamespaceSonr
|
||||
DIDNamespaceBitcoin
|
||||
DIDNamespaceEthereum
|
||||
DIDNamespaceIBC
|
||||
DIDNamespaceWebauthn
|
||||
DIDNamespaceDWN
|
||||
DIDNamespaceService
|
||||
)
|
||||
|
||||
// PermissionScope defines the Capabilities Controllers can grant for Services
|
||||
type PermissionScope int
|
||||
|
||||
const (
|
||||
PermissionScopeUnspecified PermissionScope = iota
|
||||
PermissionScopeBasicInfo
|
||||
PermissionScopeRecordsRead
|
||||
PermissionScopeRecordsWrite
|
||||
PermissionScopeTransactionsRead
|
||||
PermissionScopeTransactionsWrite
|
||||
PermissionScopeWalletsRead
|
||||
PermissionScopeWalletsCreate
|
||||
PermissionScopeWalletsSubscribe
|
||||
PermissionScopeWalletsUpdate
|
||||
PermissionScopeTransactionsVerify
|
||||
PermissionScopeTransactionsBroadcast
|
||||
PermissionScopeAdminUser
|
||||
PermissionScopeAdminValidator
|
||||
)
|
||||
+9
-22
@@ -4,11 +4,12 @@ import (
|
||||
"crypto/rand"
|
||||
|
||||
"github.com/ncruces/go-sqlite3/gormlite"
|
||||
"github.com/ncruces/go-sqlite3/vfs"
|
||||
"golang.org/x/crypto/argon2"
|
||||
"gorm.io/gorm"
|
||||
"lukechampine.com/adiantum/hbsh"
|
||||
"lukechampine.com/adiantum/hpolyc"
|
||||
|
||||
_ "github.com/ncruces/go-sqlite3/embed"
|
||||
)
|
||||
|
||||
type DBOption func(config *DBConfig)
|
||||
@@ -19,46 +20,32 @@ func WithDir(dir string) DBOption {
|
||||
}
|
||||
}
|
||||
|
||||
func WithInMemory() DBOption {
|
||||
return func(config *DBConfig) {
|
||||
config.InMemory = true
|
||||
}
|
||||
}
|
||||
|
||||
func WithSecretKey(secretKey string) DBOption {
|
||||
return func(config *DBConfig) {
|
||||
config.SecretKey = secretKey
|
||||
}
|
||||
}
|
||||
|
||||
func WithOpenFlag(flag vfs.OpenFlag) DBOption {
|
||||
return func(config *DBConfig) {
|
||||
config.OpenFlag = flag
|
||||
}
|
||||
}
|
||||
|
||||
type DBConfig struct {
|
||||
Dir string
|
||||
InMemory bool
|
||||
SecretKey string
|
||||
OpenFlag vfs.OpenFlag
|
||||
|
||||
fileName string
|
||||
}
|
||||
|
||||
func (config *DBConfig) ConnectionString() string {
|
||||
connStr := "file:"
|
||||
if config.InMemory {
|
||||
connStr += ":memory:"
|
||||
} else {
|
||||
connStr += config.Dir + "/" + config.fileName
|
||||
}
|
||||
connStr += config.Dir + "/" + config.fileName
|
||||
return connStr
|
||||
}
|
||||
|
||||
// GormDialector creates a gorm dialector for the database.
|
||||
func (config *DBConfig) GormDialector() (*gorm.DB, error) {
|
||||
return gorm.Open(gormlite.Open(config.ConnectionString()))
|
||||
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.
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
// Code generated from Pkl module `orm`. DO NOT EDIT.
|
||||
package orm
|
||||
|
||||
type Account struct {
|
||||
Id uint `pkl:"id" gorm:"primaryKey,autoIncrement" json:"id,omitempty" query:"id"`
|
||||
|
||||
Name string `pkl:"name" json:"name,omitempty" param:"name"`
|
||||
|
||||
Address string `pkl:"address" json:"address,omitempty" param:"address"`
|
||||
|
||||
PublicKey string `pkl:"publicKey" json:"publicKey,omitempty" param:"publicKey"`
|
||||
|
||||
CreatedAt *string `pkl:"createdAt" json:"createdAt,omitempty" param:"createdAt"`
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
// Code generated from Pkl module `orm`. DO NOT EDIT.
|
||||
package orm
|
||||
|
||||
type Asset struct {
|
||||
Id uint `pkl:"id" gorm:"primaryKey,autoIncrement" json:"id,omitempty" query:"id"`
|
||||
|
||||
Name string `pkl:"name" json:"name,omitempty" param:"name"`
|
||||
|
||||
Symbol string `pkl:"symbol" json:"symbol,omitempty" param:"symbol"`
|
||||
|
||||
Decimals int `pkl:"decimals" json:"decimals,omitempty" param:"decimals"`
|
||||
|
||||
ChainId *int `pkl:"chainId" json:"chainId,omitempty" param:"chainId"`
|
||||
|
||||
CreatedAt *string `pkl:"createdAt" json:"createdAt,omitempty" param:"createdAt"`
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
// Code generated from Pkl module `orm`. DO NOT EDIT.
|
||||
package orm
|
||||
|
||||
type Chain struct {
|
||||
Id uint `pkl:"id" gorm:"primaryKey,autoIncrement" json:"id,omitempty" query:"id"`
|
||||
|
||||
Name string `pkl:"name" json:"name,omitempty" param:"name"`
|
||||
|
||||
NetworkId string `pkl:"networkId" json:"networkId,omitempty" param:"networkId"`
|
||||
|
||||
CreatedAt *string `pkl:"createdAt" json:"createdAt,omitempty" param:"createdAt"`
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
// Code generated from Pkl module `orm`. DO NOT EDIT.
|
||||
package orm
|
||||
|
||||
type Credential struct {
|
||||
Id uint `pkl:"id" gorm:"primaryKey,autoIncrement" json:"id,omitempty" query:"id"`
|
||||
|
||||
Subject string `pkl:"subject" json:"subject,omitempty" param:"subject"`
|
||||
|
||||
Controller string `pkl:"controller" json:"controller,omitempty" param:"controller"`
|
||||
|
||||
AttestationType string `pkl:"attestationType" json:"attestationType,omitempty" param:"attestationType"`
|
||||
|
||||
Origin string `pkl:"origin" json:"origin,omitempty" param:"origin"`
|
||||
|
||||
CredentialId string `pkl:"credentialId" json:"credentialId,omitempty" param:"credentialId"`
|
||||
|
||||
PublicKey string `pkl:"publicKey" json:"publicKey,omitempty" param:"publicKey"`
|
||||
|
||||
Transport string `pkl:"transport" json:"transport,omitempty" param:"transport"`
|
||||
|
||||
SignCount uint `pkl:"signCount" json:"signCount,omitempty" param:"signCount"`
|
||||
|
||||
UserPresent bool `pkl:"userPresent" json:"userPresent,omitempty" param:"userPresent"`
|
||||
|
||||
UserVerified bool `pkl:"userVerified" json:"userVerified,omitempty" param:"userVerified"`
|
||||
|
||||
BackupEligible bool `pkl:"backupEligible" json:"backupEligible,omitempty" param:"backupEligible"`
|
||||
|
||||
BackupState bool `pkl:"backupState" json:"backupState,omitempty" param:"backupState"`
|
||||
|
||||
CloneWarning bool `pkl:"cloneWarning" json:"cloneWarning,omitempty" param:"cloneWarning"`
|
||||
|
||||
CreatedAt *string `pkl:"createdAt" json:"createdAt,omitempty" param:"createdAt"`
|
||||
|
||||
UpdatedAt *string `pkl:"updatedAt" json:"updatedAt,omitempty" param:"updatedAt"`
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
// Code generated from Pkl module `orm`. DO NOT EDIT.
|
||||
package orm
|
||||
|
||||
type DiscoveryDocument struct {
|
||||
Issuer string `pkl:"issuer" json:"issuer,omitempty" param:"issuer"`
|
||||
|
||||
AuthorizationEndpoint string `pkl:"authorization_endpoint" json:"authorization_endpoint,omitempty" param:"authorization_endpoint"`
|
||||
|
||||
TokenEndpoint string `pkl:"token_endpoint" json:"token_endpoint,omitempty" param:"token_endpoint"`
|
||||
|
||||
UserinfoEndpoint string `pkl:"userinfo_endpoint" json:"userinfo_endpoint,omitempty" param:"userinfo_endpoint"`
|
||||
|
||||
JwksUri string `pkl:"jwks_uri" json:"jwks_uri,omitempty" param:"jwks_uri"`
|
||||
|
||||
RegistrationEndpoint string `pkl:"registration_endpoint" json:"registration_endpoint,omitempty" param:"registration_endpoint"`
|
||||
|
||||
ScopesSupported []string `pkl:"scopes_supported" json:"scopes_supported,omitempty" param:"scopes_supported"`
|
||||
|
||||
ResponseTypesSupported []string `pkl:"response_types_supported" json:"response_types_supported,omitempty" param:"response_types_supported"`
|
||||
|
||||
ResponseModesSupported []string `pkl:"response_modes_supported" json:"response_modes_supported,omitempty" param:"response_modes_supported"`
|
||||
|
||||
SubjectTypesSupported []string `pkl:"subject_types_supported" json:"subject_types_supported,omitempty" param:"subject_types_supported"`
|
||||
|
||||
IdTokenSigningAlgValuesSupported []string `pkl:"id_token_signing_alg_values_supported" json:"id_token_signing_alg_values_supported,omitempty" param:"id_token_signing_alg_values_supported"`
|
||||
|
||||
ClaimsSupported []string `pkl:"claims_supported" json:"claims_supported,omitempty" param:"claims_supported"`
|
||||
|
||||
GrantTypesSupported []string `pkl:"grant_types_supported" json:"grant_types_supported,omitempty" param:"grant_types_supported"`
|
||||
|
||||
AcrValuesSupported []string `pkl:"acr_values_supported" json:"acr_values_supported,omitempty" param:"acr_values_supported"`
|
||||
|
||||
TokenEndpointAuthMethodsSupported []string `pkl:"token_endpoint_auth_methods_supported" json:"token_endpoint_auth_methods_supported,omitempty" param:"token_endpoint_auth_methods_supported"`
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
// Code generated from Pkl module `orm`. DO NOT EDIT.
|
||||
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"`
|
||||
|
||||
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"`
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
// Code generated from Pkl module `orm`. DO NOT EDIT.
|
||||
package orm
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/apple/pkl-go/pkl"
|
||||
)
|
||||
|
||||
type Orm struct {
|
||||
}
|
||||
|
||||
// LoadFromPath loads the pkl module at the given path and evaluates it into a Orm
|
||||
func LoadFromPath(ctx context.Context, path string) (ret *Orm, err error) {
|
||||
evaluator, err := pkl.NewEvaluator(ctx, pkl.PreconfiguredOptions)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer func() {
|
||||
cerr := evaluator.Close()
|
||||
if err == nil {
|
||||
err = cerr
|
||||
}
|
||||
}()
|
||||
ret, err = Load(ctx, evaluator, pkl.FileSource(path))
|
||||
return ret, err
|
||||
}
|
||||
|
||||
// Load loads the pkl module at the given source and evaluates it with the given evaluator into a Orm
|
||||
func Load(ctx context.Context, evaluator pkl.Evaluator, source *pkl.ModuleSource) (*Orm, error) {
|
||||
var ret Orm
|
||||
if err := evaluator.EvaluateModule(ctx, source, &ret); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &ret, nil
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
// Code generated from Pkl module `orm`. DO NOT EDIT.
|
||||
package orm
|
||||
|
||||
type Permission struct {
|
||||
Id uint `pkl:"id" gorm:"primaryKey,autoIncrement" json:"id,omitempty" query:"id"`
|
||||
|
||||
ServiceId string `pkl:"serviceId" json:"serviceId,omitempty" param:"serviceId"`
|
||||
|
||||
Grants string `pkl:"grants" json:"grants,omitempty" param:"grants"`
|
||||
|
||||
Scopes string `pkl:"scopes" json:"scopes,omitempty" param:"scopes"`
|
||||
|
||||
CreatedAt *string `pkl:"createdAt" json:"createdAt,omitempty" param:"createdAt"`
|
||||
|
||||
UpdatedAt *string `pkl:"updatedAt" json:"updatedAt,omitempty" param:"updatedAt"`
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
// Code generated from Pkl module `orm`. DO NOT EDIT.
|
||||
package orm
|
||||
|
||||
type Profile struct {
|
||||
Id string `pkl:"id" gorm:"primaryKey,autoIncrement" json:"id,omitempty" query:"id"`
|
||||
|
||||
Subject string `pkl:"subject" json:"subject,omitempty" param:"subject"`
|
||||
|
||||
Controller string `pkl:"controller" json:"controller,omitempty" param:"controller"`
|
||||
|
||||
OriginUri *string `pkl:"originUri" json:"originUri,omitempty" param:"originUri"`
|
||||
|
||||
PublicMetadata *string `pkl:"publicMetadata" json:"publicMetadata,omitempty" param:"publicMetadata"`
|
||||
|
||||
PrivateMetadata *string `pkl:"privateMetadata" json:"privateMetadata,omitempty" param:"privateMetadata"`
|
||||
|
||||
CreatedAt *string `pkl:"createdAt" json:"createdAt,omitempty" param:"createdAt"`
|
||||
|
||||
UpdatedAt *string `pkl:"updatedAt" json:"updatedAt,omitempty" param:"updatedAt"`
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
// Code generated from Pkl module `orm`. DO NOT EDIT.
|
||||
package orm
|
||||
|
||||
type Property struct {
|
||||
Id uint `pkl:"id" gorm:"primaryKey,autoIncrement" json:"id,omitempty" query:"id"`
|
||||
|
||||
ProfileId string `pkl:"profileId" json:"profileId,omitempty" param:"profileId"`
|
||||
|
||||
Key string `pkl:"key" json:"key,omitempty" param:"key"`
|
||||
|
||||
Accumulator string `pkl:"accumulator" json:"accumulator,omitempty" param:"accumulator"`
|
||||
|
||||
PropertyKey string `pkl:"propertyKey" json:"propertyKey,omitempty" param:"propertyKey"`
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
// 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"`
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
// Code generated from Pkl module `orm`. DO NOT EDIT.
|
||||
package orm
|
||||
|
||||
import "github.com/apple/pkl-go/pkl"
|
||||
|
||||
func init() {
|
||||
pkl.RegisterMapping("orm", Orm{})
|
||||
pkl.RegisterMapping("orm#Account", Account{})
|
||||
pkl.RegisterMapping("orm#Asset", Asset{})
|
||||
pkl.RegisterMapping("orm#Chain", Chain{})
|
||||
pkl.RegisterMapping("orm#Credential", Credential{})
|
||||
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{})
|
||||
}
|
||||
@@ -1,79 +0,0 @@
|
||||
package db
|
||||
|
||||
import "fmt"
|
||||
|
||||
// Account queries
|
||||
func insertAccountQuery(name, address string) string {
|
||||
return fmt.Sprintf(`INSERT INTO accounts (name, address) VALUES (%s, %s)`, name, address)
|
||||
}
|
||||
|
||||
// Asset queries
|
||||
func insertAssetQuery(name, symbol string, decimals int, chainID int64) string {
|
||||
return fmt.Sprintf(
|
||||
`INSERT INTO assets (name, symbol, decimals, chain_id) VALUES (%s, %s, %d, %d)`,
|
||||
name,
|
||||
symbol,
|
||||
decimals,
|
||||
chainID,
|
||||
)
|
||||
}
|
||||
|
||||
// Chain queries
|
||||
func insertChainQuery(name string, networkID string) string {
|
||||
return fmt.Sprintf(`INSERT INTO chains (name, network_id) VALUES (%s, %s)`, name, networkID)
|
||||
}
|
||||
|
||||
// Credential queries
|
||||
func insertCredentialQuery(
|
||||
handle, controller, attestationType, origin string,
|
||||
credentialID, publicKey []byte,
|
||||
transport string,
|
||||
signCount uint32,
|
||||
userPresent, userVerified, backupEligible, backupState, cloneWarning bool,
|
||||
) string {
|
||||
return fmt.Sprintf(`INSERT INTO credentials (
|
||||
handle, controller, attestation_type, origin,
|
||||
credential_id, public_key, transport, sign_count,
|
||||
user_present, user_verified, backup_eligible,
|
||||
backup_state, clone_warning
|
||||
) VALUES (%s, %s, %s, %s, %s, %s, %s, %d, %t, %t, %t, %t, %t)`,
|
||||
handle, controller, attestationType, origin,
|
||||
credentialID, publicKey, transport, signCount,
|
||||
userPresent, userVerified, backupEligible,
|
||||
backupState, cloneWarning)
|
||||
}
|
||||
|
||||
// Profile queries
|
||||
func insertProfileQuery(
|
||||
id, subject, controller, originURI, publicMetadata, privateMetadata string,
|
||||
) string {
|
||||
return fmt.Sprintf(`INSERT INTO profiles (
|
||||
id, subject, controller, origin_uri,
|
||||
public_metadata, private_metadata
|
||||
) VALUES (%s, %s, %s, %s, %s, %s)`,
|
||||
id, subject, controller, originURI,
|
||||
publicMetadata, privateMetadata)
|
||||
}
|
||||
|
||||
// Property queries
|
||||
func insertPropertyQuery(profileID, key, accumulator, propertyKey string) string {
|
||||
return fmt.Sprintf(`INSERT INTO properties (
|
||||
profile_id, key, accumulator, property_key
|
||||
) VALUES (%s, %s, %s, %s)`,
|
||||
profileID, key, accumulator, propertyKey)
|
||||
}
|
||||
|
||||
// Permission queries
|
||||
func insertPermissionQuery(serviceID, grants, scopes string) string {
|
||||
return fmt.Sprintf(
|
||||
`INSERT INTO permissions (service_id, grants, scopes) VALUES (%s, %s, %s)`,
|
||||
serviceID,
|
||||
grants,
|
||||
scopes,
|
||||
)
|
||||
}
|
||||
|
||||
// GetPermission query
|
||||
func getPermissionQuery(serviceID string) string {
|
||||
return fmt.Sprintf(`SELECT grants, scopes FROM permissions WHERE service_id = %s`, serviceID)
|
||||
}
|
||||
@@ -1,104 +0,0 @@
|
||||
package db
|
||||
|
||||
const (
|
||||
createAccountsTable = `
|
||||
CREATE TABLE IF NOT EXISTS accounts (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
name TEXT NOT NULL,
|
||||
address TEXT NOT NULL UNIQUE,
|
||||
public_key BLOB NOT NULL,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
)
|
||||
`
|
||||
|
||||
createAssetsTable = `
|
||||
CREATE TABLE IF NOT EXISTS assets (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
name TEXT NOT NULL,
|
||||
symbol TEXT NOT NULL,
|
||||
decimals INTEGER NOT NULL,
|
||||
chain_id INTEGER,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (chain_id) REFERENCES chains(id)
|
||||
)
|
||||
`
|
||||
|
||||
createChainsTable = `
|
||||
CREATE TABLE IF NOT EXISTS chains (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
name TEXT NOT NULL,
|
||||
network_id TEXT NOT NULL UNIQUE,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
)
|
||||
`
|
||||
|
||||
createCredentialsTable = `
|
||||
CREATE TABLE IF NOT EXISTS credentials (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
handle TEXT NOT NULL,
|
||||
controller TEXT NOT NULL,
|
||||
attestation_type TEXT NOT NULL,
|
||||
origin TEXT NOT NULL,
|
||||
credential_id BLOB NOT NULL,
|
||||
public_key BLOB NOT NULL,
|
||||
transport TEXT NOT NULL,
|
||||
sign_count INTEGER NOT NULL,
|
||||
user_present BOOLEAN NOT NULL,
|
||||
user_verified BOOLEAN NOT NULL,
|
||||
backup_eligible BOOLEAN NOT NULL,
|
||||
backup_state BOOLEAN NOT NULL,
|
||||
clone_warning BOOLEAN NOT NULL,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
)
|
||||
`
|
||||
|
||||
createProfilesTable = `
|
||||
CREATE TABLE IF NOT EXISTS profiles (
|
||||
id TEXT PRIMARY KEY,
|
||||
subject TEXT NOT NULL,
|
||||
controller TEXT NOT NULL,
|
||||
origin_uri TEXT,
|
||||
public_metadata TEXT,
|
||||
private_metadata TEXT,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
)
|
||||
`
|
||||
|
||||
createPropertiesTable = `
|
||||
CREATE TABLE IF NOT EXISTS properties (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
profile_id TEXT NOT NULL,
|
||||
key TEXT NOT NULL,
|
||||
accumulator BLOB NOT NULL,
|
||||
property_key BLOB NOT NULL,
|
||||
FOREIGN KEY (profile_id) REFERENCES profiles(id)
|
||||
)
|
||||
`
|
||||
|
||||
createKeysharesTable = `
|
||||
CREATE TABLE IF NOT EXISTS keyshares (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
metadata TEXT NOT NULL,
|
||||
payloads TEXT NOT NULL,
|
||||
protocol TEXT NOT NULL,
|
||||
public_key BLOB NOT NULL,
|
||||
role INTEGER NOT NULL,
|
||||
version INTEGER NOT NULL,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
)
|
||||
`
|
||||
|
||||
createPermissionsTable = `
|
||||
CREATE TABLE IF NOT EXISTS permissions (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
service_id TEXT NOT NULL,
|
||||
grants TEXT NOT NULL,
|
||||
scopes TEXT NOT NULL,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (service_id) REFERENCES services(id)
|
||||
)
|
||||
`
|
||||
)
|
||||
@@ -1,22 +0,0 @@
|
||||
package front
|
||||
|
||||
import (
|
||||
"log"
|
||||
"net/http"
|
||||
|
||||
"github.com/labstack/echo/v4"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
func NewServeFrontendCmd() *cobra.Command {
|
||||
return &cobra.Command{
|
||||
Use: "serve-web",
|
||||
Short: "TUI for managing the local Sonr validator node",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
e := echo.New()
|
||||
if err := e.Start(":42069"); err != http.ErrServerClosed {
|
||||
log.Fatal(err)
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
package handlers
|
||||
@@ -1 +0,0 @@
|
||||
package handlers
|
||||
@@ -1 +0,0 @@
|
||||
package handlers
|
||||
@@ -1 +0,0 @@
|
||||
package handlers
|
||||
@@ -1 +0,0 @@
|
||||
package routes
|
||||
@@ -1 +0,0 @@
|
||||
package routes
|
||||
@@ -0,0 +1,67 @@
|
||||
package elements
|
||||
|
||||
func Alert(variant Variant, icon Icon, title, message string) templ.Component {
|
||||
return alertElement(variant.Attributes(), title, message, icon.Render())
|
||||
}
|
||||
|
||||
templ alertElement(attrs templ.Attributes, title, message string, icon templ.Component) {
|
||||
<div { attrs... }>
|
||||
@icon
|
||||
<h5 class="mb-1 font-medium leading-none tracking-tight">{ title }</h5>
|
||||
<div class="text-sm opacity-70">{ message }</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
type AlertVariant int
|
||||
|
||||
const (
|
||||
AlertVariant_Default AlertVariant = iota
|
||||
AlertVariant_Info
|
||||
AlertVariant_Error
|
||||
AlertVariant_Success
|
||||
AlertVariant_Warning
|
||||
AlertVariant_Subtle_Info
|
||||
AlertVariant_Subtle_Error
|
||||
AlertVariant_Subtle_Success
|
||||
AlertVariant_Subtle_Warning
|
||||
)
|
||||
|
||||
func (v AlertVariant) Attributes() templ.Attributes {
|
||||
switch v {
|
||||
case AlertVariant_Info:
|
||||
return templ.Attributes{
|
||||
"class": "relative w-full rounded-lg border border-transparent bg-blue-600 p-4 [&>svg]:absolute [&>svg]:text-foreground [&>svg]:left-4 [&>svg]:top-4 [&>svg+div]:translate-y-[-3px] [&:has(svg)]:pl-11 text-white",
|
||||
}
|
||||
case AlertVariant_Error:
|
||||
return templ.Attributes{
|
||||
"class": "relative w-full rounded-lg border border-transparent bg-red-600 p-4 [&>svg]:absolute [&>svg]:text-foreground [&>svg]:left-4 [&>svg]:top-4 [&>svg+div]:translate-y-[-3px] [&:has(svg)]:pl-11 text-white",
|
||||
}
|
||||
case AlertVariant_Success:
|
||||
return templ.Attributes{
|
||||
"class": "relative w-full rounded-lg border border-transparent bg-green-500 p-4 [&>svg]:absolute [&>svg]:text-foreground [&>svg]:left-4 [&>svg]:top-4 [&>svg+div]:translate-y-[-3px] [&:has(svg)]:pl-11 text-white",
|
||||
}
|
||||
case AlertVariant_Warning:
|
||||
return templ.Attributes{
|
||||
"class": "relative w-full rounded-lg border border-transparent bg-yellow-500 p-4 [&>svg]:absolute [&>svg]:text-foreground [&>svg]:left-4 [&>svg]:top-4 [&>svg+div]:translate-y-[-3px] [&:has(svg)]:pl-11 text-white",
|
||||
}
|
||||
case AlertVariant_Subtle_Info:
|
||||
return templ.Attributes{
|
||||
"class": "relative w-full rounded-lg border border-transparent bg-blue-50 p-4 [&>svg]:absolute [&>svg]:text-foreground [&>svg]:left-4 [&>svg]:top-4 [&>svg+div]:translate-y-[-3px] [&:has(svg)]:pl-11 text-blue-600",
|
||||
}
|
||||
case AlertVariant_Subtle_Error:
|
||||
return templ.Attributes{
|
||||
"class": "relative w-full rounded-lg border border-transparent bg-red-50 p-4 [&>svg]:absolute [&>svg]:text-foreground [&>svg]:left-4 [&>svg]:top-4 [&>svg+div]:translate-y-[-3px] [&:has(svg)]:pl-11 text-red-600",
|
||||
}
|
||||
case AlertVariant_Subtle_Success:
|
||||
return templ.Attributes{
|
||||
"class": "relative w-full rounded-lg border border-transparent bg-green-50 p-4 [&>svg]:absolute [&>svg]:text-foreground [&>svg]:left-4 [&>svg]:top-4 [&>svg+div]:translate-y-[-3px] [&:has(svg)]:pl-11 text-green-600",
|
||||
}
|
||||
case AlertVariant_Subtle_Warning:
|
||||
return templ.Attributes{
|
||||
"class": "relative w-full rounded-lg border border-transparent bg-yellow-50 p-4 [&>svg]:absolute [&>svg]:text-foreground [&>svg]:left-4 [&>svg]:top-4 [&>svg+div]:translate-y-[-3px] [&:has(svg)]:pl-11 text-yellow-600",
|
||||
}
|
||||
}
|
||||
return templ.Attributes{
|
||||
"class": "relative w-full rounded-lg border bg-white p-4 [&>svg]:absolute [&>svg]:text-foreground [&>svg]:left-4 [&>svg]:top-4 [&>svg+div]:translate-y-[-3px] [&:has(svg)]:pl-11 text-neutral-900",
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,137 @@
|
||||
// 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 Alert(variant Variant, icon Icon, title, message string) templ.Component {
|
||||
return alertElement(variant.Attributes(), title, message, icon.Render())
|
||||
}
|
||||
|
||||
func alertElement(attrs templ.Attributes, title, message string, icon templ.Component) 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")
|
||||
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 = icon.Render(ctx, templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<h5 class=\"mb-1 font-medium leading-none tracking-tight\">")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var2 string
|
||||
templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs(title)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/gui/elements/alert.templ`, Line: 10, Col: 66}
|
||||
}
|
||||
_, 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("</h5><div class=\"text-sm opacity-70\">")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var3 string
|
||||
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(message)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/gui/elements/alert.templ`, Line: 11, Col: 43}
|
||||
}
|
||||
_, 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("</div></div>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
}
|
||||
|
||||
type AlertVariant int
|
||||
|
||||
const (
|
||||
AlertVariant_Default AlertVariant = iota
|
||||
AlertVariant_Info
|
||||
AlertVariant_Error
|
||||
AlertVariant_Success
|
||||
AlertVariant_Warning
|
||||
AlertVariant_Subtle_Info
|
||||
AlertVariant_Subtle_Error
|
||||
AlertVariant_Subtle_Success
|
||||
AlertVariant_Subtle_Warning
|
||||
)
|
||||
|
||||
func (v AlertVariant) Attributes() templ.Attributes {
|
||||
switch v {
|
||||
case AlertVariant_Info:
|
||||
return templ.Attributes{
|
||||
"class": "relative w-full rounded-lg border border-transparent bg-blue-600 p-4 [&>svg]:absolute [&>svg]:text-foreground [&>svg]:left-4 [&>svg]:top-4 [&>svg+div]:translate-y-[-3px] [&:has(svg)]:pl-11 text-white",
|
||||
}
|
||||
case AlertVariant_Error:
|
||||
return templ.Attributes{
|
||||
"class": "relative w-full rounded-lg border border-transparent bg-red-600 p-4 [&>svg]:absolute [&>svg]:text-foreground [&>svg]:left-4 [&>svg]:top-4 [&>svg+div]:translate-y-[-3px] [&:has(svg)]:pl-11 text-white",
|
||||
}
|
||||
case AlertVariant_Success:
|
||||
return templ.Attributes{
|
||||
"class": "relative w-full rounded-lg border border-transparent bg-green-500 p-4 [&>svg]:absolute [&>svg]:text-foreground [&>svg]:left-4 [&>svg]:top-4 [&>svg+div]:translate-y-[-3px] [&:has(svg)]:pl-11 text-white",
|
||||
}
|
||||
case AlertVariant_Warning:
|
||||
return templ.Attributes{
|
||||
"class": "relative w-full rounded-lg border border-transparent bg-yellow-500 p-4 [&>svg]:absolute [&>svg]:text-foreground [&>svg]:left-4 [&>svg]:top-4 [&>svg+div]:translate-y-[-3px] [&:has(svg)]:pl-11 text-white",
|
||||
}
|
||||
case AlertVariant_Subtle_Info:
|
||||
return templ.Attributes{
|
||||
"class": "relative w-full rounded-lg border border-transparent bg-blue-50 p-4 [&>svg]:absolute [&>svg]:text-foreground [&>svg]:left-4 [&>svg]:top-4 [&>svg+div]:translate-y-[-3px] [&:has(svg)]:pl-11 text-blue-600",
|
||||
}
|
||||
case AlertVariant_Subtle_Error:
|
||||
return templ.Attributes{
|
||||
"class": "relative w-full rounded-lg border border-transparent bg-red-50 p-4 [&>svg]:absolute [&>svg]:text-foreground [&>svg]:left-4 [&>svg]:top-4 [&>svg+div]:translate-y-[-3px] [&:has(svg)]:pl-11 text-red-600",
|
||||
}
|
||||
case AlertVariant_Subtle_Success:
|
||||
return templ.Attributes{
|
||||
"class": "relative w-full rounded-lg border border-transparent bg-green-50 p-4 [&>svg]:absolute [&>svg]:text-foreground [&>svg]:left-4 [&>svg]:top-4 [&>svg+div]:translate-y-[-3px] [&:has(svg)]:pl-11 text-green-600",
|
||||
}
|
||||
case AlertVariant_Subtle_Warning:
|
||||
return templ.Attributes{
|
||||
"class": "relative w-full rounded-lg border border-transparent bg-yellow-50 p-4 [&>svg]:absolute [&>svg]:text-foreground [&>svg]:left-4 [&>svg]:top-4 [&>svg+div]:translate-y-[-3px] [&:has(svg)]:pl-11 text-yellow-600",
|
||||
}
|
||||
}
|
||||
return templ.Attributes{
|
||||
"class": "relative w-full rounded-lg border bg-white p-4 [&>svg]:absolute [&>svg]:text-foreground [&>svg]:left-4 [&>svg]:top-4 [&>svg+div]:translate-y-[-3px] [&:has(svg)]:pl-11 text-neutral-900",
|
||||
}
|
||||
}
|
||||
|
||||
var _ = templruntime.GeneratedTemplate
|
||||
@@ -0,0 +1,5 @@
|
||||
package elements
|
||||
|
||||
templ Animation() {
|
||||
<lottie-player src="https://assets5.lottiefiles.com/packages/lf20_0c0a2a8a.json" background="transparent" speed="1" style="width: 100%; height: 100%;" loop autoplay></lottie-player>
|
||||
}
|
||||
@@ -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 Animation() 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("<lottie-player src=\"https://assets5.lottiefiles.com/packages/lf20_0c0a2a8a.json\" background=\"transparent\" speed=\"1\" style=\"width: 100%; height: 100%;\" loop autoplay></lottie-player>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
}
|
||||
|
||||
var _ = templruntime.GeneratedTemplate
|
||||
@@ -0,0 +1,134 @@
|
||||
package elements
|
||||
|
||||
func Button(variant Variant) templ.Component {
|
||||
return renderButton(variant.Attributes())
|
||||
}
|
||||
|
||||
templ renderButton(attrs templ.Attributes) {
|
||||
<button { attrs... }>
|
||||
{ children... }
|
||||
</button>
|
||||
}
|
||||
|
||||
type ButtonVariant int
|
||||
|
||||
const (
|
||||
ButtonVariantDefault ButtonVariant = iota
|
||||
ButtonVariantPrimary
|
||||
ButtonVariantInfo
|
||||
ButtonVariantError
|
||||
ButtonVariantSuccess
|
||||
ButtonVariantWarning
|
||||
)
|
||||
|
||||
func (v ButtonVariant) Attributes() templ.Attributes {
|
||||
switch v {
|
||||
case ButtonVariantPrimary:
|
||||
return templ.Attributes{
|
||||
"class": "inline-flex items-center justify-center px-4 py-2 text-sm font-medium tracking-wide text-white transition-colors duration-200 rounded-md bg-neutral-950 hover:bg-neutral-900 focus:ring-2 focus:ring-offset-2 focus:ring-neutral-900 focus:shadow-outline focus:outline-none",
|
||||
"type": "button",
|
||||
}
|
||||
case ButtonVariantInfo:
|
||||
return templ.Attributes{
|
||||
"class": "inline-flex items-center justify-center px-4 py-2 text-sm font-medium tracking-wide text-white transition-colors duration-200 bg-blue-600 rounded-md hover:bg-blue-700 focus:ring-2 focus:ring-offset-2 focus:ring-blue-700 focus:shadow-outline focus:outline-none",
|
||||
"type": "button",
|
||||
}
|
||||
case ButtonVariantError:
|
||||
return templ.Attributes{
|
||||
"class": "inline-flex items-center justify-center px-4 py-2 text-sm font-medium tracking-wide text-white transition-colors duration-200 rounded-md bg-red-600 hover:bg-red-700 focus:ring-2 focus:ring-offset-2 focus:ring-red-700 focus:shadow-outline focus:outline-none",
|
||||
"type": "button",
|
||||
}
|
||||
case ButtonVariantSuccess:
|
||||
return templ.Attributes{
|
||||
"class": "inline-flex items-center justify-center px-4 py-2 text-sm font-medium tracking-wide text-white transition-colors duration-200 rounded-md bg-green-600 hover:bg-green-700 focus:ring-2 focus:ring-offset-2 focus:ring-green-700 focus:shadow-outline focus:outline-none",
|
||||
"type": "button",
|
||||
}
|
||||
case ButtonVariantWarning:
|
||||
return templ.Attributes{
|
||||
"class": "inline-flex items-center justify-center px-4 py-2 text-sm font-medium tracking-wide text-white transition-colors duration-200 rounded-md bg-yellow-600 hover:bg-yellow-700 focus:ring-2 focus:ring-offset-2 focus:ring-yellow-700 focus:shadow-outline focus:outline-none",
|
||||
"type": "button",
|
||||
}
|
||||
}
|
||||
return templ.Attributes{
|
||||
"class": "inline-flex items-center justify-center px-4 py-2 text-sm font-medium tracking-wide transition-colors duration-200 bg-white border rounded-md text-neutral-500 hover:text-neutral-700 border-neutral-200/70 hover:bg-neutral-100 active:bg-white focus:bg-white focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-neutral-200/60 focus:shadow-outline",
|
||||
"type": "button",
|
||||
}
|
||||
}
|
||||
|
||||
type SubtleButtonVariant int
|
||||
|
||||
const (
|
||||
SubtleButtonVariantDefault SubtleButtonVariant = iota
|
||||
SubtleButtonVariantInfo
|
||||
SubtleButtonVariantError
|
||||
SubtleButtonVariantSuccess
|
||||
SubtleButtonVariantWarning
|
||||
)
|
||||
|
||||
func (v SubtleButtonVariant) Attributes() templ.Attributes {
|
||||
switch v {
|
||||
case SubtleButtonVariantInfo:
|
||||
return templ.Attributes{
|
||||
"class": "inline-flex items-center justify-center px-4 py-2 text-sm font-medium tracking-wide text-blue-500 transition-colors duration-100 rounded-md focus:ring-2 focus:ring-offset-2 focus:ring-blue-100 bg-blue-50 hover:text-blue-600 hover:bg-blue-100",
|
||||
"type": "button",
|
||||
}
|
||||
case SubtleButtonVariantError:
|
||||
return templ.Attributes{
|
||||
"class": "inline-flex items-center justify-center px-4 py-2 text-sm font-medium tracking-wide text-red-500 transition-colors duration-100 rounded-md focus:ring-2 focus:ring-offset-2 focus:ring-red-100 bg-red-50 hover:text-red-600 hover:bg-red-100",
|
||||
"type": "button",
|
||||
}
|
||||
case SubtleButtonVariantSuccess:
|
||||
return templ.Attributes{
|
||||
"class": "inline-flex items-center justify-center px-4 py-2 text-sm font-medium tracking-wide text-green-500 transition-colors duration-100 rounded-md focus:ring-2 focus:ring-offset-2 focus:ring-green-100 bg-green-50 hover:text-green-600 hover:bg-green-100",
|
||||
"type": "button",
|
||||
}
|
||||
case SubtleButtonVariantWarning:
|
||||
return templ.Attributes{
|
||||
"class": "inline-flex items-center justify-center px-4 py-2 text-sm font-medium tracking-wide text-yellow-600 transition-colors duration-100 rounded-md focus:ring-2 focus:ring-offset-2 focus:ring-yellow-100 bg-yellow-50 hover:text-yellow-700 hover:bg-yellow-100",
|
||||
"type": "button",
|
||||
}
|
||||
}
|
||||
return templ.Attributes{
|
||||
"class": "inline-flex items-center justify-center px-4 py-2 text-sm font-medium tracking-wide transition-colors duration-100 rounded-md text-neutral-500 bg-neutral-50 focus:ring-2 focus:ring-offset-2 focus:ring-neutral-100 hover:text-neutral-600 hover:bg-neutral-100",
|
||||
"type": "button",
|
||||
}
|
||||
}
|
||||
|
||||
type OutlineButtonVariant int
|
||||
|
||||
const (
|
||||
OutlineButtonVariantDefault OutlineButtonVariant = iota
|
||||
OutlineButtonVariantInfo
|
||||
OutlineButtonVariantError
|
||||
OutlineButtonVariantSuccess
|
||||
OutlineButtonVariantWarning
|
||||
)
|
||||
|
||||
func (v OutlineButtonVariant) Attributes() templ.Attributes {
|
||||
switch v {
|
||||
case OutlineButtonVariantInfo:
|
||||
return templ.Attributes{
|
||||
"class": "inline-flex items-center justify-center px-4 py-2 text-sm font-medium tracking-wide text-blue-600 transition-colors duration-100 bg-white border-2 border-blue-600 rounded-md hover:text-white hover:bg-blue-600",
|
||||
"type": "button",
|
||||
}
|
||||
case OutlineButtonVariantError:
|
||||
return templ.Attributes{
|
||||
"class": "inline-flex items-center justify-center px-4 py-2 text-sm font-medium tracking-wide text-red-600 transition-colors duration-100 bg-white border-2 border-red-600 rounded-md hover:text-white hover:bg-red-600",
|
||||
"type": "button",
|
||||
}
|
||||
case OutlineButtonVariantSuccess:
|
||||
return templ.Attributes{
|
||||
"class": "inline-flex items-center justify-center px-4 py-2 text-sm font-medium tracking-wide text-green-600 transition-colors duration-100 bg-white border-2 border-green-600 rounded-md hover:text-white hover:bg-green-600",
|
||||
"type": "button",
|
||||
}
|
||||
case OutlineButtonVariantWarning:
|
||||
return templ.Attributes{
|
||||
"class": "inline-flex items-center justify-center px-4 py-2 text-sm font-medium tracking-wide text-yellow-600 transition-colors duration-100 bg-white border-2 border-yellow-500 rounded-md hover:text-white hover:bg-yellow-500",
|
||||
"type": "button",
|
||||
}
|
||||
}
|
||||
return templ.Attributes{
|
||||
"class": "inline-flex items-center justify-center px-4 py-2 text-sm font-medium tracking-wide transition-colors duration-100 bg-white border-2 rounded-md text-neutral-900 hover:text-white border-neutral-900 hover:bg-neutral-900",
|
||||
"type": "button",
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,180 @@
|
||||
// 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 Button(variant Variant) templ.Component {
|
||||
return renderButton(variant.Attributes())
|
||||
}
|
||||
|
||||
func renderButton(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_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("<button")
|
||||
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_Var1.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 (
|
||||
ButtonVariantDefault ButtonVariant = iota
|
||||
ButtonVariantPrimary
|
||||
ButtonVariantInfo
|
||||
ButtonVariantError
|
||||
ButtonVariantSuccess
|
||||
ButtonVariantWarning
|
||||
)
|
||||
|
||||
func (v ButtonVariant) Attributes() templ.Attributes {
|
||||
switch v {
|
||||
case ButtonVariantPrimary:
|
||||
return templ.Attributes{
|
||||
"class": "inline-flex items-center justify-center px-4 py-2 text-sm font-medium tracking-wide text-white transition-colors duration-200 rounded-md bg-neutral-950 hover:bg-neutral-900 focus:ring-2 focus:ring-offset-2 focus:ring-neutral-900 focus:shadow-outline focus:outline-none",
|
||||
"type": "button",
|
||||
}
|
||||
case ButtonVariantInfo:
|
||||
return templ.Attributes{
|
||||
"class": "inline-flex items-center justify-center px-4 py-2 text-sm font-medium tracking-wide text-white transition-colors duration-200 bg-blue-600 rounded-md hover:bg-blue-700 focus:ring-2 focus:ring-offset-2 focus:ring-blue-700 focus:shadow-outline focus:outline-none",
|
||||
"type": "button",
|
||||
}
|
||||
case ButtonVariantError:
|
||||
return templ.Attributes{
|
||||
"class": "inline-flex items-center justify-center px-4 py-2 text-sm font-medium tracking-wide text-white transition-colors duration-200 rounded-md bg-red-600 hover:bg-red-700 focus:ring-2 focus:ring-offset-2 focus:ring-red-700 focus:shadow-outline focus:outline-none",
|
||||
"type": "button",
|
||||
}
|
||||
case ButtonVariantSuccess:
|
||||
return templ.Attributes{
|
||||
"class": "inline-flex items-center justify-center px-4 py-2 text-sm font-medium tracking-wide text-white transition-colors duration-200 rounded-md bg-green-600 hover:bg-green-700 focus:ring-2 focus:ring-offset-2 focus:ring-green-700 focus:shadow-outline focus:outline-none",
|
||||
"type": "button",
|
||||
}
|
||||
case ButtonVariantWarning:
|
||||
return templ.Attributes{
|
||||
"class": "inline-flex items-center justify-center px-4 py-2 text-sm font-medium tracking-wide text-white transition-colors duration-200 rounded-md bg-yellow-600 hover:bg-yellow-700 focus:ring-2 focus:ring-offset-2 focus:ring-yellow-700 focus:shadow-outline focus:outline-none",
|
||||
"type": "button",
|
||||
}
|
||||
}
|
||||
return templ.Attributes{
|
||||
"class": "inline-flex items-center justify-center px-4 py-2 text-sm font-medium tracking-wide transition-colors duration-200 bg-white border rounded-md text-neutral-500 hover:text-neutral-700 border-neutral-200/70 hover:bg-neutral-100 active:bg-white focus:bg-white focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-neutral-200/60 focus:shadow-outline",
|
||||
"type": "button",
|
||||
}
|
||||
}
|
||||
|
||||
type SubtleButtonVariant int
|
||||
|
||||
const (
|
||||
SubtleButtonVariantDefault SubtleButtonVariant = iota
|
||||
SubtleButtonVariantInfo
|
||||
SubtleButtonVariantError
|
||||
SubtleButtonVariantSuccess
|
||||
SubtleButtonVariantWarning
|
||||
)
|
||||
|
||||
func (v SubtleButtonVariant) Attributes() templ.Attributes {
|
||||
switch v {
|
||||
case SubtleButtonVariantInfo:
|
||||
return templ.Attributes{
|
||||
"class": "inline-flex items-center justify-center px-4 py-2 text-sm font-medium tracking-wide text-blue-500 transition-colors duration-100 rounded-md focus:ring-2 focus:ring-offset-2 focus:ring-blue-100 bg-blue-50 hover:text-blue-600 hover:bg-blue-100",
|
||||
"type": "button",
|
||||
}
|
||||
case SubtleButtonVariantError:
|
||||
return templ.Attributes{
|
||||
"class": "inline-flex items-center justify-center px-4 py-2 text-sm font-medium tracking-wide text-red-500 transition-colors duration-100 rounded-md focus:ring-2 focus:ring-offset-2 focus:ring-red-100 bg-red-50 hover:text-red-600 hover:bg-red-100",
|
||||
"type": "button",
|
||||
}
|
||||
case SubtleButtonVariantSuccess:
|
||||
return templ.Attributes{
|
||||
"class": "inline-flex items-center justify-center px-4 py-2 text-sm font-medium tracking-wide text-green-500 transition-colors duration-100 rounded-md focus:ring-2 focus:ring-offset-2 focus:ring-green-100 bg-green-50 hover:text-green-600 hover:bg-green-100",
|
||||
"type": "button",
|
||||
}
|
||||
case SubtleButtonVariantWarning:
|
||||
return templ.Attributes{
|
||||
"class": "inline-flex items-center justify-center px-4 py-2 text-sm font-medium tracking-wide text-yellow-600 transition-colors duration-100 rounded-md focus:ring-2 focus:ring-offset-2 focus:ring-yellow-100 bg-yellow-50 hover:text-yellow-700 hover:bg-yellow-100",
|
||||
"type": "button",
|
||||
}
|
||||
}
|
||||
return templ.Attributes{
|
||||
"class": "inline-flex items-center justify-center px-4 py-2 text-sm font-medium tracking-wide transition-colors duration-100 rounded-md text-neutral-500 bg-neutral-50 focus:ring-2 focus:ring-offset-2 focus:ring-neutral-100 hover:text-neutral-600 hover:bg-neutral-100",
|
||||
"type": "button",
|
||||
}
|
||||
}
|
||||
|
||||
type OutlineButtonVariant int
|
||||
|
||||
const (
|
||||
OutlineButtonVariantDefault OutlineButtonVariant = iota
|
||||
OutlineButtonVariantInfo
|
||||
OutlineButtonVariantError
|
||||
OutlineButtonVariantSuccess
|
||||
OutlineButtonVariantWarning
|
||||
)
|
||||
|
||||
func (v OutlineButtonVariant) Attributes() templ.Attributes {
|
||||
switch v {
|
||||
case OutlineButtonVariantInfo:
|
||||
return templ.Attributes{
|
||||
"class": "inline-flex items-center justify-center px-4 py-2 text-sm font-medium tracking-wide text-blue-600 transition-colors duration-100 bg-white border-2 border-blue-600 rounded-md hover:text-white hover:bg-blue-600",
|
||||
"type": "button",
|
||||
}
|
||||
case OutlineButtonVariantError:
|
||||
return templ.Attributes{
|
||||
"class": "inline-flex items-center justify-center px-4 py-2 text-sm font-medium tracking-wide text-red-600 transition-colors duration-100 bg-white border-2 border-red-600 rounded-md hover:text-white hover:bg-red-600",
|
||||
"type": "button",
|
||||
}
|
||||
case OutlineButtonVariantSuccess:
|
||||
return templ.Attributes{
|
||||
"class": "inline-flex items-center justify-center px-4 py-2 text-sm font-medium tracking-wide text-green-600 transition-colors duration-100 bg-white border-2 border-green-600 rounded-md hover:text-white hover:bg-green-600",
|
||||
"type": "button",
|
||||
}
|
||||
case OutlineButtonVariantWarning:
|
||||
return templ.Attributes{
|
||||
"class": "inline-flex items-center justify-center px-4 py-2 text-sm font-medium tracking-wide text-yellow-600 transition-colors duration-100 bg-white border-2 border-yellow-500 rounded-md hover:text-white hover:bg-yellow-500",
|
||||
"type": "button",
|
||||
}
|
||||
}
|
||||
return templ.Attributes{
|
||||
"class": "inline-flex items-center justify-center px-4 py-2 text-sm font-medium tracking-wide transition-colors duration-100 bg-white border-2 rounded-md text-neutral-900 hover:text-white border-neutral-900 hover:bg-neutral-900",
|
||||
"type": "button",
|
||||
}
|
||||
}
|
||||
|
||||
var _ = templruntime.GeneratedTemplate
|
||||
@@ -0,0 +1,17 @@
|
||||
package elements
|
||||
|
||||
func Card(size Size) templ.Component {
|
||||
return renderCard(size.CardAttributes())
|
||||
}
|
||||
|
||||
templ renderCard(attrs templ.Attributes) {
|
||||
<div { attrs... }>
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-md-12 space-3">
|
||||
{ children... }
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
// 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 Card(size Size) templ.Component {
|
||||
return renderCard(size.CardAttributes())
|
||||
}
|
||||
|
||||
func renderCard(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_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")
|
||||
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("><div class=\"container\"><div class=\"row\"><div class=\"col-md-12 space-3\">")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templ_7745c5c3_Var1.Render(ctx, templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div></div></div></div>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
}
|
||||
|
||||
var _ = templruntime.GeneratedTemplate
|
||||
@@ -0,0 +1,37 @@
|
||||
package elements
|
||||
|
||||
templ Layout(title string) {
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
@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>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
}
|
||||
|
||||
templ Spacer() {
|
||||
<br/>
|
||||
}
|
||||
|
||||
templ ServiceWorker(path string) {
|
||||
<script>
|
||||
navigator.serviceWorker.register({ path })
|
||||
</script>
|
||||
}
|
||||
|
||||
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.tailwindcss.com"></script>
|
||||
}
|
||||
@@ -0,0 +1,144 @@
|
||||
// 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 Layout(title 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)
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<!doctype html><html><head>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = defaultStyles().Render(ctx, templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<title>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var2 string
|
||||
templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs(title)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/gui/elements/global.templ`, Line: 8, Col: 17}
|
||||
}
|
||||
_, 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("</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\">")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templ_7745c5c3_Var1.Render(ctx, templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div></main></body></html>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
}
|
||||
|
||||
func Spacer() 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("<br>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
}
|
||||
|
||||
func ServiceWorker(path 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_Var4 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var4 == nil {
|
||||
templ_7745c5c3_Var4 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<script>\n\t navigator.serviceWorker.register({ path })\n </script>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
}
|
||||
|
||||
func defaultStyles() 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("<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>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
}
|
||||
|
||||
var _ = templruntime.GeneratedTemplate
|
||||
@@ -0,0 +1,28 @@
|
||||
package elements
|
||||
|
||||
type Icons int
|
||||
|
||||
const (
|
||||
Icons_Info Icons = iota
|
||||
Icons_Error
|
||||
Icons_Success
|
||||
Icons_Warning
|
||||
)
|
||||
|
||||
func (v Icons) Render() templ.Component {
|
||||
return renderIconVariant(v)
|
||||
}
|
||||
|
||||
templ renderIconVariant(v Icons) {
|
||||
switch v {
|
||||
case Icons_Info:
|
||||
<svg class="w-5 h-5 -translate-y-0.5" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M11.25 11.25l.041-.02a.75.75 0 011.063.852l-.708 2.836a.75.75 0 001.063.853l.041-.021M21 12a9 9 0 11-18 0 9 9 0 0118 0zm-9-3.75h.008v.008H12V8.25z"></path></svg>
|
||||
case Icons_Error:
|
||||
<svg class="w-5 h-5 -translate-y-0.5" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M12 9v3.75m9-.75a9 9 0 11-18 0 9 9 0 0118 0zm-9 3.75h.008v.008H12v-.008z"></path></svg>
|
||||
case Icons_Success:
|
||||
<svg class="w-5 h-5 -translate-y-0.5" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M9 12.75L11.25 15 15 9.75M21 12a9 9 0 11-18 0 9 9 0 0118 0z"></path></svg>
|
||||
case Icons_Warning:
|
||||
<svg class="w-5 h-5 -translate-y-0.5" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-6 h-6"><path stroke-linecap="round" stroke-linejoin="round" d="M12 9v3.75m-9.303 3.376c-.866 1.5.217 3.374 1.948 3.374h14.71c1.73 0 2.813-1.874 1.948-3.374L13.949 3.378c-.866-1.5-3.032-1.5-3.898 0L2.697 16.126zM12 15.75h.007v.008H12v-.008z"></path></svg>
|
||||
}
|
||||
<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>
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
// 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 Icons int
|
||||
|
||||
const (
|
||||
Icons_Info Icons = iota
|
||||
Icons_Error
|
||||
Icons_Success
|
||||
Icons_Warning
|
||||
)
|
||||
|
||||
func (v Icons) Render() templ.Component {
|
||||
return renderIconVariant(v)
|
||||
}
|
||||
|
||||
func renderIconVariant(v Icons) 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 v {
|
||||
case Icons_Info:
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<svg class=\"w-5 h-5 -translate-y-0.5\" xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\" stroke-width=\"1.5\" stroke=\"currentColor\"><path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M11.25 11.25l.041-.02a.75.75 0 011.063.852l-.708 2.836a.75.75 0 001.063.853l.041-.021M21 12a9 9 0 11-18 0 9 9 0 0118 0zm-9-3.75h.008v.008H12V8.25z\"></path></svg> ")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
case Icons_Error:
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<svg class=\"w-5 h-5 -translate-y-0.5\" xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\" stroke-width=\"1.5\" stroke=\"currentColor\"><path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M12 9v3.75m9-.75a9 9 0 11-18 0 9 9 0 0118 0zm-9 3.75h.008v.008H12v-.008z\"></path></svg> ")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
case Icons_Success:
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<svg class=\"w-5 h-5 -translate-y-0.5\" xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\" stroke-width=\"1.5\" stroke=\"currentColor\"><path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 12.75L11.25 15 15 9.75M21 12a9 9 0 11-18 0 9 9 0 0118 0z\"></path></svg> ")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
case Icons_Warning:
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<svg class=\"w-5 h-5 -translate-y-0.5\" xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\" stroke-width=\"1.5\" stroke=\"currentColor\" class=\"w-6 h-6\"><path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M12 9v3.75m-9.303 3.376c-.866 1.5.217 3.374 1.948 3.374h14.71c1.73 0 2.813-1.874 1.948-3.374L13.949 3.378c-.866-1.5-3.032-1.5-3.898 0L2.697 16.126zM12 15.75h.007v.008H12v-.008z\"></path></svg> ")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<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>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
}
|
||||
|
||||
var _ = templruntime.GeneratedTemplate
|
||||
@@ -0,0 +1,61 @@
|
||||
package elements
|
||||
|
||||
type Size int
|
||||
|
||||
const (
|
||||
SizeDefault Size = iota
|
||||
SizeSmall
|
||||
SizeMedium
|
||||
SizeLarge
|
||||
)
|
||||
|
||||
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",
|
||||
}
|
||||
case SizeLarge:
|
||||
return templ.Attributes{
|
||||
"class": "max-w-xl 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",
|
||||
}
|
||||
}
|
||||
|
||||
func (s Size) SvgAttributes() templ.Attributes {
|
||||
switch s {
|
||||
case SizeSmall:
|
||||
return templ.Attributes{
|
||||
"height": "16",
|
||||
"width": "16",
|
||||
}
|
||||
case SizeLarge:
|
||||
return templ.Attributes{
|
||||
"height": "32",
|
||||
"width": "32",
|
||||
}
|
||||
}
|
||||
return templ.Attributes{
|
||||
"height": "24",
|
||||
"width": "24",
|
||||
}
|
||||
}
|
||||
|
||||
func (s Size) TextAttributes() templ.Attributes {
|
||||
switch s {
|
||||
case SizeSmall:
|
||||
return templ.Attributes{
|
||||
"class": "text-sm",
|
||||
}
|
||||
case SizeLarge:
|
||||
return templ.Attributes{
|
||||
"class": "text-lg",
|
||||
}
|
||||
}
|
||||
return templ.Attributes{
|
||||
"class": "text-md",
|
||||
}
|
||||
}
|
||||
@@ -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"
|
||||
|
||||
type Size int
|
||||
|
||||
const (
|
||||
SizeDefault Size = iota
|
||||
SizeSmall
|
||||
SizeMedium
|
||||
SizeLarge
|
||||
)
|
||||
|
||||
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",
|
||||
}
|
||||
case SizeLarge:
|
||||
return templ.Attributes{
|
||||
"class": "max-w-xl 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",
|
||||
}
|
||||
}
|
||||
|
||||
func (s Size) SvgAttributes() templ.Attributes {
|
||||
switch s {
|
||||
case SizeSmall:
|
||||
return templ.Attributes{
|
||||
"height": "16",
|
||||
"width": "16",
|
||||
}
|
||||
case SizeLarge:
|
||||
return templ.Attributes{
|
||||
"height": "32",
|
||||
"width": "32",
|
||||
}
|
||||
}
|
||||
return templ.Attributes{
|
||||
"height": "24",
|
||||
"width": "24",
|
||||
}
|
||||
}
|
||||
|
||||
func (s Size) TextAttributes() templ.Attributes {
|
||||
switch s {
|
||||
case SizeSmall:
|
||||
return templ.Attributes{
|
||||
"class": "text-sm",
|
||||
}
|
||||
case SizeLarge:
|
||||
return templ.Attributes{
|
||||
"class": "text-lg",
|
||||
}
|
||||
}
|
||||
return templ.Attributes{
|
||||
"class": "text-md",
|
||||
}
|
||||
}
|
||||
|
||||
var _ = templruntime.GeneratedTemplate
|
||||
@@ -0,0 +1,124 @@
|
||||
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",
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,380 @@
|
||||
// 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"
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
func renderHeading(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_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("<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
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
}
|
||||
|
||||
func renderLink(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_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("<a")
|
||||
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_Var6 string
|
||||
templ_7745c5c3_Var6, 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}
|
||||
}
|
||||
_, 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("</a>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
}
|
||||
|
||||
func renderStrong(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_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("<strong")
|
||||
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_Var8 string
|
||||
templ_7745c5c3_Var8, 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}
|
||||
}
|
||||
_, 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("</strong>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
}
|
||||
|
||||
func renderEmphasis(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_Var9 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var9 == nil {
|
||||
templ_7745c5c3_Var9 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<em")
|
||||
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_Var10 string
|
||||
templ_7745c5c3_Var10, 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}
|
||||
}
|
||||
_, 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("</em>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
}
|
||||
|
||||
func renderCode(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_Var11 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var11 == nil {
|
||||
templ_7745c5c3_Var11 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<code")
|
||||
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_Var12 string
|
||||
templ_7745c5c3_Var12, 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}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var12))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</code>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
}
|
||||
|
||||
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
|
||||
@@ -0,0 +1,37 @@
|
||||
package elements
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/a-h/templ"
|
||||
)
|
||||
|
||||
type Icon interface {
|
||||
Render() templ.Component
|
||||
}
|
||||
|
||||
type Variant interface {
|
||||
Attributes() templ.Attributes
|
||||
}
|
||||
|
||||
func clsxMerge(variants ...Variant) templ.Attributes {
|
||||
combinedAttrs := templ.Attributes{}
|
||||
var classElements []string
|
||||
|
||||
for _, variant := range variants {
|
||||
attrs := variant.Attributes()
|
||||
if class, ok := attrs["class"].(string); ok {
|
||||
classElements = append(classElements, strings.Fields(class)...)
|
||||
}
|
||||
for key, value := range attrs {
|
||||
if key != "class" {
|
||||
combinedAttrs[key] = value
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if len(classElements) > 0 {
|
||||
combinedAttrs["class"] = strings.Join(classElements, " ")
|
||||
}
|
||||
return combinedAttrs
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package views
|
||||
|
||||
import (
|
||||
"github.com/labstack/echo/v4"
|
||||
"github.com/onsonr/sonr/internal/gui/elements"
|
||||
)
|
||||
|
||||
func HomeView(c echo.Context) error {
|
||||
return echoComponentResponse(c, renderHomeView())
|
||||
}
|
||||
|
||||
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.Spacer()
|
||||
@elements.Button(elements.ButtonVariantPrimary) {
|
||||
@elements.Text("Get Started", elements.TextSizeMedium, elements.TextStyleParagraph)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,124 @@
|
||||
// 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 HomeView(c echo.Context) error {
|
||||
return echoComponentResponse(c, renderHomeView())
|
||||
}
|
||||
|
||||
func renderHomeView() 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.Text("Sonr.ID", elements.TextSizeLarge, elements.TextStyleHeading).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.Text("Neo-tree is a file manager for NeoFS.", elements.TextSizeMedium, elements.TextStyleParagraph).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("Get Started", elements.TextSizeMedium, elements.TextStyleParagraph).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)
|
||||
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
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
templ_7745c5c3_Err = elements.Layout("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
|
||||
@@ -0,0 +1,23 @@
|
||||
package views
|
||||
|
||||
import (
|
||||
"github.com/labstack/echo/v4"
|
||||
"github.com/onsonr/sonr/internal/gui/elements"
|
||||
)
|
||||
|
||||
func LoginView(c echo.Context) error {
|
||||
return echoComponentResponse(c, renderLoginView())
|
||||
}
|
||||
|
||||
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.Spacer()
|
||||
@elements.Button(elements.ButtonVariantPrimary) {
|
||||
@elements.Text("Login", elements.TextSizeMedium, elements.TextStyleParagraph)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,124 @@
|
||||
// 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 LoginView(c echo.Context) error {
|
||||
return echoComponentResponse(c, renderLoginView())
|
||||
}
|
||||
|
||||
func renderLoginView() 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.Text("Sonr.ID", elements.TextSizeLarge, elements.TextStyleHeading).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.Text("Neo-tree is a file manager for NeoFS.", elements.TextSizeMedium, elements.TextStyleParagraph).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("Login", elements.TextSizeMedium, elements.TextStyleParagraph).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)
|
||||
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
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
templ_7745c5c3_Err = elements.Layout("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
|
||||
@@ -0,0 +1,19 @@
|
||||
package views
|
||||
|
||||
import (
|
||||
"github.com/labstack/echo/v4"
|
||||
"github.com/onsonr/sonr/internal/gui/elements"
|
||||
)
|
||||
|
||||
func AuthorizeView(c echo.Context) error {
|
||||
return echoComponentResponse(c, renderAuthorizeView())
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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 AuthorizeView(c echo.Context) error {
|
||||
return echoComponentResponse(c, renderAuthorizeView())
|
||||
}
|
||||
|
||||
func renderAuthorizeView() 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.Text("Sonr.ID", elements.TextSizeLarge, elements.TextStyleHeading).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.Text("Neo-tree is a file manager for NeoFS.", elements.TextSizeMedium, elements.TextStyleParagraph).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)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
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
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
}
|
||||
|
||||
var _ = templruntime.GeneratedTemplate
|
||||
@@ -0,0 +1,33 @@
|
||||
package views
|
||||
|
||||
import (
|
||||
"github.com/labstack/echo/v4"
|
||||
"github.com/onsonr/sonr/internal/gui/elements"
|
||||
)
|
||||
|
||||
func RegisterView(c echo.Context) error {
|
||||
return echoComponentResponse(c, renderRegisterView())
|
||||
}
|
||||
|
||||
templ renderRegisterView() {
|
||||
@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>
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,142 @@
|
||||
// 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 RegisterView(c echo.Context) error {
|
||||
return echoComponentResponse(c, renderRegisterView())
|
||||
}
|
||||
|
||||
func renderRegisterView() 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.Text("Sonr.ID", elements.TextSizeLarge, elements.TextStyleHeading).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.Text("Neo-tree is a file manager for NeoFS.", elements.TextSizeMedium, elements.TextStyleParagraph).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)
|
||||
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)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
templ_7745c5c3_Err = elements.Layout("Register | 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
|
||||
@@ -0,0 +1,27 @@
|
||||
package views
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
|
||||
"github.com/a-h/templ"
|
||||
"github.com/labstack/echo/v4"
|
||||
)
|
||||
|
||||
// render renders a templ.Component
|
||||
func echoComponentResponse(c echo.Context, cmp templ.Component) 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)
|
||||
|
||||
// Write the buffered content to the response
|
||||
_, err = c.Response().Write(buf.Bytes())
|
||||
return err
|
||||
}
|
||||
@@ -1,88 +0,0 @@
|
||||
package ipfs
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrNotInitialized = fmt.Errorf("IPFS client not initialized")
|
||||
ErrNotMounted = fmt.Errorf("IPFS client not mounted")
|
||||
ErrCIDNotFound = fmt.Errorf("CID not found")
|
||||
ErrIPNSNotFound = fmt.Errorf("IPNS not found")
|
||||
ErrInternal = fmt.Errorf("internal error")
|
||||
)
|
||||
|
||||
type FileSystem interface {
|
||||
// NewFile initializes a File on the specified volume at path 'absFilePath'.
|
||||
//
|
||||
// * Accepts volume and an absolute file path.
|
||||
// * Upon success, a vfs.File, representing the file's new path (location path + file relative path), will be returned.
|
||||
// * On error, nil is returned for the file.
|
||||
// * Note that not all file systems will have a "volume" and will therefore be "":
|
||||
// file:///path/to/file has a volume of "" and name /path/to/file
|
||||
// whereas
|
||||
// s3://mybucket/path/to/file has a volume of "mybucket and name /path/to/file
|
||||
// results in /tmp/dir1/newerdir/file.txt for the final vfs.File path.
|
||||
// * The file may or may not already exist.
|
||||
NewFile(volume string, absFilePath string) (File, error)
|
||||
|
||||
// Name returns the name of the FileSystem ie: Amazon S3, os, Google Cloud Storage, etc.
|
||||
Name() string
|
||||
}
|
||||
|
||||
type File interface {
|
||||
io.Closer
|
||||
io.Reader
|
||||
io.Seeker
|
||||
io.Writer
|
||||
fmt.Stringer
|
||||
|
||||
// Exists returns boolean if the file exists on the file system. Returns an error, if any.
|
||||
Exists() (bool, error)
|
||||
|
||||
// CopyToFile will copy the current file to the provided file instance.
|
||||
//
|
||||
// * In the case of an error, nil is returned for the file.
|
||||
// * CopyToLocation should use native functions when possible within the same scheme.
|
||||
// * If the file already exists, the contents will be overwritten with the current file's contents.
|
||||
// * CopyToFile will Close both the source and target Files which therefore can't be appended to without first
|
||||
// calling Seek() to move the cursor to the end of the file.
|
||||
CopyToFile(file File) error
|
||||
|
||||
// MoveToFile will move the current file to the provided file instance.
|
||||
//
|
||||
// * If the file already exists, the contents will be overwritten with the current file's contents.
|
||||
// * The current instance of the file will be removed.
|
||||
// * MoveToFile will Close both the source and target Files which therefore can't be appended to without first
|
||||
// calling Seek() to move the cursor to the end of the file.
|
||||
MoveToFile(file File) error
|
||||
|
||||
// Delete unlinks the File on the file system.
|
||||
Delete() error
|
||||
|
||||
// LastModified returns the timestamp the file was last modified (as *time.Time).
|
||||
LastModified() (*time.Time, error)
|
||||
|
||||
// Size returns the size of the file in bytes.
|
||||
Size() (uint64, error)
|
||||
|
||||
// Path returns absolute path, including filename, ie /some/path/to/file.txt
|
||||
//
|
||||
// If the directory portion of a file is desired, call
|
||||
// someFile.Location().Path()
|
||||
Path() string
|
||||
|
||||
// Name returns the base name of the file path.
|
||||
//
|
||||
// For file:///some/path/to/file.txt, it would return file.txt
|
||||
Name() string
|
||||
|
||||
// Touch creates a zero-length file on the vfs.File if no File exists. Update File's last modified timestamp.
|
||||
// Returns error if unable to touch File.
|
||||
Touch() error
|
||||
|
||||
// URI returns the fully qualified absolute URI for the File. IE, s3://bucket/some/path/to/file.txt
|
||||
URI() string
|
||||
}
|
||||
@@ -1,173 +0,0 @@
|
||||
package ipfs
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/ipfs/boxo/files"
|
||||
"github.com/ipfs/boxo/path"
|
||||
"github.com/ipfs/kubo/client/rpc"
|
||||
)
|
||||
|
||||
var (
|
||||
initialized bool
|
||||
localMount bool
|
||||
ipfsClient *rpc.HttpApi
|
||||
ipfsFS FileSystem
|
||||
)
|
||||
|
||||
// init initializes the IPFS client and checks for local mounts
|
||||
func init() {
|
||||
var err error
|
||||
ipfsClient, err = rpc.NewLocalApi()
|
||||
if err != nil {
|
||||
initialized = false
|
||||
localMount = false
|
||||
return
|
||||
}
|
||||
|
||||
initialized = true
|
||||
ipfsFS = &IPFSFileSystem{client: ipfsClient}
|
||||
|
||||
// Check if /ipfs and /ipns are mounted using os package
|
||||
_, errIPFS := os.Stat("/ipfs")
|
||||
_, errIPNS := os.Stat("/ipns")
|
||||
localMount = !os.IsNotExist(errIPFS) && !os.IsNotExist(errIPNS)
|
||||
}
|
||||
|
||||
// GetFileSystem returns the IPFS FileSystem implementation
|
||||
func GetFileSystem() FileSystem {
|
||||
return ipfsFS
|
||||
}
|
||||
|
||||
// AddFile adds a single file to IPFS and returns its CID
|
||||
func AddFile(ctx context.Context, filePath string) (string, error) {
|
||||
if !initialized {
|
||||
return "", ErrNotInitialized
|
||||
}
|
||||
|
||||
file, err := os.Open(filePath)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to open file: %w", err)
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
fileNode := files.NewReaderFile(file)
|
||||
|
||||
cidFile, err := ipfsClient.Unixfs().Add(ctx, fileNode)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to add file to IPFS: %w", err)
|
||||
}
|
||||
|
||||
return cidFile.String(), nil
|
||||
}
|
||||
|
||||
// AddFolder adds a folder and its contents to IPFS and returns the CID of the folder
|
||||
func AddFolder(ctx context.Context, folderPath string) (string, error) {
|
||||
if !initialized {
|
||||
return "", ErrNotInitialized
|
||||
}
|
||||
|
||||
stat, err := os.Stat(folderPath)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to get folder info: %w", err)
|
||||
}
|
||||
|
||||
if !stat.IsDir() {
|
||||
return "", fmt.Errorf("provided path is not a directory")
|
||||
}
|
||||
|
||||
folderNode, err := files.NewSerialFile(folderPath, false, stat)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to create folder node: %w", err)
|
||||
}
|
||||
|
||||
cidFolder, err := ipfsClient.Unixfs().Add(ctx, folderNode)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to add folder to IPFS: %w", err)
|
||||
}
|
||||
|
||||
return cidFolder.String(), nil
|
||||
}
|
||||
|
||||
func GetCID(ctx context.Context, cid string) ([]byte, error) {
|
||||
if !initialized {
|
||||
return nil, ErrNotInitialized
|
||||
}
|
||||
|
||||
if localMount {
|
||||
// Try to read from local filesystem first
|
||||
data, err := os.ReadFile(filepath.Join("/ipfs", cid))
|
||||
if err == nil {
|
||||
return data, nil
|
||||
}
|
||||
// If local read fails, fall back to IPFS client
|
||||
}
|
||||
|
||||
// Use IPFS client to fetch the data
|
||||
p, err := path.NewPath("/ipfs/" + cid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
n, err := ipfsClient.Unixfs().Get(ctx, p)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return readNodeData(n)
|
||||
}
|
||||
|
||||
func GetIPNS(ctx context.Context, name string) ([]byte, error) {
|
||||
if !initialized {
|
||||
return nil, ErrNotInitialized
|
||||
}
|
||||
|
||||
if localMount {
|
||||
// Try to read from local filesystem first
|
||||
data, err := os.ReadFile(filepath.Join("/ipns", name))
|
||||
if err == nil {
|
||||
return data, nil
|
||||
}
|
||||
// If local read fails, fall back to IPFS client
|
||||
}
|
||||
|
||||
// Use IPFS client to fetch the data
|
||||
p, err := path.NewPath("/ipns/" + name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
n, err := ipfsClient.Unixfs().Get(ctx, p)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return readNodeData(n)
|
||||
}
|
||||
|
||||
func PinCID(ctx context.Context, cid string, name string) error {
|
||||
if !initialized {
|
||||
return ErrNotInitialized
|
||||
}
|
||||
|
||||
p, err := path.NewPath(cid)
|
||||
if err != nil {
|
||||
return ErrNotInitialized
|
||||
}
|
||||
err = ipfsClient.Pin().Add(ctx, p)
|
||||
if err != nil {
|
||||
return ErrInternal
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func readNodeData(n files.Node) ([]byte, error) {
|
||||
switch n := n.(type) {
|
||||
case files.File:
|
||||
return io.ReadAll(n)
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupported node type: %T", n)
|
||||
}
|
||||
}
|
||||
@@ -1,119 +0,0 @@
|
||||
package ipfs
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/ipfs/boxo/files"
|
||||
"github.com/ipfs/boxo/path"
|
||||
"github.com/ipfs/kubo/client/rpc"
|
||||
)
|
||||
|
||||
type IPFSFile struct {
|
||||
node files.Node
|
||||
path string
|
||||
name string
|
||||
client *rpc.HttpApi
|
||||
}
|
||||
|
||||
func (f *IPFSFile) Close() error {
|
||||
return nil // IPFS nodes don't need to be closed
|
||||
}
|
||||
|
||||
func (f *IPFSFile) Read(p []byte) (n int, err error) {
|
||||
if file, ok := f.node.(files.File); ok {
|
||||
return file.Read(p)
|
||||
}
|
||||
return 0, fmt.Errorf("not a file")
|
||||
}
|
||||
|
||||
func (f *IPFSFile) Seek(offset int64, whence int) (int64, error) {
|
||||
if file, ok := f.node.(files.File); ok {
|
||||
return file.Seek(offset, whence)
|
||||
}
|
||||
return 0, fmt.Errorf("not a file")
|
||||
}
|
||||
|
||||
func (f *IPFSFile) Write(p []byte) (n int, err error) {
|
||||
return 0, fmt.Errorf("write operation not supported for IPFS files")
|
||||
}
|
||||
|
||||
func (f *IPFSFile) String() string {
|
||||
return f.path
|
||||
}
|
||||
|
||||
func (f *IPFSFile) Exists() (bool, error) {
|
||||
// In IPFS, if we have the node, it exists
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func (f *IPFSFile) CopyToFile(file File) error {
|
||||
// Implementation depends on how you want to handle copying between IPFS and other file types
|
||||
return fmt.Errorf("CopyToFile not implemented for IPFS files")
|
||||
}
|
||||
|
||||
func (f *IPFSFile) MoveToFile(file File) error {
|
||||
// Moving files in IPFS doesn't make sense in the traditional way
|
||||
return fmt.Errorf("MoveToFile not applicable for IPFS files")
|
||||
}
|
||||
|
||||
func (f *IPFSFile) Delete() error {
|
||||
// Deleting in IPFS is not straightforward, might need to implement unpinning
|
||||
return fmt.Errorf("Delete operation not supported for IPFS files")
|
||||
}
|
||||
|
||||
func (f *IPFSFile) LastModified() (*time.Time, error) {
|
||||
// IPFS doesn't have a concept of last modified time
|
||||
return nil, fmt.Errorf("LastModified not applicable for IPFS files")
|
||||
}
|
||||
|
||||
func (f *IPFSFile) Size() (uint64, error) {
|
||||
if file, ok := f.node.(files.File); ok {
|
||||
s, _ := file.Size()
|
||||
return uint64(s), nil
|
||||
}
|
||||
return 0, fmt.Errorf("not a file")
|
||||
}
|
||||
|
||||
func (f *IPFSFile) Path() string {
|
||||
return f.path
|
||||
}
|
||||
|
||||
func (f *IPFSFile) Name() string {
|
||||
return f.name
|
||||
}
|
||||
|
||||
func (f *IPFSFile) Touch() error {
|
||||
return fmt.Errorf("Touch operation not supported for IPFS files")
|
||||
}
|
||||
|
||||
func (f *IPFSFile) URI() string {
|
||||
return fmt.Sprintf("ipfs://%s", f.path)
|
||||
}
|
||||
|
||||
type IPFSFileSystem struct {
|
||||
client *rpc.HttpApi
|
||||
}
|
||||
|
||||
func (fs *IPFSFileSystem) NewFile(volume string, absFilePath string) (File, error) {
|
||||
p, err := path.NewPath(absFilePath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
node, err := fs.client.Unixfs().Get(context.Background(), p)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &IPFSFile{
|
||||
node: node,
|
||||
path: absFilePath,
|
||||
name: p.String(),
|
||||
client: fs.client,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (fs *IPFSFileSystem) Name() string {
|
||||
return "IPFS"
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
package mdw
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
echojwt "github.com/labstack/echo-jwt/v4"
|
||||
"github.com/labstack/echo/v4"
|
||||
"gopkg.in/macaroon.v2"
|
||||
)
|
||||
|
||||
type Authz struct {
|
||||
echo.Context
|
||||
echojwt.Config
|
||||
|
||||
signKey []byte
|
||||
}
|
||||
|
||||
func newAuthz(c echo.Context, signKey []byte) *Authz {
|
||||
return &Authz{Context: c, signKey: signKey}
|
||||
}
|
||||
|
||||
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 ValidateMacaroonMiddleware(secretKey []byte, location string) echo.MiddlewareFunc {
|
||||
return func(next echo.HandlerFunc) echo.HandlerFunc {
|
||||
return func(c echo.Context) error {
|
||||
// Extract the macaroon from the Authorization header
|
||||
auth := c.Request().Header.Get("Authorization")
|
||||
if auth == "" {
|
||||
return c.JSON(http.StatusUnauthorized, map[string]string{"error": "Missing Authorization header"})
|
||||
}
|
||||
|
||||
// Decode the macaroon
|
||||
mac, err := macaroon.Base64Decode([]byte(auth))
|
||||
if err != nil {
|
||||
return c.JSON(http.StatusBadRequest, map[string]string{"error": "Invalid macaroon encoding"})
|
||||
}
|
||||
|
||||
token, err := macaroon.New(secretKey, mac, location, macaroon.LatestVersion)
|
||||
if err != nil {
|
||||
return c.JSON(http.StatusBadRequest, map[string]string{"error": "Invalid macaroon"})
|
||||
}
|
||||
|
||||
// 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)
|
||||
return nil // Return nil if the caveat is valid
|
||||
}, nil)
|
||||
if err != nil {
|
||||
return c.JSON(http.StatusUnauthorized, map[string]string{"error": "Invalid macaroon"})
|
||||
}
|
||||
|
||||
// Macaroon is valid, proceed to the next handler
|
||||
return next(c)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
package mdw
|
||||
|
||||
import "github.com/labstack/echo/v4"
|
||||
|
||||
type RequestHeaders struct {
|
||||
Authorization *string `header:"Authorization"`
|
||||
CacheControl *string `header:"Cache-Control"`
|
||||
DeviceMemory *string `header:"Device-Memory"`
|
||||
Forwarded *string `header:"Forwarded"`
|
||||
From *string `header:"From"`
|
||||
Host *string `header:"Host"`
|
||||
Link *string `header:"Link"`
|
||||
PermissionsPolicy *string `header:"Permissions-Policy"`
|
||||
ProxyAuthorization *string `header:"Proxy-Authorization"`
|
||||
Referer *string `header:"Referer"`
|
||||
UserAgent *string `header:"User-Agent"`
|
||||
ViewportWidth *string `header:"Viewport-Width"`
|
||||
Width *string `header:"Width"`
|
||||
WWWAuthenticate *string `header:"WWW-Authenticate"`
|
||||
|
||||
// HTMX Specific
|
||||
HXBoosted *string `header:"HX-Boosted"`
|
||||
HXCurrentURL *string `header:"HX-Current-URL"`
|
||||
HXHistoryRestoreRequest *string `header:"HX-History-Restore-Request"`
|
||||
HXPrompt *string `header:"HX-Prompt"`
|
||||
HXRequest *string `header:"HX-Request"`
|
||||
HXTarget *string `header:"HX-Target"`
|
||||
HXTriggerName *string `header:"HX-Trigger-Name"`
|
||||
HXTrigger *string `header:"HX-Trigger"`
|
||||
}
|
||||
|
||||
type ResponseHeaders struct {
|
||||
AcceptCH *string `header:"Accept-CH"`
|
||||
AccessControlAllowCredentials *string `header:"Access-Control-Allow-Credentials"`
|
||||
AccessControlAllowHeaders *string `header:"Access-Control-Allow-Headers"`
|
||||
AccessControlAllowMethods *string `header:"Access-Control-Allow-Methods"`
|
||||
AccessControlExposeHeaders *string `header:"Access-Control-Expose-Headers"`
|
||||
AccessControlRequestHeaders *string `header:"Access-Control-Request-Headers"`
|
||||
ContentSecurityPolicy *string `header:"Content-Security-Policy"`
|
||||
CrossOriginEmbedderPolicy *string `header:"Cross-Origin-Embedder-Policy"`
|
||||
PermissionsPolicy *string `header:"Permissions-Policy"`
|
||||
ProxyAuthorization *string `header:"Proxy-Authorization"`
|
||||
WWWAuthenticate *string `header:"WWW-Authenticate"`
|
||||
|
||||
// HTMX Specific
|
||||
HXLocation *string `header:"HX-Location"`
|
||||
HXPushURL *string `header:"HX-Push-Url"`
|
||||
HXRedirect *string `header:"HX-Redirect"`
|
||||
HXRefresh *string `header:"HX-Refresh"`
|
||||
HXReplaceURL *string `header:"HX-Replace-Url"`
|
||||
HXReswap *string `header:"HX-Reswap"`
|
||||
HXRetarget *string `header:"HX-Retarget"`
|
||||
HXReselect *string `header:"HX-Reselect"`
|
||||
HXTrigger *string `header:"HX-Trigger"`
|
||||
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)
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
package mdw
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/donseba/go-htmx"
|
||||
"github.com/labstack/echo/v4"
|
||||
"github.com/onsonr/sonr/internal/db"
|
||||
"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)
|
||||
}
|
||||
}
|
||||
|
||||
// GetSession returns the current Session
|
||||
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
|
||||
}
|
||||
|
||||
func (c *Session) DB() *db.DB {
|
||||
return c.dB
|
||||
}
|
||||
|
||||
func newSession(c echo.Context) *Session {
|
||||
s := &Session{Context: c}
|
||||
if val := readCookie(c, "session"); val == "" {
|
||||
id := ksuid.New().String()
|
||||
writeCookie(c, "session", id)
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
func readCookie(c echo.Context, key string) string {
|
||||
cookie, err := c.Cookie(key)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
if cookie == nil {
|
||||
return ""
|
||||
}
|
||||
return cookie.Value
|
||||
}
|
||||
|
||||
func writeCookie(c echo.Context, key string, value string) {
|
||||
cookie := new(http.Cookie)
|
||||
cookie.Name = key
|
||||
cookie.Value = value
|
||||
cookie.Expires = time.Now().Add(24 * time.Hour)
|
||||
c.SetCookie(cookie)
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
package mdw
|
||||
@@ -0,0 +1,44 @@
|
||||
package svc
|
||||
|
||||
import (
|
||||
"github.com/labstack/echo/v4"
|
||||
"github.com/onsonr/sonr/internal/db/orm"
|
||||
)
|
||||
|
||||
func GrantAuthorization(e echo.Context) error {
|
||||
// Implement authorization endpoint using passkey authentication
|
||||
// Store session data in cache
|
||||
return nil
|
||||
}
|
||||
|
||||
func GetJWKS(e echo.Context) error {
|
||||
// Implement token endpoint
|
||||
// Use cached session data for validation
|
||||
return nil
|
||||
}
|
||||
|
||||
func GetToken(e echo.Context) error {
|
||||
// Implement token endpoint
|
||||
// Use cached session data for validation
|
||||
return nil
|
||||
}
|
||||
|
||||
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",
|
||||
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 e.JSON(200, discoveryDoc)
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package svc
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"github.com/go-webauthn/webauthn/protocol"
|
||||
"github.com/labstack/echo/v4"
|
||||
)
|
||||
|
||||
func CheckSubjectIsValid(e echo.Context) error {
|
||||
credentialID := e.FormValue("credentialID")
|
||||
return e.JSON(200, credentialID)
|
||||
}
|
||||
|
||||
func HandleCredentialAssertion(e echo.Context) error {
|
||||
return e.JSON(200, "HandleCredentialAssertion")
|
||||
}
|
||||
|
||||
func HandleCredentialCreation(e echo.Context) error {
|
||||
// Get the serialized credential data from the form
|
||||
credentialDataJSON := e.FormValue("credentialData")
|
||||
|
||||
// Deserialize the JSON into a temporary struct
|
||||
var ccr protocol.CredentialCreationResponse
|
||||
err := json.Unmarshal([]byte(credentialDataJSON), &ccr)
|
||||
if err != nil {
|
||||
return e.JSON(500, err.Error())
|
||||
}
|
||||
//
|
||||
// // Parse the CredentialCreationResponse
|
||||
// parsedData, err := ccr.Parse()
|
||||
// if err != nil {
|
||||
// return e.JSON(500, err.Error())
|
||||
// }
|
||||
//
|
||||
// // Create the Credential
|
||||
// // credential := orm.NewCredential(parsedData, e.Request().Host, "")
|
||||
//
|
||||
// // Set additional fields
|
||||
// credential.Controller = "" // Set this to the appropriate controller value
|
||||
return e.JSON(200, fmt.Sprintf("REGISTER: %s", string(ccr.ID)))
|
||||
}
|
||||
@@ -5,8 +5,8 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
kServiceWorkerFileName = "sw.js"
|
||||
kVaultFileName = "vault.wasm"
|
||||
kServiceWorkerFileName = "server/sw.js"
|
||||
kVaultFileName = "server/vault.wasm"
|
||||
kIndexFileName = "index.html"
|
||||
)
|
||||
|
||||
@@ -14,7 +14,6 @@ func AssembleDirectory() files.Directory {
|
||||
fileMap := map[string]files.Node{
|
||||
kVaultFileName: DWNWasmFile(),
|
||||
kServiceWorkerFileName: SWJSFile(),
|
||||
kIndexFileName: IndexHTMLFile(),
|
||||
}
|
||||
|
||||
return files.NewMapDirectory(fileMap)
|
||||
|
||||
Binary file not shown.
+4
-10
@@ -9,20 +9,14 @@ import (
|
||||
//go:embed dwn.wasm
|
||||
var dwnWasmData []byte
|
||||
|
||||
//go:embed sw.js
|
||||
var swJSData []byte
|
||||
|
||||
func DWNWasmFile() files.Node {
|
||||
return files.NewBytesFile(dwnWasmData)
|
||||
}
|
||||
|
||||
//go:embed sw.js
|
||||
var swJSData []byte
|
||||
|
||||
// Use ServiceWorkerJS template to generate the service worker file
|
||||
func SWJSFile() files.Node {
|
||||
return files.NewBytesFile(swJSData)
|
||||
}
|
||||
|
||||
//go:embed index.html
|
||||
var indexHTMLData []byte
|
||||
|
||||
func IndexHTMLFile() files.Node {
|
||||
return files.NewBytesFile(indexHTMLData)
|
||||
}
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Sonr Vault</title>
|
||||
<script>
|
||||
navigator.serviceWorker.register({ swPath });
|
||||
|
||||
// Skip installed stage and jump to activating stage
|
||||
addEventListener("install", (event) => {
|
||||
event.waitUntil(skipWaiting());
|
||||
});
|
||||
|
||||
// Start controlling clients as soon as the SW is activated
|
||||
addEventListener("activate", (event) => {
|
||||
event.waitUntil(clients.claim());
|
||||
});
|
||||
</script>
|
||||
</head>
|
||||
</html>
|
||||
+2
-3
@@ -1,9 +1,8 @@
|
||||
importScripts(
|
||||
"https://cdn.jsdelivr.net/gh/golang/go@go1.18.4/misc/wasm/wasm_exec.js",
|
||||
);
|
||||
|
||||
importScripts(
|
||||
"https://cdn.jsdelivr.net/gh/nlepage/go-wasm-http-server@v1.1.0/sw.js",
|
||||
"https://cdn.jsdelivr.net/npm/htmx.org@1.9.12/dist/htmx.min.js",
|
||||
"https://cdn.jsdelivr.net/npm/alpinejs@3.14.1/dist/cdn.min.js",
|
||||
);
|
||||
|
||||
registerWasmHTTPListener("dwn.wasm");
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
//go:build js && wasm
|
||||
|
||||
package wasm
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"syscall/js"
|
||||
|
||||
promise "github.com/nlepage/go-js-promise"
|
||||
)
|
||||
|
||||
// Request builds and returns the equivalent http.Request
|
||||
func Request(r js.Value) *http.Request {
|
||||
jsBody := js.Global().Get("Uint8Array").New(promise.Await(r.Call("arrayBuffer")))
|
||||
body := make([]byte, jsBody.Get("length").Int())
|
||||
js.CopyBytesToGo(body, jsBody)
|
||||
|
||||
req := httptest.NewRequest(
|
||||
r.Get("method").String(),
|
||||
r.Get("url").String(),
|
||||
bytes.NewBuffer(body),
|
||||
)
|
||||
|
||||
headersIt := r.Get("headers").Call("entries")
|
||||
for {
|
||||
e := headersIt.Call("next")
|
||||
if e.Get("done").Bool() {
|
||||
break
|
||||
}
|
||||
v := e.Get("value")
|
||||
req.Header.Set(v.Index(0).String(), v.Index(1).String())
|
||||
}
|
||||
|
||||
return req
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
//go:build js && wasm
|
||||
|
||||
package wasm
|
||||
|
||||
import (
|
||||
"io"
|
||||
"net/http/httptest"
|
||||
"syscall/js"
|
||||
)
|
||||
|
||||
// ResponseRecorder uses httptest.ResponseRecorder to build a JS Response
|
||||
type ResponseRecorder struct {
|
||||
*httptest.ResponseRecorder
|
||||
}
|
||||
|
||||
// NewResponseRecorder returns a new ResponseRecorder
|
||||
func NewResponseRecorder() ResponseRecorder {
|
||||
return ResponseRecorder{httptest.NewRecorder()}
|
||||
}
|
||||
|
||||
// JSResponse builds and returns the equivalent JS Response
|
||||
func (rr ResponseRecorder) JSResponse() js.Value {
|
||||
res := rr.Result()
|
||||
|
||||
body := js.Undefined()
|
||||
if res.ContentLength != 0 {
|
||||
b, err := io.ReadAll(res.Body)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
body = js.Global().Get("Uint8Array").New(len(b))
|
||||
js.CopyBytesToJS(body, b)
|
||||
}
|
||||
|
||||
init := make(map[string]interface{}, 2)
|
||||
|
||||
if res.StatusCode != 0 {
|
||||
init["status"] = res.StatusCode
|
||||
}
|
||||
|
||||
if len(res.Header) != 0 {
|
||||
headers := make(map[string]interface{}, len(res.Header))
|
||||
for k := range res.Header {
|
||||
headers[k] = res.Header.Get(k)
|
||||
}
|
||||
init["headers"] = headers
|
||||
}
|
||||
|
||||
return js.Global().Get("Response").New(body, init)
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
//go:build js && wasm
|
||||
|
||||
package wasm
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strings"
|
||||
"syscall/js"
|
||||
|
||||
promise "github.com/nlepage/go-js-promise"
|
||||
)
|
||||
|
||||
// Serve serves HTTP requests using handler or http.DefaultServeMux if handler is nil.
|
||||
func Serve(handler http.Handler) func() {
|
||||
h := handler
|
||||
if h == nil {
|
||||
h = http.DefaultServeMux
|
||||
}
|
||||
|
||||
prefix := js.Global().Get("wasmhttp").Get("path").String()
|
||||
for strings.HasSuffix(prefix, "/") {
|
||||
prefix = strings.TrimSuffix(prefix, "/")
|
||||
}
|
||||
|
||||
if prefix != "" {
|
||||
mux := http.NewServeMux()
|
||||
mux.Handle(prefix+"/", http.StripPrefix(prefix, h))
|
||||
h = mux
|
||||
}
|
||||
|
||||
cb := js.FuncOf(func(_ js.Value, args []js.Value) interface{} {
|
||||
resPromise, resolve, reject := promise.New()
|
||||
|
||||
go func() {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
if err, ok := r.(error); ok {
|
||||
reject(fmt.Sprintf("wasmhttp: panic: %+v\n", err))
|
||||
} else {
|
||||
reject(fmt.Sprintf("wasmhttp: panic: %v\n", r))
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
res := NewResponseRecorder()
|
||||
|
||||
h.ServeHTTP(res, Request(args[0]))
|
||||
|
||||
resolve(res.JSResponse())
|
||||
}()
|
||||
|
||||
return resPromise
|
||||
})
|
||||
|
||||
js.Global().Get("wasmhttp").Call("setHandler", cb)
|
||||
|
||||
return cb.Release
|
||||
}
|
||||
Reference in New Issue
Block a user