Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/main'
Browse files Browse the repository at this point in the history
  • Loading branch information
ruibaby committed Apr 25, 2024
2 parents d3c2bdb + fbf2b06 commit 02dca81
Show file tree
Hide file tree
Showing 21 changed files with 813 additions and 87 deletions.
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ RUN java -Djarmode=layertools -jar application.jar extract
################################

FROM ibm-semeru-runtimes:open-21-jre
MAINTAINER johnniang <johnniang@fastmail.com>
LABEL maintainer="johnniang <johnniang@foxmail.com>"
WORKDIR application
COPY --from=builder application/dependencies/ ./
COPY --from=builder application/spring-boot-loader/ ./
Expand Down
104 changes: 101 additions & 3 deletions api-docs/openapi/v3_0/aggregated.json
Original file line number Diff line number Diff line change
Expand Up @@ -3585,6 +3585,88 @@
]
}
},
"/apis/api.console.halo.run/v1alpha1/tags": {
"get": {
"description": "List Post Tags.",
"operationId": "ListPostTags",
"parameters": [
{
"description": "Page number. Default is 0.",
"in": "query",
"name": "page",
"schema": {
"type": "integer",
"format": "int32"
}
},
{
"description": "Size number. Default is 0.",
"in": "query",
"name": "size",
"schema": {
"type": "integer",
"format": "int32"
}
},
{
"description": "Label selector. e.g.: hidden!\u003dtrue",
"in": "query",
"name": "labelSelector",
"schema": {
"type": "array",
"items": {
"type": "string"
}
}
},
{
"description": "Field selector. e.g.: metadata.name\u003d\u003dhalo",
"in": "query",
"name": "fieldSelector",
"schema": {
"type": "array",
"items": {
"type": "string"
}
}
},
{
"description": "Sorting criteria in the format: property,(asc|desc). Default sort order is ascending. Multiple sort criteria are supported.",
"in": "query",
"name": "sort",
"schema": {
"type": "array",
"items": {
"type": "string"
}
}
},
{
"description": "Post tags filtered by keyword.",
"in": "query",
"name": "keyword",
"schema": {
"type": "string"
}
}
],
"responses": {
"default": {
"content": {
"*/*": {
"schema": {
"$ref": "#/components/schemas/TagList"
}
}
},
"description": "default response"
}
},
"tags": [
"api.console.halo.run/v1alpha1/Tag"
]
}
},
"/apis/api.console.halo.run/v1alpha1/themes": {
"get": {
"description": "List themes.",
Expand Down Expand Up @@ -13467,6 +13549,10 @@
"type": "string",
"format": "date-time"
},
"observedVersion": {
"type": "integer",
"format": "int64"
},
"replyCount": {
"type": "integer",
"format": "int32"
Expand Down Expand Up @@ -16437,8 +16523,7 @@
"RESOLVED",
"STARTED",
"STOPPED",
"FAILED",
"UNLOADED"
"FAILED"
]
},
"lastStartTime": {
Expand Down Expand Up @@ -17469,7 +17554,8 @@
"apiVersion",
"kind",
"metadata",
"spec"
"spec",
"status"
],
"type": "object",
"properties": {
Expand All @@ -17484,6 +17570,9 @@
},
"spec": {
"$ref": "#/components/schemas/ReplySpec"
},
"status": {
"$ref": "#/components/schemas/ReplyStatus"
}
}
},
Expand Down Expand Up @@ -17642,6 +17731,15 @@
}
}
},
"ReplyStatus": {
"type": "object",
"properties": {
"observedVersion": {
"type": "integer",
"format": "int64"
}
}
},
"ReplyVo": {
"required": [
"metadata",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
package run.halo.app.core.extension.endpoint;

import static org.springdoc.core.fn.builders.apiresponse.Builder.responseBuilder;
import static org.springdoc.core.fn.builders.parameter.Builder.parameterBuilder;
import static run.halo.app.extension.index.query.QueryFactory.all;
import static run.halo.app.extension.router.QueryParamBuildUtil.sortParameter;
import static run.halo.app.extension.router.selector.SelectorUtil.labelAndFieldSelectorToListOptions;

import io.swagger.v3.oas.annotations.enums.ParameterIn;
import io.swagger.v3.oas.annotations.media.ArraySchema;
import io.swagger.v3.oas.annotations.media.Schema;
import java.util.Optional;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springdoc.core.fn.builders.operation.Builder;
import org.springdoc.webflux.core.fn.SpringdocRouteBuilder;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.reactive.function.server.RouterFunction;
import org.springframework.web.reactive.function.server.ServerRequest;
import org.springframework.web.reactive.function.server.ServerResponse;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
import run.halo.app.core.extension.content.Tag;
import run.halo.app.extension.ListOptions;
import run.halo.app.extension.ListResult;
import run.halo.app.extension.PageRequestImpl;
import run.halo.app.extension.ReactiveExtensionClient;
import run.halo.app.extension.index.query.QueryFactory;
import run.halo.app.extension.router.IListRequest;

/**
* post tag endpoint.
*
* @author LIlGG
*/
@Slf4j
@Component
@RequiredArgsConstructor
public class TagEndpoint implements CustomEndpoint {

private final ReactiveExtensionClient client;

@Override
public RouterFunction<ServerResponse> endpoint() {
final var tag = "api.console.halo.run/v1alpha1/Tag";
return SpringdocRouteBuilder.route()
.GET("tags", this::listTag, builder -> {
builder.operationId("ListPostTags")
.description("List Post Tags.")
.tag(tag)
.response(
responseBuilder()
.implementation(ListResult.generateGenericClass(Tag.class))
);
TagQuery.buildParameters(builder);
}
)
.build();
}

Mono<ServerResponse> listTag(ServerRequest request) {
var tagQuery = new TagQuery(request);
return client.listBy(Tag.class, tagQuery.toListOptions(),
PageRequestImpl.of(tagQuery.getPage(), tagQuery.getSize(), tagQuery.getSort())
)
.flatMap(tags -> ServerResponse.ok().bodyValue(tags));
}

public interface ITagQuery extends IListRequest {

@Schema(description = "Keyword for searching.")
Optional<String> getKeyword();

@ArraySchema(uniqueItems = true,
arraySchema = @Schema(name = "sort",
description = "Sort property and direction of the list result. Supported fields: "
+ "creationTimestamp, name"),
schema = @Schema(description = "like field,asc or field,desc",
implementation = String.class,
example = "creationTimestamp,desc"))
Sort getSort();
}

public static class TagQuery extends IListRequest.QueryListRequest
implements ITagQuery {

private final ServerWebExchange exchange;

public TagQuery(ServerRequest request) {
super(request.queryParams());
this.exchange = request.exchange();
}

@Override
public Optional<String> getKeyword() {
return Optional.ofNullable(queryParams.getFirst("keyword"))
.filter(StringUtils::hasText);
}

@Override
public Sort getSort() {
var sort = SortResolver.defaultInstance.resolve(exchange);
sort = sort.and(Sort.by(
Sort.Order.desc("metadata.creationTimestamp"),
Sort.Order.asc("metadata.name")
));
return sort;
}

public ListOptions toListOptions() {
final var listOptions =
labelAndFieldSelectorToListOptions(getLabelSelector(), getFieldSelector());

var fieldQuery = all();
if (getKeyword().isPresent()) {
fieldQuery = QueryFactory.and(fieldQuery, QueryFactory.or(
QueryFactory.contains("spec.displayName", getKeyword().get()),
QueryFactory.contains("spec.slug", getKeyword().get())
));
}

listOptions.setFieldSelector(listOptions.getFieldSelector().andQuery(fieldQuery));
return listOptions;
}

public static void buildParameters(Builder builder) {
IListRequest.buildParameters(builder);
builder.parameter(sortParameter())
.parameter(parameterBuilder()
.in(ParameterIn.QUERY)
.name("keyword")
.description("Post tags filtered by keyword.")
.implementation(String.class)
.required(false));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,9 @@ public void onApplicationEvent(@NonNull ApplicationContextInitializedEvent event
category -> defaultIfNull(category.getSpec().getPriority(), 0).toString())));
});
schemeManager.register(Tag.class, indexSpecs -> {
indexSpecs.add(new IndexSpec()
.setName("spec.displayName")
.setIndexFunc(simpleAttribute(Tag.class, tag -> tag.getSpec().getDisplayName())));
indexSpecs.add(new IndexSpec()
.setName("spec.slug")
.setIndexFunc(simpleAttribute(Tag.class, tag -> tag.getSpec().getSlug()))
Expand Down
Loading

0 comments on commit 02dca81

Please sign in to comment.