* Provide storage policy config APIs to make it easy to use
* Update api client
Signed-off-by: Ryan Wang <i@ryanc.cc>
---------
Signed-off-by: Ryan Wang <i@ryanc.cc>
Co-authored-by: Ryan Wang <i@ryanc.cc>
#### What type of PR is this?
/area ui
/kind feautre
/milestone 2.21.x
#### What this PR does / why we need it:
This PR adds a core Dashboard Widget called Stack Widget, which is used to stack a batch of components in the same location and supports manual or automatic switching.
<img width="737" alt="image" src="https://github.com/user-attachments/assets/de448cd8-cf62-4608-8523-88395298e734" />
<img width="827" alt="image" src="https://github.com/user-attachments/assets/fecaf637-9cb8-444a-888b-0ee2a9700bc7" />
#### Which issue(s) this PR fixes:
Fixes #
#### Special notes for your reviewer:
#### Does this PR introduce a user-facing change?
```release-note
为仪表盘添加堆叠小部件
```
#### What type of PR is this?
/area ui
/kind improvement
/milestone 2.21.x
#### What this PR does / why we need it:
<img width="1202" alt="image" src="https://github.com/user-attachments/assets/cac050d2-b984-4b48-afe0-e18db220ec19" />
#### Does this PR introduce a user-facing change?
```release-note
将 Console 端文章列表的发布时间改为语义化时间
```
#### What type of PR is this?
/area ui
/kind improvement
/milestone 2.21.x
#### What this PR does / why we need it:
Migrate system settings to new configmap API
#### Which issue(s) this PR fixes:
Fixes#7515
#### Special notes for your reviewer:
Need to test whether the system setting is working properly
#### Does this PR introduce a user-facing change?
```release-note
None
```
* refactor: redesign ui of comment management page
Signed-off-by: Ryan Wang <i@ryanc.cc>
* Add comment detail modal
Signed-off-by: Ryan Wang <i@ryanc.cc>
* Add reply detail modal
Signed-off-by: Ryan Wang <i@ryanc.cc>
* Improve ui
Signed-off-by: Ryan Wang <i@ryanc.cc>
* Add pending comments widget
Signed-off-by: Ryan Wang <i@ryanc.cc>
* Improve ui
Signed-off-by: Ryan Wang <i@ryanc.cc>
* Improve ui
Signed-off-by: Ryan Wang <i@ryanc.cc>
---------
Signed-off-by: Ryan Wang <i@ryanc.cc>
#### What type of PR is this?
/kind cleanup
/area ui
#### What this PR does / why we need it:
Fix correct package import paths
#### Does this PR introduce a user-facing change?
```release-note
None
```
* Add support for configuring my preferences
* Update api client
Signed-off-by: Ryan Wang <i@ryanc.cc>
* Update api client
Signed-off-by: Ryan Wang <i@ryanc.cc>
---------
Signed-off-by: Ryan Wang <i@ryanc.cc>
Co-authored-by: Ryan Wang <i@ryanc.cc>
#### What type of PR is this?
/area ui
/kind improvement
/milestone 2.21.x
#### What this PR does / why we need it:
As per the title, the time shown in the plugin list is the installation time of the plugin. For usage purposes, this time seems to have no meaning or reference value.
#### Which issue(s) this PR fixes:
Fixes#7493
#### Does this PR introduce a user-facing change?
```release-note
移除插件列表的时间字段,并在插件详情中显示安装时间。
```
* fix: exclude reserved users from global search results
Signed-off-by: Ryan Wang <i@ryanc.cc>
* Use labelSelector
Signed-off-by: Ryan Wang <i@ryanc.cc>
---------
Signed-off-by: Ryan Wang <i@ryanc.cc>
#### What type of PR is this?
/kind improvement
/area core
/milestone 2.21.x
#### What this PR does / why we need it:
This PR allows users to set external URL at setup page without performing a restart.
#### Which issue(s) this PR fixes:
Fixes https://github.com/halo-dev/halo/issues/7479
#### Special notes for your reviewer:
1. Try to start Halo instance with a fresh environment.
2. Request index page and you will be redirected to setup page.
3. Check if the external URL is equal to the base URL in your browser.
4. Try to change external URL and finish the setup process.
5. Login to console and check the external URL in overview page.
#### Does this PR introduce a user-facing change?
```release-note
支持在初始化页面设置外部访问地址
```
#### What type of PR is this?
/area ui
/kind bug
/milestone 2.21.x
#### What this PR does / why we need it:
Fix correct attachment selection state after new upload.
#### Which issue(s) this PR fixes:
Fixes https://github.com/halo-dev/halo/issues/7472
#### Does this PR introduce a user-facing change?
```release-note
修复当有已选择附件时,上传新附件导致所选附件状态异常的问题。
```
#### What type of PR is this?
/area ui
/kind bug
/milestone 2.21.x
#### What this PR does / why we need it:
See https://github.com/halo-dev/halo/issues/7480
#### Which issue(s) this PR fixes:
Fixes https://github.com/halo-dev/halo/issues/7480
#### Special notes for your reviewer:
#### Does this PR introduce a user-facing change?
```release-note
None
```
#### What type of PR is this?
/area ui
/kind bug
/milestone 2.21.x
#### What this PR does / why we need it:
Resolve ui issue of global search component cause by https://github.com/halo-dev/halo/pull/7383
#### Which issue(s) this PR fixes:
Fixes https://github.com/halo-dev/halo/issues/7478
#### Special notes for your reviewer:
#### Does this PR introduce a user-facing change?
```release-note
修复 2.21.0-alpha.1 中 Console 的全局搜索样式问题。
```
#### What type of PR is this?
/kind improvement
/area editor
/milestone 2.21.x
#### What this PR does / why we need it:
Improve English translations for the editor. The changes in https://github.com/halo-dev/halo/pull/7444 did not provide English translations.
#### Does this PR introduce a user-facing change?
```release-note
None
```
#### What type of PR is this?
/kind bug
/area core
/milestone 2.21.x
#### What this PR does / why we need it:
This PR fixes the problem of not working for relative permalink caused by <https://github.com/halo-dev/halo/pull/7459>.
#### Special notes for your reviewer:
1. Try to start Halo instance with `halo.use-absolute-permalink=false` and check the permalinks of posts and attachments.
1. Try to start Halo instance with `halo.use-absolute-permalink=true` and check the permalinks of posts and attachments.
#### Does this PR introduce a user-facing change?
```release-note
None
```
#### What type of PR is this?
/kind cleanup
/area core
/milestone 2.21.x
#### What this PR does / why we need it:
This PR corrects location of LogoutHandler instead of in LogoutSuccessHandler. LogoutHanadler should be invoked before LogoutSuccessHandler.
#### Does this PR introduce a user-facing change?
```release-note
None
```
#### What type of PR is this?
/kind improvement
#### What this PR does / why we need it:
This PR adds UserLoginEvent and UserLogoutEvent which are shared to plugins.
#### Which issue(s) this PR fixes:
Fixes https://github.com/halo-dev/halo/issues/7436
#### Does this PR introduce a user-facing change?
```release-note
添加用户登录/登出事件
```
#### What type of PR is this?
/kind improvement
/area core
/milestone 2.21.x
#### What this PR does / why we need it:
This PR bumps Spring Boot to [3.5.0](https://github.com/spring-projects/spring-boot/releases/tag/v3.5.0).
#### Does this PR introduce a user-facing change?
```release-note
升级依赖 Spring Boot 至 3.5.0
```
* Add support for configuring external URL online
* Fix the problem of timeout on external URL initialization
* Add external URL editing capability to overview page
Signed-off-by: Ryan Wang <i@ryanc.cc>
---------
Signed-off-by: Ryan Wang <i@ryanc.cc>
Co-authored-by: Ryan Wang <i@ryanc.cc>
#### What type of PR is this?
/kind bug
/area core
/milestone 2.21.x
#### What this PR does / why we need it:
This PR check if the locale is undetermined during resolving locale. Or it will cause the error below if locale is `und`:
```java
2025-05-21T17:28:45.953+08:00 ERROR 58760 --- [undedElastic-14] o.s.w.s.adapter.HttpWebHandlerAdapter : [c1824fa5-1] 500 Server Error for HTTP GET "/"
org.thymeleaf.exceptions.TemplateOutputException: An error happened during template rendering
at org.thymeleaf.engine.OutputTemplateHandler.handleText(OutputTemplateHandler.java:75) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.thymeleaf.engine.AbstractTemplateHandler.handleText(AbstractTemplateHandler.java:221) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.thymeleaf.engine.ProcessorTemplateHandler.handleText(ProcessorTemplateHandler.java:587) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.thymeleaf.engine.Text.beHandled(Text.java:97) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.thymeleaf.engine.Model.process(Model.java:300) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.thymeleaf.engine.GatheringModelProcessable.process(GatheringModelProcessable.java:78) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.thymeleaf.engine.ProcessorTemplateHandler.queueProcessable(ProcessorTemplateHandler.java:2106) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.thymeleaf.engine.ProcessorTemplateHandler.handleCloseElement(ProcessorTemplateHandler.java:1642) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.thymeleaf.engine.CloseElementTag.beHandled(CloseElementTag.java:139) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.thymeleaf.engine.Model.process(Model.java:300) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.thymeleaf.engine.OpenElementTagModelProcessable.process(OpenElementTagModelProcessable.java:110) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.thymeleaf.engine.ProcessorTemplateHandler.queueProcessable(ProcessorTemplateHandler.java:2106) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.thymeleaf.engine.ProcessorTemplateHandler.handleOpenElement(ProcessorTemplateHandler.java:1559) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.thymeleaf.engine.OpenElementTag.beHandled(OpenElementTag.java:205) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.thymeleaf.engine.TemplateModel.process(TemplateModel.java:155) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.thymeleaf.engine.ThrottledTemplateProcessor.process(ThrottledTemplateProcessor.java:235) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.thymeleaf.engine.ThrottledTemplateProcessor.process(ThrottledTemplateProcessor.java:200) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.thymeleaf.spring6.SpringWebFluxTemplateEngine$StreamThrottledTemplateProcessor.process(SpringWebFluxTemplateEngine.java:720) ~[thymeleaf-spring6-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.thymeleaf.spring6.SpringWebFluxTemplateEngine.lambda$createChunkedStream$2(SpringWebFluxTemplateEngine.java:269) ~[thymeleaf-spring6-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at reactor.core.publisher.FluxGenerate$GenerateSubscription.slowPath(FluxGenerate.java:271) ~[reactor-core-3.7.5.jar:3.7.5]
at reactor.core.publisher.FluxGenerate$GenerateSubscription.request(FluxGenerate.java:213) ~[reactor-core-3.7.5.jar:3.7.5]
at reactor.core.publisher.FluxPeekFuseable$PeekFuseableSubscriber.request(FluxPeekFuseable.java:144) ~[reactor-core-3.7.5.jar:3.7.5]
at reactor.core.publisher.FluxSubscribeOn$SubscribeOnSubscriber.requestUpstream(FluxSubscribeOn.java:131) ~[reactor-core-3.7.5.jar:3.7.5]
at reactor.core.publisher.FluxSubscribeOn$SubscribeOnSubscriber.onSubscribe(FluxSubscribeOn.java:124) ~[reactor-core-3.7.5.jar:3.7.5]
at reactor.core.publisher.FluxPeekFuseable$PeekFuseableSubscriber.onSubscribe(FluxPeekFuseable.java:178) ~[reactor-core-3.7.5.jar:3.7.5]
at reactor.core.publisher.FluxGenerate.subscribe(FluxGenerate.java:85) ~[reactor-core-3.7.5.jar:3.7.5]
at reactor.core.publisher.InternalFluxOperator.subscribe(InternalFluxOperator.java:68) ~[reactor-core-3.7.5.jar:3.7.5]
at reactor.core.publisher.FluxSubscribeOn$SubscribeOnSubscriber.run(FluxSubscribeOn.java:194) ~[reactor-core-3.7.5.jar:3.7.5]
at reactor.core.scheduler.BoundedElasticThreadPerTaskScheduler$SchedulerTask.run(BoundedElasticThreadPerTaskScheduler.java:1013) ~[reactor-core-3.7.5.jar:3.7.5]
at java.base/java.lang.VirtualThread.run(VirtualThread.java:329) ~[na:na]
Caused by: org.thymeleaf.exceptions.TemplateProcessingException: Locale "" cannot be used as it does not specify a language. (template: "modules/layout" - line 12, col 49)
at org.thymeleaf.messageresolver.StandardMessageResolutionUtils.computeMessageResourceNamesFromBase(StandardMessageResolutionUtils.java:202) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.thymeleaf.messageresolver.StandardMessageResolutionUtils.resolveMessagesForTemplate(StandardMessageResolutionUtils.java:69) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.thymeleaf.messageresolver.StandardMessageResolver.resolveMessagesForTemplate(StandardMessageResolver.java:380) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.thymeleaf.messageresolver.StandardMessageResolver.resolveMessage(StandardMessageResolver.java:282) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.thymeleaf.messageresolver.StandardMessageResolver.resolveMessage(StandardMessageResolver.java:227) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.thymeleaf.context.AbstractEngineContext.getMessage(AbstractEngineContext.java:134) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.thymeleaf.standard.expression.MessageExpression.executeMessageExpression(MessageExpression.java:265) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.thymeleaf.standard.expression.SimpleExpression.executeSimple(SimpleExpression.java:69) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.thymeleaf.standard.expression.Expression.execute(Expression.java:109) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.thymeleaf.standard.expression.Expression.execute(Expression.java:138) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.thymeleaf.standard.processor.StandardUtextTagProcessor.doProcess(StandardUtextTagProcessor.java:87) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.thymeleaf.processor.element.AbstractAttributeTagProcessor.doProcess(AbstractAttributeTagProcessor.java:74) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.thymeleaf.processor.element.AbstractElementTagProcessor.process(AbstractElementTagProcessor.java:95) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.thymeleaf.util.ProcessorConfigurationUtils$ElementTagProcessorWrapper.process(ProcessorConfigurationUtils.java:633) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.thymeleaf.engine.ProcessorTemplateHandler.handleOpenElement(ProcessorTemplateHandler.java:1314) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.thymeleaf.engine.OpenElementTag.beHandled(OpenElementTag.java:205) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.thymeleaf.engine.TemplateModel.process(TemplateModel.java:136) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.thymeleaf.engine.TemplateManager.process(TemplateManager.java:519) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.thymeleaf.util.LazyProcessingCharSequence.writeUnresolved(LazyProcessingCharSequence.java:85) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.thymeleaf.util.AbstractLazyCharSequence.write(AbstractLazyCharSequence.java:103) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.thymeleaf.engine.AbstractTextualTemplateEvent.writeContent(AbstractTextualTemplateEvent.java:224) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.thymeleaf.engine.Text.write(Text.java:78) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
at org.thymeleaf.engine.OutputTemplateHandler.handleText(OutputTemplateHandler.java:71) ~[thymeleaf-3.1.3.RELEASE.jar:3.1.3.RELEASE]
... 29 common frames omitted
```
#### Does this PR introduce a user-facing change?
```release-note
修复因 Locale 解析错误导致无法访问页面的问题
```
#### What type of PR is this?
/kind improvement
/area core
/milestone 2.21.x
#### What this PR does / why we need it:
This PR removes `/uploads/**` from static resources to make it protected by Halo security.
#### Does this PR introduce a user-facing change?
```release-note
None
```
* refactor: improve entity component layout for better device responsiveness
Signed-off-by: Ryan Wang <i@ryanc.cc>
* Resolve CSS style conflicts
Signed-off-by: Ryan Wang <i@ryanc.cc>
* Update missing translaions
Signed-off-by: Ryan Wang <i@ryanc.cc>
---------
Signed-off-by: Ryan Wang <i@ryanc.cc>
#### What type of PR is this?
/kind improvement
/area core
/milestone 2.21.x
#### What this PR does / why we need it:
This PR sets Java 21 as minimal version. After doing that, Halo can only run on Java 21 or newer version.
Fortunately, all plugins and themes won't be affected by the restriction.
> https://docs.gradle.org/current/userguide/toolchains.html#sec:release-flag-toolchain
#### Which issue(s) this PR fixes:
Fixes https://github.com/halo-dev/halo/issues/6867
#### Does this PR introduce a user-facing change?
```release-note
[Action Required] 更新最低运行环境为 Java 21
```