diff --git a/api-docs/openapi/v3_0/aggregated.json b/api-docs/openapi/v3_0/aggregated.json index d1ac45a17e..7dd8b12963 100644 --- a/api-docs/openapi/v3_0/aggregated.json +++ b/api-docs/openapi/v3_0/aggregated.json @@ -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" diff --git a/application/src/main/java/run/halo/app/content/AbstractContentService.java b/application/src/main/java/run/halo/app/content/AbstractContentService.java index 530cd72bff..f5c47460bf 100644 --- a/application/src/main/java/run/halo/app/content/AbstractContentService.java +++ b/application/src/main/java/run/halo/app/content/AbstractContentService.java @@ -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.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 @@ protected void checkBaseSnapshot(Snapshot snapshot) { } protected Mono 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 draftContent(String baseSnapshotName, ContentRequest content) { + return this.draftContent(baseSnapshotName, content, content.headSnapshotName()); + } + + private Mono 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 @@ protected Mono draftContent(@Nullable String baseSnapshotName, 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 draftContent(String baseSnapshotName, ContentRequest content) { - return this.draftContent(baseSnapshotName, content, content.headSnapshotName()); + .flatMap(client::create); } protected Mono updateContent(String baseSnapshotName, @@ -98,17 +114,23 @@ protected Mono updateContent(String baseSnapshotName, 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 @@ protected Mono updateContent(String baseSnapshotName, .flatMap(head -> restoredContent(baseSnapshotName, head)); } + protected Flux 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 restoredContent(String baseSnapshotName, Snapshot headSnapshot) { return client.fetch(Snapshot.class, baseSnapshotName) .doOnNext(this::checkBaseSnapshot) diff --git a/application/src/main/java/run/halo/app/content/ContentRequest.java b/application/src/main/java/run/halo/app/content/ContentRequest.java index 041815324b..95b7bc2008 100644 --- a/application/src/main/java/run/halo/app/content/ContentRequest.java +++ b/application/src/main/java/run/halo/app/content/ContentRequest.java @@ -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 @@ * @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) { diff --git a/application/src/main/java/run/halo/app/content/ContentUpdateParam.java b/application/src/main/java/run/halo/app/content/ContentUpdateParam.java new file mode 100644 index 0000000000..0eeb1466e4 --- /dev/null +++ b/application/src/main/java/run/halo/app/content/ContentUpdateParam.java @@ -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()); + } +} diff --git a/application/src/main/java/run/halo/app/content/ListedSnapshotDto.java b/application/src/main/java/run/halo/app/content/ListedSnapshotDto.java new file mode 100644 index 0000000000..c0a275708d --- /dev/null +++ b/application/src/main/java/run/halo/app/content/ListedSnapshotDto.java @@ -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()) + ); + } +} diff --git a/application/src/main/java/run/halo/app/content/PostRequest.java b/application/src/main/java/run/halo/app/content/PostRequest.java index 1d6dfb00d9..9da438c23a 100644 --- a/application/src/main/java/run/halo/app/content/PostRequest.java +++ b/application/src/main/java/run/halo/app/content/PostRequest.java @@ -14,12 +14,12 @@ * @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()); } } diff --git a/application/src/main/java/run/halo/app/content/PostService.java b/application/src/main/java/run/halo/app/content/PostService.java index 756b2c9ced..cf4c0b44a3 100644 --- a/application/src/main/java/run/halo/app/content/PostService.java +++ b/application/src/main/java/run/halo/app/content/PostService.java @@ -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 getContent(String snapshotName, String baseSnapshotName); + Flux listSnapshots(String name); + Mono publish(Post post); Mono unpublish(Post post); @@ -43,4 +46,8 @@ public interface PostService { * @return full post data or empty. */ Mono getByUsername(String postName, String username); + + Mono revertToSpecifiedSnapshot(String postName, String snapshotName); + + Mono deleteContent(String postName, String snapshotName); } diff --git a/application/src/main/java/run/halo/app/content/SinglePageRequest.java b/application/src/main/java/run/halo/app/content/SinglePageRequest.java index 93ad8c762d..8e93adff5d 100644 --- a/application/src/main/java/run/halo/app/content/SinglePageRequest.java +++ b/application/src/main/java/run/halo/app/content/SinglePageRequest.java @@ -13,12 +13,12 @@ * @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()); } } diff --git a/application/src/main/java/run/halo/app/content/SinglePageService.java b/application/src/main/java/run/halo/app/content/SinglePageService.java index f10bd753f6..fbaf0dc7ed 100644 --- a/application/src/main/java/run/halo/app/content/SinglePageService.java +++ b/application/src/main/java/run/halo/app/content/SinglePageService.java @@ -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 getContent(String snapshotName, String baseSnapshotName); + Flux listSnapshots(String pageName); + Mono> list(SinglePageQuery listRequest); Mono draft(SinglePageRequest pageRequest); Mono update(SinglePageRequest pageRequest); + + Mono revertToSpecifiedSnapshot(String pageName, String snapshotName); + + Mono deleteContent(String postName, String snapshotName); } diff --git a/application/src/main/java/run/halo/app/content/impl/PostServiceImpl.java b/application/src/main/java/run/halo/app/content/impl/PostServiceImpl.java index 8448ea51bf..4223c42c27 100644 --- a/application/src/main/java/run/halo/app/content/impl/PostServiceImpl.java +++ b/application/src/main/java/run/halo/app/content/impl/PostServiceImpl.java @@ -14,6 +14,7 @@ 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.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 Mono draftPost(PostRequest postRequest) { } 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 Mono getReleaseContent(Post post) { return getContent(releaseSnapshot, post.getSpec().getBaseSnapshot()); } + @Override + public Flux listSnapshots(String name) { + return client.fetch(Post.class, name) + .flatMapMany(page -> listSnapshotsBy(Ref.of(page))) + .map(ListedSnapshotDto::from); + } + @Override public Mono publish(Post post) { var spec = post.getSpec(); @@ -284,4 +295,81 @@ public Mono getByUsername(String postName, String username) { .filter(post -> post.getSpec() != null) .filter(post -> Objects.equals(username, post.getSpec().getOwner())); } + + @Override + public Mono 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 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 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 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)) + ); + } } diff --git a/application/src/main/java/run/halo/app/content/impl/SinglePageServiceImpl.java b/application/src/main/java/run/halo/app/content/impl/SinglePageServiceImpl.java index 6cfe474ced..11e60e9292 100644 --- a/application/src/main/java/run/halo/app/content/impl/SinglePageServiceImpl.java +++ b/application/src/main/java/run/halo/app/content/impl/SinglePageServiceImpl.java @@ -10,6 +10,7 @@ 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.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 Mono getReleaseContent(String singlePageName) { }); } + @Override + public Flux listSnapshots(String pageName) { + return client.fetch(SinglePage.class, pageName) + .flatMapMany(page -> listSnapshotsBy(Ref.of(page))) + .map(ListedSnapshotDto::from); + } + @Override public Mono> list(SinglePageQuery query) { return client.list(SinglePage.class, query.toPredicate(), @@ -103,6 +113,7 @@ public Mono draft(SinglePageRequest pageRequest) { .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 Mono update(SinglePageRequest pageRequest) { }); } + @Override + public Mono 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 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 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 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 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 getListedSinglePage(SinglePage singlePage) { Assert.notNull(singlePage, "The singlePage must not be null."); var listedSinglePage = new ListedSinglePage() diff --git a/application/src/main/java/run/halo/app/core/extension/endpoint/PostEndpoint.java b/application/src/main/java/run/halo/app/core/extension/endpoint/PostEndpoint.java index 9d9826de29..42161266ac 100644 --- a/application/src/main/java/run/halo/app/core/extension/endpoint/PostEndpoint.java +++ b/application/src/main/java/run/halo/app/core/extension/endpoint/PostEndpoint.java @@ -6,6 +6,7 @@ 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.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 RouterFunction endpoint() { .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 RouterFunction endpoint() { .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 RouterFunction endpoint() { .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 RouterFunction endpoint() { .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 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 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 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 listSnapshots(ServerRequest request) { + String name = request.pathVariable("name"); + var resultFlux = postService.listSnapshots(name); + return ServerResponse.ok().body(resultFlux, ListedSnapshotDto.class); + } + private Mono fetchReleaseContent(ServerRequest request) { final var name = request.pathVariable("name"); return postService.getReleaseContent(name) @@ -191,7 +296,7 @@ Mono draftPost(ServerRequest request) { Mono 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); diff --git a/application/src/main/java/run/halo/app/core/extension/endpoint/SinglePageEndpoint.java b/application/src/main/java/run/halo/app/core/extension/endpoint/SinglePageEndpoint.java index 86b9e0e945..abeb1da333 100644 --- a/application/src/main/java/run/halo/app/core/extension/endpoint/SinglePageEndpoint.java +++ b/application/src/main/java/run/halo/app/core/extension/endpoint/SinglePageEndpoint.java @@ -6,6 +6,7 @@ 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.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 RouterFunction endpoint() { .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 RouterFunction endpoint() { .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 RouterFunction endpoint() { .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 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 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 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 listSnapshots(ServerRequest request) { + final var name = request.pathVariable("name"); + var resultFlux = singlePageService.listSnapshots(name); + return ServerResponse.ok().body(resultFlux, ListedSnapshotDto.class); + } + private Mono fetchReleaseContent(ServerRequest request) { final var name = request.pathVariable("name"); return singlePageService.getReleaseContent(name) @@ -169,7 +273,7 @@ Mono draftSinglePage(ServerRequest request) { Mono 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); diff --git a/application/src/main/java/run/halo/app/endpoint/uc/content/UcPostEndpoint.java b/application/src/main/java/run/halo/app/endpoint/uc/content/UcPostEndpoint.java index 91a0eafa33..89f5e901ef 100644 --- a/application/src/main/java/run/halo/app/endpoint/uc/content/UcPostEndpoint.java +++ b/application/src/main/java/run/halo/app/endpoint/uc/content/UcPostEndpoint.java @@ -19,6 +19,7 @@ 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 @@ private Mono createMyPost(ServerRequest request) { } 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); } diff --git a/application/src/main/resources/extensions/role-template-post.yaml b/application/src/main/resources/extensions/role-template-post.yaml index bb442c66c3..9089d4e46a 100644 --- a/application/src/main/resources/extensions/role-template-post.yaml +++ b/application/src/main/resources/extensions/role-template-post.yaml @@ -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" ] diff --git a/application/src/main/resources/extensions/role-template-singlepage.yaml b/application/src/main/resources/extensions/role-template-singlepage.yaml index 140162e470..010c2e3c5d 100644 --- a/application/src/main/resources/extensions/role-template-singlepage.yaml +++ b/application/src/main/resources/extensions/role-template-singlepage.yaml @@ -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" ] diff --git a/application/src/test/java/run/halo/app/content/ContentRequestTest.java b/application/src/test/java/run/halo/app/content/ContentRequestTest.java index 1f786f87c8..3130735272 100644 --- a/application/src/test/java/run/halo/app/content/ContentRequestTest.java +++ b/application/src/test/java/run/halo/app/content/ContentRequestTest.java @@ -24,7 +24,7 @@ void setUp() { 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 diff --git a/application/src/test/java/run/halo/app/core/extension/endpoint/PostEndpointTest.java b/application/src/test/java/run/halo/app/core/extension/endpoint/PostEndpointTest.java index 23e6d6a44a..7933535bdc 100644 --- a/application/src/test/java/run/halo/app/core/extension/endpoint/PostEndpointTest.java +++ b/application/src/test/java/run/halo/app/core/extension/endpoint/PostEndpointTest.java @@ -18,7 +18,7 @@ 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 @@ void shouldFailIfWaitTimeoutForPublishedStatus() { } PostRequest postRequest(Post post) { - return new PostRequest(post, new Content("B", "

B

", "MARKDOWN")); + return new PostRequest(post, new ContentUpdateParam(null, "B", "

B

", "MARKDOWN")); } } \ No newline at end of file diff --git a/ui/console-src/modules/contents/pages/SinglePageEditor.vue b/ui/console-src/modules/contents/pages/SinglePageEditor.vue index 667e293bcf..e60911b78a 100644 --- a/ui/console-src/modules/contents/pages/SinglePageEditor.vue +++ b/ui/console-src/modules/contents/pages/SinglePageEditor.vue @@ -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" /> + + + {{ $t("core.page_editor.actions.snapshots") }} + +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("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, + } +); + + + diff --git a/ui/console-src/modules/contents/pages/components/SinglePageSettingModal.vue b/ui/console-src/modules/contents/pages/components/SinglePageSettingModal.vue index ff31097671..6eddc706ce 100644 --- a/ui/console-src/modules/contents/pages/components/SinglePageSettingModal.vue +++ b/ui/console-src/modules/contents/pages/components/SinglePageSettingModal.vue @@ -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(); diff --git a/ui/console-src/modules/contents/pages/components/SnapshotContent.vue b/ui/console-src/modules/contents/pages/components/SnapshotContent.vue new file mode 100644 index 0000000000..cae47283fd --- /dev/null +++ b/ui/console-src/modules/contents/pages/components/SnapshotContent.vue @@ -0,0 +1,113 @@ + + + + diff --git a/ui/console-src/modules/contents/pages/components/SnapshotListItem.vue b/ui/console-src/modules/contents/pages/components/SnapshotListItem.vue new file mode 100644 index 0000000000..d4ad9446bc --- /dev/null +++ b/ui/console-src/modules/contents/pages/components/SnapshotListItem.vue @@ -0,0 +1,137 @@ + + diff --git a/ui/console-src/modules/contents/pages/composables/use-page-update-mutate.ts b/ui/console-src/modules/contents/pages/composables/use-page-update-mutate.ts index 7aec27e3cb..92edb5b231 100644 --- a/ui/console-src/modules/contents/pages/composables/use-page-update-mutate.ts +++ b/ui/console-src/modules/contents/pages/composables/use-page-update-mutate.ts @@ -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")); }, }); diff --git a/ui/console-src/modules/contents/pages/module.ts b/ui/console-src/modules/contents/pages/module.ts index df2e4bc690..0638087a8f 100644 --- a/ui/console-src/modules/contents/pages/module.ts +++ b/ui/console-src/modules/contents/pages/module.ts @@ -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"], + }, + }, ], }, ], diff --git a/ui/console-src/modules/contents/posts/PostEditor.vue b/ui/console-src/modules/contents/posts/PostEditor.vue index 994447de76..669e273107 100644 --- a/ui/console-src/modules/contents/posts/PostEditor.vue +++ b/ui/console-src/modules/contents/posts/PostEditor.vue @@ -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" /> + + + {{ $t("core.post_editor.actions.snapshots") }} + +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("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, + } +); + + + diff --git a/ui/console-src/modules/contents/posts/components/SnapshotContent.vue b/ui/console-src/modules/contents/posts/components/SnapshotContent.vue new file mode 100644 index 0000000000..3c78c96e1d --- /dev/null +++ b/ui/console-src/modules/contents/posts/components/SnapshotContent.vue @@ -0,0 +1,113 @@ + + + + diff --git a/ui/console-src/modules/contents/posts/components/SnapshotListItem.vue b/ui/console-src/modules/contents/posts/components/SnapshotListItem.vue new file mode 100644 index 0000000000..4790d26465 --- /dev/null +++ b/ui/console-src/modules/contents/posts/components/SnapshotListItem.vue @@ -0,0 +1,135 @@ + + diff --git a/ui/console-src/modules/contents/posts/module.ts b/ui/console-src/modules/contents/posts/module.ts index c199669497..2b8dd997f0 100644 --- a/ui/console-src/modules/contents/posts/module.ts +++ b/ui/console-src/modules/contents/posts/module.ts @@ -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, diff --git a/ui/packages/api-client/src/.openapi-generator/FILES b/ui/packages/api-client/src/.openapi-generator/FILES index bb8c1cdc40..75f44ff38a 100644 --- a/ui/packages/api-client/src/.openapi-generator/FILES +++ b/ui/packages/api-client/src/.openapi-generator/FILES @@ -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 diff --git a/ui/packages/api-client/src/api/api-console-halo-run-v1alpha1-post-api.ts b/ui/packages/api-client/src/api/api-console-halo-run-v1alpha1-post-api.ts index b3572eecaf..c5e00c97f9 100644 --- a/ui/packages/api-client/src/api/api-console-halo-run-v1alpha1-post-api.ts +++ b/ui/packages/api-client/src/api/api-console-halo-run-v1alpha1-post-api.ts @@ -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 => { + // 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 => { + // 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 => { + // 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 => { + // 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> { + 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> { + 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>> { + 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> { + 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 { + 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 { 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 { + 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 { 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> { + 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 { 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 { + 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. diff --git a/ui/packages/api-client/src/api/api-console-halo-run-v1alpha1-single-page-api.ts b/ui/packages/api-client/src/api/api-console-halo-run-v1alpha1-single-page-api.ts index 9c52f01e3a..bc0b5c6fc1 100644 --- a/ui/packages/api-client/src/api/api-console-halo-run-v1alpha1-single-page-api.ts +++ b/ui/packages/api-client/src/api/api-console-halo-run-v1alpha1-single-page-api.ts @@ -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 => { + // 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 => { + // 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 => { + // 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 => { + // 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> { + 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> { + 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>> { + 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> { + 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 { + 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 { 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 { + 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 { 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> { + 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 { 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 { + 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. diff --git a/ui/packages/api-client/src/models/content-update-param.ts b/ui/packages/api-client/src/models/content-update-param.ts new file mode 100644 index 0000000000..ac8e03439e --- /dev/null +++ b/ui/packages/api-client/src/models/content-update-param.ts @@ -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; +} + diff --git a/ui/packages/api-client/src/models/index.ts b/ui/packages/api-client/src/models/index.ts index fb7893f6f1..d4734faee3 100644 --- a/ui/packages/api-client/src/models/index.ts +++ b/ui/packages/api-client/src/models/index.ts @@ -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'; diff --git a/ui/packages/api-client/src/models/listed-snapshot-dto.ts b/ui/packages/api-client/src/models/listed-snapshot-dto.ts new file mode 100644 index 0000000000..4efd6fd047 --- /dev/null +++ b/ui/packages/api-client/src/models/listed-snapshot-dto.ts @@ -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; +} + diff --git a/ui/packages/api-client/src/models/listed-snapshot-spec.ts b/ui/packages/api-client/src/models/listed-snapshot-spec.ts new file mode 100644 index 0000000000..69597e08dc --- /dev/null +++ b/ui/packages/api-client/src/models/listed-snapshot-spec.ts @@ -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; +} + diff --git a/ui/packages/api-client/src/models/post-request.ts b/ui/packages/api-client/src/models/post-request.ts index 5d144c0178..398cddde13 100644 --- a/ui/packages/api-client/src/models/post-request.ts +++ b/ui/packages/api-client/src/models/post-request.ts @@ -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} diff --git a/ui/packages/api-client/src/models/revert-snapshot-for-post-param.ts b/ui/packages/api-client/src/models/revert-snapshot-for-post-param.ts new file mode 100644 index 0000000000..61548debd6 --- /dev/null +++ b/ui/packages/api-client/src/models/revert-snapshot-for-post-param.ts @@ -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; +} + diff --git a/ui/packages/api-client/src/models/revert-snapshot-for-single-param.ts b/ui/packages/api-client/src/models/revert-snapshot-for-single-param.ts new file mode 100644 index 0000000000..ee95aed435 --- /dev/null +++ b/ui/packages/api-client/src/models/revert-snapshot-for-single-param.ts @@ -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; +} + diff --git a/ui/packages/api-client/src/models/single-page-request.ts b/ui/packages/api-client/src/models/single-page-request.ts index 91a618cd9c..227e8ea00b 100644 --- a/ui/packages/api-client/src/models/single-page-request.ts +++ b/ui/packages/api-client/src/models/single-page-request.ts @@ -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} diff --git a/ui/packages/components/src/icons/icons.ts b/ui/packages/components/src/icons/icons.ts index 0b93a33616..26ca5df919 100644 --- a/ui/packages/components/src/icons/icons.ts +++ b/ui/packages/components/src/icons/icons.ts @@ -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, }; diff --git a/ui/src/locales/en.yaml b/ui/src/locales/en.yaml index 0e2fdc367f..ccf946831a 100644 --- a/ui/src/locales/en.yaml +++ b/ui/src/locales/en.yaml @@ -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 diff --git a/ui/src/locales/zh-CN.yaml b/ui/src/locales/zh-CN.yaml index 2950c20eeb..340bf01ffe 100644 --- a/ui/src/locales/zh-CN.yaml +++ b/ui/src/locales/zh-CN.yaml @@ -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: 页面版本历史 diff --git a/ui/src/locales/zh-TW.yaml b/ui/src/locales/zh-TW.yaml index 3b8e3f17ba..28aadb3082 100644 --- a/ui/src/locales/zh-TW.yaml +++ b/ui/src/locales/zh-TW.yaml @@ -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: 頁面版本歷史