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.")
private Ref postRef;
@Schema(description = "Page reference.")
private Ref pageRef;
@Schema(description = "SinglePage reference.")
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.MenuItemStatus;
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.extension.ExtensionClient;
import run.halo.app.extension.Ref;
@ -35,9 +36,8 @@ public class MenuItemReconciler implements Reconciler<Request> {
return handleCategoryRef(request.name(), status, spec.getCategoryRef());
} else if (spec.getTagRef() != null) {
return handleTagRef(request.name(), status, spec.getTagRef());
} else if (spec.getPageRef() != null) {
// TODO resolve permalink from page. At present, we don't have Page extension.
return new Result(false, null);
} else if (spec.getSinglePageRef() != null) {
return handleSinglePageSpec(request.name(), status, spec.getSinglePageRef());
} else if (spec.getPostRef() != null) {
return handlePostRef(request.name(), status, spec.getPostRef());
} else {
@ -79,6 +79,18 @@ public class MenuItemReconciler implements Reconciler<Request> {
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) {
if (spec.getHref() != null && StringUtils.hasText(spec.getDisplayName())) {
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.MenuItem;
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.Metadata;
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
class WhenOtherRefsNotSet {