updated templater library
This commit is contained in:
@@ -2,7 +2,7 @@ module ruben/inventory2
|
|||||||
|
|
||||||
go 1.24.2
|
go 1.24.2
|
||||||
|
|
||||||
replace github.com/angelbeltran/templater v0.1.0 => ../../github.com/angelbeltran/templater
|
replace github.com/angelbeltran/templater v0.2.2 => ../../github.com/angelbeltran/templater
|
||||||
|
|
||||||
require github.com/jackc/pgx/v5 v5.7.6
|
require github.com/jackc/pgx/v5 v5.7.6
|
||||||
|
|
||||||
|
|||||||
@@ -9,8 +9,6 @@ github.com/alecthomas/units v0.0.0-20231202071711-9a357b53e9c9 h1:ez/4by2iGztzR4
|
|||||||
github.com/alecthomas/units v0.0.0-20231202071711-9a357b53e9c9/go.mod h1:OMCwj8VM1Kc9e19TLln2VL61YJF0x1XFtfdL4JdbSyE=
|
github.com/alecthomas/units v0.0.0-20231202071711-9a357b53e9c9/go.mod h1:OMCwj8VM1Kc9e19TLln2VL61YJF0x1XFtfdL4JdbSyE=
|
||||||
github.com/angelbeltran/concurry v0.0.0-20260109231127-8e2678d8928c h1:BIa061RHaIVP9TjpIQf0PldVpQmeln/2U1Cf2w8ALNI=
|
github.com/angelbeltran/concurry v0.0.0-20260109231127-8e2678d8928c h1:BIa061RHaIVP9TjpIQf0PldVpQmeln/2U1Cf2w8ALNI=
|
||||||
github.com/angelbeltran/concurry v0.0.0-20260109231127-8e2678d8928c/go.mod h1:Aii6F8lZCJb8Ns0d1FH35bDxNoyiuvwXd5BYJroJnks=
|
github.com/angelbeltran/concurry v0.0.0-20260109231127-8e2678d8928c/go.mod h1:Aii6F8lZCJb8Ns0d1FH35bDxNoyiuvwXd5BYJroJnks=
|
||||||
github.com/angelbeltran/templater v0.2.1 h1:9N2eNRE5/sYUgu7nZrU6VSSrrpKcOTlAw+UeeK3kyhk=
|
|
||||||
github.com/angelbeltran/templater v0.2.1/go.mod h1:ZA0T/ZmXxPi3gFjgp+RwEkcY9Q+JGyMStGw0c1jvgqA=
|
|
||||||
github.com/apapsch/go-jsonmerge/v2 v2.0.0 h1:axGnT1gRIfimI7gJifB699GoE/oq+F2MU7Dml6nw9rQ=
|
github.com/apapsch/go-jsonmerge/v2 v2.0.0 h1:axGnT1gRIfimI7gJifB699GoE/oq+F2MU7Dml6nw9rQ=
|
||||||
github.com/apapsch/go-jsonmerge/v2 v2.0.0/go.mod h1:lvDnEdqiQrp0O42VQGgmlKpxL1AP2+08jFMw88y4klk=
|
github.com/apapsch/go-jsonmerge/v2 v2.0.0/go.mod h1:lvDnEdqiQrp0O42VQGgmlKpxL1AP2+08jFMw88y4klk=
|
||||||
github.com/bmatcuk/doublestar v1.1.1/go.mod h1:UD6OnuiIn0yFxxA2le/rnRU1G4RaI4UvFv1sNto9p6w=
|
github.com/bmatcuk/doublestar v1.1.1/go.mod h1:UD6OnuiIn0yFxxA2le/rnRU1G4RaI4UvFv1sNto9p6w=
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
package templates
|
package templates
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"path"
|
|
||||||
"path/filepath"
|
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
"text/template"
|
||||||
|
|
||||||
"ruben/inventory2/internal/domains/accounts"
|
"ruben/inventory2/internal/domains/accounts"
|
||||||
etsy_platform "ruben/inventory2/internal/domains/platforms/etsy"
|
etsy_platform "ruben/inventory2/internal/domains/platforms/etsy"
|
||||||
@@ -43,23 +43,60 @@ func SetupRoutes(
|
|||||||
logger *logging.Logger,
|
logger *logging.Logger,
|
||||||
r gin.IRouter,
|
r gin.IRouter,
|
||||||
contentDir string,
|
contentDir string,
|
||||||
tmpl *templater.Templater,
|
|
||||||
rawEvents *raw_events.Store,
|
rawEvents *raw_events.Store,
|
||||||
accts *accounts.Store,
|
accts *accounts.Store,
|
||||||
etsy *etsy_platform.Platform,
|
etsy *etsy_platform.Platform,
|
||||||
authMiddleware *middleware.Auth,
|
authMiddleware *middleware.Auth,
|
||||||
) {
|
) {
|
||||||
|
|
||||||
s := &webpageRouter{
|
s := &webpageRouter{
|
||||||
log: logger,
|
log: logger,
|
||||||
contentDir: contentDir,
|
contentDir: contentDir,
|
||||||
templater: tmpl,
|
// TODO: clean up the references to the templates dir throughout as well (should only be referred to in the 'main' package
|
||||||
|
templater: new(templater.Templater).With(templater.Config{
|
||||||
|
Funcs: func(name string, props map[string]any) template.FuncMap {
|
||||||
|
return template.FuncMap{
|
||||||
|
// parsing
|
||||||
|
"parseInt": func(s string) (int, error) {
|
||||||
|
return strconv.Atoi(s)
|
||||||
|
},
|
||||||
|
"parseInt64": func(s string) (int64, error) {
|
||||||
|
return strconv.ParseInt(s, 10, 64)
|
||||||
|
},
|
||||||
|
"parsePlatform": func(s string) (accounts.Platform, error) {
|
||||||
|
return accounts.NewPlatform(s)
|
||||||
|
},
|
||||||
|
|
||||||
|
// arithmetic
|
||||||
|
"addInt": func(a, b int) int {
|
||||||
|
return a + b
|
||||||
|
},
|
||||||
|
"subInt": func(a, b int) int {
|
||||||
|
return a - b
|
||||||
|
},
|
||||||
|
"multInt": func(a, b int) int {
|
||||||
|
return a * b
|
||||||
|
},
|
||||||
|
|
||||||
|
// json
|
||||||
|
"prettyPrintJSON": func(j json.RawMessage) string {
|
||||||
|
b, err := json.MarshalIndent(j, " ", "")
|
||||||
|
if err != nil {
|
||||||
|
return string(j)
|
||||||
|
}
|
||||||
|
return string(b)
|
||||||
|
},
|
||||||
|
"marshalJSON": json.Marshal,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}),
|
||||||
rawEvents: rawEvents,
|
rawEvents: rawEvents,
|
||||||
accts: accts,
|
accts: accts,
|
||||||
etsy: etsy,
|
etsy: etsy,
|
||||||
authMiddleware: authMiddleware,
|
authMiddleware: authMiddleware,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn2 := s.authMiddleware.AuthenticateAndAddIdentity(s.serveTemplates)
|
authAndServeTemplate := s.authMiddleware.AuthenticateAndAddIdentity(s.serveTemplate)
|
||||||
|
|
||||||
r.GET("/*rest", response.Handler(func(c *gin.Context) (response.Response, error) {
|
r.GET("/*rest", response.Handler(func(c *gin.Context) (response.Response, error) {
|
||||||
c.Request.URL.Path = c.Request.URL.Path[3:]
|
c.Request.URL.Path = c.Request.URL.Path[3:]
|
||||||
@@ -73,48 +110,21 @@ func SetupRoutes(
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return s.serveTemplates(c)
|
return s.serveTemplate(c)
|
||||||
}
|
}
|
||||||
return fn2(c)
|
|
||||||
|
return authAndServeTemplate(c)
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
// GET /
|
// GET /
|
||||||
// compiles the page template or component template matching the url
|
// compiles the page template or component template matching the url
|
||||||
// func (s *Server) serveTemplates(r *http.Request) (response.Response, error) {
|
func (s *webpageRouter) serveTemplate(c *gin.Context) (response.Response, error) {
|
||||||
func (s *webpageRouter) serveTemplates(c *gin.Context) (response.Response, error) {
|
|
||||||
r := c.Request
|
r := c.Request
|
||||||
name, args := s.getTemplateNameAndArgs(r, s.contentDir+"/templates/components")
|
|
||||||
fmt.Println("name:", name)
|
|
||||||
fmt.Println("args:", args)
|
|
||||||
|
|
||||||
// TODO: update
|
|
||||||
b, err := s.templater.ExecuteComponent(name, args...)
|
|
||||||
if err == nil {
|
|
||||||
return response.HTML(b), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if !isFileNotFoundError(err) {
|
|
||||||
return s.handleTemplateError(err, args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
name, args = s.getTemplateNameAndArgs(r, s.contentDir+"/templates/pages")
|
|
||||||
fmt.Println("name (page):", name)
|
|
||||||
fmt.Println("args (page):", args)
|
|
||||||
|
|
||||||
if b, err = s.templater.ExecutePage(name, args...); err == nil {
|
|
||||||
return response.HTML(b), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return s.handleTemplateError(err, args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// func (s *Server) getTemplateNameAndArgs(r *http.Request, templateDir string) (name string, args []any) {
|
|
||||||
func (s *webpageRouter) getTemplateNameAndArgs(r *http.Request, templateDir string) (name string, args []any) {
|
|
||||||
ctx := r.Context()
|
ctx := r.Context()
|
||||||
name, pathParams := getTemplateNameForURL(r.URL, templateDir)
|
|
||||||
|
|
||||||
return name, []any{
|
b, err := s.templater.Execute(
|
||||||
|
strings.Trim(r.URL.Path, "/"),
|
||||||
"Request",
|
"Request",
|
||||||
r,
|
r,
|
||||||
// add services and data here
|
// add services and data here
|
||||||
@@ -122,95 +132,25 @@ func (s *webpageRouter) getTemplateNameAndArgs(r *http.Request, templateDir stri
|
|||||||
s.rawEvents.WithContext(ctx),
|
s.rawEvents.WithContext(ctx),
|
||||||
"URLCalc",
|
"URLCalc",
|
||||||
newURLCalculator(r.URL),
|
newURLCalculator(r.URL),
|
||||||
"PathParams",
|
|
||||||
pathParams,
|
|
||||||
"Accounts",
|
"Accounts",
|
||||||
s.accts.WithContext(ctx),
|
s.accts.WithContext(ctx),
|
||||||
"Etsy",
|
"Etsy",
|
||||||
s.etsy.WithContext(ctx),
|
s.etsy.WithContext(ctx),
|
||||||
|
|
||||||
// TODO: apply auth to all templates needed!
|
|
||||||
// auth tooling
|
// auth tooling
|
||||||
/*
|
|
||||||
AccessToken string
|
|
||||||
Claims authentication.AccessTokenClaims
|
|
||||||
User accounts.OAuthUser
|
|
||||||
Account *accounts.Account
|
|
||||||
*/
|
|
||||||
"Identity",
|
"Identity",
|
||||||
middleware.GetIdentity(r.Context()),
|
middleware.GetIdentity(ctx),
|
||||||
"Auth",
|
"Auth",
|
||||||
newTemplateAuthenticator(r),
|
newTemplateAuthenticator(r),
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return s.handleTemplateError(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return response.HTML(b), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: clean this up...
|
func (s *webpageRouter) handleTemplateError(err error) (response.Response, error) {
|
||||||
// TODO: somehow tell what the path params are and pass them up.
|
|
||||||
// - then consider pushing this functionality into the template library.
|
|
||||||
//
|
|
||||||
// getComponentTemplateNameForURL eliminate any trailing .html or /, and checks for any
|
|
||||||
// file with path parameters in the name, eg '{abc}.html.tmpl', prefering exact filename matches.
|
|
||||||
func getTemplateNameForURL(u *url.URL, templateDir string) (name string, params map[string]string) {
|
|
||||||
templateDir = path.Clean(templateDir)
|
|
||||||
fp := strings.TrimPrefix(strings.TrimSuffix(strings.TrimSuffix(u.Path, ".html"), "/"), "/")
|
|
||||||
if fp == "" {
|
|
||||||
// "/" maps to "/index"
|
|
||||||
fp = "index"
|
|
||||||
}
|
|
||||||
|
|
||||||
fpParts := strings.Split(fp, "/")
|
|
||||||
res := getMatchingGlobPatternsCapturingFilepathIncludingParametrizedFilepaths(fpParts)
|
|
||||||
for _, combs := range res {
|
|
||||||
pattern := path.Join(templateDir, path.Join(combs...)) + ".html.tmpl"
|
|
||||||
|
|
||||||
matches, _ := filepath.Glob(pattern)
|
|
||||||
if len(matches) == 0 {
|
|
||||||
pattern := path.Join(templateDir, path.Join(combs...), "index") + ".html.tmpl"
|
|
||||||
matches, _ = filepath.Glob(pattern)
|
|
||||||
}
|
|
||||||
if len(matches) > 0 {
|
|
||||||
match := matches[0]
|
|
||||||
name = strings.TrimPrefix(strings.TrimSuffix(match, ".html.tmpl"), templateDir+"/")
|
|
||||||
|
|
||||||
patternParts := strings.Split(name, "/")
|
|
||||||
params = make(map[string]string)
|
|
||||||
for i, pp := range patternParts {
|
|
||||||
if strings.HasPrefix(pp, "{") && strings.HasSuffix(pp, "}") {
|
|
||||||
params[pp[1:len(pp)-1]] = fpParts[i]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return name, params
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return fp, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func getMatchingGlobPatternsCapturingFilepathIncludingParametrizedFilepaths(filepathParts []string) [][]string {
|
|
||||||
switch len(filepathParts) {
|
|
||||||
case 0:
|
|
||||||
return nil
|
|
||||||
case 1:
|
|
||||||
return [][]string{
|
|
||||||
[]string{filepathParts[0]},
|
|
||||||
[]string{"{*}"},
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
tailCombs := getMatchingGlobPatternsCapturingFilepathIncludingParametrizedFilepaths(filepathParts[1:])
|
|
||||||
|
|
||||||
combs := make([][]string, 2*len(tailCombs))
|
|
||||||
for i, c := range tailCombs {
|
|
||||||
combs[i*2] = append([]string{filepathParts[0]}, c...)
|
|
||||||
combs[i*2+1] = append([]string{"{*}"}, c...)
|
|
||||||
}
|
|
||||||
|
|
||||||
return combs
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// func (s *Server) handleTemplateError(err error, templateArgs ...any) (response.Response, error) {
|
|
||||||
func (s *webpageRouter) handleTemplateError(err error, templateArgs ...any) (response.Response, error) {
|
|
||||||
if isFileNotFoundError(err) {
|
if isFileNotFoundError(err) {
|
||||||
return nil, response.NotFound().
|
return nil, response.NotFound().
|
||||||
Wrap(ErrTemplateNotFound{
|
Wrap(ErrTemplateNotFound{
|
||||||
@@ -223,31 +163,10 @@ func (s *webpageRouter) handleTemplateError(err error, templateArgs ...any) (res
|
|||||||
}
|
}
|
||||||
|
|
||||||
func isFileNotFoundError(err error) bool {
|
func isFileNotFoundError(err error) bool {
|
||||||
/*
|
|
||||||
var pe *os.PathError
|
|
||||||
isPathErr := errors.As(err, &pe)
|
|
||||||
|
|
||||||
return isPathErr && pe.Err != nil && pe.Err.Error() == "no such file or directory"
|
|
||||||
*/
|
|
||||||
|
|
||||||
var te *templater.ErrNotTemplateFileFound
|
var te *templater.ErrNotTemplateFileFound
|
||||||
return errors.As(err, &te)
|
return errors.As(err, &te)
|
||||||
}
|
}
|
||||||
|
|
||||||
func getHTTPStatusCode(err error) int {
|
|
||||||
rerr, ok := response.GetError(err)
|
|
||||||
if !ok {
|
|
||||||
return http.StatusInternalServerError
|
|
||||||
}
|
|
||||||
|
|
||||||
code, ok := rerr.GetStatus()
|
|
||||||
if !ok {
|
|
||||||
return http.StatusInternalServerError
|
|
||||||
}
|
|
||||||
|
|
||||||
return code
|
|
||||||
}
|
|
||||||
|
|
||||||
// template tooling
|
// template tooling
|
||||||
|
|
||||||
type URLCalculator struct {
|
type URLCalculator struct {
|
||||||
|
|||||||
@@ -2,15 +2,10 @@ package server
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"html/template"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"path"
|
"path"
|
||||||
"strconv"
|
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/angelbeltran/templater"
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
|
|
||||||
"ruben/inventory2/internal/domains/accounts"
|
"ruben/inventory2/internal/domains/accounts"
|
||||||
@@ -73,56 +68,6 @@ func Router(
|
|||||||
logger.WithGroup("templates"),
|
logger.WithGroup("templates"),
|
||||||
r.Group("/ui"),
|
r.Group("/ui"),
|
||||||
contentDir,
|
contentDir,
|
||||||
// TODO: move this constructor call up to main.go
|
|
||||||
// TODO: clean up the references to the templates dir throughout as well (should only be referred to in the 'main' package
|
|
||||||
new(templater.Templater).With(templater.Config{
|
|
||||||
Funcs: func(name string, props map[string]any) template.FuncMap {
|
|
||||||
return template.FuncMap{
|
|
||||||
// params
|
|
||||||
"addPathParam": func(k string, v any, args map[string]any) (map[string]any, error) {
|
|
||||||
pathParams, ok := args["PathParams"].(map[string]any)
|
|
||||||
if !ok {
|
|
||||||
return nil, fmt.Errorf("PathParams not set as args: %v", args)
|
|
||||||
}
|
|
||||||
|
|
||||||
pathParams[k] = fmt.Sprint(v)
|
|
||||||
|
|
||||||
return args, nil
|
|
||||||
},
|
|
||||||
|
|
||||||
// parsing
|
|
||||||
"parseInt": func(s string) (int, error) {
|
|
||||||
return strconv.Atoi(s)
|
|
||||||
},
|
|
||||||
"parseInt64": func(s string) (int64, error) {
|
|
||||||
return strconv.ParseInt(s, 10, 64)
|
|
||||||
},
|
|
||||||
"parsePlatform": func(s string) (accounts.Platform, error) {
|
|
||||||
return accounts.NewPlatform(s)
|
|
||||||
},
|
|
||||||
|
|
||||||
// arithmetic
|
|
||||||
"addInt": func(a, b int) int {
|
|
||||||
return a + b
|
|
||||||
},
|
|
||||||
"subInt": func(a, b int) int {
|
|
||||||
return a - b
|
|
||||||
},
|
|
||||||
"multInt": func(a, b int) int {
|
|
||||||
return a * b
|
|
||||||
},
|
|
||||||
|
|
||||||
// json
|
|
||||||
"prettyPrintJSON": func(j json.RawMessage) string {
|
|
||||||
b, err := json.MarshalIndent(j, " ", "")
|
|
||||||
if err != nil {
|
|
||||||
return string(j)
|
|
||||||
}
|
|
||||||
return string(b)
|
|
||||||
},
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
rawEvents,
|
rawEvents,
|
||||||
accts,
|
accts,
|
||||||
etsy,
|
etsy,
|
||||||
|
|||||||
+5
-9
@@ -1,12 +1,8 @@
|
|||||||
{{/* TODO: make the save button disabled based on an api call */}}
|
{{/* TODO: make the save button disabled based on an api call */}}
|
||||||
{{/* .Identity.Account.AccountID, .Accounts */}}
|
|
||||||
|
|
||||||
{{- $dot := or .dot . -}}
|
{{- $acctID := .PathParams.acctID }}
|
||||||
|
{{- $orderIndex := .PathParams.orderIndex }}
|
||||||
{{- $acctID := $dot.Identity.Account.AccountID }}
|
{{- $entry := .Accounts.GetSyncGroupListingDraft $acctID $orderIndex }}
|
||||||
|
|
||||||
{{- $orderIndex := or $dot.OrderIndex (parseInt $dot.PathParams.orderIndex) -}}
|
|
||||||
{{- $entry := $dot.Accounts.GetSyncGroupListingDraft $acctID $orderIndex }}
|
|
||||||
{{- $selectedShopPlatform := $entry.Platform }}
|
{{- $selectedShopPlatform := $entry.Platform }}
|
||||||
{{- $selectedShopID := $entry.ShopID }}
|
{{- $selectedShopID := $entry.ShopID }}
|
||||||
{{- $selectedListingID := $entry.ListingID }}
|
{{- $selectedListingID := $entry.ListingID }}
|
||||||
@@ -30,7 +26,7 @@
|
|||||||
"
|
"
|
||||||
>
|
>
|
||||||
<td>
|
<td>
|
||||||
{{- $shops := $dot.Accounts.GetShops $acctID -}}
|
{{- $shops := .Accounts.GetShops $acctID -}}
|
||||||
<select
|
<select
|
||||||
class="min-w-fit cursor-pointer"
|
class="min-w-fit cursor-pointer"
|
||||||
hx-put="/api/accounts/{{$acctID}}/inventory/sync-groups/draft/listings/{{$orderIndex}}/shop"
|
hx-put="/api/accounts/{{$acctID}}/inventory/sync-groups/draft/listings/{{$orderIndex}}/shop"
|
||||||
@@ -64,7 +60,7 @@
|
|||||||
<td>
|
<td>
|
||||||
{{- $selectedListing := "" }}
|
{{- $selectedListing := "" }}
|
||||||
{{- if $selectedShopID }}
|
{{- if $selectedShopID }}
|
||||||
{{- $listings := $dot.Accounts.GetListingsForShop $acctID $selectedShopPlatform $selectedShopID }}
|
{{- $listings := .Accounts.GetListingsForShop $acctID $selectedShopPlatform $selectedShopID }}
|
||||||
{{- if $listings }}
|
{{- if $listings }}
|
||||||
<select
|
<select
|
||||||
class="min-w-fit cursor-pointer"
|
class="min-w-fit cursor-pointer"
|
||||||
+4
-15
@@ -1,17 +1,8 @@
|
|||||||
{{- $dot := or .dot . }}
|
|
||||||
{{- .Auth.ByMatchingAccountID 2 }}
|
{{- .Auth.ByMatchingAccountID 2 }}
|
||||||
|
|
||||||
|
|
||||||
|
{{- $acctID := .PathParams.acctID }}
|
||||||
{{- $acctID := 0 }}
|
{{- $stores := .Accounts.GetShops $acctID -}}
|
||||||
{{- if $dot.Identity }}
|
|
||||||
{{- $acctID = $dot.Identity.Account.AccountID }}
|
|
||||||
{{- else if .PathParams }}
|
|
||||||
{{- $acctID = $dot.PathParams.acctID | parseInt64 }}
|
|
||||||
{{- else }}
|
|
||||||
{{- $acctID = $dot.AccountID }}
|
|
||||||
{{- end }}
|
|
||||||
{{- $stores := $dot.Accounts.GetShops $acctID -}}
|
|
||||||
|
|
||||||
|
|
||||||
<table id="accounts-acct-id-inventory-sync-groups-draft-table" class="max-w-full overflow-x-auto">
|
<table id="accounts-acct-id-inventory-sync-groups-draft-table" class="max-w-full overflow-x-auto">
|
||||||
@@ -58,11 +49,9 @@
|
|||||||
send setDisabled(disabled: not allRowsFilledOut or numRows < 2) to #create-sync-group-button
|
send setDisabled(disabled: not allRowsFilledOut or numRows < 2) to #create-sync-group-button
|
||||||
"
|
"
|
||||||
>
|
>
|
||||||
{{- $listings := $dot.Accounts.GetSyncGroupListingDrafts $acctID }}
|
{{- $listings := .Accounts.GetSyncGroupListingDrafts $acctID }}
|
||||||
{{- range $listing := $listings }}
|
{{- range $listing := $listings }}
|
||||||
{{- component "accounts/{acctID}/inventory/sync-groups/draft/listings/{orderIndex}"
|
{{- component (printf "accounts/%d/inventory/sync-groups/draft/listings/%d" $acctID $listing.OrderIndex) }}
|
||||||
"dot" ($dot | addPathParam "orderIndex" $listing.OrderIndex)
|
|
||||||
}}
|
|
||||||
{{- end }}
|
{{- end }}
|
||||||
</tbody>
|
</tbody>
|
||||||
<tfoot>
|
<tfoot>
|
||||||
+2
-1
@@ -17,7 +17,8 @@
|
|||||||
<h4>
|
<h4>
|
||||||
(Draft 2)
|
(Draft 2)
|
||||||
</h4>
|
</h4>
|
||||||
{{ component "accounts/{acctID}/inventory/sync-groups/draft/table" "dot" . }}
|
{{/* component "accounts/{acctID}/inventory/sync-groups/draft/table" "dot" . */}}
|
||||||
|
{{ component (printf "accounts/%d/inventory/sync-groups/draft/table" $acctID) "dot" . }}
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
{{ component "button"
|
{{ component "button"
|
||||||
Reference in New Issue
Block a user