Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add the notification mechanism implementation #4527

Merged
merged 17 commits into from
Sep 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,16 @@
* @author guqing
* @since 2.0.0
*/
public interface CommentSubject<T extends Extension> extends ExtensionPoint {
public interface CommentSubject<T extends Extension> extends ExtensionPoint {

Mono<T> get(String name);

default Mono<SubjectDisplay> getSubjectDisplay(String name) {
return Mono.empty();
}

boolean supports(Ref ref);

record SubjectDisplay(String title, String url, String kindName) {
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package run.halo.app.core.extension.notification;

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.EqualsAndHashCode;
import run.halo.app.extension.AbstractExtension;
import run.halo.app.extension.GVK;

/**
* <p>{@link Notification} is a custom extension that used to store notification information for
* inner use, it's on-site notification.</p>
*
* <p>Supports the following operations:</p>
* <ul>
* <li>Marked as read: {@link NotificationSpec#setUnread(boolean)}</li>
* <li>Get the last read time: {@link NotificationSpec#getLastReadAt()}</li>
* <li>Filter by recipient: {@link NotificationSpec#getRecipient()}</li>
* </ul>
*
* @author guqing
* @see Reason
* @see ReasonType
* @since 2.10.0
*/
@Data
@EqualsAndHashCode(callSuper = true)
@GVK(group = "notification.halo.run", version = "v1alpha1", kind = "Notification", plural =
"notifications", singular = "notification")
public class Notification extends AbstractExtension {

@Schema
private NotificationSpec spec;

@Data
public static class NotificationSpec {
@Schema(requiredMode = REQUIRED, minLength = 1, description = "The name of user")
private String recipient;

@Schema(requiredMode = REQUIRED, minLength = 1, description = "The name of reason")
private String reason;

@Schema(requiredMode = REQUIRED, minLength = 1)
private String title;

@Schema(requiredMode = REQUIRED)
private String rawContent;

@Schema(requiredMode = REQUIRED)
private String htmlContent;

private boolean unread;

private Instant lastReadAt;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package run.halo.app.core.extension.notification;

import static io.swagger.v3.oas.annotations.media.Schema.RequiredMode.REQUIRED;

import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import run.halo.app.extension.AbstractExtension;
import run.halo.app.extension.GVK;

/**
* <p>{@link NotificationTemplate} is a custom extension that defines a notification template.</p>
* <p>It describes the notification template's name, description, and the template content.</p>
* <p>{@link Spec#getReasonSelector()} is used to select the template by reasonType and language,
* if multiple templates are matched, the best match will be selected. This is useful when you
* want to override the default template.</p>
*
* @author guqing
* @since 2.10.0
*/
@Data
@EqualsAndHashCode(callSuper = true)
@GVK(group = "notification.halo.run", version = "v1alpha1", kind = "NotificationTemplate",
plural = "notificationtemplates", singular = "notificationtemplate")
public class NotificationTemplate extends AbstractExtension {

@Schema
private Spec spec;

@Data
@Schema(name = "NotificationTemplateSpec")
public static class Spec {
@Schema
private ReasonSelector reasonSelector;

@Schema
private Template template;
}

@Data
@Schema(name = "TemplateContent")
public static class Template {
@Schema(requiredMode = REQUIRED, minLength = 1)
private String title;

private String htmlBody;

private String rawBody;
}

@Data
public static class ReasonSelector {
@Schema(requiredMode = REQUIRED, minLength = 1)
private String reasonType;

@Schema(requiredMode = REQUIRED, minLength = 1, defaultValue = "default")
private String language;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package run.halo.app.core.extension.notification;

import static io.swagger.v3.oas.annotations.media.Schema.RequiredMode.REQUIRED;

import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import run.halo.app.extension.AbstractExtension;
import run.halo.app.extension.GVK;

/**
* <p>{@link NotifierDescriptor} is a custom extension that defines a notifier.</p>
* <p>It describes the notifier's name, description, and the extension name of the notifier to
* let the user know what the notifier is and what it can do in the UI and also let the
* {@code NotificationCenter} know how to load the notifier and prepare the notifier's settings.</p>
*
* @author guqing
* @since 2.10.0
*/
@Data
@EqualsAndHashCode(callSuper = true)
@GVK(group = "notification.halo.run", version = "v1alpha1", kind = "NotifierDescriptor",
plural = "notifierDescriptors", singular = "notifierDescriptor")
public class NotifierDescriptor extends AbstractExtension {

@Schema
private Spec spec;

@Data
@Schema(name = "NotifierDescriptorSpec")
public static class Spec {
@Schema(requiredMode = REQUIRED, minLength = 1)
private String displayName;

private String description;

@Schema(requiredMode = REQUIRED, minLength = 1)
private String notifierExtName;

private SettingRef senderSettingRef;

private SettingRef receiverSettingRef;
}

@Data
@Schema(name = "NotifierSettingRef")
public static class SettingRef {
@Schema(requiredMode = REQUIRED)
private String name;

@Schema(requiredMode = REQUIRED)
private String group;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package run.halo.app.core.extension.notification;

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 lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import run.halo.app.extension.AbstractExtension;
import run.halo.app.extension.GVK;
import run.halo.app.notification.ReasonAttributes;

/**
* <p>{@link Reason} is a custom extension that defines a reason for a notification, It represents
* an instance of a {@link ReasonType}.</p>
* <p>It can be understood as an event that triggers a notification.</p>
*
* @author guqing
* @since 2.10.0
*/
@Data
@EqualsAndHashCode(callSuper = true)
@GVK(group = "notification.halo.run", version = "v1alpha1", kind = "Reason", plural =
"reasons", singular = "reason")
public class Reason extends AbstractExtension {

@Schema
private Spec spec;

@Data
@Schema(name = "ReasonSpec")
public static class Spec {
@Schema(requiredMode = REQUIRED)
private String reasonType;

@Schema(requiredMode = REQUIRED)
private Subject subject;

@Schema(requiredMode = REQUIRED)
private String author;

@Schema(implementation = ReasonAttributes.class, requiredMode = NOT_REQUIRED,
description = "Attributes used to transfer data")
private ReasonAttributes attributes;
}

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Schema(name = "ReasonSubject")
public static class Subject {
@Schema(requiredMode = REQUIRED)
private String apiVersion;

@Schema(requiredMode = REQUIRED)
private String kind;

@Schema(requiredMode = REQUIRED)
private String name;

@Schema(requiredMode = REQUIRED)
private String title;

private String url;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package run.halo.app.core.extension.notification;

import static io.swagger.v3.oas.annotations.media.Schema.RequiredMode.REQUIRED;

import io.swagger.v3.oas.annotations.media.Schema;
import java.util.List;
import lombok.Data;
import lombok.EqualsAndHashCode;
import run.halo.app.extension.AbstractExtension;
import run.halo.app.extension.GVK;

/**
* <p>{@link ReasonType} is a custom extension that defines a type of reason.</p>
* <p>One {@link ReasonType} can have multiple {@link Reason}s to notify.</p>
*
* @author guqing
* @see NotificationTemplate
* @see Reason
* @since 2.10.0
*/
@Data
@EqualsAndHashCode(callSuper = true)
@GVK(group = "notification.halo.run", version = "v1alpha1", kind = "ReasonType",
plural = "reasontypes", singular = "reasontype")
public class ReasonType extends AbstractExtension {
public static final String LOCALIZED_RESOURCE_NAME_ANNO =
"notification.halo.run/localized-resource-name";

@Schema
private Spec spec;

@Data
@Schema(name = "ReasonTypeSpec")
public static class Spec {

@Schema(requiredMode = REQUIRED, minLength = 1)
private String displayName;

@Schema(requiredMode = REQUIRED, minLength = 1)
private String description;

private List<ReasonProperty> properties;
}

@Data
public static class ReasonProperty {
@Schema(requiredMode = REQUIRED, minLength = 1)
private String name;

@Schema(requiredMode = REQUIRED, minLength = 1)
private String type;

private String description;

@Schema(defaultValue = "false")
private boolean optional;
}
}
Loading