Reconcile SinglePage reference of MenuItem (#2395)

#### What type of PR is this?

/kind feature

#### What this PR does / why we need it:

Synchronize premalink and display name from SinglePage every 1 minute if only `spec.pageRef` is set.

#### Special notes for your reviewer:

See https://github.com/halo-dev/halo/pull/2380 for more.

How to test?

1. Checkout https://github.com/halo-dev/halo-admin/pull/608 and run it.
2. Create a custom page
3. Select the custom page you created just now when creating menu item
4. Check the permalink of the menu item
5. Change slug name of the custom page and check the permalink of it
6. Wait for 1 minute and check the permalink of of the menu item

#### Does this PR introduce a user-facing change?

```release-note
支持绑定自定义页面至菜单项
```
pull/2417/head
John Niang 2022-09-08 18:12:10 +08:00 committed by GitHub
parent a2ee2e492e
commit d1902ef50f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 63 additions and 5 deletions

View File

@ -49,8 +49,8 @@ public class MenuItem extends AbstractExtension {
@Schema(description = "Post reference.") @Schema(description = "Post reference.")
private Ref postRef; private Ref postRef;
@Schema(description = "Page reference.") @Schema(description = "SinglePage reference.")
private Ref pageRef; private Ref singlePageRef;
} }

View File

@ -8,6 +8,7 @@ import run.halo.app.core.extension.MenuItem;
import run.halo.app.core.extension.MenuItem.MenuItemSpec; import run.halo.app.core.extension.MenuItem.MenuItemSpec;
import run.halo.app.core.extension.MenuItem.MenuItemStatus; import run.halo.app.core.extension.MenuItem.MenuItemStatus;
import run.halo.app.core.extension.Post; import run.halo.app.core.extension.Post;
import run.halo.app.core.extension.SinglePage;
import run.halo.app.core.extension.Tag; import run.halo.app.core.extension.Tag;
import run.halo.app.extension.ExtensionClient; import run.halo.app.extension.ExtensionClient;
import run.halo.app.extension.Ref; import run.halo.app.extension.Ref;
@ -35,9 +36,8 @@ public class MenuItemReconciler implements Reconciler<Request> {
return handleCategoryRef(request.name(), status, spec.getCategoryRef()); return handleCategoryRef(request.name(), status, spec.getCategoryRef());
} else if (spec.getTagRef() != null) { } else if (spec.getTagRef() != null) {
return handleTagRef(request.name(), status, spec.getTagRef()); return handleTagRef(request.name(), status, spec.getTagRef());
} else if (spec.getPageRef() != null) { } else if (spec.getSinglePageRef() != null) {
// TODO resolve permalink from page. At present, we don't have Page extension. return handleSinglePageSpec(request.name(), status, spec.getSinglePageRef());
return new Result(false, null);
} else if (spec.getPostRef() != null) { } else if (spec.getPostRef() != null) {
return handlePostRef(request.name(), status, spec.getPostRef()); return handlePostRef(request.name(), status, spec.getPostRef());
} else { } else {
@ -79,6 +79,18 @@ public class MenuItemReconciler implements Reconciler<Request> {
return new Result(true, Duration.ofMinutes(1)); return new Result(true, Duration.ofMinutes(1));
} }
private Result handleSinglePageSpec(String menuItemName, MenuItemStatus status, Ref pageRef) {
client.fetch(SinglePage.class, pageRef.getName())
.filter(page -> page.getStatus() != null)
.filter(page -> StringUtils.hasText(page.getStatus().getPermalink()))
.ifPresent(page -> {
status.setHref(page.getStatus().getPermalink());
status.setDisplayName(page.getSpec().getTitle());
updateStatus(menuItemName, status);
});
return new Result(true, Duration.ofMinutes(1));
}
private Result handleMenuSpec(String menuItemName, MenuItemStatus status, MenuItemSpec spec) { private Result handleMenuSpec(String menuItemName, MenuItemStatus status, MenuItemSpec spec) {
if (spec.getHref() != null && StringUtils.hasText(spec.getDisplayName())) { if (spec.getHref() != null && StringUtils.hasText(spec.getDisplayName())) {
status.setHref(spec.getHref()); status.setHref(spec.getHref());

View File

@ -23,6 +23,7 @@ import org.mockito.junit.jupiter.MockitoExtension;
import run.halo.app.core.extension.Category; import run.halo.app.core.extension.Category;
import run.halo.app.core.extension.MenuItem; import run.halo.app.core.extension.MenuItem;
import run.halo.app.core.extension.MenuItem.MenuItemSpec; import run.halo.app.core.extension.MenuItem.MenuItemSpec;
import run.halo.app.core.extension.SinglePage;
import run.halo.app.extension.ExtensionClient; import run.halo.app.extension.ExtensionClient;
import run.halo.app.extension.Metadata; import run.halo.app.extension.Metadata;
import run.halo.app.extension.Ref; import run.halo.app.extension.Ref;
@ -101,6 +102,51 @@ class MenuItemReconcilerTest {
} }
} }
@Nested
class WhenSinglePageRefSet {
@Test
void shouldUpdateMenuItemIfPageFound() {
Supplier<MenuItem> menuItemSupplier = () -> createMenuItem("fake-name", spec -> {
spec.setSinglePageRef(Ref.of("fake-page"));
});
when(client.fetch(MenuItem.class, "fake-name"))
.thenReturn(Optional.of(menuItemSupplier.get()))
.thenReturn(Optional.of(menuItemSupplier.get()));
when(client.fetch(SinglePage.class, "fake-page"))
.thenReturn(Optional.of(createSinglePage()));
var result = reconciler.reconcile(new Request("fake-name"));
assertTrue(result.reEnqueue());
assertEquals(Duration.ofMinutes(1), result.retryAfter());
verify(client, times(2)).fetch(MenuItem.class, "fake-name");
verify(client).fetch(SinglePage.class, "fake-page");
verify(client).<MenuItem>update(argThat(menuItem -> {
var status = menuItem.getStatus();
return status.getHref().equals("fake://permalink")
&& status.getDisplayName().equals("fake-title");
}));
}
SinglePage createSinglePage() {
var metadata = new Metadata();
metadata.setName("fake-page");
var spec = new SinglePage.SinglePageSpec();
spec.setTitle("fake-title");
var status = new SinglePage.SinglePageStatus();
status.setPermalink("fake://permalink");
var singlePage = new SinglePage();
singlePage.setMetadata(metadata);
singlePage.setSpec(spec);
singlePage.setStatus(status);
return singlePage;
}
}
@Nested @Nested
class WhenOtherRefsNotSet { class WhenOtherRefsNotSet {