Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

except partial load support #2

Merged
merged 1 commit into from
Jun 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion helpers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,14 @@ func asInertiaRequest(r *http.Request) {
r.Header.Set("X-Inertia", "true")
}

func withPartialData(r *http.Request, data []string) {
func withOnly(r *http.Request, data []string) {
r.Header.Set("X-Inertia-Partial-Data", strings.Join(data, ","))
}

func withExcept(r *http.Request, data []string) {
r.Header.Set("X-Inertia-Partial-Except", strings.Join(data, ","))
}

func withPartialComponent(r *http.Request, component string) {
r.Header.Set("X-Inertia-Partial-Component", component)
}
Expand Down
11 changes: 10 additions & 1 deletion http.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ func setResponseStatus(w http.ResponseWriter, status int) {
w.WriteHeader(status)
}

func partialDataFromRequest(r *http.Request) []string {
func onlyFromRequest(r *http.Request) []string {
header := r.Header.Get("X-Inertia-Partial-Data")
if header == "" {
return nil
Expand All @@ -36,6 +36,15 @@ func partialDataFromRequest(r *http.Request) []string {
return strings.Split(header, ",")
}

func exceptFromRequest(r *http.Request) []string {
header := r.Header.Get("X-Inertia-Partial-Except")
if header == "" {
return nil
}

return strings.Split(header, ",")
}

func partialComponentFromRequest(r *http.Request) string {
return r.Header.Get("X-Inertia-Partial-Component")
}
Expand Down
27 changes: 25 additions & 2 deletions inertia_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -277,7 +277,7 @@ func TestInertia_Render(t *testing.T) {

w, r := requestMock(http.MethodGet, "/home")
asInertiaRequest(r)
withPartialData(r, []string{"foo", "closure", "lazy"})
withOnly(r, []string{"foo", "closure", "lazy"})
withPartialComponent(r, "Some/Component")

err := I().Render(w, r, "Some/Component", Props{
Expand Down Expand Up @@ -306,7 +306,7 @@ func TestInertia_Render(t *testing.T) {

w, r := requestMock(http.MethodGet, "/home")
asInertiaRequest(r)
withPartialData(r, []string{"foo", "closure", "lazy"})
withOnly(r, []string{"foo", "closure", "lazy"})
withPartialComponent(r, "Other/Component")

err := I().Render(w, r, "Some/Component", Props{
Expand All @@ -327,6 +327,29 @@ func TestInertia_Render(t *testing.T) {
})
})
})

t.Run("except", func(t *testing.T) {
w, r := requestMock(http.MethodGet, "/home")
asInertiaRequest(r)
withOnly(r, []string{"foo", "baz"})
withExcept(r, []string{"foo"})
withPartialComponent(r, "Some/Component")

err := I().Render(w, r, "Some/Component", Props{
"foo": "bar",
"baz": "quz",
"bez": "bee",
})
if err != nil {
t.Fatalf("unexpected error: %#v", err)
}

assertable := AssertFromString(t, w.Body.String())
assertable.AssertProps(Props{
"baz": "quz",
"errors": map[string]any{},
})
})
})

t.Run("shared funcs", func(t *testing.T) {
Expand Down
47 changes: 26 additions & 21 deletions props.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,26 +49,31 @@ func (i *Inertia) prepareProps(r *http.Request, component string, props Props) (
result[key] = val
}

// Get props keys to return. If len == 0, then return all.
only := i.propsKeysToReturn(r, component)

// Filter props.
if len(only) > 0 {
for key, val := range result {
if _, ok := only[key]; ok {
continue
}
if _, ok := val.(AlwaysProp); ok {
continue
}
{
// Only (include keys) and except (exclude keys) logic.
only, except := i.getOnlyAndExcept(r, component)

// Filter props.
if len(only) > 0 {
for key, val := range result {
if _, ok := only[key]; ok {
continue
}
if _, ok := val.(AlwaysProp); ok {
continue
}

delete(result, key)
}
} else {
for key, val := range result {
if _, ok := val.(LazyProp); ok {
delete(result, key)
}
} else {
for key, val := range result {
if _, ok := val.(LazyProp); ok {
delete(result, key)
}
}
}
for key := range except {
delete(result, key)
}
}

Expand All @@ -84,15 +89,15 @@ func (i *Inertia) prepareProps(r *http.Request, component string, props Props) (
return result, nil
}

func (i *Inertia) propsKeysToReturn(r *http.Request, component string) map[string]struct{} {
func (i *Inertia) getOnlyAndExcept(r *http.Request, component string) (only, except map[string]struct{}) {
// Partial reloads only work for visits made to the same page component.
//
// https://inertiajs.com/partial-reloads
if partialComponentFromRequest(r) == component {
return setOf[string](partialDataFromRequest(r))
if partialComponentFromRequest(r) != component {
return nil, nil
}

return nil
return setOf[string](onlyFromRequest(r)), setOf[string](exceptFromRequest(r))
}

func resolvePropVal(val any) (_ any, err error) {
Expand Down
Loading