feat: add features for view post history snapshots (#5787)

* Add snapshots related api

* feat: add features for view post history snapshots

---------

Co-authored-by: guqing <i@guqing.email>
pull/5818/head
Ryan Wang 2024-04-26 18:10:06 +08:00 committed by GitHub
parent 1ade8493da
commit 58f82d2cc2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
45 changed files with 2830 additions and 45 deletions

View File

@ -2933,6 +2933,80 @@
}
},
"/apis/api.console.halo.run/v1alpha1/posts/{name}/content": {
"delete": {
"description": "Delete a content for post.",
"operationId": "deletePostContent",
"parameters": [
{
"in": "path",
"name": "name",
"required": true,
"schema": {
"type": "string"
}
},
{
"in": "query",
"name": "snapshotName",
"required": true,
"schema": {
"type": "string"
}
}
],
"responses": {
"default": {
"content": {
"*/*": {
"schema": {
"$ref": "#/components/schemas/ContentWrapper"
}
}
},
"description": "default response"
}
},
"tags": [
"api.console.halo.run/v1alpha1/Post"
]
},
"get": {
"description": "Fetch content of post.",
"operationId": "fetchPostContent",
"parameters": [
{
"in": "path",
"name": "name",
"required": true,
"schema": {
"type": "string"
}
},
{
"in": "query",
"name": "snapshotName",
"required": true,
"schema": {
"type": "string"
}
}
],
"responses": {
"default": {
"content": {
"*/*": {
"schema": {
"$ref": "#/components/schemas/ContentWrapper"
}
}
},
"description": "default response"
}
},
"tags": [
"api.console.halo.run/v1alpha1/Post"
]
},
"put": {
"description": "Update a post\u0027s content.",
"operationId": "UpdatePostContent",
@ -3094,6 +3168,81 @@
]
}
},
"/apis/api.console.halo.run/v1alpha1/posts/{name}/revert-content": {
"put": {
"description": "Revert to specified snapshot for post content.",
"operationId": "revertToSpecifiedSnapshotForPost",
"parameters": [
{
"in": "path",
"name": "name",
"required": true,
"schema": {
"type": "string"
}
}
],
"requestBody": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/RevertSnapshotForPostParam"
}
}
},
"required": true
},
"responses": {
"default": {
"content": {
"*/*": {
"schema": {
"$ref": "#/components/schemas/Post"
}
}
},
"description": "default response"
}
},
"tags": [
"api.console.halo.run/v1alpha1/Post"
]
}
},
"/apis/api.console.halo.run/v1alpha1/posts/{name}/snapshot": {
"get": {
"description": "List all snapshots for post content.",
"operationId": "listPostSnapshots",
"parameters": [
{
"in": "path",
"name": "name",
"required": true,
"schema": {
"type": "string"
}
}
],
"responses": {
"default": {
"content": {
"*/*": {
"schema": {
"type": "array",
"items": {
"$ref": "#/components/schemas/ListedSnapshotDto"
}
}
}
},
"description": "default response"
}
},
"tags": [
"api.console.halo.run/v1alpha1/Post"
]
}
},
"/apis/api.console.halo.run/v1alpha1/posts/{name}/unpublish": {
"put": {
"description": "Publish a post.",
@ -3399,6 +3548,80 @@
}
},
"/apis/api.console.halo.run/v1alpha1/singlepages/{name}/content": {
"delete": {
"description": "Delete a content for post.",
"operationId": "deleteSinglePageContent",
"parameters": [
{
"in": "path",
"name": "name",
"required": true,
"schema": {
"type": "string"
}
},
{
"in": "query",
"name": "snapshotName",
"required": true,
"schema": {
"type": "string"
}
}
],
"responses": {
"default": {
"content": {
"*/*": {
"schema": {
"$ref": "#/components/schemas/ContentWrapper"
}
}
},
"description": "default response"
}
},
"tags": [
"api.console.halo.run/v1alpha1/SinglePage"
]
},
"get": {
"description": "Fetch content of single page.",
"operationId": "fetchSinglePageContent",
"parameters": [
{
"in": "path",
"name": "name",
"required": true,
"schema": {
"type": "string"
}
},
{
"in": "query",
"name": "snapshotName",
"required": true,
"schema": {
"type": "string"
}
}
],
"responses": {
"default": {
"content": {
"*/*": {
"schema": {
"$ref": "#/components/schemas/ContentWrapper"
}
}
},
"description": "default response"
}
},
"tags": [
"api.console.halo.run/v1alpha1/SinglePage"
]
},
"put": {
"description": "Update a single page\u0027s content.",
"operationId": "UpdateSinglePageContent",
@ -3532,6 +3755,81 @@
]
}
},
"/apis/api.console.halo.run/v1alpha1/singlepages/{name}/revert-content": {
"put": {
"description": "Revert to specified snapshot for single page content.",
"operationId": "revertToSpecifiedSnapshotForSinglePage",
"parameters": [
{
"in": "path",
"name": "name",
"required": true,
"schema": {
"type": "string"
}
}
],
"requestBody": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/RevertSnapshotForSingleParam"
}
}
},
"required": true
},
"responses": {
"default": {
"content": {
"*/*": {
"schema": {
"$ref": "#/components/schemas/Post"
}
}
},
"description": "default response"
}
},
"tags": [
"api.console.halo.run/v1alpha1/SinglePage"
]
}
},
"/apis/api.console.halo.run/v1alpha1/singlepages/{name}/snapshot": {
"get": {
"description": "List all snapshots for single page content.",
"operationId": "listSinglePageSnapshots",
"parameters": [
{
"in": "path",
"name": "name",
"required": true,
"schema": {
"type": "string"
}
}
],
"responses": {
"default": {
"content": {
"*/*": {
"schema": {
"type": "array",
"items": {
"$ref": "#/components/schemas/ListedSnapshotDto"
}
}
}
},
"description": "default response"
}
},
"tags": [
"api.console.halo.run/v1alpha1/SinglePage"
]
}
},
"/apis/api.console.halo.run/v1alpha1/stats": {
"get": {
"description": "Get stats.",
@ -13890,6 +14188,24 @@
}
}
},
"ContentUpdateParam": {
"type": "object",
"properties": {
"content": {
"type": "string"
},
"raw": {
"type": "string"
},
"rawType": {
"type": "string"
},
"version": {
"type": "integer",
"format": "int64"
}
}
},
"ContentVo": {
"type": "object",
"properties": {
@ -15373,6 +15689,36 @@
}
}
},
"ListedSnapshotDto": {
"required": [
"metadata",
"spec"
],
"type": "object",
"properties": {
"metadata": {
"$ref": "#/components/schemas/Metadata"
},
"spec": {
"$ref": "#/components/schemas/ListedSnapshotSpec"
}
}
},
"ListedSnapshotSpec": {
"required": [
"owner"
],
"type": "object",
"properties": {
"modifyTime": {
"type": "string",
"format": "date-time"
},
"owner": {
"type": "string"
}
}
},
"ListedUser": {
"required": [
"roles",
@ -16952,7 +17298,7 @@
"type": "object",
"properties": {
"content": {
"$ref": "#/components/schemas/Content"
"$ref": "#/components/schemas/ContentUpdateParam"
},
"post": {
"$ref": "#/components/schemas/Post"
@ -17954,6 +18300,30 @@
}
}
},
"RevertSnapshotForPostParam": {
"required": [
"snapshotName"
],
"type": "object",
"properties": {
"snapshotName": {
"minLength": 1,
"type": "string"
}
}
},
"RevertSnapshotForSingleParam": {
"required": [
"snapshotName"
],
"type": "object",
"properties": {
"snapshotName": {
"minLength": 1,
"type": "string"
}
}
},
"Role": {
"required": [
"apiVersion",
@ -18595,7 +18965,7 @@
"type": "object",
"properties": {
"content": {
"$ref": "#/components/schemas/Content"
"$ref": "#/components/schemas/ContentUpdateParam"
},
"page": {
"$ref": "#/components/schemas/SinglePage"

View File

@ -1,5 +1,9 @@
package run.halo.app.content;
import static run.halo.app.extension.index.query.QueryFactory.and;
import static run.halo.app.extension.index.query.QueryFactory.equal;
import static run.halo.app.extension.index.query.QueryFactory.isNull;
import java.security.Principal;
import java.time.Duration;
import java.time.Instant;
@ -8,15 +12,20 @@ import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.dao.OptimisticLockingFailureException;
import org.springframework.data.domain.Sort;
import org.springframework.lang.Nullable;
import org.springframework.security.core.context.ReactiveSecurityContextHolder;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.util.Assert;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import reactor.util.retry.Retry;
import run.halo.app.core.extension.content.Snapshot;
import run.halo.app.extension.ListOptions;
import run.halo.app.extension.MetadataUtil;
import run.halo.app.extension.ReactiveExtensionClient;
import run.halo.app.extension.Ref;
import run.halo.app.extension.router.selector.FieldSelector;
/**
* Abstract Service for {@link Snapshot}.
@ -62,14 +71,27 @@ public abstract class AbstractContentService {
}
protected Mono<ContentWrapper> draftContent(@Nullable String baseSnapshotName,
ContentRequest contentRequest,
@Nullable String parentSnapshotName) {
return create(baseSnapshotName, contentRequest, parentSnapshotName)
.flatMap(head -> {
String baseSnapshotNameToUse =
StringUtils.defaultIfBlank(baseSnapshotName, head.getMetadata().getName());
return restoredContent(baseSnapshotNameToUse, head);
});
}
protected Mono<ContentWrapper> draftContent(String baseSnapshotName, ContentRequest content) {
return this.draftContent(baseSnapshotName, content, content.headSnapshotName());
}
private Mono<Snapshot> create(@Nullable String baseSnapshotName,
ContentRequest contentRequest,
@Nullable String parentSnapshotName) {
Snapshot snapshot = contentRequest.toSnapshot();
snapshot.getMetadata().setName(UUID.randomUUID().toString());
snapshot.getSpec().setParentSnapshotName(parentSnapshotName);
final String baseSnapshotNameToUse =
StringUtils.defaultIfBlank(baseSnapshotName, snapshot.getMetadata().getName());
return client.fetch(Snapshot.class, baseSnapshotName)
.doOnNext(this::checkBaseSnapshot)
.defaultIfEmpty(snapshot)
@ -77,19 +99,13 @@ public abstract class AbstractContentService {
contentRequest)
)
.flatMap(source -> getContextUsername()
.map(username -> {
.doOnNext(username -> {
Snapshot.addContributor(source, username);
source.getSpec().setOwner(username);
return source;
})
.defaultIfEmpty(source)
.thenReturn(source)
)
.flatMap(snapshotToCreate -> client.create(snapshotToCreate)
.flatMap(head -> restoredContent(baseSnapshotNameToUse, head)));
}
protected Mono<ContentWrapper> draftContent(String baseSnapshotName, ContentRequest content) {
return this.draftContent(baseSnapshotName, content, content.headSnapshotName());
.flatMap(client::create);
}
protected Mono<ContentWrapper> updateContent(String baseSnapshotName,
@ -98,17 +114,23 @@ public abstract class AbstractContentService {
Assert.notNull(baseSnapshotName, "The baseSnapshotName must not be null");
Assert.notNull(contentRequest.headSnapshotName(), "The headSnapshotName must not be null");
return Mono.defer(() -> client.fetch(Snapshot.class, contentRequest.headSnapshotName())
.flatMap(headSnapshot -> {
var oldVersion = contentRequest.version();
var version = headSnapshot.getMetadata().getVersion();
if (hasConflict(oldVersion, version)) {
// draft a new snapshot as the head snapshot
return create(baseSnapshotName, contentRequest,
contentRequest.headSnapshotName());
}
return Mono.just(headSnapshot);
})
.flatMap(headSnapshot -> client.fetch(Snapshot.class, baseSnapshotName)
.map(baseSnapshot -> determineRawAndContentPatch(headSnapshot, baseSnapshot,
contentRequest)
)
.map(baseSnapshot -> determineRawAndContentPatch(headSnapshot,
baseSnapshot, contentRequest))
)
.flatMap(headSnapshot -> getContextUsername()
.map(username -> {
Snapshot.addContributor(headSnapshot, username);
return headSnapshot;
})
.defaultIfEmpty(headSnapshot)
.doOnNext(username -> Snapshot.addContributor(headSnapshot, username))
.thenReturn(headSnapshot)
)
.flatMap(client::update)
)
@ -117,6 +139,19 @@ public abstract class AbstractContentService {
.flatMap(head -> restoredContent(baseSnapshotName, head));
}
protected Flux<Snapshot> listSnapshotsBy(Ref ref) {
var snapshotListOptions = new ListOptions();
var query = and(isNull("metadata.deletionTimestamp"),
equal("spec.subjectRef", Snapshot.toSubjectRefKey(ref)));
snapshotListOptions.setFieldSelector(FieldSelector.of(query));
var sort = Sort.by("metadata.creationTimestamp", "metadata.name").descending();
return client.listAll(Snapshot.class, snapshotListOptions, sort);
}
boolean hasConflict(Long oldVersion, Long newVersion) {
return oldVersion != null && !newVersion.equals(oldVersion);
}
protected Mono<ContentWrapper> restoredContent(String baseSnapshotName, Snapshot headSnapshot) {
return client.fetch(Snapshot.class, baseSnapshotName)
.doOnNext(this::checkBaseSnapshot)

View File

@ -1,9 +1,11 @@
package run.halo.app.content;
import static io.swagger.v3.oas.annotations.media.Schema.RequiredMode.NOT_REQUIRED;
import static io.swagger.v3.oas.annotations.media.Schema.RequiredMode.REQUIRED;
import io.swagger.v3.oas.annotations.media.Schema;
import java.util.HashMap;
import lombok.Builder;
import org.apache.commons.lang3.StringUtils;
import run.halo.app.core.extension.content.Snapshot;
import run.halo.app.extension.Metadata;
@ -13,8 +15,10 @@ import run.halo.app.extension.Ref;
* @author guqing
* @since 2.0.0
*/
@Builder
public record ContentRequest(@Schema(requiredMode = REQUIRED) Ref subjectRef,
String headSnapshotName,
@Schema(requiredMode = NOT_REQUIRED) Long version,
@Schema(requiredMode = REQUIRED) String raw,
@Schema(requiredMode = REQUIRED) String content,
@Schema(requiredMode = REQUIRED) String rawType) {

View File

@ -0,0 +1,9 @@
package run.halo.app.content;
public record ContentUpdateParam(Long version, String raw, String content, String rawType) {
public static ContentUpdateParam from(Content content) {
return new ContentUpdateParam(null, content.raw(), content.content(),
content.rawType());
}
}

View File

@ -0,0 +1,42 @@
package run.halo.app.content;
import static io.swagger.v3.oas.annotations.media.Schema.RequiredMode.REQUIRED;
import io.swagger.v3.oas.annotations.media.Schema;
import java.time.Instant;
import lombok.Data;
import lombok.experimental.Accessors;
import run.halo.app.core.extension.content.Snapshot;
import run.halo.app.extension.MetadataOperator;
@Data
@Accessors(chain = true)
public class ListedSnapshotDto {
@Schema(requiredMode = REQUIRED)
private MetadataOperator metadata;
@Schema(requiredMode = REQUIRED)
private Spec spec;
@Data
@Accessors(chain = true)
@Schema(name = "ListedSnapshotSpec")
public static class Spec {
@Schema(requiredMode = REQUIRED)
private String owner;
private Instant modifyTime;
}
/**
* Creates from snapshot.
*/
public static ListedSnapshotDto from(Snapshot snapshot) {
return new ListedSnapshotDto()
.setMetadata(snapshot.getMetadata())
.setSpec(new Spec()
.setOwner(snapshot.getSpec().getOwner())
.setModifyTime(snapshot.getSpec().getLastModifyTime())
);
}
}

View File

@ -14,12 +14,12 @@ import run.halo.app.extension.Ref;
* @since 2.0.0
*/
public record PostRequest(@Schema(requiredMode = REQUIRED) @NonNull Post post,
Content content) {
ContentUpdateParam content) {
public ContentRequest contentRequest() {
Ref subjectRef = Ref.of(post);
return new ContentRequest(subjectRef, post.getSpec().getHeadSnapshot(), content.raw(),
content.content(), content.rawType());
return new ContentRequest(subjectRef, post.getSpec().getHeadSnapshot(), content.version(),
content.raw(), content.content(), content.rawType());
}
}

View File

@ -1,6 +1,7 @@
package run.halo.app.content;
import org.springframework.lang.NonNull;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import run.halo.app.core.extension.content.Post;
import run.halo.app.extension.ListResult;
@ -31,6 +32,8 @@ public interface PostService {
Mono<ContentWrapper> getContent(String snapshotName, String baseSnapshotName);
Flux<ListedSnapshotDto> listSnapshots(String name);
Mono<Post> publish(Post post);
Mono<Post> unpublish(Post post);
@ -43,4 +46,8 @@ public interface PostService {
* @return full post data or empty.
*/
Mono<Post> getByUsername(String postName, String username);
Mono<Post> revertToSpecifiedSnapshot(String postName, String snapshotName);
Mono<ContentWrapper> deleteContent(String postName, String snapshotName);
}

View File

@ -13,12 +13,12 @@ import run.halo.app.extension.Ref;
* @since 2.0.0
*/
public record SinglePageRequest(@Schema(requiredMode = REQUIRED) SinglePage page,
@Schema(requiredMode = REQUIRED) Content content) {
@Schema(requiredMode = REQUIRED) ContentUpdateParam content) {
public ContentRequest contentRequest() {
Ref subjectRef = Ref.of(page);
return new ContentRequest(subjectRef, page.getSpec().getHeadSnapshot(), content.raw(),
content.content(), content.rawType());
return new ContentRequest(subjectRef, page.getSpec().getHeadSnapshot(), content.version(),
content.raw(), content.content(), content.rawType());
}
}

View File

@ -1,5 +1,6 @@
package run.halo.app.content;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import run.halo.app.core.extension.content.SinglePage;
import run.halo.app.extension.ListResult;
@ -18,9 +19,15 @@ public interface SinglePageService {
Mono<ContentWrapper> getContent(String snapshotName, String baseSnapshotName);
Flux<ListedSnapshotDto> listSnapshots(String pageName);
Mono<ListResult<ListedSinglePage>> list(SinglePageQuery listRequest);
Mono<SinglePage> draft(SinglePageRequest pageRequest);
Mono<SinglePage> update(SinglePageRequest pageRequest);
Mono<SinglePage> revertToSpecifiedSnapshot(String pageName, String snapshotName);
Mono<ContentWrapper> deleteContent(String postName, String snapshotName);
}

View File

@ -14,6 +14,7 @@ import org.springframework.data.domain.Sort;
import org.springframework.lang.NonNull;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;
import org.springframework.web.server.ServerWebInputException;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import reactor.util.retry.Retry;
@ -22,12 +23,14 @@ import run.halo.app.content.ContentRequest;
import run.halo.app.content.ContentWrapper;
import run.halo.app.content.Contributor;
import run.halo.app.content.ListedPost;
import run.halo.app.content.ListedSnapshotDto;
import run.halo.app.content.PostQuery;
import run.halo.app.content.PostRequest;
import run.halo.app.content.PostService;
import run.halo.app.content.Stats;
import run.halo.app.core.extension.content.Category;
import run.halo.app.core.extension.content.Post;
import run.halo.app.core.extension.content.Snapshot;
import run.halo.app.core.extension.content.Tag;
import run.halo.app.core.extension.service.UserService;
import run.halo.app.extension.ListOptions;
@ -173,6 +176,7 @@ public class PostServiceImpl extends AbstractContentService implements PostServi
}
var contentRequest =
new ContentRequest(Ref.of(post), post.getSpec().getHeadSnapshot(),
null,
postRequest.content().raw(), postRequest.content().content(),
postRequest.content().rawType());
return draftContent(post.getSpec().getBaseSnapshot(), contentRequest)
@ -261,6 +265,13 @@ public class PostServiceImpl extends AbstractContentService implements PostServi
return getContent(releaseSnapshot, post.getSpec().getBaseSnapshot());
}
@Override
public Flux<ListedSnapshotDto> listSnapshots(String name) {
return client.fetch(Post.class, name)
.flatMapMany(page -> listSnapshotsBy(Ref.of(page)))
.map(ListedSnapshotDto::from);
}
@Override
public Mono<Post> publish(Post post) {
var spec = post.getSpec();
@ -284,4 +295,81 @@ public class PostServiceImpl extends AbstractContentService implements PostServi
.filter(post -> post.getSpec() != null)
.filter(post -> Objects.equals(username, post.getSpec().getOwner()));
}
@Override
public Mono<Post> revertToSpecifiedSnapshot(String postName, String snapshotName) {
return client.get(Post.class, postName)
.filter(post -> {
var head = post.getSpec().getHeadSnapshot();
return !StringUtils.equals(head, snapshotName);
})
.flatMap(post -> {
var baseSnapshot = post.getSpec().getBaseSnapshot();
return getContent(snapshotName, baseSnapshot)
.map(content -> ContentRequest.builder()
.subjectRef(Ref.of(post))
.headSnapshotName(post.getSpec().getHeadSnapshot())
.content(content.getContent())
.raw(content.getRaw())
.rawType(content.getRawType())
.build()
)
.flatMap(contentRequest -> draftContent(baseSnapshot, contentRequest))
.flatMap(content -> {
post.getSpec().setHeadSnapshot(content.getSnapshotName());
return publishPostWithRetry(post);
});
});
}
@Override
public Mono<ContentWrapper> deleteContent(String postName, String snapshotName) {
return client.get(Post.class, postName)
.flatMap(post -> {
var headSnapshotName = post.getSpec().getHeadSnapshot();
if (StringUtils.equals(headSnapshotName, snapshotName)) {
// update head to release
post.getSpec().setHeadSnapshot(post.getSpec().getReleaseSnapshot());
return updatePostWithRetry(post);
}
return Mono.just(post);
})
.flatMap(post -> {
var baseSnapshotName = post.getSpec().getBaseSnapshot();
var releaseSnapshotName = post.getSpec().getReleaseSnapshot();
if (StringUtils.equals(releaseSnapshotName, snapshotName)) {
return Mono.error(new ServerWebInputException(
"The snapshot to delete is the release snapshot, please"
+ " revert to another snapshot first."));
}
if (StringUtils.equals(baseSnapshotName, snapshotName)) {
return Mono.error(
new ServerWebInputException("The first snapshot cannot be deleted."));
}
return client.fetch(Snapshot.class, snapshotName)
.flatMap(client::delete)
.flatMap(deleted -> restoredContent(baseSnapshotName, deleted));
});
}
private Mono<Post> updatePostWithRetry(Post post) {
return client.update(post)
.onErrorResume(OptimisticLockingFailureException.class,
e -> Mono.defer(() -> client.get(Post.class, post.getMetadata().getName())
.flatMap(client::update))
.retryWhen(Retry.backoff(8, Duration.ofMillis(100))
.filter(OptimisticLockingFailureException.class::isInstance)
)
);
}
Mono<Post> publishPostWithRetry(Post post) {
return publish(post)
.onErrorResume(OptimisticLockingFailureException.class,
e -> Mono.defer(() -> client.get(Post.class, post.getMetadata().getName())
.flatMap(this::publish))
.retryWhen(Retry.backoff(8, Duration.ofMillis(100))
.filter(OptimisticLockingFailureException.class::isInstance))
);
}
}

View File

@ -10,6 +10,7 @@ import org.apache.commons.lang3.StringUtils;
import org.springframework.dao.OptimisticLockingFailureException;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.web.server.ServerWebInputException;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import reactor.util.retry.Retry;
@ -18,12 +19,14 @@ import run.halo.app.content.ContentRequest;
import run.halo.app.content.ContentWrapper;
import run.halo.app.content.Contributor;
import run.halo.app.content.ListedSinglePage;
import run.halo.app.content.ListedSnapshotDto;
import run.halo.app.content.SinglePageQuery;
import run.halo.app.content.SinglePageRequest;
import run.halo.app.content.SinglePageService;
import run.halo.app.content.Stats;
import run.halo.app.core.extension.content.Post;
import run.halo.app.core.extension.content.SinglePage;
import run.halo.app.core.extension.content.Snapshot;
import run.halo.app.core.extension.service.UserService;
import run.halo.app.extension.ListResult;
import run.halo.app.extension.ReactiveExtensionClient;
@ -73,6 +76,13 @@ public class SinglePageServiceImpl extends AbstractContentService implements Sin
});
}
@Override
public Flux<ListedSnapshotDto> listSnapshots(String pageName) {
return client.fetch(SinglePage.class, pageName)
.flatMapMany(page -> listSnapshotsBy(Ref.of(page)))
.map(ListedSnapshotDto::from);
}
@Override
public Mono<ListResult<ListedSinglePage>> list(SinglePageQuery query) {
return client.list(SinglePage.class, query.toPredicate(),
@ -103,6 +113,7 @@ public class SinglePageServiceImpl extends AbstractContentService implements Sin
.flatMap(page -> {
var contentRequest =
new ContentRequest(Ref.of(page), page.getSpec().getHeadSnapshot(),
null,
pageRequest.content().raw(), pageRequest.content().content(),
pageRequest.content().rawType());
return draftContent(page.getSpec().getBaseSnapshot(), contentRequest)
@ -163,6 +174,93 @@ public class SinglePageServiceImpl extends AbstractContentService implements Sin
});
}
@Override
public Mono<SinglePage> revertToSpecifiedSnapshot(String pageName, String snapshotName) {
return client.get(SinglePage.class, pageName)
.filter(page -> {
var head = page.getSpec().getHeadSnapshot();
return !StringUtils.equals(head, snapshotName);
})
.flatMap(page -> {
var baseSnapshot = page.getSpec().getBaseSnapshot();
return getContent(snapshotName, baseSnapshot)
.map(content -> ContentRequest.builder()
.subjectRef(Ref.of(page))
.headSnapshotName(page.getSpec().getHeadSnapshot())
.content(content.getContent())
.raw(content.getRaw())
.rawType(content.getRawType())
.build()
)
.flatMap(contentRequest -> draftContent(baseSnapshot, contentRequest))
.flatMap(content -> {
page.getSpec().setHeadSnapshot(content.getSnapshotName());
return publishPageWithRetry(page);
});
});
}
@Override
public Mono<ContentWrapper> deleteContent(String pageName, String snapshotName) {
return client.get(SinglePage.class, pageName)
.flatMap(page -> {
var headSnapshotName = page.getSpec().getHeadSnapshot();
if (StringUtils.equals(headSnapshotName, snapshotName)) {
// update head to release
page.getSpec().setHeadSnapshot(page.getSpec().getReleaseSnapshot());
return updatePostWithRetry(page);
}
return Mono.just(page);
})
.flatMap(page -> {
var baseSnapshotName = page.getSpec().getBaseSnapshot();
var releaseSnapshotName = page.getSpec().getReleaseSnapshot();
if (StringUtils.equals(releaseSnapshotName, snapshotName)) {
return Mono.error(new ServerWebInputException(
"The snapshot to delete is the release snapshot, please"
+ " revert to another snapshot first."));
}
if (StringUtils.equals(baseSnapshotName, snapshotName)) {
return Mono.error(
new ServerWebInputException("The first snapshot cannot be deleted."));
}
return client.fetch(Snapshot.class, snapshotName)
.flatMap(client::delete)
.flatMap(deleted -> restoredContent(baseSnapshotName, deleted));
});
}
private Mono<SinglePage> updatePostWithRetry(SinglePage page) {
return client.update(page)
.onErrorResume(OptimisticLockingFailureException.class,
e -> Mono.defer(() -> client.get(SinglePage.class, page.getMetadata().getName())
.flatMap(client::update))
.retryWhen(Retry.backoff(8, Duration.ofMillis(100))
.filter(OptimisticLockingFailureException.class::isInstance)
)
);
}
private Mono<SinglePage> publish(SinglePage singlePage) {
var spec = singlePage.getSpec();
spec.setPublish(true);
if (spec.getHeadSnapshot() == null) {
spec.setHeadSnapshot(spec.getBaseSnapshot());
}
spec.setReleaseSnapshot(spec.getHeadSnapshot());
return client.update(singlePage);
}
Mono<SinglePage> publishPageWithRetry(SinglePage page) {
return publish(page)
.onErrorResume(OptimisticLockingFailureException.class,
e -> Mono.defer(() -> client.get(SinglePage.class, page.getMetadata().getName())
.flatMap(this::publish))
.retryWhen(Retry.backoff(8, Duration.ofMillis(100))
.filter(OptimisticLockingFailureException.class::isInstance))
);
}
private Mono<ListedSinglePage> getListedSinglePage(SinglePage singlePage) {
Assert.notNull(singlePage, "The singlePage must not be null.");
var listedSinglePage = new ListedSinglePage()

View File

@ -6,6 +6,7 @@ import static org.springdoc.core.fn.builders.parameter.Builder.parameterBuilder;
import static org.springdoc.core.fn.builders.requestbody.Builder.requestBodyBuilder;
import io.swagger.v3.oas.annotations.enums.ParameterIn;
import io.swagger.v3.oas.annotations.media.Schema;
import java.time.Duration;
import java.util.Objects;
import lombok.RequiredArgsConstructor;
@ -20,12 +21,15 @@ 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.ServerErrorException;
import org.springframework.web.server.ServerWebInputException;
import reactor.core.Exceptions;
import reactor.core.publisher.Mono;
import reactor.util.retry.Retry;
import run.halo.app.content.Content;
import run.halo.app.content.ContentUpdateParam;
import run.halo.app.content.ContentWrapper;
import run.halo.app.content.ListedPost;
import run.halo.app.content.ListedSnapshotDto;
import run.halo.app.content.PostQuery;
import run.halo.app.content.PostRequest;
import run.halo.app.content.PostService;
@ -75,6 +79,23 @@ public class PostEndpoint implements CustomEndpoint {
.response(responseBuilder()
.implementation(ContentWrapper.class))
)
.GET("posts/{name}/content", this::fetchContent,
builder -> builder.operationId("fetchPostContent")
.description("Fetch content of post.")
.tag(tag)
.parameter(parameterBuilder().name("name")
.in(ParameterIn.PATH)
.required(true)
.implementation(String.class)
)
.parameter(parameterBuilder()
.name("snapshotName")
.in(ParameterIn.QUERY)
.required(true)
.implementation(String.class))
.response(responseBuilder()
.implementation(ContentWrapper.class))
)
.GET("posts/{name}/release-content", this::fetchReleaseContent,
builder -> builder.operationId("fetchPostReleaseContent")
.description("Fetch release content of post.")
@ -87,6 +108,17 @@ public class PostEndpoint implements CustomEndpoint {
.response(responseBuilder()
.implementation(ContentWrapper.class))
)
.GET("posts/{name}/snapshot", this::listSnapshots,
builder -> builder.operationId("listPostSnapshots")
.description("List all snapshots for post content.")
.tag(tag)
.parameter(parameterBuilder().name("name")
.in(ParameterIn.PATH)
.required(true)
.implementation(String.class))
.response(responseBuilder()
.implementationArray(ListedSnapshotDto.class))
)
.POST("posts", this::draftPost,
builder -> builder.operationId("DraftPost")
.description("Draft a post.")
@ -137,6 +169,24 @@ public class PostEndpoint implements CustomEndpoint {
.response(responseBuilder()
.implementation(Post.class))
)
.PUT("posts/{name}/revert-content", this::revertToSpecifiedSnapshot,
builder -> builder.operationId("revertToSpecifiedSnapshotForPost")
.description("Revert to specified snapshot for post content.")
.tag(tag)
.parameter(parameterBuilder().name("name")
.in(ParameterIn.PATH)
.required(true)
.implementation(String.class))
.requestBody(requestBodyBuilder()
.required(true)
.content(contentBuilder()
.mediaType(MediaType.APPLICATION_JSON_VALUE)
.schema(Builder.schemaBuilder()
.implementation(RevertSnapshotParam.class))
))
.response(responseBuilder()
.implementation(Post.class))
)
.PUT("posts/{name}/publish", this::publishPost,
builder -> builder.operationId("PublishPost")
.description("Publish a post.")
@ -168,9 +218,64 @@ public class PostEndpoint implements CustomEndpoint {
.parameter(parameterBuilder().name("name")
.in(ParameterIn.PATH)
.required(true)))
.DELETE("posts/{name}/content", this::deleteContent,
builder -> builder.operationId("deletePostContent")
.description("Delete a content for post.")
.tag(tag)
.parameter(parameterBuilder().name("name")
.in(ParameterIn.PATH)
.required(true)
.implementation(String.class)
)
.parameter(parameterBuilder()
.name("snapshotName")
.in(ParameterIn.QUERY)
.required(true)
.implementation(String.class))
.response(responseBuilder()
.implementation(ContentWrapper.class))
)
.build();
}
private Mono<ServerResponse> deleteContent(ServerRequest request) {
final var postName = request.pathVariable("name");
final var snapshotName = request.queryParam("snapshotName").orElseThrow();
return postService.deleteContent(postName, snapshotName)
.flatMap(content -> ServerResponse.ok().bodyValue(content));
}
private Mono<ServerResponse> revertToSpecifiedSnapshot(ServerRequest request) {
final var postName = request.pathVariable("name");
return request.bodyToMono(RevertSnapshotParam.class)
.switchIfEmpty(
Mono.error(new ServerWebInputException("Required request body is missing.")))
.flatMap(param -> postService.revertToSpecifiedSnapshot(postName, param.snapshotName))
.flatMap(post -> ServerResponse.ok().bodyValue(post));
}
@Schema(name = "RevertSnapshotForPostParam")
record RevertSnapshotParam(
@Schema(requiredMode = Schema.RequiredMode.REQUIRED, minLength = 1) String snapshotName) {
}
private Mono<ServerResponse> fetchContent(ServerRequest request) {
final var name = request.pathVariable("name");
final var snapshotName = request.queryParam("snapshotName").orElseThrow();
return client.fetch(Post.class, name)
.flatMap(post -> {
var baseSnapshot = post.getSpec().getBaseSnapshot();
return postService.getContent(snapshotName, baseSnapshot);
})
.flatMap(content -> ServerResponse.ok().bodyValue(content));
}
private Mono<ServerResponse> listSnapshots(ServerRequest request) {
String name = request.pathVariable("name");
var resultFlux = postService.listSnapshots(name);
return ServerResponse.ok().body(resultFlux, ListedSnapshotDto.class);
}
private Mono<ServerResponse> fetchReleaseContent(ServerRequest request) {
final var name = request.pathVariable("name");
return postService.getReleaseContent(name)
@ -191,7 +296,7 @@ public class PostEndpoint implements CustomEndpoint {
Mono<ServerResponse> updateContent(ServerRequest request) {
String postName = request.pathVariable("name");
return request.bodyToMono(Content.class)
return request.bodyToMono(ContentUpdateParam.class)
.flatMap(content -> Mono.defer(() -> client.fetch(Post.class, postName)
.flatMap(post -> {
PostRequest postRequest = new PostRequest(post, content);

View File

@ -6,6 +6,7 @@ import static org.springdoc.core.fn.builders.parameter.Builder.parameterBuilder;
import static org.springdoc.core.fn.builders.requestbody.Builder.requestBodyBuilder;
import io.swagger.v3.oas.annotations.enums.ParameterIn;
import io.swagger.v3.oas.annotations.media.Schema;
import java.time.Duration;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@ -18,12 +19,15 @@ import org.springframework.stereotype.Component;
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.ServerWebInputException;
import org.thymeleaf.util.StringUtils;
import reactor.core.publisher.Mono;
import reactor.util.retry.Retry;
import run.halo.app.content.Content;
import run.halo.app.content.ContentUpdateParam;
import run.halo.app.content.ContentWrapper;
import run.halo.app.content.ListedSinglePage;
import run.halo.app.content.ListedSnapshotDto;
import run.halo.app.content.SinglePageQuery;
import run.halo.app.content.SinglePageRequest;
import run.halo.app.content.SinglePageService;
@ -85,6 +89,33 @@ public class SinglePageEndpoint implements CustomEndpoint {
.response(responseBuilder()
.implementation(ContentWrapper.class))
)
.GET("singlepages/{name}/content", this::fetchContent,
builder -> builder.operationId("fetchSinglePageContent")
.description("Fetch content of single page.")
.tag(tag)
.parameter(parameterBuilder().name("name")
.in(ParameterIn.PATH)
.required(true)
.implementation(String.class)
)
.parameter(parameterBuilder().name("snapshotName")
.in(ParameterIn.QUERY)
.required(true)
.implementation(String.class))
.response(responseBuilder()
.implementation(ContentWrapper.class))
)
.GET("singlepages/{name}/snapshot", this::listSnapshots,
builder -> builder.operationId("listSinglePageSnapshots")
.description("List all snapshots for single page content.")
.tag(tag)
.parameter(parameterBuilder().name("name")
.in(ParameterIn.PATH)
.required(true)
.implementation(String.class))
.response(responseBuilder()
.implementationArray(ListedSnapshotDto.class))
)
.POST("singlepages", this::draftSinglePage,
builder -> builder.operationId("DraftSinglePage")
.description("Draft a single page.")
@ -135,6 +166,24 @@ public class SinglePageEndpoint implements CustomEndpoint {
.response(responseBuilder()
.implementation(Post.class))
)
.PUT("singlepages/{name}/revert-content", this::revertToSpecifiedSnapshot,
builder -> builder.operationId("revertToSpecifiedSnapshotForSinglePage")
.description("Revert to specified snapshot for single page content.")
.tag(tag)
.parameter(parameterBuilder().name("name")
.in(ParameterIn.PATH)
.required(true)
.implementation(String.class))
.requestBody(requestBodyBuilder()
.required(true)
.content(contentBuilder()
.mediaType(MediaType.APPLICATION_JSON_VALUE)
.schema(Builder.schemaBuilder()
.implementation(RevertSnapshotParam.class))
))
.response(responseBuilder()
.implementation(Post.class))
)
.PUT("singlepages/{name}/publish", this::publishSinglePage,
builder -> builder.operationId("PublishSinglePage")
.description("Publish a single page.")
@ -146,9 +195,64 @@ public class SinglePageEndpoint implements CustomEndpoint {
.response(responseBuilder()
.implementation(SinglePage.class))
)
.DELETE("singlepages/{name}/content", this::deleteContent,
builder -> builder.operationId("deleteSinglePageContent")
.description("Delete a content for post.")
.tag(tag)
.parameter(parameterBuilder().name("name")
.in(ParameterIn.PATH)
.required(true)
.implementation(String.class)
)
.parameter(parameterBuilder()
.name("snapshotName")
.in(ParameterIn.QUERY)
.required(true)
.implementation(String.class))
.response(responseBuilder()
.implementation(ContentWrapper.class))
)
.build();
}
private Mono<ServerResponse> deleteContent(ServerRequest request) {
final var postName = request.pathVariable("name");
final var snapshotName = request.queryParam("snapshotName").orElseThrow();
return singlePageService.deleteContent(postName, snapshotName)
.flatMap(content -> ServerResponse.ok().bodyValue(content));
}
private Mono<ServerResponse> revertToSpecifiedSnapshot(ServerRequest request) {
final var postName = request.pathVariable("name");
return request.bodyToMono(RevertSnapshotParam.class)
.switchIfEmpty(
Mono.error(new ServerWebInputException("Required request body is missing.")))
.flatMap(
param -> singlePageService.revertToSpecifiedSnapshot(postName, param.snapshotName))
.flatMap(page -> ServerResponse.ok().bodyValue(page));
}
@Schema(name = "RevertSnapshotForSingleParam")
record RevertSnapshotParam(
@Schema(requiredMode = Schema.RequiredMode.REQUIRED, minLength = 1) String snapshotName) {
}
private Mono<ServerResponse> fetchContent(ServerRequest request) {
final var snapshotName = request.queryParam("snapshotName").orElseThrow();
return client.fetch(SinglePage.class, request.pathVariable("name"))
.flatMap(page -> {
var baseSnapshot = page.getSpec().getBaseSnapshot();
return singlePageService.getContent(snapshotName, baseSnapshot);
})
.flatMap(content -> ServerResponse.ok().bodyValue(content));
}
private Mono<ServerResponse> listSnapshots(ServerRequest request) {
final var name = request.pathVariable("name");
var resultFlux = singlePageService.listSnapshots(name);
return ServerResponse.ok().body(resultFlux, ListedSnapshotDto.class);
}
private Mono<ServerResponse> fetchReleaseContent(ServerRequest request) {
final var name = request.pathVariable("name");
return singlePageService.getReleaseContent(name)
@ -169,7 +273,7 @@ public class SinglePageEndpoint implements CustomEndpoint {
Mono<ServerResponse> updateContent(ServerRequest request) {
String pageName = request.pathVariable("name");
return request.bodyToMono(Content.class)
return request.bodyToMono(ContentUpdateParam.class)
.flatMap(content -> Mono.defer(() -> client.fetch(SinglePage.class, pageName)
.flatMap(page -> {
SinglePageRequest pageRequest = new SinglePageRequest(page, content);

View File

@ -19,6 +19,7 @@ import org.springframework.web.reactive.function.server.ServerResponse;
import org.springframework.web.server.ServerWebInputException;
import reactor.core.publisher.Mono;
import run.halo.app.content.Content;
import run.halo.app.content.ContentUpdateParam;
import run.halo.app.content.ListedPost;
import run.halo.app.content.PostQuery;
import run.halo.app.content.PostRequest;
@ -280,7 +281,7 @@ public class UcPostEndpoint implements CustomEndpoint {
}
post.getSpec().setOwner(username);
}))
.map(post -> new PostRequest(post, getContent(post)))
.map(post -> new PostRequest(post, ContentUpdateParam.from(getContent(post))))
.flatMap(postService::draftPost);
return ServerResponse.ok().body(createdPost, Post.class);
}

View File

@ -16,7 +16,7 @@ rules:
resources: [ "posts" ]
verbs: [ "*" ]
- apiGroups: [ "api.console.halo.run" ]
resources: [ "posts", "posts/publish", "posts/unpublish", "posts/recycle", "posts/content", "indices/post" ]
resources: [ "posts", "posts/publish", "posts/unpublish", "posts/recycle", "posts/content", "indices/post", "posts/revert-content" ]
verbs: [ "create", "patch", "update", "delete", "deletecollection" ]
---
apiVersion: v1alpha1
@ -37,5 +37,5 @@ rules:
resources: [ "posts" ]
verbs: [ "get", "list" ]
- apiGroups: [ "api.console.halo.run" ]
resources: [ "posts", "posts/head-content", "posts/release-content" ]
resources: [ "posts", "posts/head-content", "posts/release-content", "posts/snapshot" ]
verbs: [ "get", "list" ]

View File

@ -15,7 +15,7 @@ rules:
resources: [ "singlepages" ]
verbs: [ "*" ]
- apiGroups: [ "api.console.halo.run" ]
resources: [ "singlepages", "singlepages/publish", "singlepages/content" ]
resources: [ "singlepages", "singlepages/publish", "singlepages/content", "singlepages/revert-content" ]
verbs: [ "create", "patch", "update", "delete", "deletecollection" ]
---
apiVersion: v1alpha1
@ -35,5 +35,5 @@ rules:
resources: [ "singlepages" ]
verbs: [ "get", "list" ]
- apiGroups: [ "api.console.halo.run" ]
resources: [ "singlepages", "singlepages/head-content", "singlepages/release-content" ]
resources: [ "singlepages", "singlepages/head-content", "singlepages/release-content", "singlepages/snapshot" ]
verbs: [ "get", "list" ]

View File

@ -24,7 +24,7 @@ class ContentRequestTest {
ref.setKind(Post.KIND);
ref.setGroup("content.halo.run");
ref.setName("test-post");
contentRequest = new ContentRequest(ref, "snapshot-1", """
contentRequest = new ContentRequest(ref, "snapshot-1", null, """
Four score and seven
years ago our fathers

View File

@ -18,7 +18,7 @@ import org.springframework.context.ApplicationEventPublisher;
import org.springframework.dao.OptimisticLockingFailureException;
import org.springframework.test.web.reactive.server.WebTestClient;
import reactor.core.publisher.Mono;
import run.halo.app.content.Content;
import run.halo.app.content.ContentUpdateParam;
import run.halo.app.content.PostRequest;
import run.halo.app.content.PostService;
import run.halo.app.content.TestPost;
@ -177,6 +177,6 @@ class PostEndpointTest {
}
PostRequest postRequest(Post post) {
return new PostRequest(post, new Content("B", "<p>B</p>", "MARKDOWN"));
return new PostRequest(post, new ContentUpdateParam(null, "B", "<p>B</p>", "MARKDOWN"));
}
}

View File

@ -2,6 +2,7 @@
import {
Dialog,
IconEye,
IconHistoryLine,
IconPages,
IconSave,
IconSendPlaneFill,
@ -452,6 +453,22 @@ async function handleUploadImage(file: File, options?: AxiosRequestConfig) {
:allow-forced-select="!isUpdateMode"
@select="handleChangeEditorProvider"
/>
<VButton
v-if="isUpdateMode"
size="sm"
type="default"
@click="
$router.push({
name: 'SinglePageSnapshots',
query: { name: routeQueryName },
})
"
>
<template #icon>
<IconHistoryLine class="h-full w-full" />
</template>
{{ $t("core.page_editor.actions.snapshots") }}
</VButton>
<VButton
size="sm"
type="default"

View File

@ -0,0 +1,134 @@
<script setup lang="ts">
import {
IconHistoryLine,
VButton,
VCard,
VLoading,
VPageHeader,
} from "@halo-dev/components";
import { useQuery } from "@tanstack/vue-query";
import { useRoute } from "vue-router";
import { apiClient } from "@/utils/api-client";
import { computed, watch } from "vue";
import { OverlayScrollbarsComponent } from "overlayscrollbars-vue";
import { useRouteQuery } from "@vueuse/router";
import SnapshotContent from "./components/SnapshotContent.vue";
import SnapshotListItem from "./components/SnapshotListItem.vue";
const route = useRoute();
const singlePageName = computed(() => route.query.name as string);
const { data: singlePage } = useQuery({
queryKey: ["singlePage-by-name", singlePageName],
queryFn: async () => {
const { data } =
await apiClient.extension.singlePage.getcontentHaloRunV1alpha1SinglePage({
name: singlePageName.value,
});
return data;
},
enabled: computed(() => !!singlePageName.value),
});
const { data: snapshots, isLoading } = useQuery({
queryKey: ["singlePage-snapshots-by-singlePage-name", singlePageName],
queryFn: async () => {
const { data } = await apiClient.singlePage.listSinglePageSnapshots({
name: singlePageName.value,
});
return data;
},
refetchInterval(data) {
const hasDeletingData = data?.some(
(item) => !!item.metadata.deletionTimestamp
);
return hasDeletingData ? 1000 : false;
},
enabled: computed(() => !!singlePageName.value),
});
const selectedSnapshotName = useRouteQuery<string | undefined>("snapshot-name");
watch(
() => snapshots.value,
(value) => {
if (value && !selectedSnapshotName.value) {
selectedSnapshotName.value = value[0].metadata.name;
}
// Reset selectedSnapshotName if the selected snapshot is deleted
if (
!value?.some(
(snapshot) => snapshot.metadata.name === selectedSnapshotName.value
)
) {
selectedSnapshotName.value = value?.[0].metadata.name;
}
},
{
immediate: true,
}
);
</script>
<template>
<VPageHeader :title="singlePage?.spec.title">
<template #icon>
<IconHistoryLine class="mr-2 self-center" />
</template>
<template #actions>
<VButton size="sm" @click="$router.back()">
{{ $t("core.common.buttons.back") }}
</VButton>
</template>
</VPageHeader>
<div class="m-0 md:m-4">
<VCard
style="height: calc(100vh - 5.5rem)"
:body-class="['h-full', '!p-0']"
>
<div class="grid h-full grid-cols-12 divide-y sm:divide-x sm:divide-y-0">
<div
class="relative col-span-12 h-full overflow-auto sm:col-span-6 lg:col-span-3 xl:col-span-2"
>
<OverlayScrollbarsComponent
element="div"
:options="{ scrollbars: { autoHide: 'scroll' } }"
class="h-full w-full"
defer
>
<VLoading v-if="isLoading" />
<Transition v-else appear name="fade">
<ul
class="box-border h-full w-full divide-y divide-gray-100"
role="list"
>
<li
v-for="snapshot in snapshots"
:key="snapshot.metadata.name"
@click="selectedSnapshotName = snapshot.metadata.name"
>
<SnapshotListItem
:snapshot="snapshot"
:single-page="singlePage"
:selected-snapshot-name="selectedSnapshotName"
/>
</li>
</ul>
</Transition>
</OverlayScrollbarsComponent>
</div>
<div
class="col-span-12 h-full overflow-auto sm:col-span-6 lg:col-span-9 xl:col-span-10"
>
<SnapshotContent
:single-page-name="singlePageName"
:snapshot-name="selectedSnapshotName"
/>
</div>
</div>
</VCard>
</div>
</template>

View File

@ -117,7 +117,7 @@ const handlePublishClick = () => {
};
// Fix me:
// Force update post settings,
// Force update singlePage settings,
// because currently there may be errors caused by changes in version due to asynchronous processing.
const { mutateAsync: singlePageUpdateMutate } = usePageUpdateMutate();

View File

@ -0,0 +1,113 @@
<script setup lang="ts">
import { useQuery } from "@tanstack/vue-query";
import { apiClient } from "@/utils/api-client";
import { computed, toRefs } from "vue";
import { Toast, VLoading } from "@halo-dev/components";
import { OverlayScrollbarsComponent } from "overlayscrollbars-vue";
const props = withDefaults(
defineProps<{
singlePageName?: string;
snapshotName?: string;
}>(),
{
singlePageName: undefined,
snapshotName: undefined,
}
);
const { singlePageName, snapshotName } = toRefs(props);
const { data: snapshot, isLoading } = useQuery({
queryKey: ["singlePage-snapshot-by-name", singlePageName, snapshotName],
queryFn: async () => {
if (!singlePageName.value || !snapshotName.value) {
throw new Error("singlePageName and snapshotName are required");
}
const { data } = await apiClient.singlePage.fetchSinglePageContent({
name: singlePageName.value,
snapshotName: snapshotName.value,
});
return data;
},
onError(err) {
if (err instanceof Error) {
Toast.error(err.message);
}
},
enabled: computed(() => !!singlePageName.value && !!snapshotName.value),
});
</script>
<template>
<OverlayScrollbarsComponent
element="div"
:options="{ scrollbars: { autoHide: 'scroll' } }"
class="h-full w-full"
defer
>
<VLoading v-if="isLoading" />
<div
v-else
class="snapshot-content markdown-body h-full w-full p-4"
v-html="snapshot?.content"
></div>
</OverlayScrollbarsComponent>
</template>
<style scoped lang="scss">
::v-deep(.snapshot-content) {
p {
margin-top: 0.75em;
margin-bottom: 0;
}
pre {
background: #0d0d0d;
padding: 0.75rem 1rem;
margin: 0;
code {
background: none;
font-size: 0.8rem;
padding: 0 !important;
border-radius: 0;
}
}
ul[data-type="taskList"] {
list-style: none;
padding: 0;
p {
margin: 0;
}
li {
display: flex;
> label {
flex: 0 0 auto;
margin-right: 0.5rem;
user-select: none;
}
> div {
flex: 1 1 auto;
}
}
}
ul {
list-style: disc !important;
}
ol {
list-style: decimal !important;
}
code br {
display: initial;
}
}
</style>

View File

@ -0,0 +1,137 @@
<script setup lang="ts">
import type { ListedSnapshotDto, SinglePage } from "@halo-dev/api-client";
import { apiClient } from "@/utils/api-client";
import { Dialog, Toast, VButton, VStatusDot, VTag } from "@halo-dev/components";
import { useQueryClient } from "@tanstack/vue-query";
import { computed } from "vue";
import { relativeTimeTo } from "@/utils/date";
import { useI18n } from "vue-i18n";
const { t } = useI18n();
const queryClient = useQueryClient();
const props = withDefaults(
defineProps<{
singlePage?: SinglePage;
snapshot: ListedSnapshotDto;
selectedSnapshotName?: string;
}>(),
{
singlePage: undefined,
selectedSnapshotName: undefined,
}
);
async function handleRestore() {
Dialog.warning({
title: t("core.page_snapshots.operations.revert.title"),
description: t("core.page_snapshots.operations.revert.description"),
confirmText: t("core.common.buttons.confirm"),
cancelText: t("core.common.buttons.cancel"),
async onConfirm() {
await apiClient.singlePage.revertToSpecifiedSnapshotForSinglePage({
name: props.singlePage?.metadata.name as string,
revertSnapshotForSingleParam: {
snapshotName: props.snapshot.metadata.name,
},
});
await queryClient.invalidateQueries({
queryKey: ["singlePage-snapshots-by-singlePage-name"],
});
Toast.success(t("core.page_snapshots.operations.revert.toast_success"));
},
});
}
function handleDelete() {
Dialog.warning({
title: t("core.page_snapshots.operations.delete.title"),
description: t("core.page_snapshots.operations.delete.description"),
confirmText: t("core.common.buttons.confirm"),
cancelText: t("core.common.buttons.cancel"),
async onConfirm() {
await apiClient.singlePage.deleteSinglePageContent({
name: props.singlePage?.metadata.name as string,
snapshotName: props.snapshot.metadata.name,
});
await queryClient.invalidateQueries({
queryKey: ["singlePage-snapshots-by-singlePage-name"],
});
Toast.success(t("core.common.toast.delete_success"));
},
});
}
const isSelected = computed(() => {
return props.selectedSnapshotName === props.snapshot.metadata.name;
});
const isReleased = computed(() => {
return (
props.singlePage?.spec.releaseSnapshot === props.snapshot.metadata.name
);
});
const isHead = computed(() => {
const { headSnapshot, releaseSnapshot } = props.singlePage?.spec || {};
return (
headSnapshot !== releaseSnapshot &&
headSnapshot === props.snapshot.metadata.name
);
});
const isBase = computed(() => {
return props.singlePage?.spec.baseSnapshot === props.snapshot.metadata.name;
});
</script>
<template>
<div
class="group relative flex cursor-pointer flex-col gap-5 p-4"
:class="{ 'bg-gray-50': isSelected }"
>
<div
v-if="isSelected"
class="absolute inset-y-0 left-0 w-0.5 bg-primary"
></div>
<div class="flex items-center justify-between">
<div
class="truncate text-sm"
:class="{
'font-semibold': isSelected,
}"
>
{{ relativeTimeTo(snapshot.metadata.creationTimestamp) }}
</div>
<div class="inline-flex flex-none items-center space-x-3">
<VTag v-if="isReleased" theme="primary">
{{ $t("core.page_snapshots.status.released") }}
</VTag>
<VTag v-if="isHead">
{{ $t("core.page_snapshots.status.draft") }}
</VTag>
<VStatusDot
v-if="snapshot.metadata.deletionTimestamp"
v-tooltip="$t('core.common.status.deleting')"
state="warning"
animate
/>
</div>
</div>
<div class="flex h-6 items-end justify-between gap-2">
<div class="flex-1 truncate text-xs text-gray-600">
{{ snapshot.spec.owner }}
</div>
<div
v-if="!isReleased"
class="hidden flex-none space-x-2 group-hover:block"
>
<VButton v-if="!isHead" size="xs" @click="handleRestore()">
{{ $t("core.page_snapshots.operations.revert.button") }}
</VButton>
<VButton v-if="!isBase" size="xs" type="danger" @click="handleDelete">
{{ $t("core.common.buttons.delete") }}
</VButton>
</div>
</div>
</div>
</template>

View File

@ -35,7 +35,7 @@ export function usePageUpdateMutate() {
},
retry: 3,
onError: (error) => {
console.error("Failed to update post", error);
console.error("Failed to update singlePage", error);
Toast.error(t("core.common.toast.server_internal_error"));
},
});

View File

@ -6,6 +6,7 @@ import SinglePageEditor from "./SinglePageEditor.vue";
import SinglePageStatsWidget from "./widgets/SinglePageStatsWidget.vue";
import { IconPages } from "@halo-dev/components";
import { markRaw } from "vue";
import SinglePageSnapshots from "./SinglePageSnapshots.vue";
export default definePlugin({
components: {
@ -54,6 +55,17 @@ export default definePlugin({
permissions: ["system:singlepages:manage"],
},
},
{
path: "snapshots",
name: "SinglePageSnapshots",
component: SinglePageSnapshots,
meta: {
title: "core.page_snapshots.title",
searchable: false,
hideFooter: true,
permissions: ["system:singlepages:manage"],
},
},
],
},
],

View File

@ -3,6 +3,7 @@ import {
Dialog,
IconBookRead,
IconEye,
IconHistoryLine,
IconSave,
IconSendPlaneFill,
IconSettings,
@ -480,6 +481,19 @@ async function handleUploadImage(file: File, options?: AxiosRequestConfig) {
:allow-forced-select="!isUpdateMode"
@select="handleChangeEditorProvider"
/>
<VButton
v-if="isUpdateMode"
size="sm"
type="default"
@click="
$router.push({ name: 'PostSnapshots', query: { name: name } })
"
>
<template #icon>
<IconHistoryLine class="h-full w-full" />
</template>
{{ $t("core.post_editor.actions.snapshots") }}
</VButton>
<VButton
size="sm"
type="default"

View File

@ -0,0 +1,134 @@
<script setup lang="ts">
import {
IconHistoryLine,
VButton,
VCard,
VLoading,
VPageHeader,
} from "@halo-dev/components";
import { useQuery } from "@tanstack/vue-query";
import { useRoute } from "vue-router";
import { apiClient } from "@/utils/api-client";
import { computed, watch } from "vue";
import { OverlayScrollbarsComponent } from "overlayscrollbars-vue";
import { useRouteQuery } from "@vueuse/router";
import SnapshotContent from "@console/modules/contents/posts/components/SnapshotContent.vue";
import SnapshotListItem from "@console/modules/contents/posts/components/SnapshotListItem.vue";
const route = useRoute();
const postName = computed(() => route.query.name as string);
const { data: post } = useQuery({
queryKey: ["post-by-name", postName],
queryFn: async () => {
const { data } =
await apiClient.extension.post.getcontentHaloRunV1alpha1Post({
name: postName.value,
});
return data;
},
enabled: computed(() => !!postName.value),
});
const { data: snapshots, isLoading } = useQuery({
queryKey: ["post-snapshots-by-post-name", postName],
queryFn: async () => {
const { data } = await apiClient.post.listPostSnapshots({
name: postName.value,
});
return data;
},
refetchInterval(data) {
const hasDeletingData = data?.some(
(item) => !!item.metadata.deletionTimestamp
);
return hasDeletingData ? 1000 : false;
},
enabled: computed(() => !!postName.value),
});
const selectedSnapshotName = useRouteQuery<string | undefined>("snapshot-name");
watch(
() => snapshots.value,
(value) => {
if (value && !selectedSnapshotName.value) {
selectedSnapshotName.value = value[0].metadata.name;
}
// Reset selectedSnapshotName if the selected snapshot is deleted
if (
!value?.some(
(snapshot) => snapshot.metadata.name === selectedSnapshotName.value
)
) {
selectedSnapshotName.value = value?.[0].metadata.name;
}
},
{
immediate: true,
}
);
</script>
<template>
<VPageHeader :title="post?.spec.title">
<template #icon>
<IconHistoryLine class="mr-2 self-center" />
</template>
<template #actions>
<VButton size="sm" @click="$router.back()">
{{ $t("core.common.buttons.back") }}
</VButton>
</template>
</VPageHeader>
<div class="m-0 md:m-4">
<VCard
style="height: calc(100vh - 5.5rem)"
:body-class="['h-full', '!p-0']"
>
<div class="grid h-full grid-cols-12 divide-y sm:divide-x sm:divide-y-0">
<div
class="relative col-span-12 h-full overflow-auto sm:col-span-6 lg:col-span-3 xl:col-span-2"
>
<OverlayScrollbarsComponent
element="div"
:options="{ scrollbars: { autoHide: 'scroll' } }"
class="h-full w-full"
defer
>
<VLoading v-if="isLoading" />
<Transition v-else appear name="fade">
<ul
class="box-border h-full w-full divide-y divide-gray-100"
role="list"
>
<li
v-for="snapshot in snapshots"
:key="snapshot.metadata.name"
@click="selectedSnapshotName = snapshot.metadata.name"
>
<SnapshotListItem
:snapshot="snapshot"
:post="post"
:selected-snapshot-name="selectedSnapshotName"
/>
</li>
</ul>
</Transition>
</OverlayScrollbarsComponent>
</div>
<div
class="col-span-12 h-full overflow-auto sm:col-span-6 lg:col-span-9 xl:col-span-10"
>
<SnapshotContent
:post-name="postName"
:snapshot-name="selectedSnapshotName"
/>
</div>
</div>
</VCard>
</div>
</template>

View File

@ -0,0 +1,113 @@
<script setup lang="ts">
import { useQuery } from "@tanstack/vue-query";
import { apiClient } from "@/utils/api-client";
import { computed, toRefs } from "vue";
import { Toast, VLoading } from "@halo-dev/components";
import { OverlayScrollbarsComponent } from "overlayscrollbars-vue";
const props = withDefaults(
defineProps<{
postName?: string;
snapshotName?: string;
}>(),
{
postName: undefined,
snapshotName: undefined,
}
);
const { postName, snapshotName } = toRefs(props);
const { data: snapshot, isLoading } = useQuery({
queryKey: ["post-snapshot-by-name", postName, snapshotName],
queryFn: async () => {
if (!postName.value || !snapshotName.value) {
throw new Error("postName and snapshotName are required");
}
const { data } = await apiClient.post.fetchPostContent({
name: postName.value,
snapshotName: snapshotName.value,
});
return data;
},
onError(err) {
if (err instanceof Error) {
Toast.error(err.message);
}
},
enabled: computed(() => !!postName.value && !!snapshotName.value),
});
</script>
<template>
<OverlayScrollbarsComponent
element="div"
:options="{ scrollbars: { autoHide: 'scroll' } }"
class="h-full w-full"
defer
>
<VLoading v-if="isLoading" />
<div
v-else
class="snapshot-content markdown-body h-full w-full p-4"
v-html="snapshot?.content"
></div>
</OverlayScrollbarsComponent>
</template>
<style scoped lang="scss">
::v-deep(.snapshot-content) {
p {
margin-top: 0.75em;
margin-bottom: 0;
}
pre {
background: #0d0d0d;
padding: 0.75rem 1rem;
margin: 0;
code {
background: none;
font-size: 0.8rem;
padding: 0 !important;
border-radius: 0;
}
}
ul[data-type="taskList"] {
list-style: none;
padding: 0;
p {
margin: 0;
}
li {
display: flex;
> label {
flex: 0 0 auto;
margin-right: 0.5rem;
user-select: none;
}
> div {
flex: 1 1 auto;
}
}
}
ul {
list-style: disc !important;
}
ol {
list-style: decimal !important;
}
code br {
display: initial;
}
}
</style>

View File

@ -0,0 +1,135 @@
<script setup lang="ts">
import type { ListedSnapshotDto, Post } from "@halo-dev/api-client";
import { apiClient } from "@/utils/api-client";
import { Dialog, Toast, VButton, VStatusDot, VTag } from "@halo-dev/components";
import { useQueryClient } from "@tanstack/vue-query";
import { computed } from "vue";
import { relativeTimeTo } from "@/utils/date";
import { useI18n } from "vue-i18n";
const { t } = useI18n();
const queryClient = useQueryClient();
const props = withDefaults(
defineProps<{
post?: Post;
snapshot: ListedSnapshotDto;
selectedSnapshotName?: string;
}>(),
{
post: undefined,
selectedSnapshotName: undefined,
}
);
async function handleRestore() {
Dialog.warning({
title: t("core.post_snapshots.operations.revert.title"),
description: t("core.post_snapshots.operations.revert.description"),
confirmText: t("core.common.buttons.confirm"),
cancelText: t("core.common.buttons.cancel"),
async onConfirm() {
await apiClient.post.revertToSpecifiedSnapshotForPost({
name: props.post?.metadata.name as string,
revertSnapshotForPostParam: {
snapshotName: props.snapshot.metadata.name,
},
});
await queryClient.invalidateQueries({
queryKey: ["post-snapshots-by-post-name"],
});
Toast.success(t("core.post_snapshots.operations.revert.toast_success"));
},
});
}
function handleDelete() {
Dialog.warning({
title: t("core.post_snapshots.operations.delete.title"),
description: t("core.post_snapshots.operations.delete.description"),
confirmText: t("core.common.buttons.confirm"),
cancelText: t("core.common.buttons.cancel"),
async onConfirm() {
await apiClient.post.deletePostContent({
name: props.post?.metadata.name as string,
snapshotName: props.snapshot.metadata.name,
});
await queryClient.invalidateQueries({
queryKey: ["post-snapshots-by-post-name"],
});
Toast.success(t("core.common.toast.delete_success"));
},
});
}
const isSelected = computed(() => {
return props.selectedSnapshotName === props.snapshot.metadata.name;
});
const isReleased = computed(() => {
return props.post?.spec.releaseSnapshot === props.snapshot.metadata.name;
});
const isHead = computed(() => {
const { headSnapshot, releaseSnapshot } = props.post?.spec || {};
return (
headSnapshot !== releaseSnapshot &&
headSnapshot === props.snapshot.metadata.name
);
});
const isBase = computed(() => {
return props.post?.spec.baseSnapshot === props.snapshot.metadata.name;
});
</script>
<template>
<div
class="group relative flex cursor-pointer flex-col gap-5 p-4"
:class="{ 'bg-gray-50': isSelected }"
>
<div
v-if="isSelected"
class="absolute inset-y-0 left-0 w-0.5 bg-primary"
></div>
<div class="flex items-center justify-between">
<div
class="truncate text-sm"
:class="{
'font-semibold': isSelected,
}"
>
{{ relativeTimeTo(snapshot.metadata.creationTimestamp) }}
</div>
<div class="inline-flex flex-none items-center space-x-3">
<VTag v-if="isReleased" theme="primary">
{{ $t("core.post_snapshots.status.released") }}
</VTag>
<VTag v-if="isHead">
{{ $t("core.post_snapshots.status.draft") }}
</VTag>
<VStatusDot
v-if="snapshot.metadata.deletionTimestamp"
v-tooltip="$t('core.common.status.deleting')"
state="warning"
animate
/>
</div>
</div>
<div class="flex h-6 items-end justify-between gap-2">
<div class="flex-1 truncate text-xs text-gray-600">
{{ snapshot.spec.owner }}
</div>
<div
v-if="!isReleased"
class="hidden flex-none space-x-2 group-hover:block"
>
<VButton v-if="!isHead" size="xs" @click="handleRestore()">
{{ $t("core.post_snapshots.operations.revert.button") }}
</VButton>
<VButton v-if="!isBase" size="xs" type="danger" @click="handleDelete">
{{ $t("core.common.buttons.delete") }}
</VButton>
</div>
</div>
</div>
</template>

View File

@ -10,6 +10,7 @@ import TagList from "./tags/TagList.vue";
import PostStatsWidget from "./widgets/PostStatsWidget.vue";
import RecentPublishedWidget from "./widgets/RecentPublishedWidget.vue";
import { markRaw } from "vue";
import PostSnapshots from "./PostSnapshots.vue";
export default definePlugin({
components: {
@ -60,6 +61,17 @@ export default definePlugin({
permissions: ["system:posts:manage"],
},
},
{
path: "snapshots",
name: "PostSnapshots",
component: PostSnapshots,
meta: {
title: "core.post_snapshots.title",
searchable: false,
hideFooter: true,
permissions: ["system:posts:manage"],
},
},
{
path: "categories",
component: BlankLayout,

View File

@ -120,6 +120,7 @@ models/condition.ts
models/config-map-list.ts
models/config-map-ref.ts
models/config-map.ts
models/content-update-param.ts
models/content-vo.ts
models/content-wrapper.ts
models/content.ts
@ -168,6 +169,8 @@ models/listed-single-page-list.ts
models/listed-single-page-vo-list.ts
models/listed-single-page-vo.ts
models/listed-single-page.ts
models/listed-snapshot-dto.ts
models/listed-snapshot-spec.ts
models/listed-user.ts
models/login-history.ts
models/mark-specified-request.ts
@ -248,6 +251,8 @@ models/reset-password-request.ts
models/reverse-proxy-list.ts
models/reverse-proxy-rule.ts
models/reverse-proxy.ts
models/revert-snapshot-for-post-param.ts
models/revert-snapshot-for-single-param.ts
models/role-binding-list.ts
models/role-binding.ts
models/role-list.ts

View File

@ -28,15 +28,67 @@ import { ContentWrapper } from '../models';
// @ts-ignore
import { ListedPostList } from '../models';
// @ts-ignore
import { ListedSnapshotDto } from '../models';
// @ts-ignore
import { Post } from '../models';
// @ts-ignore
import { PostRequest } from '../models';
// @ts-ignore
import { RevertSnapshotForPostParam } from '../models';
/**
* ApiConsoleHaloRunV1alpha1PostApi - axios parameter creator
* @export
*/
export const ApiConsoleHaloRunV1alpha1PostApiAxiosParamCreator = function (configuration?: Configuration) {
return {
/**
* Delete a content for post.
* @param {string} name
* @param {string} snapshotName
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
deletePostContent: async (name: string, snapshotName: string, options: RawAxiosRequestConfig = {}): Promise<RequestArgs> => {
// verify required parameter 'name' is not null or undefined
assertParamExists('deletePostContent', 'name', name)
// verify required parameter 'snapshotName' is not null or undefined
assertParamExists('deletePostContent', 'snapshotName', snapshotName)
const localVarPath = `/apis/api.console.halo.run/v1alpha1/posts/{name}/content`
.replace(`{${"name"}}`, encodeURIComponent(String(name)));
// 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: 'DELETE', ...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 (snapshotName !== undefined) {
localVarQueryParameter['snapshotName'] = snapshotName;
}
setSearchParams(localVarUrlObj, localVarQueryParameter);
let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
return {
url: toPathString(localVarUrlObj),
options: localVarRequestOptions,
};
},
/**
* Draft a post.
* @param {PostRequest} postRequest
@ -80,6 +132,54 @@ export const ApiConsoleHaloRunV1alpha1PostApiAxiosParamCreator = function (confi
options: localVarRequestOptions,
};
},
/**
* Fetch content of post.
* @param {string} name
* @param {string} snapshotName
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
fetchPostContent: async (name: string, snapshotName: string, options: RawAxiosRequestConfig = {}): Promise<RequestArgs> => {
// verify required parameter 'name' is not null or undefined
assertParamExists('fetchPostContent', 'name', name)
// verify required parameter 'snapshotName' is not null or undefined
assertParamExists('fetchPostContent', 'snapshotName', snapshotName)
const localVarPath = `/apis/api.console.halo.run/v1alpha1/posts/{name}/content`
.replace(`{${"name"}}`, encodeURIComponent(String(name)));
// 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 (snapshotName !== undefined) {
localVarQueryParameter['snapshotName'] = snapshotName;
}
setSearchParams(localVarUrlObj, localVarQueryParameter);
let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
return {
url: toPathString(localVarUrlObj),
options: localVarRequestOptions,
};
},
/**
* Fetch head content of post.
* @param {string} name
@ -153,6 +253,47 @@ export const ApiConsoleHaloRunV1alpha1PostApiAxiosParamCreator = function (confi
setSearchParams(localVarUrlObj, localVarQueryParameter);
let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
return {
url: toPathString(localVarUrlObj),
options: localVarRequestOptions,
};
},
/**
* List all snapshots for post content.
* @param {string} name
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
listPostSnapshots: async (name: string, options: RawAxiosRequestConfig = {}): Promise<RequestArgs> => {
// verify required parameter 'name' is not null or undefined
assertParamExists('listPostSnapshots', 'name', name)
const localVarPath = `/apis/api.console.halo.run/v1alpha1/posts/{name}/snapshot`
.replace(`{${"name"}}`, encodeURIComponent(String(name)));
// 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)
setSearchParams(localVarUrlObj, localVarQueryParameter);
let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
@ -321,6 +462,53 @@ export const ApiConsoleHaloRunV1alpha1PostApiAxiosParamCreator = function (confi
options: localVarRequestOptions,
};
},
/**
* Revert to specified snapshot for post content.
* @param {string} name
* @param {RevertSnapshotForPostParam} revertSnapshotForPostParam
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
revertToSpecifiedSnapshotForPost: async (name: string, revertSnapshotForPostParam: RevertSnapshotForPostParam, options: RawAxiosRequestConfig = {}): Promise<RequestArgs> => {
// verify required parameter 'name' is not null or undefined
assertParamExists('revertToSpecifiedSnapshotForPost', 'name', name)
// verify required parameter 'revertSnapshotForPostParam' is not null or undefined
assertParamExists('revertToSpecifiedSnapshotForPost', 'revertSnapshotForPostParam', revertSnapshotForPostParam)
const localVarPath = `/apis/api.console.halo.run/v1alpha1/posts/{name}/revert-content`
.replace(`{${"name"}}`, encodeURIComponent(String(name)));
// 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: 'PUT', ...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)
localVarHeaderParameter['Content-Type'] = 'application/json';
setSearchParams(localVarUrlObj, localVarQueryParameter);
let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
localVarRequestOptions.data = serializeDataIfNeeded(revertSnapshotForPostParam, localVarRequestOptions, configuration)
return {
url: toPathString(localVarUrlObj),
options: localVarRequestOptions,
};
},
/**
* Publish a post.
* @param {string} name
@ -466,6 +654,19 @@ export const ApiConsoleHaloRunV1alpha1PostApiAxiosParamCreator = function (confi
export const ApiConsoleHaloRunV1alpha1PostApiFp = function(configuration?: Configuration) {
const localVarAxiosParamCreator = ApiConsoleHaloRunV1alpha1PostApiAxiosParamCreator(configuration)
return {
/**
* Delete a content for post.
* @param {string} name
* @param {string} snapshotName
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async deletePostContent(name: string, snapshotName: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<ContentWrapper>> {
const localVarAxiosArgs = await localVarAxiosParamCreator.deletePostContent(name, snapshotName, options);
const localVarOperationServerIndex = configuration?.serverIndex ?? 0;
const localVarOperationServerBasePath = operationServerMap['ApiConsoleHaloRunV1alpha1PostApi.deletePostContent']?.[localVarOperationServerIndex]?.url;
return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath);
},
/**
* Draft a post.
* @param {PostRequest} postRequest
@ -478,6 +679,19 @@ export const ApiConsoleHaloRunV1alpha1PostApiFp = function(configuration?: Confi
const localVarOperationServerBasePath = operationServerMap['ApiConsoleHaloRunV1alpha1PostApi.draftPost']?.[localVarOperationServerIndex]?.url;
return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath);
},
/**
* Fetch content of post.
* @param {string} name
* @param {string} snapshotName
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async fetchPostContent(name: string, snapshotName: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<ContentWrapper>> {
const localVarAxiosArgs = await localVarAxiosParamCreator.fetchPostContent(name, snapshotName, options);
const localVarOperationServerIndex = configuration?.serverIndex ?? 0;
const localVarOperationServerBasePath = operationServerMap['ApiConsoleHaloRunV1alpha1PostApi.fetchPostContent']?.[localVarOperationServerIndex]?.url;
return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath);
},
/**
* Fetch head content of post.
* @param {string} name
@ -502,6 +716,18 @@ export const ApiConsoleHaloRunV1alpha1PostApiFp = function(configuration?: Confi
const localVarOperationServerBasePath = operationServerMap['ApiConsoleHaloRunV1alpha1PostApi.fetchPostReleaseContent']?.[localVarOperationServerIndex]?.url;
return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath);
},
/**
* List all snapshots for post content.
* @param {string} name
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async listPostSnapshots(name: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<Array<ListedSnapshotDto>>> {
const localVarAxiosArgs = await localVarAxiosParamCreator.listPostSnapshots(name, options);
const localVarOperationServerIndex = configuration?.serverIndex ?? 0;
const localVarOperationServerBasePath = operationServerMap['ApiConsoleHaloRunV1alpha1PostApi.listPostSnapshots']?.[localVarOperationServerIndex]?.url;
return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath);
},
/**
* List posts.
* @param {number} [page] Page number. Default is 0.
@ -545,6 +771,19 @@ export const ApiConsoleHaloRunV1alpha1PostApiFp = function(configuration?: Confi
const localVarOperationServerBasePath = operationServerMap['ApiConsoleHaloRunV1alpha1PostApi.recyclePost']?.[localVarOperationServerIndex]?.url;
return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath);
},
/**
* Revert to specified snapshot for post content.
* @param {string} name
* @param {RevertSnapshotForPostParam} revertSnapshotForPostParam
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async revertToSpecifiedSnapshotForPost(name: string, revertSnapshotForPostParam: RevertSnapshotForPostParam, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<Post>> {
const localVarAxiosArgs = await localVarAxiosParamCreator.revertToSpecifiedSnapshotForPost(name, revertSnapshotForPostParam, options);
const localVarOperationServerIndex = configuration?.serverIndex ?? 0;
const localVarOperationServerBasePath = operationServerMap['ApiConsoleHaloRunV1alpha1PostApi.revertToSpecifiedSnapshotForPost']?.[localVarOperationServerIndex]?.url;
return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath);
},
/**
* Publish a post.
* @param {string} name
@ -593,6 +832,15 @@ export const ApiConsoleHaloRunV1alpha1PostApiFp = function(configuration?: Confi
export const ApiConsoleHaloRunV1alpha1PostApiFactory = function (configuration?: Configuration, basePath?: string, axios?: AxiosInstance) {
const localVarFp = ApiConsoleHaloRunV1alpha1PostApiFp(configuration)
return {
/**
* Delete a content for post.
* @param {ApiConsoleHaloRunV1alpha1PostApiDeletePostContentRequest} requestParameters Request parameters.
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
deletePostContent(requestParameters: ApiConsoleHaloRunV1alpha1PostApiDeletePostContentRequest, options?: RawAxiosRequestConfig): AxiosPromise<ContentWrapper> {
return localVarFp.deletePostContent(requestParameters.name, requestParameters.snapshotName, options).then((request) => request(axios, basePath));
},
/**
* Draft a post.
* @param {ApiConsoleHaloRunV1alpha1PostApiDraftPostRequest} requestParameters Request parameters.
@ -602,6 +850,15 @@ export const ApiConsoleHaloRunV1alpha1PostApiFactory = function (configuration?:
draftPost(requestParameters: ApiConsoleHaloRunV1alpha1PostApiDraftPostRequest, options?: RawAxiosRequestConfig): AxiosPromise<Post> {
return localVarFp.draftPost(requestParameters.postRequest, options).then((request) => request(axios, basePath));
},
/**
* Fetch content of post.
* @param {ApiConsoleHaloRunV1alpha1PostApiFetchPostContentRequest} requestParameters Request parameters.
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
fetchPostContent(requestParameters: ApiConsoleHaloRunV1alpha1PostApiFetchPostContentRequest, options?: RawAxiosRequestConfig): AxiosPromise<ContentWrapper> {
return localVarFp.fetchPostContent(requestParameters.name, requestParameters.snapshotName, options).then((request) => request(axios, basePath));
},
/**
* Fetch head content of post.
* @param {ApiConsoleHaloRunV1alpha1PostApiFetchPostHeadContentRequest} requestParameters Request parameters.
@ -620,6 +877,15 @@ export const ApiConsoleHaloRunV1alpha1PostApiFactory = function (configuration?:
fetchPostReleaseContent(requestParameters: ApiConsoleHaloRunV1alpha1PostApiFetchPostReleaseContentRequest, options?: RawAxiosRequestConfig): AxiosPromise<ContentWrapper> {
return localVarFp.fetchPostReleaseContent(requestParameters.name, options).then((request) => request(axios, basePath));
},
/**
* List all snapshots for post content.
* @param {ApiConsoleHaloRunV1alpha1PostApiListPostSnapshotsRequest} requestParameters Request parameters.
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
listPostSnapshots(requestParameters: ApiConsoleHaloRunV1alpha1PostApiListPostSnapshotsRequest, options?: RawAxiosRequestConfig): AxiosPromise<Array<ListedSnapshotDto>> {
return localVarFp.listPostSnapshots(requestParameters.name, options).then((request) => request(axios, basePath));
},
/**
* List posts.
* @param {ApiConsoleHaloRunV1alpha1PostApiListPostsRequest} requestParameters Request parameters.
@ -647,6 +913,15 @@ export const ApiConsoleHaloRunV1alpha1PostApiFactory = function (configuration?:
recyclePost(requestParameters: ApiConsoleHaloRunV1alpha1PostApiRecyclePostRequest, options?: RawAxiosRequestConfig): AxiosPromise<void> {
return localVarFp.recyclePost(requestParameters.name, options).then((request) => request(axios, basePath));
},
/**
* Revert to specified snapshot for post content.
* @param {ApiConsoleHaloRunV1alpha1PostApiRevertToSpecifiedSnapshotForPostRequest} requestParameters Request parameters.
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
revertToSpecifiedSnapshotForPost(requestParameters: ApiConsoleHaloRunV1alpha1PostApiRevertToSpecifiedSnapshotForPostRequest, options?: RawAxiosRequestConfig): AxiosPromise<Post> {
return localVarFp.revertToSpecifiedSnapshotForPost(requestParameters.name, requestParameters.revertSnapshotForPostParam, options).then((request) => request(axios, basePath));
},
/**
* Publish a post.
* @param {ApiConsoleHaloRunV1alpha1PostApiUnpublishPostRequest} requestParameters Request parameters.
@ -677,6 +952,27 @@ export const ApiConsoleHaloRunV1alpha1PostApiFactory = function (configuration?:
};
};
/**
* Request parameters for deletePostContent operation in ApiConsoleHaloRunV1alpha1PostApi.
* @export
* @interface ApiConsoleHaloRunV1alpha1PostApiDeletePostContentRequest
*/
export interface ApiConsoleHaloRunV1alpha1PostApiDeletePostContentRequest {
/**
*
* @type {string}
* @memberof ApiConsoleHaloRunV1alpha1PostApiDeletePostContent
*/
readonly name: string
/**
*
* @type {string}
* @memberof ApiConsoleHaloRunV1alpha1PostApiDeletePostContent
*/
readonly snapshotName: string
}
/**
* Request parameters for draftPost operation in ApiConsoleHaloRunV1alpha1PostApi.
* @export
@ -691,6 +987,27 @@ export interface ApiConsoleHaloRunV1alpha1PostApiDraftPostRequest {
readonly postRequest: PostRequest
}
/**
* Request parameters for fetchPostContent operation in ApiConsoleHaloRunV1alpha1PostApi.
* @export
* @interface ApiConsoleHaloRunV1alpha1PostApiFetchPostContentRequest
*/
export interface ApiConsoleHaloRunV1alpha1PostApiFetchPostContentRequest {
/**
*
* @type {string}
* @memberof ApiConsoleHaloRunV1alpha1PostApiFetchPostContent
*/
readonly name: string
/**
*
* @type {string}
* @memberof ApiConsoleHaloRunV1alpha1PostApiFetchPostContent
*/
readonly snapshotName: string
}
/**
* Request parameters for fetchPostHeadContent operation in ApiConsoleHaloRunV1alpha1PostApi.
* @export
@ -719,6 +1036,20 @@ export interface ApiConsoleHaloRunV1alpha1PostApiFetchPostReleaseContentRequest
readonly name: string
}
/**
* Request parameters for listPostSnapshots operation in ApiConsoleHaloRunV1alpha1PostApi.
* @export
* @interface ApiConsoleHaloRunV1alpha1PostApiListPostSnapshotsRequest
*/
export interface ApiConsoleHaloRunV1alpha1PostApiListPostSnapshotsRequest {
/**
*
* @type {string}
* @memberof ApiConsoleHaloRunV1alpha1PostApiListPostSnapshots
*/
readonly name: string
}
/**
* Request parameters for listPosts operation in ApiConsoleHaloRunV1alpha1PostApi.
* @export
@ -810,6 +1141,27 @@ export interface ApiConsoleHaloRunV1alpha1PostApiRecyclePostRequest {
readonly name: string
}
/**
* Request parameters for revertToSpecifiedSnapshotForPost operation in ApiConsoleHaloRunV1alpha1PostApi.
* @export
* @interface ApiConsoleHaloRunV1alpha1PostApiRevertToSpecifiedSnapshotForPostRequest
*/
export interface ApiConsoleHaloRunV1alpha1PostApiRevertToSpecifiedSnapshotForPostRequest {
/**
*
* @type {string}
* @memberof ApiConsoleHaloRunV1alpha1PostApiRevertToSpecifiedSnapshotForPost
*/
readonly name: string
/**
*
* @type {RevertSnapshotForPostParam}
* @memberof ApiConsoleHaloRunV1alpha1PostApiRevertToSpecifiedSnapshotForPost
*/
readonly revertSnapshotForPostParam: RevertSnapshotForPostParam
}
/**
* Request parameters for unpublishPost operation in ApiConsoleHaloRunV1alpha1PostApi.
* @export
@ -873,6 +1225,17 @@ export interface ApiConsoleHaloRunV1alpha1PostApiUpdatePostContentRequest {
* @extends {BaseAPI}
*/
export class ApiConsoleHaloRunV1alpha1PostApi extends BaseAPI {
/**
* Delete a content for post.
* @param {ApiConsoleHaloRunV1alpha1PostApiDeletePostContentRequest} requestParameters Request parameters.
* @param {*} [options] Override http request option.
* @throws {RequiredError}
* @memberof ApiConsoleHaloRunV1alpha1PostApi
*/
public deletePostContent(requestParameters: ApiConsoleHaloRunV1alpha1PostApiDeletePostContentRequest, options?: RawAxiosRequestConfig) {
return ApiConsoleHaloRunV1alpha1PostApiFp(this.configuration).deletePostContent(requestParameters.name, requestParameters.snapshotName, options).then((request) => request(this.axios, this.basePath));
}
/**
* Draft a post.
* @param {ApiConsoleHaloRunV1alpha1PostApiDraftPostRequest} requestParameters Request parameters.
@ -884,6 +1247,17 @@ export class ApiConsoleHaloRunV1alpha1PostApi extends BaseAPI {
return ApiConsoleHaloRunV1alpha1PostApiFp(this.configuration).draftPost(requestParameters.postRequest, options).then((request) => request(this.axios, this.basePath));
}
/**
* Fetch content of post.
* @param {ApiConsoleHaloRunV1alpha1PostApiFetchPostContentRequest} requestParameters Request parameters.
* @param {*} [options] Override http request option.
* @throws {RequiredError}
* @memberof ApiConsoleHaloRunV1alpha1PostApi
*/
public fetchPostContent(requestParameters: ApiConsoleHaloRunV1alpha1PostApiFetchPostContentRequest, options?: RawAxiosRequestConfig) {
return ApiConsoleHaloRunV1alpha1PostApiFp(this.configuration).fetchPostContent(requestParameters.name, requestParameters.snapshotName, options).then((request) => request(this.axios, this.basePath));
}
/**
* Fetch head content of post.
* @param {ApiConsoleHaloRunV1alpha1PostApiFetchPostHeadContentRequest} requestParameters Request parameters.
@ -906,6 +1280,17 @@ export class ApiConsoleHaloRunV1alpha1PostApi extends BaseAPI {
return ApiConsoleHaloRunV1alpha1PostApiFp(this.configuration).fetchPostReleaseContent(requestParameters.name, options).then((request) => request(this.axios, this.basePath));
}
/**
* List all snapshots for post content.
* @param {ApiConsoleHaloRunV1alpha1PostApiListPostSnapshotsRequest} requestParameters Request parameters.
* @param {*} [options] Override http request option.
* @throws {RequiredError}
* @memberof ApiConsoleHaloRunV1alpha1PostApi
*/
public listPostSnapshots(requestParameters: ApiConsoleHaloRunV1alpha1PostApiListPostSnapshotsRequest, options?: RawAxiosRequestConfig) {
return ApiConsoleHaloRunV1alpha1PostApiFp(this.configuration).listPostSnapshots(requestParameters.name, options).then((request) => request(this.axios, this.basePath));
}
/**
* List posts.
* @param {ApiConsoleHaloRunV1alpha1PostApiListPostsRequest} requestParameters Request parameters.
@ -939,6 +1324,17 @@ export class ApiConsoleHaloRunV1alpha1PostApi extends BaseAPI {
return ApiConsoleHaloRunV1alpha1PostApiFp(this.configuration).recyclePost(requestParameters.name, options).then((request) => request(this.axios, this.basePath));
}
/**
* Revert to specified snapshot for post content.
* @param {ApiConsoleHaloRunV1alpha1PostApiRevertToSpecifiedSnapshotForPostRequest} requestParameters Request parameters.
* @param {*} [options] Override http request option.
* @throws {RequiredError}
* @memberof ApiConsoleHaloRunV1alpha1PostApi
*/
public revertToSpecifiedSnapshotForPost(requestParameters: ApiConsoleHaloRunV1alpha1PostApiRevertToSpecifiedSnapshotForPostRequest, options?: RawAxiosRequestConfig) {
return ApiConsoleHaloRunV1alpha1PostApiFp(this.configuration).revertToSpecifiedSnapshotForPost(requestParameters.name, requestParameters.revertSnapshotForPostParam, options).then((request) => request(this.axios, this.basePath));
}
/**
* Publish a post.
* @param {ApiConsoleHaloRunV1alpha1PostApiUnpublishPostRequest} requestParameters Request parameters.

View File

@ -28,8 +28,12 @@ import { ContentWrapper } from '../models';
// @ts-ignore
import { ListedSinglePageList } from '../models';
// @ts-ignore
import { ListedSnapshotDto } from '../models';
// @ts-ignore
import { Post } from '../models';
// @ts-ignore
import { RevertSnapshotForSingleParam } from '../models';
// @ts-ignore
import { SinglePage } from '../models';
// @ts-ignore
import { SinglePageRequest } from '../models';
@ -39,6 +43,54 @@ import { SinglePageRequest } from '../models';
*/
export const ApiConsoleHaloRunV1alpha1SinglePageApiAxiosParamCreator = function (configuration?: Configuration) {
return {
/**
* Delete a content for post.
* @param {string} name
* @param {string} snapshotName
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
deleteSinglePageContent: async (name: string, snapshotName: string, options: RawAxiosRequestConfig = {}): Promise<RequestArgs> => {
// verify required parameter 'name' is not null or undefined
assertParamExists('deleteSinglePageContent', 'name', name)
// verify required parameter 'snapshotName' is not null or undefined
assertParamExists('deleteSinglePageContent', 'snapshotName', snapshotName)
const localVarPath = `/apis/api.console.halo.run/v1alpha1/singlepages/{name}/content`
.replace(`{${"name"}}`, encodeURIComponent(String(name)));
// 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: 'DELETE', ...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 (snapshotName !== undefined) {
localVarQueryParameter['snapshotName'] = snapshotName;
}
setSearchParams(localVarUrlObj, localVarQueryParameter);
let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
return {
url: toPathString(localVarUrlObj),
options: localVarRequestOptions,
};
},
/**
* Draft a single page.
* @param {SinglePageRequest} singlePageRequest
@ -82,6 +134,54 @@ export const ApiConsoleHaloRunV1alpha1SinglePageApiAxiosParamCreator = function
options: localVarRequestOptions,
};
},
/**
* Fetch content of single page.
* @param {string} name
* @param {string} snapshotName
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
fetchSinglePageContent: async (name: string, snapshotName: string, options: RawAxiosRequestConfig = {}): Promise<RequestArgs> => {
// verify required parameter 'name' is not null or undefined
assertParamExists('fetchSinglePageContent', 'name', name)
// verify required parameter 'snapshotName' is not null or undefined
assertParamExists('fetchSinglePageContent', 'snapshotName', snapshotName)
const localVarPath = `/apis/api.console.halo.run/v1alpha1/singlepages/{name}/content`
.replace(`{${"name"}}`, encodeURIComponent(String(name)));
// 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 (snapshotName !== undefined) {
localVarQueryParameter['snapshotName'] = snapshotName;
}
setSearchParams(localVarUrlObj, localVarQueryParameter);
let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
return {
url: toPathString(localVarUrlObj),
options: localVarRequestOptions,
};
},
/**
* Fetch head content of single page.
* @param {string} name
@ -155,6 +255,47 @@ export const ApiConsoleHaloRunV1alpha1SinglePageApiAxiosParamCreator = function
setSearchParams(localVarUrlObj, localVarQueryParameter);
let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
return {
url: toPathString(localVarUrlObj),
options: localVarRequestOptions,
};
},
/**
* List all snapshots for single page content.
* @param {string} name
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
listSinglePageSnapshots: async (name: string, options: RawAxiosRequestConfig = {}): Promise<RequestArgs> => {
// verify required parameter 'name' is not null or undefined
assertParamExists('listSinglePageSnapshots', 'name', name)
const localVarPath = `/apis/api.console.halo.run/v1alpha1/singlepages/{name}/snapshot`
.replace(`{${"name"}}`, encodeURIComponent(String(name)));
// 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)
setSearchParams(localVarUrlObj, localVarQueryParameter);
let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
@ -287,6 +428,53 @@ export const ApiConsoleHaloRunV1alpha1SinglePageApiAxiosParamCreator = function
options: localVarRequestOptions,
};
},
/**
* Revert to specified snapshot for single page content.
* @param {string} name
* @param {RevertSnapshotForSingleParam} revertSnapshotForSingleParam
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
revertToSpecifiedSnapshotForSinglePage: async (name: string, revertSnapshotForSingleParam: RevertSnapshotForSingleParam, options: RawAxiosRequestConfig = {}): Promise<RequestArgs> => {
// verify required parameter 'name' is not null or undefined
assertParamExists('revertToSpecifiedSnapshotForSinglePage', 'name', name)
// verify required parameter 'revertSnapshotForSingleParam' is not null or undefined
assertParamExists('revertToSpecifiedSnapshotForSinglePage', 'revertSnapshotForSingleParam', revertSnapshotForSingleParam)
const localVarPath = `/apis/api.console.halo.run/v1alpha1/singlepages/{name}/revert-content`
.replace(`{${"name"}}`, encodeURIComponent(String(name)));
// 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: 'PUT', ...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)
localVarHeaderParameter['Content-Type'] = 'application/json';
setSearchParams(localVarUrlObj, localVarQueryParameter);
let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
localVarRequestOptions.data = serializeDataIfNeeded(revertSnapshotForSingleParam, localVarRequestOptions, configuration)
return {
url: toPathString(localVarUrlObj),
options: localVarRequestOptions,
};
},
/**
* Update a single page.
* @param {string} name
@ -391,6 +579,19 @@ export const ApiConsoleHaloRunV1alpha1SinglePageApiAxiosParamCreator = function
export const ApiConsoleHaloRunV1alpha1SinglePageApiFp = function(configuration?: Configuration) {
const localVarAxiosParamCreator = ApiConsoleHaloRunV1alpha1SinglePageApiAxiosParamCreator(configuration)
return {
/**
* Delete a content for post.
* @param {string} name
* @param {string} snapshotName
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async deleteSinglePageContent(name: string, snapshotName: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<ContentWrapper>> {
const localVarAxiosArgs = await localVarAxiosParamCreator.deleteSinglePageContent(name, snapshotName, options);
const localVarOperationServerIndex = configuration?.serverIndex ?? 0;
const localVarOperationServerBasePath = operationServerMap['ApiConsoleHaloRunV1alpha1SinglePageApi.deleteSinglePageContent']?.[localVarOperationServerIndex]?.url;
return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath);
},
/**
* Draft a single page.
* @param {SinglePageRequest} singlePageRequest
@ -403,6 +604,19 @@ export const ApiConsoleHaloRunV1alpha1SinglePageApiFp = function(configuration?:
const localVarOperationServerBasePath = operationServerMap['ApiConsoleHaloRunV1alpha1SinglePageApi.draftSinglePage']?.[localVarOperationServerIndex]?.url;
return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath);
},
/**
* Fetch content of single page.
* @param {string} name
* @param {string} snapshotName
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async fetchSinglePageContent(name: string, snapshotName: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<ContentWrapper>> {
const localVarAxiosArgs = await localVarAxiosParamCreator.fetchSinglePageContent(name, snapshotName, options);
const localVarOperationServerIndex = configuration?.serverIndex ?? 0;
const localVarOperationServerBasePath = operationServerMap['ApiConsoleHaloRunV1alpha1SinglePageApi.fetchSinglePageContent']?.[localVarOperationServerIndex]?.url;
return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath);
},
/**
* Fetch head content of single page.
* @param {string} name
@ -427,6 +641,18 @@ export const ApiConsoleHaloRunV1alpha1SinglePageApiFp = function(configuration?:
const localVarOperationServerBasePath = operationServerMap['ApiConsoleHaloRunV1alpha1SinglePageApi.fetchSinglePageReleaseContent']?.[localVarOperationServerIndex]?.url;
return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath);
},
/**
* List all snapshots for single page content.
* @param {string} name
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async listSinglePageSnapshots(name: string, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<Array<ListedSnapshotDto>>> {
const localVarAxiosArgs = await localVarAxiosParamCreator.listSinglePageSnapshots(name, options);
const localVarOperationServerIndex = configuration?.serverIndex ?? 0;
const localVarOperationServerBasePath = operationServerMap['ApiConsoleHaloRunV1alpha1SinglePageApi.listSinglePageSnapshots']?.[localVarOperationServerIndex]?.url;
return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath);
},
/**
* List single pages.
* @param {number} [page] Page number. Default is 0.
@ -459,6 +685,19 @@ export const ApiConsoleHaloRunV1alpha1SinglePageApiFp = function(configuration?:
const localVarOperationServerBasePath = operationServerMap['ApiConsoleHaloRunV1alpha1SinglePageApi.publishSinglePage']?.[localVarOperationServerIndex]?.url;
return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath);
},
/**
* Revert to specified snapshot for single page content.
* @param {string} name
* @param {RevertSnapshotForSingleParam} revertSnapshotForSingleParam
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async revertToSpecifiedSnapshotForSinglePage(name: string, revertSnapshotForSingleParam: RevertSnapshotForSingleParam, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<Post>> {
const localVarAxiosArgs = await localVarAxiosParamCreator.revertToSpecifiedSnapshotForSinglePage(name, revertSnapshotForSingleParam, options);
const localVarOperationServerIndex = configuration?.serverIndex ?? 0;
const localVarOperationServerBasePath = operationServerMap['ApiConsoleHaloRunV1alpha1SinglePageApi.revertToSpecifiedSnapshotForSinglePage']?.[localVarOperationServerIndex]?.url;
return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, localVarOperationServerBasePath || basePath);
},
/**
* Update a single page.
* @param {string} name
@ -495,6 +734,15 @@ export const ApiConsoleHaloRunV1alpha1SinglePageApiFp = function(configuration?:
export const ApiConsoleHaloRunV1alpha1SinglePageApiFactory = function (configuration?: Configuration, basePath?: string, axios?: AxiosInstance) {
const localVarFp = ApiConsoleHaloRunV1alpha1SinglePageApiFp(configuration)
return {
/**
* Delete a content for post.
* @param {ApiConsoleHaloRunV1alpha1SinglePageApiDeleteSinglePageContentRequest} requestParameters Request parameters.
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
deleteSinglePageContent(requestParameters: ApiConsoleHaloRunV1alpha1SinglePageApiDeleteSinglePageContentRequest, options?: RawAxiosRequestConfig): AxiosPromise<ContentWrapper> {
return localVarFp.deleteSinglePageContent(requestParameters.name, requestParameters.snapshotName, options).then((request) => request(axios, basePath));
},
/**
* Draft a single page.
* @param {ApiConsoleHaloRunV1alpha1SinglePageApiDraftSinglePageRequest} requestParameters Request parameters.
@ -504,6 +752,15 @@ export const ApiConsoleHaloRunV1alpha1SinglePageApiFactory = function (configura
draftSinglePage(requestParameters: ApiConsoleHaloRunV1alpha1SinglePageApiDraftSinglePageRequest, options?: RawAxiosRequestConfig): AxiosPromise<SinglePage> {
return localVarFp.draftSinglePage(requestParameters.singlePageRequest, options).then((request) => request(axios, basePath));
},
/**
* Fetch content of single page.
* @param {ApiConsoleHaloRunV1alpha1SinglePageApiFetchSinglePageContentRequest} requestParameters Request parameters.
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
fetchSinglePageContent(requestParameters: ApiConsoleHaloRunV1alpha1SinglePageApiFetchSinglePageContentRequest, options?: RawAxiosRequestConfig): AxiosPromise<ContentWrapper> {
return localVarFp.fetchSinglePageContent(requestParameters.name, requestParameters.snapshotName, options).then((request) => request(axios, basePath));
},
/**
* Fetch head content of single page.
* @param {ApiConsoleHaloRunV1alpha1SinglePageApiFetchSinglePageHeadContentRequest} requestParameters Request parameters.
@ -522,6 +779,15 @@ export const ApiConsoleHaloRunV1alpha1SinglePageApiFactory = function (configura
fetchSinglePageReleaseContent(requestParameters: ApiConsoleHaloRunV1alpha1SinglePageApiFetchSinglePageReleaseContentRequest, options?: RawAxiosRequestConfig): AxiosPromise<ContentWrapper> {
return localVarFp.fetchSinglePageReleaseContent(requestParameters.name, options).then((request) => request(axios, basePath));
},
/**
* List all snapshots for single page content.
* @param {ApiConsoleHaloRunV1alpha1SinglePageApiListSinglePageSnapshotsRequest} requestParameters Request parameters.
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
listSinglePageSnapshots(requestParameters: ApiConsoleHaloRunV1alpha1SinglePageApiListSinglePageSnapshotsRequest, options?: RawAxiosRequestConfig): AxiosPromise<Array<ListedSnapshotDto>> {
return localVarFp.listSinglePageSnapshots(requestParameters.name, options).then((request) => request(axios, basePath));
},
/**
* List single pages.
* @param {ApiConsoleHaloRunV1alpha1SinglePageApiListSinglePagesRequest} requestParameters Request parameters.
@ -540,6 +806,15 @@ export const ApiConsoleHaloRunV1alpha1SinglePageApiFactory = function (configura
publishSinglePage(requestParameters: ApiConsoleHaloRunV1alpha1SinglePageApiPublishSinglePageRequest, options?: RawAxiosRequestConfig): AxiosPromise<SinglePage> {
return localVarFp.publishSinglePage(requestParameters.name, options).then((request) => request(axios, basePath));
},
/**
* Revert to specified snapshot for single page content.
* @param {ApiConsoleHaloRunV1alpha1SinglePageApiRevertToSpecifiedSnapshotForSinglePageRequest} requestParameters Request parameters.
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
revertToSpecifiedSnapshotForSinglePage(requestParameters: ApiConsoleHaloRunV1alpha1SinglePageApiRevertToSpecifiedSnapshotForSinglePageRequest, options?: RawAxiosRequestConfig): AxiosPromise<Post> {
return localVarFp.revertToSpecifiedSnapshotForSinglePage(requestParameters.name, requestParameters.revertSnapshotForSingleParam, options).then((request) => request(axios, basePath));
},
/**
* Update a single page.
* @param {ApiConsoleHaloRunV1alpha1SinglePageApiUpdateDraftSinglePageRequest} requestParameters Request parameters.
@ -561,6 +836,27 @@ export const ApiConsoleHaloRunV1alpha1SinglePageApiFactory = function (configura
};
};
/**
* Request parameters for deleteSinglePageContent operation in ApiConsoleHaloRunV1alpha1SinglePageApi.
* @export
* @interface ApiConsoleHaloRunV1alpha1SinglePageApiDeleteSinglePageContentRequest
*/
export interface ApiConsoleHaloRunV1alpha1SinglePageApiDeleteSinglePageContentRequest {
/**
*
* @type {string}
* @memberof ApiConsoleHaloRunV1alpha1SinglePageApiDeleteSinglePageContent
*/
readonly name: string
/**
*
* @type {string}
* @memberof ApiConsoleHaloRunV1alpha1SinglePageApiDeleteSinglePageContent
*/
readonly snapshotName: string
}
/**
* Request parameters for draftSinglePage operation in ApiConsoleHaloRunV1alpha1SinglePageApi.
* @export
@ -575,6 +871,27 @@ export interface ApiConsoleHaloRunV1alpha1SinglePageApiDraftSinglePageRequest {
readonly singlePageRequest: SinglePageRequest
}
/**
* Request parameters for fetchSinglePageContent operation in ApiConsoleHaloRunV1alpha1SinglePageApi.
* @export
* @interface ApiConsoleHaloRunV1alpha1SinglePageApiFetchSinglePageContentRequest
*/
export interface ApiConsoleHaloRunV1alpha1SinglePageApiFetchSinglePageContentRequest {
/**
*
* @type {string}
* @memberof ApiConsoleHaloRunV1alpha1SinglePageApiFetchSinglePageContent
*/
readonly name: string
/**
*
* @type {string}
* @memberof ApiConsoleHaloRunV1alpha1SinglePageApiFetchSinglePageContent
*/
readonly snapshotName: string
}
/**
* Request parameters for fetchSinglePageHeadContent operation in ApiConsoleHaloRunV1alpha1SinglePageApi.
* @export
@ -603,6 +920,20 @@ export interface ApiConsoleHaloRunV1alpha1SinglePageApiFetchSinglePageReleaseCon
readonly name: string
}
/**
* Request parameters for listSinglePageSnapshots operation in ApiConsoleHaloRunV1alpha1SinglePageApi.
* @export
* @interface ApiConsoleHaloRunV1alpha1SinglePageApiListSinglePageSnapshotsRequest
*/
export interface ApiConsoleHaloRunV1alpha1SinglePageApiListSinglePageSnapshotsRequest {
/**
*
* @type {string}
* @memberof ApiConsoleHaloRunV1alpha1SinglePageApiListSinglePageSnapshots
*/
readonly name: string
}
/**
* Request parameters for listSinglePages operation in ApiConsoleHaloRunV1alpha1SinglePageApi.
* @export
@ -687,6 +1018,27 @@ export interface ApiConsoleHaloRunV1alpha1SinglePageApiPublishSinglePageRequest
readonly name: string
}
/**
* Request parameters for revertToSpecifiedSnapshotForSinglePage operation in ApiConsoleHaloRunV1alpha1SinglePageApi.
* @export
* @interface ApiConsoleHaloRunV1alpha1SinglePageApiRevertToSpecifiedSnapshotForSinglePageRequest
*/
export interface ApiConsoleHaloRunV1alpha1SinglePageApiRevertToSpecifiedSnapshotForSinglePageRequest {
/**
*
* @type {string}
* @memberof ApiConsoleHaloRunV1alpha1SinglePageApiRevertToSpecifiedSnapshotForSinglePage
*/
readonly name: string
/**
*
* @type {RevertSnapshotForSingleParam}
* @memberof ApiConsoleHaloRunV1alpha1SinglePageApiRevertToSpecifiedSnapshotForSinglePage
*/
readonly revertSnapshotForSingleParam: RevertSnapshotForSingleParam
}
/**
* Request parameters for updateDraftSinglePage operation in ApiConsoleHaloRunV1alpha1SinglePageApi.
* @export
@ -736,6 +1088,17 @@ export interface ApiConsoleHaloRunV1alpha1SinglePageApiUpdateSinglePageContentRe
* @extends {BaseAPI}
*/
export class ApiConsoleHaloRunV1alpha1SinglePageApi extends BaseAPI {
/**
* Delete a content for post.
* @param {ApiConsoleHaloRunV1alpha1SinglePageApiDeleteSinglePageContentRequest} requestParameters Request parameters.
* @param {*} [options] Override http request option.
* @throws {RequiredError}
* @memberof ApiConsoleHaloRunV1alpha1SinglePageApi
*/
public deleteSinglePageContent(requestParameters: ApiConsoleHaloRunV1alpha1SinglePageApiDeleteSinglePageContentRequest, options?: RawAxiosRequestConfig) {
return ApiConsoleHaloRunV1alpha1SinglePageApiFp(this.configuration).deleteSinglePageContent(requestParameters.name, requestParameters.snapshotName, options).then((request) => request(this.axios, this.basePath));
}
/**
* Draft a single page.
* @param {ApiConsoleHaloRunV1alpha1SinglePageApiDraftSinglePageRequest} requestParameters Request parameters.
@ -747,6 +1110,17 @@ export class ApiConsoleHaloRunV1alpha1SinglePageApi extends BaseAPI {
return ApiConsoleHaloRunV1alpha1SinglePageApiFp(this.configuration).draftSinglePage(requestParameters.singlePageRequest, options).then((request) => request(this.axios, this.basePath));
}
/**
* Fetch content of single page.
* @param {ApiConsoleHaloRunV1alpha1SinglePageApiFetchSinglePageContentRequest} requestParameters Request parameters.
* @param {*} [options] Override http request option.
* @throws {RequiredError}
* @memberof ApiConsoleHaloRunV1alpha1SinglePageApi
*/
public fetchSinglePageContent(requestParameters: ApiConsoleHaloRunV1alpha1SinglePageApiFetchSinglePageContentRequest, options?: RawAxiosRequestConfig) {
return ApiConsoleHaloRunV1alpha1SinglePageApiFp(this.configuration).fetchSinglePageContent(requestParameters.name, requestParameters.snapshotName, options).then((request) => request(this.axios, this.basePath));
}
/**
* Fetch head content of single page.
* @param {ApiConsoleHaloRunV1alpha1SinglePageApiFetchSinglePageHeadContentRequest} requestParameters Request parameters.
@ -769,6 +1143,17 @@ export class ApiConsoleHaloRunV1alpha1SinglePageApi extends BaseAPI {
return ApiConsoleHaloRunV1alpha1SinglePageApiFp(this.configuration).fetchSinglePageReleaseContent(requestParameters.name, options).then((request) => request(this.axios, this.basePath));
}
/**
* List all snapshots for single page content.
* @param {ApiConsoleHaloRunV1alpha1SinglePageApiListSinglePageSnapshotsRequest} requestParameters Request parameters.
* @param {*} [options] Override http request option.
* @throws {RequiredError}
* @memberof ApiConsoleHaloRunV1alpha1SinglePageApi
*/
public listSinglePageSnapshots(requestParameters: ApiConsoleHaloRunV1alpha1SinglePageApiListSinglePageSnapshotsRequest, options?: RawAxiosRequestConfig) {
return ApiConsoleHaloRunV1alpha1SinglePageApiFp(this.configuration).listSinglePageSnapshots(requestParameters.name, options).then((request) => request(this.axios, this.basePath));
}
/**
* List single pages.
* @param {ApiConsoleHaloRunV1alpha1SinglePageApiListSinglePagesRequest} requestParameters Request parameters.
@ -791,6 +1176,17 @@ export class ApiConsoleHaloRunV1alpha1SinglePageApi extends BaseAPI {
return ApiConsoleHaloRunV1alpha1SinglePageApiFp(this.configuration).publishSinglePage(requestParameters.name, options).then((request) => request(this.axios, this.basePath));
}
/**
* Revert to specified snapshot for single page content.
* @param {ApiConsoleHaloRunV1alpha1SinglePageApiRevertToSpecifiedSnapshotForSinglePageRequest} requestParameters Request parameters.
* @param {*} [options] Override http request option.
* @throws {RequiredError}
* @memberof ApiConsoleHaloRunV1alpha1SinglePageApi
*/
public revertToSpecifiedSnapshotForSinglePage(requestParameters: ApiConsoleHaloRunV1alpha1SinglePageApiRevertToSpecifiedSnapshotForSinglePageRequest, options?: RawAxiosRequestConfig) {
return ApiConsoleHaloRunV1alpha1SinglePageApiFp(this.configuration).revertToSpecifiedSnapshotForSinglePage(requestParameters.name, requestParameters.revertSnapshotForSingleParam, options).then((request) => request(this.axios, this.basePath));
}
/**
* Update a single page.
* @param {ApiConsoleHaloRunV1alpha1SinglePageApiUpdateDraftSinglePageRequest} requestParameters Request parameters.

View File

@ -0,0 +1,48 @@
/* 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.
*/
/**
*
* @export
* @interface ContentUpdateParam
*/
export interface ContentUpdateParam {
/**
*
* @type {string}
* @memberof ContentUpdateParam
*/
'content'?: string;
/**
*
* @type {string}
* @memberof ContentUpdateParam
*/
'raw'?: string;
/**
*
* @type {string}
* @memberof ContentUpdateParam
*/
'rawType'?: string;
/**
*
* @type {number}
* @memberof ContentUpdateParam
*/
'version'?: number;
}

View File

@ -39,6 +39,7 @@ export * from './config-map';
export * from './config-map-list';
export * from './config-map-ref';
export * from './content';
export * from './content-update-param';
export * from './content-vo';
export * from './content-wrapper';
export * from './contributor';
@ -85,6 +86,8 @@ export * from './listed-single-page';
export * from './listed-single-page-list';
export * from './listed-single-page-vo';
export * from './listed-single-page-vo-list';
export * from './listed-snapshot-dto';
export * from './listed-snapshot-spec';
export * from './listed-user';
export * from './login-history';
export * from './mark-specified-request';
@ -165,6 +168,8 @@ export * from './reset-password-request';
export * from './reverse-proxy';
export * from './reverse-proxy-list';
export * from './reverse-proxy-rule';
export * from './revert-snapshot-for-post-param';
export * from './revert-snapshot-for-single-param';
export * from './role';
export * from './role-binding';
export * from './role-binding-list';

View File

@ -0,0 +1,42 @@
/* 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.
*/
// May contain unused imports in some cases
// @ts-ignore
import { ListedSnapshotSpec } from './listed-snapshot-spec';
// May contain unused imports in some cases
// @ts-ignore
import { Metadata } from './metadata';
/**
*
* @export
* @interface ListedSnapshotDto
*/
export interface ListedSnapshotDto {
/**
*
* @type {Metadata}
* @memberof ListedSnapshotDto
*/
'metadata': Metadata;
/**
*
* @type {ListedSnapshotSpec}
* @memberof ListedSnapshotDto
*/
'spec': ListedSnapshotSpec;
}

View File

@ -0,0 +1,36 @@
/* 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.
*/
/**
*
* @export
* @interface ListedSnapshotSpec
*/
export interface ListedSnapshotSpec {
/**
*
* @type {string}
* @memberof ListedSnapshotSpec
*/
'modifyTime'?: string;
/**
*
* @type {string}
* @memberof ListedSnapshotSpec
*/
'owner': string;
}

View File

@ -15,7 +15,7 @@
// May contain unused imports in some cases
// @ts-ignore
import { Content } from './content';
import { ContentUpdateParam } from './content-update-param';
// May contain unused imports in some cases
// @ts-ignore
import { Post } from './post';
@ -28,10 +28,10 @@ import { Post } from './post';
export interface PostRequest {
/**
*
* @type {Content}
* @type {ContentUpdateParam}
* @memberof PostRequest
*/
'content'?: Content;
'content'?: ContentUpdateParam;
/**
*
* @type {Post}

View File

@ -0,0 +1,30 @@
/* 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.
*/
/**
*
* @export
* @interface RevertSnapshotForPostParam
*/
export interface RevertSnapshotForPostParam {
/**
*
* @type {string}
* @memberof RevertSnapshotForPostParam
*/
'snapshotName': string;
}

View File

@ -0,0 +1,30 @@
/* 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.
*/
/**
*
* @export
* @interface RevertSnapshotForSingleParam
*/
export interface RevertSnapshotForSingleParam {
/**
*
* @type {string}
* @memberof RevertSnapshotForSingleParam
*/
'snapshotName': string;
}

View File

@ -15,7 +15,7 @@
// May contain unused imports in some cases
// @ts-ignore
import { Content } from './content';
import { ContentUpdateParam } from './content-update-param';
// May contain unused imports in some cases
// @ts-ignore
import { SinglePage } from './single-page';
@ -28,10 +28,10 @@ import { SinglePage } from './single-page';
export interface SinglePageRequest {
/**
*
* @type {Content}
* @type {ContentUpdateParam}
* @memberof SinglePageRequest
*/
'content': Content;
'content': ContentUpdateParam;
/**
*
* @type {SinglePage}

View File

@ -72,6 +72,7 @@ import IconAccountCircleLine from "~icons/ri/account-circle-line";
import IconSettings3Line from "~icons/ri/settings-3-line";
import IconImageAddLine from "~icons/ri/image-add-line";
import IconToolsFill from "~icons/ri/tools-fill";
import IconHistoryLine from "~icons/ri/history-line";
export {
IconDashboard,
@ -148,4 +149,5 @@ export {
IconSettings3Line,
IconImageAddLine,
IconToolsFill,
IconHistoryLine,
};

View File

@ -289,6 +289,8 @@ core:
post_editor:
title: Post edit
untitled: Untitled post
actions:
snapshots: Snapshots
post_tag:
title: Post tags
header:
@ -455,6 +457,8 @@ core:
page_editor:
title: Page edit
untitled: Untitled page
actions:
snapshots: Snapshots
comment:
title: Comments
empty:
@ -1674,3 +1678,39 @@ core:
message: >-
There are currently no tools available, and system tools may be provided
by plugins
post_snapshots:
operations:
revert:
button: Revert
title: Revert snapshot
description: >-
Are you sure you want to restore this snapshot? This operation will
create a new snapshot based on this one and publish it.
toast_success: Reverted successfully
delete:
title: Delete snapshot
description: >-
Are you sure you want to delete this snapshot? This operation is
irreversible.
status:
released: Released
draft: Draft
title: Post snapshots
page_snapshots:
operations:
revert:
button: Revert
title: Revert snapshot
description: >-
Are you sure you want to restore this snapshot? This operation will
create a new snapshot based on this one and publish it.
toast_success: Reverted successfully
delete:
title: Delete snapshot
description: >-
Are you sure you want to delete this snapshot? This operation is
irreversible.
status:
released: Released
draft: Draft
title: Page snapshots

View File

@ -293,6 +293,8 @@ core:
post_editor:
title: 文章编辑
untitled: 未命名文章
actions:
snapshots: 版本历史
post_tag:
title: 文章标签
header:
@ -451,6 +453,8 @@ core:
page_editor:
title: 页面编辑
untitled: 未命名页面
actions:
snapshots: 版本历史
comment:
title: 评论
empty:
@ -1578,3 +1582,31 @@ core:
empty:
title: 没有可用工具
message: 当前没有可用的工具,系统工具可能由插件提供
post_snapshots:
operations:
revert:
button: 恢复
title: 恢复快照
description: 确定要恢复该快照吗?此操作将根据这个快照创建一个新的快照并发布。
toast_success: 恢复成功
delete:
title: 删除快照
description: 确定要删除该快照吗?此操作无法恢复。
status:
released: 已发布
draft: 草稿
title: 文章版本历史
page_snapshots:
operations:
revert:
button: 恢复
title: 恢复快照
description: 确定要恢复该快照吗?此操作将根据这个快照创建一个新的快照并发布。
toast_success: 恢复成功
delete:
title: 删除快照
description: 确定要删除该快照吗?此操作无法恢复。
status:
released: 已发布
draft: 草稿
title: 页面版本历史

View File

@ -273,6 +273,8 @@ core:
post_editor:
title: 文章編輯
untitled: 未命名文章
actions:
snapshots: 版本歷史
post_tag:
title: 文章標籤
header:
@ -431,6 +433,8 @@ core:
page_editor:
title: 頁面編輯
untitled: Untitled page
actions:
snapshots: 版本歷史
comment:
title: 留言
empty:
@ -1572,3 +1576,31 @@ core:
empty:
title: 沒有可用工具
message: 目前沒有可用的工具,系統工具可能由外掛提供
post_snapshots:
operations:
revert:
button: 恢復
title: 恢復快照
description: 確定要恢復該快照嗎?此操作將根據這個快照創建一個新的快照並發佈。
toast_success: 恢復成功
delete:
title: 刪除快照
description: 確定要刪除該快照嗎?此操作無法恢復。
status:
released: 已發布
draft: 草稿
title: 文章版本歷史
page_snapshots:
operations:
revert:
button: 恢復
title: 恢復快照
description: 確定要恢復該快照嗎?此操作將根據這個快照創建一個新的快照並發佈。
toast_success: 恢復成功
delete:
title: 刪除快照
description: 確定要刪除該快照嗎?此操作無法恢復。
status:
released: 已發布
draft: 草稿
title: 頁面版本歷史