mirror of https://github.com/halo-dev/halo
feat: add search and filtering functions to post tags (#5710)
parent
06e0b63b5b
commit
a692c622c9
|
@ -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": {
|
"/apis/api.console.halo.run/v1alpha1/themes": {
|
||||||
"get": {
|
"get": {
|
||||||
"description": "List themes.",
|
"description": "List themes.",
|
||||||
|
@ -13467,6 +13549,10 @@
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"format": "date-time"
|
"format": "date-time"
|
||||||
},
|
},
|
||||||
|
"observedVersion": {
|
||||||
|
"type": "integer",
|
||||||
|
"format": "int64"
|
||||||
|
},
|
||||||
"replyCount": {
|
"replyCount": {
|
||||||
"type": "integer",
|
"type": "integer",
|
||||||
"format": "int32"
|
"format": "int32"
|
||||||
|
@ -16437,8 +16523,7 @@
|
||||||
"RESOLVED",
|
"RESOLVED",
|
||||||
"STARTED",
|
"STARTED",
|
||||||
"STOPPED",
|
"STOPPED",
|
||||||
"FAILED",
|
"FAILED"
|
||||||
"UNLOADED"
|
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"lastStartTime": {
|
"lastStartTime": {
|
||||||
|
@ -17469,7 +17554,8 @@
|
||||||
"apiVersion",
|
"apiVersion",
|
||||||
"kind",
|
"kind",
|
||||||
"metadata",
|
"metadata",
|
||||||
"spec"
|
"spec",
|
||||||
|
"status"
|
||||||
],
|
],
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
|
@ -17484,6 +17570,9 @@
|
||||||
},
|
},
|
||||||
"spec": {
|
"spec": {
|
||||||
"$ref": "#/components/schemas/ReplySpec"
|
"$ref": "#/components/schemas/ReplySpec"
|
||||||
|
},
|
||||||
|
"status": {
|
||||||
|
"$ref": "#/components/schemas/ReplyStatus"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -17642,6 +17731,15 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"ReplyStatus": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"observedVersion": {
|
||||||
|
"type": "integer",
|
||||||
|
"format": "int64"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"ReplyVo": {
|
"ReplyVo": {
|
||||||
"required": [
|
"required": [
|
||||||
"metadata",
|
"metadata",
|
||||||
|
|
|
@ -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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -226,6 +226,9 @@ public class SchemeInitializer implements ApplicationListener<ApplicationContext
|
||||||
category -> defaultIfNull(category.getSpec().getPriority(), 0).toString())));
|
category -> defaultIfNull(category.getSpec().getPriority(), 0).toString())));
|
||||||
});
|
});
|
||||||
schemeManager.register(Tag.class, indexSpecs -> {
|
schemeManager.register(Tag.class, indexSpecs -> {
|
||||||
|
indexSpecs.add(new IndexSpec()
|
||||||
|
.setName("spec.displayName")
|
||||||
|
.setIndexFunc(simpleAttribute(Tag.class, tag -> tag.getSpec().getDisplayName())));
|
||||||
indexSpecs.add(new IndexSpec()
|
indexSpecs.add(new IndexSpec()
|
||||||
.setName("spec.slug")
|
.setName("spec.slug")
|
||||||
.setIndexFunc(simpleAttribute(Tag.class, tag -> tag.getSpec().getSlug()))
|
.setIndexFunc(simpleAttribute(Tag.class, tag -> tag.getSpec().getSlug()))
|
||||||
|
|
|
@ -0,0 +1,104 @@
|
||||||
|
package run.halo.app.core.extension.endpoint;
|
||||||
|
|
||||||
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
|
import static org.mockito.ArgumentMatchers.same;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
import static org.springframework.security.test.web.reactive.server.SecurityMockServerConfigurers.springSecurity;
|
||||||
|
import static org.springframework.test.web.reactive.server.WebTestClient.bindToRouterFunction;
|
||||||
|
|
||||||
|
import java.time.Instant;
|
||||||
|
import java.util.List;
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.Nested;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
|
import org.mockito.InjectMocks;
|
||||||
|
import org.mockito.Mock;
|
||||||
|
import org.mockito.junit.jupiter.MockitoExtension;
|
||||||
|
import org.springframework.test.web.reactive.server.WebTestClient;
|
||||||
|
import reactor.core.publisher.Mono;
|
||||||
|
import run.halo.app.core.extension.content.Tag;
|
||||||
|
import run.halo.app.extension.ListResult;
|
||||||
|
import run.halo.app.extension.Metadata;
|
||||||
|
import run.halo.app.extension.PageRequest;
|
||||||
|
import run.halo.app.extension.ReactiveExtensionClient;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tag endpoint test.
|
||||||
|
*
|
||||||
|
* @author LIlGG
|
||||||
|
*/
|
||||||
|
@ExtendWith(MockitoExtension.class)
|
||||||
|
class TagEndpointTest {
|
||||||
|
@Mock
|
||||||
|
ReactiveExtensionClient client;
|
||||||
|
|
||||||
|
@InjectMocks
|
||||||
|
TagEndpoint tagEndpoint;
|
||||||
|
|
||||||
|
WebTestClient webClient;
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
void setUp() {
|
||||||
|
webClient = WebTestClient.bindToRouterFunction(tagEndpoint.endpoint())
|
||||||
|
.apply(springSecurity())
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nested
|
||||||
|
class TagListTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void shouldListEmptyTagsWhenNoTags() {
|
||||||
|
when(client.listBy(same(Tag.class), any(), any(PageRequest.class)))
|
||||||
|
.thenReturn(Mono.just(ListResult.emptyResult()));
|
||||||
|
|
||||||
|
bindToRouterFunction(tagEndpoint.endpoint())
|
||||||
|
.build()
|
||||||
|
.get().uri("/tags")
|
||||||
|
.exchange()
|
||||||
|
.expectStatus().isOk()
|
||||||
|
.expectBody()
|
||||||
|
.jsonPath("$.items.length()").isEqualTo(0)
|
||||||
|
.jsonPath("$.total").isEqualTo(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void shouldListTagsWhenTagPresent() {
|
||||||
|
var tags = List.of(
|
||||||
|
createTag("fake-tag-1"),
|
||||||
|
createTag("fake-tag-2")
|
||||||
|
);
|
||||||
|
var expectResult = new ListResult<>(tags);
|
||||||
|
when(client.listBy(same(Tag.class), any(), any(PageRequest.class)))
|
||||||
|
.thenReturn(Mono.just(expectResult));
|
||||||
|
|
||||||
|
bindToRouterFunction(tagEndpoint.endpoint())
|
||||||
|
.build()
|
||||||
|
.get().uri("/tags")
|
||||||
|
.exchange()
|
||||||
|
.expectStatus().isOk()
|
||||||
|
.expectBody()
|
||||||
|
.jsonPath("$.items.length()").isEqualTo(2)
|
||||||
|
.jsonPath("$.total").isEqualTo(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
Tag createTag(String name) {
|
||||||
|
return createTag(name, "fake display name");
|
||||||
|
}
|
||||||
|
|
||||||
|
Tag createTag(String name, String displayName) {
|
||||||
|
var metadata = new Metadata();
|
||||||
|
metadata.setName(name);
|
||||||
|
metadata.setCreationTimestamp(Instant.now());
|
||||||
|
var spec = new Tag.TagSpec();
|
||||||
|
spec.setDisplayName(displayName);
|
||||||
|
spec.setSlug(name);
|
||||||
|
var tag = new Tag();
|
||||||
|
tag.setMetadata(metadata);
|
||||||
|
tag.setSpec(spec);
|
||||||
|
return tag;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -11,6 +11,7 @@ import {
|
||||||
VSpace,
|
VSpace,
|
||||||
VLoading,
|
VLoading,
|
||||||
VPagination,
|
VPagination,
|
||||||
|
IconRefreshLine,
|
||||||
} from "@halo-dev/components";
|
} from "@halo-dev/components";
|
||||||
import HasPermission from "@/components/permission/HasPermission.vue";
|
import HasPermission from "@/components/permission/HasPermission.vue";
|
||||||
import TagEditingModal from "./components/TagEditingModal.vue";
|
import TagEditingModal from "./components/TagEditingModal.vue";
|
||||||
|
@ -18,6 +19,12 @@ import { useRouteQuery } from "@vueuse/router";
|
||||||
import { apiClient } from "@/utils/api-client";
|
import { apiClient } from "@/utils/api-client";
|
||||||
import { usePostTag } from "./composables/use-post-tag";
|
import { usePostTag } from "./composables/use-post-tag";
|
||||||
import TagListItem from "./components/TagListItem.vue";
|
import TagListItem from "./components/TagListItem.vue";
|
||||||
|
import SearchInput from "@/components/input/SearchInput.vue";
|
||||||
|
import FilterCleanButton from "@/components/filter/FilterCleanButton.vue";
|
||||||
|
import { computed } from "vue";
|
||||||
|
import { useI18n } from "vue-i18n";
|
||||||
|
|
||||||
|
const { t } = useI18n();
|
||||||
|
|
||||||
const editingModal = ref(false);
|
const editingModal = ref(false);
|
||||||
const selectedTag = ref<Tag | null>(null);
|
const selectedTag = ref<Tag | null>(null);
|
||||||
|
@ -25,12 +32,22 @@ const selectedTag = ref<Tag | null>(null);
|
||||||
const selectedTagNames = ref<string[]>([]);
|
const selectedTagNames = ref<string[]>([]);
|
||||||
const checkedAll = ref(false);
|
const checkedAll = ref(false);
|
||||||
|
|
||||||
|
const keyword = useRouteQuery<string>("keyword", "");
|
||||||
const page = useRouteQuery<number>("page", 1, {
|
const page = useRouteQuery<number>("page", 1, {
|
||||||
transform: Number,
|
transform: Number,
|
||||||
});
|
});
|
||||||
const size = useRouteQuery<number>("size", 20, {
|
const size = useRouteQuery<number>("size", 20, {
|
||||||
transform: Number,
|
transform: Number,
|
||||||
});
|
});
|
||||||
|
const selectedSort = useRouteQuery<string | undefined>("sort");
|
||||||
|
|
||||||
|
const hasFilters = computed(() => {
|
||||||
|
return !!selectedSort.value;
|
||||||
|
});
|
||||||
|
|
||||||
|
const handleClearFilters = () => {
|
||||||
|
selectedSort.value = undefined;
|
||||||
|
};
|
||||||
|
|
||||||
const {
|
const {
|
||||||
tags,
|
tags,
|
||||||
|
@ -38,12 +55,15 @@ const {
|
||||||
hasNext,
|
hasNext,
|
||||||
hasPrevious,
|
hasPrevious,
|
||||||
isLoading,
|
isLoading,
|
||||||
|
isFetching,
|
||||||
handleFetchTags,
|
handleFetchTags,
|
||||||
handleDelete,
|
handleDelete,
|
||||||
handleDeleteInBatch,
|
handleDeleteInBatch,
|
||||||
} = usePostTag({
|
} = usePostTag({
|
||||||
page,
|
page,
|
||||||
size,
|
size,
|
||||||
|
keyword,
|
||||||
|
sort: selectedSort,
|
||||||
});
|
});
|
||||||
|
|
||||||
const handleOpenEditingModal = (tag: Tag | null) => {
|
const handleOpenEditingModal = (tag: Tag | null) => {
|
||||||
|
@ -66,10 +86,6 @@ const handleCheckAllChange = () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleSelectPrevious = async () => {
|
const handleSelectPrevious = async () => {
|
||||||
if (!hasPrevious.value) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!tags.value) return;
|
if (!tags.value) return;
|
||||||
|
|
||||||
const currentIndex = tags.value.findIndex(
|
const currentIndex = tags.value.findIndex(
|
||||||
|
@ -84,15 +100,14 @@ const handleSelectPrevious = async () => {
|
||||||
if (currentIndex === 0 && hasPrevious.value) {
|
if (currentIndex === 0 && hasPrevious.value) {
|
||||||
page.value--;
|
page.value--;
|
||||||
await handleFetchTags();
|
await handleFetchTags();
|
||||||
selectedTag.value = tags.value[tags.value.length - 1];
|
setTimeout(() => {
|
||||||
|
if (!tags.value) return;
|
||||||
|
selectedTag.value = tags.value[tags.value.length - 1];
|
||||||
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleSelectNext = async () => {
|
const handleSelectNext = async () => {
|
||||||
if (!hasNext.value) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!tags.value) return;
|
if (!tags.value) return;
|
||||||
|
|
||||||
if (!selectedTag.value) {
|
if (!selectedTag.value) {
|
||||||
|
@ -109,7 +124,10 @@ const handleSelectNext = async () => {
|
||||||
if (currentIndex === tags.value.length - 1 && hasNext.value) {
|
if (currentIndex === tags.value.length - 1 && hasNext.value) {
|
||||||
page.value++;
|
page.value++;
|
||||||
await handleFetchTags();
|
await handleFetchTags();
|
||||||
selectedTag.value = tags.value[0];
|
setTimeout(() => {
|
||||||
|
if (!tags.value) return;
|
||||||
|
selectedTag.value = tags.value[0];
|
||||||
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -184,7 +202,59 @@ watch(selectedTagNames, (newVal) => {
|
||||||
{{ $t("core.common.buttons.delete") }}
|
{{ $t("core.common.buttons.delete") }}
|
||||||
</VButton>
|
</VButton>
|
||||||
</VSpace>
|
</VSpace>
|
||||||
|
<SearchInput v-else v-model="keyword" />
|
||||||
</div>
|
</div>
|
||||||
|
<VSpace spacing="lg" class="flex-wrap">
|
||||||
|
<FilterCleanButton
|
||||||
|
v-if="hasFilters"
|
||||||
|
@click="handleClearFilters"
|
||||||
|
/>
|
||||||
|
<FilterDropdown
|
||||||
|
v-model="selectedSort"
|
||||||
|
:label="$t('core.common.filters.labels.sort')"
|
||||||
|
:items="[
|
||||||
|
{
|
||||||
|
label: t('core.common.filters.item_labels.default'),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: t(
|
||||||
|
'core.post.tag.filters.sort.items.create_time_desc'
|
||||||
|
),
|
||||||
|
value: 'metadata.creationTimestamp,desc',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: t(
|
||||||
|
'core.post.tag.filters.sort.items.create_time_asc'
|
||||||
|
),
|
||||||
|
value: 'metadata.creationTimestamp,asc',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: t(
|
||||||
|
'core.post.tag.filters.sort.items.display_name_desc'
|
||||||
|
),
|
||||||
|
value: 'spec.displayName,desc',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: t(
|
||||||
|
'core.post.tag.filters.sort.items.display_name_asc'
|
||||||
|
),
|
||||||
|
value: 'spec.displayName,asc',
|
||||||
|
},
|
||||||
|
]"
|
||||||
|
/>
|
||||||
|
<div class="flex flex-row gap-2">
|
||||||
|
<div
|
||||||
|
class="group cursor-pointer rounded p-1 hover:bg-gray-200"
|
||||||
|
@click="handleFetchTags()"
|
||||||
|
>
|
||||||
|
<IconRefreshLine
|
||||||
|
v-tooltip="$t('core.common.buttons.refresh')"
|
||||||
|
:class="{ 'animate-spin text-gray-900': isFetching }"
|
||||||
|
class="h-4 w-4 text-gray-600 group-hover:text-gray-900"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</VSpace>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { apiClient } from "@/utils/api-client";
|
import { apiClient } from "@/utils/api-client";
|
||||||
import type { Tag } from "@halo-dev/api-client";
|
import type { Tag } from "@halo-dev/api-client";
|
||||||
import { ref, type Ref } from "vue";
|
import { ref, watch, type Ref } from "vue";
|
||||||
import { Dialog, Toast } from "@halo-dev/components";
|
import { Dialog, Toast } from "@halo-dev/components";
|
||||||
import { useQuery, type QueryObserverResult } from "@tanstack/vue-query";
|
import { useQuery, type QueryObserverResult } from "@tanstack/vue-query";
|
||||||
import { useI18n } from "vue-i18n";
|
import { useI18n } from "vue-i18n";
|
||||||
|
@ -11,19 +11,21 @@ interface usePostTagReturn {
|
||||||
hasPrevious: Ref<boolean>;
|
hasPrevious: Ref<boolean>;
|
||||||
hasNext: Ref<boolean>;
|
hasNext: Ref<boolean>;
|
||||||
isLoading: Ref<boolean>;
|
isLoading: Ref<boolean>;
|
||||||
|
isFetching: Ref<boolean>;
|
||||||
handleFetchTags: () => Promise<QueryObserverResult<Tag[], unknown>>;
|
handleFetchTags: () => Promise<QueryObserverResult<Tag[], unknown>>;
|
||||||
handleDelete: (tag: Tag) => void;
|
handleDelete: (tag: Tag) => void;
|
||||||
handleDeleteInBatch: (tagNames: string[]) => Promise<void>;
|
handleDeleteInBatch: (tagNames: string[]) => Promise<void>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function usePostTag(filterOptions?: {
|
export function usePostTag(filterOptions?: {
|
||||||
sort?: Ref<string[]>;
|
sort?: Ref<string | undefined>;
|
||||||
page?: Ref<number>;
|
page?: Ref<number>;
|
||||||
size?: Ref<number>;
|
size?: Ref<number>;
|
||||||
|
keyword?: Ref<string>;
|
||||||
}): usePostTagReturn {
|
}): usePostTagReturn {
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
|
|
||||||
const { sort, page, size } = filterOptions || {};
|
const { sort, page, size, keyword } = filterOptions || {};
|
||||||
|
|
||||||
const total = ref(0);
|
const total = ref(0);
|
||||||
const hasPrevious = ref(false);
|
const hasPrevious = ref(false);
|
||||||
|
@ -32,16 +34,19 @@ export function usePostTag(filterOptions?: {
|
||||||
const {
|
const {
|
||||||
data: tags,
|
data: tags,
|
||||||
isLoading,
|
isLoading,
|
||||||
|
isFetching,
|
||||||
refetch,
|
refetch,
|
||||||
} = useQuery({
|
} = useQuery({
|
||||||
queryKey: ["post-tags", sort, page, size],
|
queryKey: ["post-tags", sort, page, size, keyword],
|
||||||
queryFn: async () => {
|
queryFn: async () => {
|
||||||
const { data } =
|
const { data } = await apiClient.tag.listPostTags({
|
||||||
await apiClient.extension.tag.listcontentHaloRunV1alpha1Tag({
|
page: page?.value || 0,
|
||||||
page: page?.value || 0,
|
size: size?.value || 0,
|
||||||
size: size?.value || 0,
|
sort: [sort?.value as string].filter(Boolean) || [
|
||||||
sort: sort?.value || ["metadata.creationTimestamp,desc"],
|
"metadata.creationTimestamp,desc",
|
||||||
});
|
],
|
||||||
|
keyword: keyword?.value,
|
||||||
|
});
|
||||||
|
|
||||||
total.value = data.total;
|
total.value = data.total;
|
||||||
hasPrevious.value = data.hasPrevious;
|
hasPrevious.value = data.hasPrevious;
|
||||||
|
@ -110,12 +115,22 @@ export function usePostTag(filterOptions?: {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => [sort?.value, keyword?.value],
|
||||||
|
() => {
|
||||||
|
if (page?.value) {
|
||||||
|
page.value = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
tags,
|
tags,
|
||||||
total,
|
total,
|
||||||
hasPrevious,
|
hasPrevious,
|
||||||
hasNext,
|
hasNext,
|
||||||
isLoading,
|
isLoading,
|
||||||
|
isFetching,
|
||||||
handleFetchTags: refetch,
|
handleFetchTags: refetch,
|
||||||
handleDelete,
|
handleDelete,
|
||||||
handleDeleteInBatch,
|
handleDeleteInBatch,
|
||||||
|
|
|
@ -12,6 +12,7 @@ api/api-console-halo-run-v1alpha1-reply-api.ts
|
||||||
api/api-console-halo-run-v1alpha1-single-page-api.ts
|
api/api-console-halo-run-v1alpha1-single-page-api.ts
|
||||||
api/api-console-halo-run-v1alpha1-stats-api.ts
|
api/api-console-halo-run-v1alpha1-stats-api.ts
|
||||||
api/api-console-halo-run-v1alpha1-system-api.ts
|
api/api-console-halo-run-v1alpha1-system-api.ts
|
||||||
|
api/api-console-halo-run-v1alpha1-tag-api.ts
|
||||||
api/api-console-halo-run-v1alpha1-theme-api.ts
|
api/api-console-halo-run-v1alpha1-theme-api.ts
|
||||||
api/api-console-halo-run-v1alpha1-user-api.ts
|
api/api-console-halo-run-v1alpha1-user-api.ts
|
||||||
api/api-console-migration-halo-run-v1alpha1-migration-api.ts
|
api/api-console-migration-halo-run-v1alpha1-migration-api.ts
|
||||||
|
|
|
@ -25,6 +25,7 @@ export * from './api/api-console-halo-run-v1alpha1-reply-api';
|
||||||
export * from './api/api-console-halo-run-v1alpha1-single-page-api';
|
export * from './api/api-console-halo-run-v1alpha1-single-page-api';
|
||||||
export * from './api/api-console-halo-run-v1alpha1-stats-api';
|
export * from './api/api-console-halo-run-v1alpha1-stats-api';
|
||||||
export * from './api/api-console-halo-run-v1alpha1-system-api';
|
export * from './api/api-console-halo-run-v1alpha1-system-api';
|
||||||
|
export * from './api/api-console-halo-run-v1alpha1-tag-api';
|
||||||
export * from './api/api-console-halo-run-v1alpha1-theme-api';
|
export * from './api/api-console-halo-run-v1alpha1-theme-api';
|
||||||
export * from './api/api-console-halo-run-v1alpha1-user-api';
|
export * from './api/api-console-halo-run-v1alpha1-user-api';
|
||||||
export * from './api/api-console-migration-halo-run-v1alpha1-migration-api';
|
export * from './api/api-console-migration-halo-run-v1alpha1-migration-api';
|
||||||
|
|
|
@ -0,0 +1,215 @@
|
||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
/**
|
||||||
|
* Halo Next API
|
||||||
|
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
|
||||||
|
*
|
||||||
|
* The version of the OpenAPI document: 2.0.0
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
||||||
|
* https://openapi-generator.tech
|
||||||
|
* Do not edit the class manually.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
import type { Configuration } from '../configuration';
|
||||||
|
import type { AxiosPromise, AxiosInstance, RawAxiosRequestConfig } from 'axios';
|
||||||
|
import globalAxios from 'axios';
|
||||||
|
// Some imports not used depending on template conditions
|
||||||
|
// @ts-ignore
|
||||||
|
import { DUMMY_BASE_URL, assertParamExists, setApiKeyToObject, setBasicAuthToObject, setBearerAuthToObject, setOAuthToObject, setSearchParams, serializeDataIfNeeded, toPathString, createRequestFunction } from '../common';
|
||||||
|
// @ts-ignore
|
||||||
|
import { BASE_PATH, COLLECTION_FORMATS, RequestArgs, BaseAPI, RequiredError, operationServerMap } from '../base';
|
||||||
|
// @ts-ignore
|
||||||
|
import { TagList } from '../models';
|
||||||
|
/**
|
||||||
|
* ApiConsoleHaloRunV1alpha1TagApi - axios parameter creator
|
||||||
|
* @export
|
||||||
|
*/
|
||||||
|
export const ApiConsoleHaloRunV1alpha1TagApiAxiosParamCreator = function (configuration?: Configuration) {
|
||||||
|
return {
|
||||||
|
/**
|
||||||
|
* List Post Tags.
|
||||||
|
* @param {Array<string>} [fieldSelector] Field selector for filtering.
|
||||||
|
* @param {string} [keyword] Keyword for searching.
|
||||||
|
* @param {Array<string>} [labelSelector] Label selector for filtering.
|
||||||
|
* @param {number} [page] The page number. Zero indicates no page.
|
||||||
|
* @param {number} [size] Size of one page. Zero indicates no limit.
|
||||||
|
* @param {Array<string>} [sort] Sort property and direction of the list result. Supported fields: creationTimestamp, name
|
||||||
|
* @param {*} [options] Override http request option.
|
||||||
|
* @throws {RequiredError}
|
||||||
|
*/
|
||||||
|
listPostTags: async (fieldSelector?: Array<string>, keyword?: string, labelSelector?: Array<string>, page?: number, size?: number, sort?: Array<string>, options: RawAxiosRequestConfig = {}): Promise<RequestArgs> => {
|
||||||
|
const localVarPath = `/apis/api.console.halo.run/v1alpha1/tags`;
|
||||||
|
// use dummy base URL string because the URL constructor only accepts absolute URLs.
|
||||||
|
const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
|
||||||
|
let baseOptions;
|
||||||
|
if (configuration) {
|
||||||
|
baseOptions = configuration.baseOptions;
|
||||||
|
}
|
||||||
|
|
||||||
|
const localVarRequestOptions = { method: 'GET', ...baseOptions, ...options};
|
||||||
|
const localVarHeaderParameter = {} as any;
|
||||||
|
const localVarQueryParameter = {} as any;
|
||||||
|
|
||||||
|
// authentication BasicAuth required
|
||||||
|
// http basic authentication required
|
||||||
|
setBasicAuthToObject(localVarRequestOptions, configuration)
|
||||||
|
|
||||||
|
// authentication BearerAuth required
|
||||||
|
// http bearer authentication required
|
||||||
|
await setBearerAuthToObject(localVarHeaderParameter, configuration)
|
||||||
|
|
||||||
|
if (fieldSelector) {
|
||||||
|
localVarQueryParameter['fieldSelector'] = fieldSelector;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (keyword !== undefined) {
|
||||||
|
localVarQueryParameter['keyword'] = keyword;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (labelSelector) {
|
||||||
|
localVarQueryParameter['labelSelector'] = labelSelector;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (page !== undefined) {
|
||||||
|
localVarQueryParameter['page'] = page;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (size !== undefined) {
|
||||||
|
localVarQueryParameter['size'] = size;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sort) {
|
||||||
|
localVarQueryParameter['sort'] = Array.from(sort);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
setSearchParams(localVarUrlObj, localVarQueryParameter);
|
||||||
|
let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
|
||||||
|
localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
|
||||||
|
|
||||||
|
return {
|
||||||
|
url: toPathString(localVarUrlObj),
|
||||||
|
options: localVarRequestOptions,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ApiConsoleHaloRunV1alpha1TagApi - functional programming interface
|
||||||
|
* @export
|
||||||
|
*/
|
||||||
|
export const ApiConsoleHaloRunV1alpha1TagApiFp = function(configuration?: Configuration) {
|
||||||
|
const localVarAxiosParamCreator = ApiConsoleHaloRunV1alpha1TagApiAxiosParamCreator(configuration)
|
||||||
|
return {
|
||||||
|
/**
|
||||||
|
* List Post Tags.
|
||||||
|
* @param {Array<string>} [fieldSelector] Field selector for filtering.
|
||||||
|
* @param {string} [keyword] Keyword for searching.
|
||||||
|
* @param {Array<string>} [labelSelector] Label selector for filtering.
|
||||||
|
* @param {number} [page] The page number. Zero indicates no page.
|
||||||
|
* @param {number} [size] Size of one page. Zero indicates no limit.
|
||||||
|
* @param {Array<string>} [sort] Sort property and direction of the list result. Supported fields: creationTimestamp, name
|
||||||
|
* @param {*} [options] Override http request option.
|
||||||
|
* @throws {RequiredError}
|
||||||
|
*/
|
||||||
|
async listPostTags(fieldSelector?: Array<string>, keyword?: string, labelSelector?: Array<string>, page?: number, size?: number, sort?: Array<string>, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<TagList>> {
|
||||||
|
const localVarAxiosArgs = await localVarAxiosParamCreator.listPostTags(fieldSelector, keyword, labelSelector, page, size, sort, options);
|
||||||
|
const localVarOperationServerIndex = configuration?.serverIndex ?? 0;
|
||||||
|
const localVarOperationServerBasePath = operationServerMap['ApiConsoleHaloRunV1alpha1TagApi.listPostTags']?.[localVarOperationServerIndex]?.url;
|
||||||
|
return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath);
|
||||||
|
},
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ApiConsoleHaloRunV1alpha1TagApi - factory interface
|
||||||
|
* @export
|
||||||
|
*/
|
||||||
|
export const ApiConsoleHaloRunV1alpha1TagApiFactory = function (configuration?: Configuration, basePath?: string, axios?: AxiosInstance) {
|
||||||
|
const localVarFp = ApiConsoleHaloRunV1alpha1TagApiFp(configuration)
|
||||||
|
return {
|
||||||
|
/**
|
||||||
|
* List Post Tags.
|
||||||
|
* @param {ApiConsoleHaloRunV1alpha1TagApiListPostTagsRequest} requestParameters Request parameters.
|
||||||
|
* @param {*} [options] Override http request option.
|
||||||
|
* @throws {RequiredError}
|
||||||
|
*/
|
||||||
|
listPostTags(requestParameters: ApiConsoleHaloRunV1alpha1TagApiListPostTagsRequest = {}, options?: RawAxiosRequestConfig): AxiosPromise<TagList> {
|
||||||
|
return localVarFp.listPostTags(requestParameters.fieldSelector, requestParameters.keyword, requestParameters.labelSelector, requestParameters.page, requestParameters.size, requestParameters.sort, options).then((request) => request(axios, basePath));
|
||||||
|
},
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Request parameters for listPostTags operation in ApiConsoleHaloRunV1alpha1TagApi.
|
||||||
|
* @export
|
||||||
|
* @interface ApiConsoleHaloRunV1alpha1TagApiListPostTagsRequest
|
||||||
|
*/
|
||||||
|
export interface ApiConsoleHaloRunV1alpha1TagApiListPostTagsRequest {
|
||||||
|
/**
|
||||||
|
* Field selector for filtering.
|
||||||
|
* @type {Array<string>}
|
||||||
|
* @memberof ApiConsoleHaloRunV1alpha1TagApiListPostTags
|
||||||
|
*/
|
||||||
|
readonly fieldSelector?: Array<string>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Keyword for searching.
|
||||||
|
* @type {string}
|
||||||
|
* @memberof ApiConsoleHaloRunV1alpha1TagApiListPostTags
|
||||||
|
*/
|
||||||
|
readonly keyword?: string
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Label selector for filtering.
|
||||||
|
* @type {Array<string>}
|
||||||
|
* @memberof ApiConsoleHaloRunV1alpha1TagApiListPostTags
|
||||||
|
*/
|
||||||
|
readonly labelSelector?: Array<string>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The page number. Zero indicates no page.
|
||||||
|
* @type {number}
|
||||||
|
* @memberof ApiConsoleHaloRunV1alpha1TagApiListPostTags
|
||||||
|
*/
|
||||||
|
readonly page?: number
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Size of one page. Zero indicates no limit.
|
||||||
|
* @type {number}
|
||||||
|
* @memberof ApiConsoleHaloRunV1alpha1TagApiListPostTags
|
||||||
|
*/
|
||||||
|
readonly size?: number
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sort property and direction of the list result. Supported fields: creationTimestamp, name
|
||||||
|
* @type {Array<string>}
|
||||||
|
* @memberof ApiConsoleHaloRunV1alpha1TagApiListPostTags
|
||||||
|
*/
|
||||||
|
readonly sort?: Array<string>
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ApiConsoleHaloRunV1alpha1TagApi - object-oriented interface
|
||||||
|
* @export
|
||||||
|
* @class ApiConsoleHaloRunV1alpha1TagApi
|
||||||
|
* @extends {BaseAPI}
|
||||||
|
*/
|
||||||
|
export class ApiConsoleHaloRunV1alpha1TagApi extends BaseAPI {
|
||||||
|
/**
|
||||||
|
* List Post Tags.
|
||||||
|
* @param {ApiConsoleHaloRunV1alpha1TagApiListPostTagsRequest} requestParameters Request parameters.
|
||||||
|
* @param {*} [options] Override http request option.
|
||||||
|
* @throws {RequiredError}
|
||||||
|
* @memberof ApiConsoleHaloRunV1alpha1TagApi
|
||||||
|
*/
|
||||||
|
public listPostTags(requestParameters: ApiConsoleHaloRunV1alpha1TagApiListPostTagsRequest = {}, options?: RawAxiosRequestConfig) {
|
||||||
|
return ApiConsoleHaloRunV1alpha1TagApiFp(this.configuration).listPostTags(requestParameters.fieldSelector, requestParameters.keyword, requestParameters.labelSelector, requestParameters.page, requestParameters.size, requestParameters.sort, options).then((request) => request(this.axios, this.basePath));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -260,6 +260,14 @@ core:
|
||||||
label: Template
|
label: Template
|
||||||
cover:
|
cover:
|
||||||
label: Cover
|
label: Cover
|
||||||
|
tag:
|
||||||
|
filters:
|
||||||
|
sort:
|
||||||
|
items:
|
||||||
|
create_time_desc: Latest Created
|
||||||
|
create_time_asc: Earliest Created
|
||||||
|
display_name_desc: Descending order by tag name
|
||||||
|
display_name_asc: Ascending order by tag name
|
||||||
deleted_post:
|
deleted_post:
|
||||||
title: Deleted Posts
|
title: Deleted Posts
|
||||||
empty:
|
empty:
|
||||||
|
|
|
@ -252,6 +252,14 @@ core:
|
||||||
label: 自定义模板
|
label: 自定义模板
|
||||||
cover:
|
cover:
|
||||||
label: 封面图
|
label: 封面图
|
||||||
|
tag:
|
||||||
|
filters:
|
||||||
|
sort:
|
||||||
|
items:
|
||||||
|
create_time_desc: 较近创建
|
||||||
|
create_time_asc: 较早创建
|
||||||
|
display_name_desc: 标签名降序
|
||||||
|
display_name_asc: 标签名升序
|
||||||
deleted_post:
|
deleted_post:
|
||||||
title: 文章回收站
|
title: 文章回收站
|
||||||
empty:
|
empty:
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import {
|
import {
|
||||||
ApiConsoleHaloRunV1alpha1PluginApi,
|
ApiConsoleHaloRunV1alpha1PluginApi,
|
||||||
ApiConsoleHaloRunV1alpha1PostApi,
|
ApiConsoleHaloRunV1alpha1PostApi,
|
||||||
|
ApiConsoleHaloRunV1alpha1TagApi,
|
||||||
ApiConsoleHaloRunV1alpha1SinglePageApi,
|
ApiConsoleHaloRunV1alpha1SinglePageApi,
|
||||||
ApiConsoleHaloRunV1alpha1ThemeApi,
|
ApiConsoleHaloRunV1alpha1ThemeApi,
|
||||||
ApiConsoleHaloRunV1alpha1UserApi,
|
ApiConsoleHaloRunV1alpha1UserApi,
|
||||||
|
@ -207,6 +208,7 @@ function setupApiClient(axios: AxiosInstance) {
|
||||||
plugin: new ApiConsoleHaloRunV1alpha1PluginApi(undefined, baseURL, axios),
|
plugin: new ApiConsoleHaloRunV1alpha1PluginApi(undefined, baseURL, axios),
|
||||||
theme: new ApiConsoleHaloRunV1alpha1ThemeApi(undefined, baseURL, axios),
|
theme: new ApiConsoleHaloRunV1alpha1ThemeApi(undefined, baseURL, axios),
|
||||||
post: new ApiConsoleHaloRunV1alpha1PostApi(undefined, baseURL, axios),
|
post: new ApiConsoleHaloRunV1alpha1PostApi(undefined, baseURL, axios),
|
||||||
|
tag: new ApiConsoleHaloRunV1alpha1TagApi(undefined, baseURL, axios),
|
||||||
singlePage: new ApiConsoleHaloRunV1alpha1SinglePageApi(
|
singlePage: new ApiConsoleHaloRunV1alpha1SinglePageApi(
|
||||||
undefined,
|
undefined,
|
||||||
baseURL,
|
baseURL,
|
||||||
|
|
Loading…
Reference in New Issue