refactor(models): update data models and remove deprecated IM entities
- Update channel, notification, PR, repo, user, workspace models - Remove deleted IM models: articles, channel follows, message attachments/bookmarks/drafts/edit history/embeds/mentions/pins/ polls/reactions/threads, saved messages, thread read states - Add new PR models: review requests, templates - Add repo release assets model - Add base_info module for API detail responses
This commit is contained in:
@@ -0,0 +1,330 @@
|
||||
//! BaseInfo structs — stable, minimal projections of core entities for API/WS responses.
|
||||
//!
|
||||
//! Every raw UUID foreign key in API / WebSocket responses must be expanded
|
||||
//! to its corresponding `*BaseInfo` object so frontend consumers never
|
||||
//! receive bare identifiers.
|
||||
//!
|
||||
//! Batch resolvers are provided to avoid N+1 queries when enriching
|
||||
//! collections of entities.
|
||||
|
||||
use std::collections::HashMap;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::error::AppError;
|
||||
use crate::models::common::{ChannelType, State, Visibility};
|
||||
use crate::models::db::AppDatabase;
|
||||
|
||||
// Section: BaseInfo structs
|
||||
|
||||
#[derive(Debug, Clone, Default, Serialize, Deserialize, utoipa::ToSchema)]
|
||||
pub struct UserBaseInfo {
|
||||
pub id: Uuid,
|
||||
pub username: String,
|
||||
pub display_name: Option<String>,
|
||||
pub avatar_url: Option<String>,
|
||||
pub is_bot: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Default, Serialize, Deserialize, utoipa::ToSchema)]
|
||||
pub struct WorkspaceBaseInfo {
|
||||
pub id: Uuid,
|
||||
pub name: String,
|
||||
pub avatar_url: Option<String>,
|
||||
pub visibility: Visibility,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, utoipa::ToSchema)]
|
||||
pub struct RepoBaseInfo {
|
||||
pub id: Uuid,
|
||||
pub name: String,
|
||||
pub workspace_id: Uuid,
|
||||
pub visibility: Visibility,
|
||||
pub is_fork: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, utoipa::ToSchema)]
|
||||
pub struct ChannelBaseInfo {
|
||||
pub id: Uuid,
|
||||
pub name: String,
|
||||
pub channel_type: ChannelType,
|
||||
pub workspace_id: Uuid,
|
||||
pub archived: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, utoipa::ToSchema)]
|
||||
pub struct IssueBaseInfo {
|
||||
pub id: Uuid,
|
||||
pub number: i64,
|
||||
pub title: String,
|
||||
pub state: State,
|
||||
pub workspace_id: Uuid,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, utoipa::ToSchema)]
|
||||
pub struct PullRequestBaseInfo {
|
||||
pub id: Uuid,
|
||||
pub number: i64,
|
||||
pub title: String,
|
||||
pub state: State,
|
||||
pub repo_id: Uuid,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, utoipa::ToSchema)]
|
||||
pub struct WikiPageBaseInfo {
|
||||
pub id: Uuid,
|
||||
pub title: String,
|
||||
pub slug: String,
|
||||
pub repo_id: Uuid,
|
||||
}
|
||||
|
||||
// Section: DB row structs for batch queries
|
||||
|
||||
#[derive(Debug, sqlx::FromRow)]
|
||||
struct UserBaseInfoRow {
|
||||
id: Uuid,
|
||||
username: String,
|
||||
display_name: Option<String>,
|
||||
avatar_url: Option<String>,
|
||||
is_bot: bool,
|
||||
}
|
||||
|
||||
impl From<UserBaseInfoRow> for UserBaseInfo {
|
||||
fn from(r: UserBaseInfoRow) -> Self {
|
||||
UserBaseInfo {
|
||||
id: r.id,
|
||||
username: r.username,
|
||||
display_name: r.display_name,
|
||||
avatar_url: r.avatar_url,
|
||||
is_bot: r.is_bot,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, sqlx::FromRow)]
|
||||
struct WorkspaceBaseInfoRow {
|
||||
id: Uuid,
|
||||
name: String,
|
||||
avatar_url: Option<String>,
|
||||
visibility: Visibility,
|
||||
}
|
||||
|
||||
impl From<WorkspaceBaseInfoRow> for WorkspaceBaseInfo {
|
||||
fn from(r: WorkspaceBaseInfoRow) -> Self {
|
||||
WorkspaceBaseInfo {
|
||||
id: r.id,
|
||||
name: r.name,
|
||||
avatar_url: r.avatar_url,
|
||||
visibility: r.visibility,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, sqlx::FromRow)]
|
||||
struct RepoBaseInfoRow {
|
||||
id: Uuid,
|
||||
name: String,
|
||||
workspace_id: Uuid,
|
||||
visibility: Visibility,
|
||||
is_fork: bool,
|
||||
}
|
||||
|
||||
impl From<RepoBaseInfoRow> for RepoBaseInfo {
|
||||
fn from(r: RepoBaseInfoRow) -> Self {
|
||||
RepoBaseInfo {
|
||||
id: r.id,
|
||||
name: r.name,
|
||||
workspace_id: r.workspace_id,
|
||||
visibility: r.visibility,
|
||||
is_fork: r.is_fork,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, sqlx::FromRow)]
|
||||
struct ChannelBaseInfoRow {
|
||||
id: Uuid,
|
||||
name: String,
|
||||
channel_type: ChannelType,
|
||||
workspace_id: Uuid,
|
||||
archived: bool,
|
||||
}
|
||||
|
||||
impl From<ChannelBaseInfoRow> for ChannelBaseInfo {
|
||||
fn from(r: ChannelBaseInfoRow) -> Self {
|
||||
ChannelBaseInfo {
|
||||
id: r.id,
|
||||
name: r.name,
|
||||
channel_type: r.channel_type,
|
||||
workspace_id: r.workspace_id,
|
||||
archived: r.archived,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, sqlx::FromRow)]
|
||||
struct IssueBaseInfoRow {
|
||||
id: Uuid,
|
||||
number: i64,
|
||||
title: String,
|
||||
state: State,
|
||||
workspace_id: Uuid,
|
||||
}
|
||||
|
||||
impl From<IssueBaseInfoRow> for IssueBaseInfo {
|
||||
fn from(r: IssueBaseInfoRow) -> Self {
|
||||
IssueBaseInfo {
|
||||
id: r.id,
|
||||
number: r.number,
|
||||
title: r.title,
|
||||
state: r.state,
|
||||
workspace_id: r.workspace_id,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, sqlx::FromRow)]
|
||||
struct PullRequestBaseInfoRow {
|
||||
id: Uuid,
|
||||
number: i64,
|
||||
title: String,
|
||||
state: State,
|
||||
repo_id: Uuid,
|
||||
}
|
||||
|
||||
impl From<PullRequestBaseInfoRow> for PullRequestBaseInfo {
|
||||
fn from(r: PullRequestBaseInfoRow) -> Self {
|
||||
PullRequestBaseInfo {
|
||||
id: r.id,
|
||||
number: r.number,
|
||||
title: r.title,
|
||||
state: r.state,
|
||||
repo_id: r.repo_id,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl UserBaseInfo {
|
||||
pub fn placeholder(id: Uuid) -> Self {
|
||||
Self {
|
||||
id,
|
||||
username: "unknown".into(),
|
||||
display_name: Some("Unknown User".into()),
|
||||
avatar_url: None,
|
||||
is_bot: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Section: Batch resolvers
|
||||
|
||||
/// Resolve multiple users to `UserBaseInfo`. Always do a single
|
||||
/// `SELECT … WHERE id = ANY($1)` to avoid N+1.
|
||||
pub async fn resolve_users(
|
||||
db: &AppDatabase,
|
||||
ids: &[Uuid],
|
||||
) -> Result<HashMap<Uuid, UserBaseInfo>, AppError> {
|
||||
if ids.is_empty() {
|
||||
return Ok(HashMap::new());
|
||||
}
|
||||
let rows = sqlx::query_as::<_, UserBaseInfoRow>(
|
||||
r#"SELECT id, username, display_name, avatar_url, is_bot
|
||||
FROM "user" WHERE id = ANY($1) AND deleted_at IS NULL"#,
|
||||
)
|
||||
.bind(ids)
|
||||
.fetch_all(db.reader())
|
||||
.await
|
||||
.map_err(AppError::Database)?;
|
||||
Ok(rows.into_iter().map(|r| (r.id, r.into())).collect())
|
||||
}
|
||||
|
||||
/// Resolve multiple workspaces to `WorkspaceBaseInfo`.
|
||||
pub async fn resolve_workspaces(
|
||||
db: &AppDatabase,
|
||||
ids: &[Uuid],
|
||||
) -> Result<HashMap<Uuid, WorkspaceBaseInfo>, AppError> {
|
||||
if ids.is_empty() {
|
||||
return Ok(HashMap::new());
|
||||
}
|
||||
let rows = sqlx::query_as::<_, WorkspaceBaseInfoRow>(
|
||||
"SELECT id, name, avatar_url, visibility FROM workspace WHERE id = ANY($1) AND deleted_at IS NULL",
|
||||
)
|
||||
.bind(ids)
|
||||
.fetch_all(db.reader())
|
||||
.await
|
||||
.map_err(AppError::Database)?;
|
||||
Ok(rows.into_iter().map(|r| (r.id, r.into())).collect())
|
||||
}
|
||||
|
||||
/// Resolve multiple repos to `RepoBaseInfo`.
|
||||
pub async fn resolve_repos(
|
||||
db: &AppDatabase,
|
||||
ids: &[Uuid],
|
||||
) -> Result<HashMap<Uuid, RepoBaseInfo>, AppError> {
|
||||
if ids.is_empty() {
|
||||
return Ok(HashMap::new());
|
||||
}
|
||||
let rows = sqlx::query_as::<_, RepoBaseInfoRow>(
|
||||
"SELECT id, name, workspace_id, visibility, is_fork FROM repo WHERE id = ANY($1) AND deleted_at IS NULL",
|
||||
)
|
||||
.bind(ids)
|
||||
.fetch_all(db.reader())
|
||||
.await
|
||||
.map_err(AppError::Database)?;
|
||||
Ok(rows.into_iter().map(|r| (r.id, r.into())).collect())
|
||||
}
|
||||
|
||||
/// Resolve multiple channels to `ChannelBaseInfo`.
|
||||
pub async fn resolve_channels(
|
||||
db: &AppDatabase,
|
||||
ids: &[Uuid],
|
||||
) -> Result<HashMap<Uuid, ChannelBaseInfo>, AppError> {
|
||||
if ids.is_empty() {
|
||||
return Ok(HashMap::new());
|
||||
}
|
||||
let rows = sqlx::query_as::<_, ChannelBaseInfoRow>(
|
||||
"SELECT id, name, channel_type, workspace_id, archived FROM channel WHERE id = ANY($1) AND deleted_at IS NULL",
|
||||
)
|
||||
.bind(ids)
|
||||
.fetch_all(db.reader())
|
||||
.await
|
||||
.map_err(AppError::Database)?;
|
||||
Ok(rows.into_iter().map(|r| (r.id, r.into())).collect())
|
||||
}
|
||||
|
||||
/// Resolve multiple issues to `IssueBaseInfo`.
|
||||
pub async fn resolve_issues(
|
||||
db: &AppDatabase,
|
||||
ids: &[Uuid],
|
||||
) -> Result<HashMap<Uuid, IssueBaseInfo>, AppError> {
|
||||
if ids.is_empty() {
|
||||
return Ok(HashMap::new());
|
||||
}
|
||||
let rows = sqlx::query_as::<_, IssueBaseInfoRow>(
|
||||
"SELECT id, number, title, state, workspace_id FROM issue WHERE id = ANY($1) AND deleted_at IS NULL",
|
||||
)
|
||||
.bind(ids)
|
||||
.fetch_all(db.reader())
|
||||
.await
|
||||
.map_err(AppError::Database)?;
|
||||
Ok(rows.into_iter().map(|r| (r.id, r.into())).collect())
|
||||
}
|
||||
|
||||
/// Resolve multiple pull requests to `PullRequestBaseInfo`.
|
||||
pub async fn resolve_pull_requests(
|
||||
db: &AppDatabase,
|
||||
ids: &[Uuid],
|
||||
) -> Result<HashMap<Uuid, PullRequestBaseInfo>, AppError> {
|
||||
if ids.is_empty() {
|
||||
return Ok(HashMap::new());
|
||||
}
|
||||
let rows = sqlx::query_as::<_, PullRequestBaseInfoRow>(
|
||||
"SELECT id, number, title, state, repo_id FROM pull_request WHERE id = ANY($1) AND deleted_at IS NULL",
|
||||
)
|
||||
.bind(ids)
|
||||
.fetch_all(db.reader())
|
||||
.await
|
||||
.map_err(AppError::Database)?;
|
||||
Ok(rows.into_iter().map(|r| (r.id, r.into())).collect())
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
use chrono::{DateTime, Utc};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use uuid::Uuid;
|
||||
|
||||
/// Discussion comment on an article (similar to blog comments).
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, sqlx::FromRow)]
|
||||
pub struct ArticleComment {
|
||||
pub id: Uuid,
|
||||
pub article_id: Uuid,
|
||||
pub channel_id: Uuid,
|
||||
pub author_id: Uuid,
|
||||
pub parent_comment_id: Option<Uuid>,
|
||||
pub body: String,
|
||||
pub edited_at: Option<DateTime<Utc>>,
|
||||
pub deleted_at: Option<DateTime<Utc>>,
|
||||
pub created_at: DateTime<Utc>,
|
||||
pub updated_at: DateTime<Utc>,
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
use crate::models::common::Status;
|
||||
use chrono::{DateTime, Utc};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use uuid::Uuid;
|
||||
|
||||
/// Tracks a single cross-post delivery when an article is published
|
||||
/// to a follower channel/workspace.
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, sqlx::FromRow)]
|
||||
pub struct ArticleCrossPost {
|
||||
pub id: Uuid,
|
||||
pub article_id: Uuid,
|
||||
pub follow_id: Uuid,
|
||||
pub target_workspace_id: Uuid,
|
||||
pub target_channel_id: Option<Uuid>,
|
||||
pub status: Status,
|
||||
pub attempts: i32,
|
||||
pub last_error: Option<String>,
|
||||
pub sent_at: Option<DateTime<Utc>>,
|
||||
pub delivered_at: Option<DateTime<Utc>>,
|
||||
pub failed_at: Option<DateTime<Utc>>,
|
||||
pub created_at: DateTime<Utc>,
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
use chrono::{DateTime, Utc};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use uuid::Uuid;
|
||||
|
||||
/// Reaction on an article (emoji reactions, separate from message reactions).
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, sqlx::FromRow)]
|
||||
pub struct ArticleReaction {
|
||||
pub id: Uuid,
|
||||
pub article_id: Uuid,
|
||||
pub channel_id: Uuid,
|
||||
pub user_id: Uuid,
|
||||
pub content: String,
|
||||
pub created_at: DateTime<Utc>,
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
use crate::models::common::{ArticleStatus, JsonValue, Visibility};
|
||||
use chrono::{DateTime, Utc};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use uuid::Uuid;
|
||||
|
||||
/// Long-form article for announcement/news channels.
|
||||
/// Unlike a plain Message, an article has a title, cover image,
|
||||
/// publish lifecycle, and can be cross-posted to followers.
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, sqlx::FromRow)]
|
||||
pub struct Article {
|
||||
pub id: Uuid,
|
||||
pub channel_id: Uuid,
|
||||
pub author_id: Uuid,
|
||||
pub title: String,
|
||||
pub slug: String,
|
||||
pub summary: Option<String>,
|
||||
pub body: String,
|
||||
pub cover_image_url: Option<String>,
|
||||
pub status: ArticleStatus,
|
||||
pub visibility: Visibility,
|
||||
pub tags: Vec<String>,
|
||||
pub published_at: Option<DateTime<Utc>>,
|
||||
pub published_by: Option<Uuid>,
|
||||
pub scheduled_at: Option<DateTime<Utc>>,
|
||||
pub unpublished_at: Option<DateTime<Utc>>,
|
||||
pub views_count: i64,
|
||||
pub comments_count: i64,
|
||||
pub reactions_count: i64,
|
||||
pub cross_posted: bool,
|
||||
pub cross_posted_from: Option<Uuid>,
|
||||
pub metadata: Option<JsonValue>,
|
||||
pub created_at: DateTime<Utc>,
|
||||
pub updated_at: DateTime<Utc>,
|
||||
pub deleted_at: Option<DateTime<Utc>>,
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
use crate::models::base_info::UserBaseInfo;
|
||||
use crate::models::common::{
|
||||
ChannelKind, ChannelType, ForumLayout, ForumSortOrder, JsonValue, Visibility,
|
||||
};
|
||||
@@ -5,7 +6,7 @@ use chrono::{DateTime, Utc};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use uuid::Uuid;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, sqlx::FromRow)]
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, sqlx::FromRow, utoipa::ToSchema)]
|
||||
pub struct Channel {
|
||||
pub id: Uuid,
|
||||
pub workspace_id: Uuid,
|
||||
@@ -41,3 +42,64 @@ pub struct Channel {
|
||||
pub updated_at: DateTime<Utc>,
|
||||
pub deleted_at: Option<DateTime<Utc>>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, utoipa::ToSchema)]
|
||||
pub struct ChannelDetail {
|
||||
pub id: Uuid,
|
||||
pub workspace_id: Uuid,
|
||||
pub repo_id: Option<Uuid>,
|
||||
pub category_id: Option<Uuid>,
|
||||
pub creator: UserBaseInfo,
|
||||
pub name: String,
|
||||
pub topic: Option<String>,
|
||||
pub description: Option<String>,
|
||||
pub channel_type: ChannelType,
|
||||
pub channel_kind: ChannelKind,
|
||||
pub visibility: Visibility,
|
||||
pub position: Option<i32>,
|
||||
pub nsfw: bool,
|
||||
pub archived: bool,
|
||||
pub read_only: bool,
|
||||
pub bitrate: Option<i32>,
|
||||
pub user_limit: Option<i32>,
|
||||
pub rtc_region: Option<String>,
|
||||
pub parent_channel_id: Option<Uuid>,
|
||||
pub last_message_id: Option<Uuid>,
|
||||
pub last_message_at: Option<DateTime<Utc>>,
|
||||
pub archived_at: Option<DateTime<Utc>>,
|
||||
pub created_at: DateTime<Utc>,
|
||||
pub updated_at: DateTime<Utc>,
|
||||
pub deleted_at: Option<DateTime<Utc>>,
|
||||
}
|
||||
|
||||
impl Channel {
|
||||
pub fn into_detail(self, creator: UserBaseInfo) -> ChannelDetail {
|
||||
ChannelDetail {
|
||||
id: self.id,
|
||||
workspace_id: self.workspace_id,
|
||||
repo_id: self.repo_id,
|
||||
category_id: self.category_id,
|
||||
creator,
|
||||
name: self.name,
|
||||
topic: self.topic,
|
||||
description: self.description,
|
||||
channel_type: self.channel_type,
|
||||
channel_kind: self.channel_kind,
|
||||
visibility: self.visibility,
|
||||
position: self.position,
|
||||
nsfw: self.nsfw,
|
||||
archived: self.archived,
|
||||
read_only: self.read_only,
|
||||
bitrate: self.bitrate,
|
||||
user_limit: self.user_limit,
|
||||
rtc_region: self.rtc_region,
|
||||
parent_channel_id: self.parent_channel_id,
|
||||
last_message_id: self.last_message_id,
|
||||
last_message_at: self.last_message_at,
|
||||
archived_at: self.archived_at,
|
||||
created_at: self.created_at,
|
||||
updated_at: self.updated_at,
|
||||
deleted_at: self.deleted_at,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ use chrono::{DateTime, Utc};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use uuid::Uuid;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, sqlx::FromRow)]
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, sqlx::FromRow, utoipa::ToSchema)]
|
||||
pub struct ChannelCategory {
|
||||
pub id: Uuid,
|
||||
pub workspace_id: Uuid,
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
use chrono::{DateTime, Utc};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use uuid::Uuid;
|
||||
|
||||
/// Follow relationship on an announcement channel.
|
||||
/// Allows another workspace or channel to receive cross-posts
|
||||
/// when articles are published.
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, sqlx::FromRow)]
|
||||
pub struct ChannelFollow {
|
||||
pub id: Uuid,
|
||||
pub source_channel_id: Uuid,
|
||||
pub target_workspace_id: Uuid,
|
||||
pub target_channel_id: Option<Uuid>,
|
||||
pub webhook_url: Option<String>,
|
||||
pub webhook_secret_ciphertext: Option<String>,
|
||||
pub enabled: bool,
|
||||
pub followed_by: Uuid,
|
||||
pub unfollowed_at: Option<DateTime<Utc>>,
|
||||
pub last_delivery_at: Option<DateTime<Utc>>,
|
||||
pub last_delivery_status: Option<String>,
|
||||
pub created_at: DateTime<Utc>,
|
||||
pub updated_at: DateTime<Utc>,
|
||||
}
|
||||
@@ -3,7 +3,7 @@ use chrono::{DateTime, Utc};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use uuid::Uuid;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, sqlx::FromRow)]
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, sqlx::FromRow, utoipa::ToSchema)]
|
||||
pub struct ChannelMember {
|
||||
pub id: Uuid,
|
||||
pub channel_id: Uuid,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use crate::models::common::{OverwriteTarget, Permission};
|
||||
use crate::models::common::OverwriteTarget;
|
||||
use chrono::{DateTime, Utc};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use uuid::Uuid;
|
||||
@@ -9,8 +9,8 @@ pub struct ChannelPermissionOverwrite {
|
||||
pub channel_id: Uuid,
|
||||
pub target_type: OverwriteTarget,
|
||||
pub target_id: Uuid,
|
||||
pub allow: Vec<Permission>,
|
||||
pub deny: Vec<Permission>,
|
||||
pub allow: Vec<String>,
|
||||
pub deny: Vec<String>,
|
||||
pub created_by: Uuid,
|
||||
pub created_at: DateTime<Utc>,
|
||||
pub updated_at: DateTime<Utc>,
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
use crate::models::common::{JsonValue, MessageType};
|
||||
use chrono::{DateTime, Utc};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use uuid::Uuid;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, sqlx::FromRow)]
|
||||
pub struct Message {
|
||||
pub id: Uuid,
|
||||
pub channel_id: Uuid,
|
||||
pub author_id: Uuid,
|
||||
pub thread_id: Option<Uuid>,
|
||||
pub reply_to_message_id: Option<Uuid>,
|
||||
pub seq: i64,
|
||||
pub message_type: MessageType,
|
||||
pub body: String,
|
||||
pub metadata: Option<JsonValue>,
|
||||
pub pinned: bool,
|
||||
pub system: bool,
|
||||
pub edited_at: Option<DateTime<Utc>>,
|
||||
pub deleted_at: Option<DateTime<Utc>>,
|
||||
pub created_at: DateTime<Utc>,
|
||||
pub updated_at: DateTime<Utc>,
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
use chrono::{DateTime, Utc};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use uuid::Uuid;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, sqlx::FromRow)]
|
||||
pub struct MessageAttachment {
|
||||
pub id: Uuid,
|
||||
pub message_id: Uuid,
|
||||
pub channel_id: Uuid,
|
||||
pub filename: String,
|
||||
pub url: String,
|
||||
pub proxy_url: Option<String>,
|
||||
pub size_bytes: i64,
|
||||
pub mime_type: String,
|
||||
pub width: Option<i32>,
|
||||
pub height: Option<i32>,
|
||||
pub duration_ms: Option<i64>,
|
||||
pub thumbnail_url: Option<String>,
|
||||
pub blurhash: Option<String>,
|
||||
pub created_at: DateTime<Utc>,
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
use chrono::{DateTime, Utc};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use uuid::Uuid;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, sqlx::FromRow)]
|
||||
pub struct MessageBookmark {
|
||||
pub id: Uuid,
|
||||
pub message_id: Uuid,
|
||||
pub channel_id: Uuid,
|
||||
pub user_id: Uuid,
|
||||
pub note: Option<String>,
|
||||
pub created_at: DateTime<Utc>,
|
||||
pub updated_at: DateTime<Utc>,
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
use crate::models::common::JsonValue;
|
||||
use chrono::{DateTime, Utc};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use uuid::Uuid;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, sqlx::FromRow)]
|
||||
pub struct MessageDraft {
|
||||
pub id: Uuid,
|
||||
pub user_id: Uuid,
|
||||
pub channel_id: Uuid,
|
||||
pub thread_id: Option<Uuid>,
|
||||
pub reply_to_message_id: Option<Uuid>,
|
||||
pub content: String,
|
||||
pub attachments: Option<JsonValue>,
|
||||
pub created_at: DateTime<Utc>,
|
||||
pub updated_at: DateTime<Utc>,
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
use chrono::{DateTime, Utc};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use uuid::Uuid;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, sqlx::FromRow)]
|
||||
pub struct MessageEditHistory {
|
||||
pub id: Uuid,
|
||||
pub message_id: Uuid,
|
||||
pub channel_id: Uuid,
|
||||
pub previous_body: String,
|
||||
pub edited_by: Uuid,
|
||||
pub edited_at: DateTime<Utc>,
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
use crate::models::common::{EmbedType, JsonValue};
|
||||
use chrono::{DateTime, Utc};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use uuid::Uuid;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, sqlx::FromRow)]
|
||||
pub struct MessageEmbed {
|
||||
pub id: Uuid,
|
||||
pub message_id: Uuid,
|
||||
pub embed_type: EmbedType,
|
||||
pub title: Option<String>,
|
||||
pub description: Option<String>,
|
||||
pub url: Option<String>,
|
||||
pub author_name: Option<String>,
|
||||
pub author_url: Option<String>,
|
||||
pub author_icon_url: Option<String>,
|
||||
pub thumbnail_url: Option<String>,
|
||||
pub thumbnail_width: Option<i32>,
|
||||
pub thumbnail_height: Option<i32>,
|
||||
pub image_url: Option<String>,
|
||||
pub image_width: Option<i32>,
|
||||
pub image_height: Option<i32>,
|
||||
pub video_url: Option<String>,
|
||||
pub video_width: Option<i32>,
|
||||
pub video_height: Option<i32>,
|
||||
pub color: Option<i32>,
|
||||
pub fields: Option<JsonValue>,
|
||||
pub footer_text: Option<String>,
|
||||
pub footer_icon_url: Option<String>,
|
||||
pub provider_name: Option<String>,
|
||||
pub provider_url: Option<String>,
|
||||
pub timestamp: Option<DateTime<Utc>>,
|
||||
pub created_at: DateTime<Utc>,
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
use chrono::{DateTime, Utc};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use uuid::Uuid;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, sqlx::FromRow)]
|
||||
pub struct MessageMention {
|
||||
pub id: Uuid,
|
||||
pub message_id: Uuid,
|
||||
pub channel_id: Uuid,
|
||||
pub mentioned_user_id: Uuid,
|
||||
pub mentioned_by: Uuid,
|
||||
pub read_at: Option<DateTime<Utc>>,
|
||||
pub created_at: DateTime<Utc>,
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
use chrono::{DateTime, Utc};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use uuid::Uuid;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, sqlx::FromRow)]
|
||||
pub struct MessagePin {
|
||||
pub id: Uuid,
|
||||
pub message_id: Uuid,
|
||||
pub channel_id: Uuid,
|
||||
pub pinned_by: Uuid,
|
||||
pub pinned_at: DateTime<Utc>,
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
use chrono::{DateTime, Utc};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use uuid::Uuid;
|
||||
|
||||
/// Poll option.
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, sqlx::FromRow)]
|
||||
pub struct MessagePollOption {
|
||||
pub id: Uuid,
|
||||
pub poll_id: Uuid,
|
||||
pub position: i32,
|
||||
pub text: String,
|
||||
pub emoji_id: Option<String>,
|
||||
pub emoji_name: Option<String>,
|
||||
pub vote_count: i64,
|
||||
pub created_at: DateTime<Utc>,
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
use chrono::{DateTime, Utc};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use uuid::Uuid;
|
||||
|
||||
/// User vote record for a poll option.
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, sqlx::FromRow)]
|
||||
pub struct MessagePollVote {
|
||||
pub id: Uuid,
|
||||
pub poll_id: Uuid,
|
||||
pub option_id: Uuid,
|
||||
pub user_id: Uuid,
|
||||
pub voted_at: DateTime<Utc>,
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
use crate::models::common::{JsonValue, PollLayout};
|
||||
use chrono::{DateTime, Utc};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use uuid::Uuid;
|
||||
|
||||
/// Message poll (similar to Discord Polls).
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, sqlx::FromRow)]
|
||||
pub struct MessagePoll {
|
||||
pub id: Uuid,
|
||||
pub message_id: Uuid,
|
||||
pub channel_id: Uuid,
|
||||
pub question: String,
|
||||
pub description: Option<String>,
|
||||
pub layout: PollLayout,
|
||||
pub allow_multiselect: bool,
|
||||
pub duration_hours: Option<i32>,
|
||||
pub ends_at: Option<DateTime<Utc>>,
|
||||
pub total_votes: i64,
|
||||
pub metadata: Option<JsonValue>,
|
||||
pub created_at: DateTime<Utc>,
|
||||
pub updated_at: DateTime<Utc>,
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
use chrono::{DateTime, Utc};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use uuid::Uuid;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, sqlx::FromRow)]
|
||||
pub struct MessageReaction {
|
||||
pub id: Uuid,
|
||||
pub message_id: Uuid,
|
||||
pub channel_id: Uuid,
|
||||
pub user_id: Uuid,
|
||||
pub content: String,
|
||||
pub created_at: DateTime<Utc>,
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
use chrono::{DateTime, Utc};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use uuid::Uuid;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, sqlx::FromRow)]
|
||||
pub struct MessageThread {
|
||||
pub id: Uuid,
|
||||
pub channel_id: Uuid,
|
||||
pub root_message_id: Uuid,
|
||||
pub created_by: Uuid,
|
||||
pub replies_count: i64,
|
||||
pub participants_count: i64,
|
||||
pub last_reply_message_id: Option<Uuid>,
|
||||
pub last_reply_at: Option<DateTime<Utc>>,
|
||||
pub resolved: bool,
|
||||
pub resolved_by: Option<Uuid>,
|
||||
pub resolved_at: Option<DateTime<Utc>>,
|
||||
// ── Forum post specific ──
|
||||
pub title: Option<String>,
|
||||
pub tags: Vec<String>,
|
||||
pub pinned: bool,
|
||||
pub locked: bool,
|
||||
pub rate_limit_per_user: Option<i32>,
|
||||
pub auto_archive_at: Option<DateTime<Utc>>,
|
||||
pub created_at: DateTime<Utc>,
|
||||
pub updated_at: DateTime<Utc>,
|
||||
}
|
||||
+1
-41
@@ -1,11 +1,6 @@
|
||||
pub mod article_comments;
|
||||
pub mod article_cross_posts;
|
||||
pub mod article_reactions;
|
||||
pub mod articles;
|
||||
pub mod channel;
|
||||
pub mod channel_categories;
|
||||
pub mod channel_events;
|
||||
pub mod channel_follows;
|
||||
pub mod channel_invitations;
|
||||
pub mod channel_member_roles;
|
||||
pub mod channel_members;
|
||||
@@ -17,32 +12,12 @@ pub mod channel_webhooks;
|
||||
pub mod custom_emojis;
|
||||
pub mod forum_tags;
|
||||
pub mod im_integrations;
|
||||
pub mod message;
|
||||
pub mod message_attachments;
|
||||
pub mod message_bookmarks;
|
||||
pub mod message_drafts;
|
||||
pub mod message_edit_history;
|
||||
pub mod message_embeds;
|
||||
pub mod message_mentions;
|
||||
pub mod message_pins;
|
||||
pub mod message_poll_options;
|
||||
pub mod message_poll_votes;
|
||||
pub mod message_polls;
|
||||
pub mod message_reactions;
|
||||
pub mod message_threads;
|
||||
pub mod saved_messages;
|
||||
pub mod stages;
|
||||
pub mod thread_read_states;
|
||||
pub mod voice_participants;
|
||||
|
||||
pub use article_comments::ArticleComment;
|
||||
pub use article_cross_posts::ArticleCrossPost;
|
||||
pub use article_reactions::ArticleReaction;
|
||||
pub use articles::Article;
|
||||
pub use channel::Channel;
|
||||
pub use channel::{Channel, ChannelDetail};
|
||||
pub use channel_categories::ChannelCategory;
|
||||
pub use channel_events::ChannelEvent;
|
||||
pub use channel_follows::ChannelFollow;
|
||||
pub use channel_invitations::ChannelInvitation;
|
||||
pub use channel_member_roles::ChannelMemberRole;
|
||||
pub use channel_members::ChannelMember;
|
||||
@@ -54,20 +29,5 @@ pub use channel_webhooks::ChannelWebhook;
|
||||
pub use custom_emojis::CustomEmoji;
|
||||
pub use forum_tags::ForumTag;
|
||||
pub use im_integrations::ImIntegration;
|
||||
pub use message::Message;
|
||||
pub use message_attachments::MessageAttachment;
|
||||
pub use message_bookmarks::MessageBookmark;
|
||||
pub use message_drafts::MessageDraft;
|
||||
pub use message_edit_history::MessageEditHistory;
|
||||
pub use message_embeds::MessageEmbed;
|
||||
pub use message_mentions::MessageMention;
|
||||
pub use message_pins::MessagePin;
|
||||
pub use message_poll_options::MessagePollOption;
|
||||
pub use message_poll_votes::MessagePollVote;
|
||||
pub use message_polls::MessagePoll;
|
||||
pub use message_reactions::MessageReaction;
|
||||
pub use message_threads::MessageThread;
|
||||
pub use saved_messages::SavedMessage;
|
||||
pub use stages::Stage;
|
||||
pub use thread_read_states::ThreadReadState;
|
||||
pub use voice_participants::VoiceParticipant;
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
use chrono::{DateTime, Utc};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use uuid::Uuid;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, sqlx::FromRow)]
|
||||
pub struct SavedMessage {
|
||||
pub id: Uuid,
|
||||
pub user_id: Uuid,
|
||||
pub message_id: Uuid,
|
||||
pub channel_id: Uuid,
|
||||
pub note: Option<String>,
|
||||
pub created_at: DateTime<Utc>,
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
use chrono::{DateTime, Utc};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use uuid::Uuid;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, sqlx::FromRow)]
|
||||
pub struct ThreadReadState {
|
||||
pub id: Uuid,
|
||||
pub user_id: Uuid,
|
||||
pub thread_id: Uuid,
|
||||
pub channel_id: Uuid,
|
||||
pub last_read_message_id: Option<Uuid>,
|
||||
pub last_read_at: Option<DateTime<Utc>>,
|
||||
pub updated_at: DateTime<Utc>,
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
use crate::models::base_info::UserBaseInfo;
|
||||
use crate::models::common::{Priority, State, Visibility};
|
||||
use chrono::{DateTime, Utc};
|
||||
use serde::{Deserialize, Serialize};
|
||||
@@ -23,3 +24,48 @@ pub struct Issue {
|
||||
pub updated_at: DateTime<Utc>,
|
||||
pub deleted_at: Option<DateTime<Utc>>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, utoipa::ToSchema)]
|
||||
pub struct IssueDetail {
|
||||
pub id: Uuid,
|
||||
pub workspace_id: Uuid,
|
||||
pub author: UserBaseInfo,
|
||||
pub number: i64,
|
||||
pub title: String,
|
||||
pub body: Option<String>,
|
||||
pub state: State,
|
||||
pub priority: Priority,
|
||||
pub visibility: Visibility,
|
||||
pub locked: bool,
|
||||
pub milestone_id: Option<Uuid>,
|
||||
pub closed_by: Option<Uuid>,
|
||||
pub closed_at: Option<DateTime<Utc>>,
|
||||
pub due_at: Option<DateTime<Utc>>,
|
||||
pub created_at: DateTime<Utc>,
|
||||
pub updated_at: DateTime<Utc>,
|
||||
pub deleted_at: Option<DateTime<Utc>>,
|
||||
}
|
||||
|
||||
impl Issue {
|
||||
pub fn into_detail(self, author: UserBaseInfo) -> IssueDetail {
|
||||
IssueDetail {
|
||||
id: self.id,
|
||||
workspace_id: self.workspace_id,
|
||||
author,
|
||||
number: self.number,
|
||||
title: self.title,
|
||||
body: self.body,
|
||||
state: self.state,
|
||||
priority: self.priority,
|
||||
visibility: self.visibility,
|
||||
locked: self.locked,
|
||||
milestone_id: self.milestone_id,
|
||||
closed_by: self.closed_by,
|
||||
closed_at: self.closed_at,
|
||||
due_at: self.due_at,
|
||||
created_at: self.created_at,
|
||||
updated_at: self.updated_at,
|
||||
deleted_at: self.deleted_at,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
use crate::models::base_info::UserBaseInfo;
|
||||
use chrono::{DateTime, Utc};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use uuid::Uuid;
|
||||
@@ -14,3 +15,30 @@ pub struct IssueComment {
|
||||
pub created_at: DateTime<Utc>,
|
||||
pub updated_at: DateTime<Utc>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, utoipa::ToSchema)]
|
||||
pub struct IssueCommentDetail {
|
||||
pub id: Uuid,
|
||||
pub issue_id: Uuid,
|
||||
pub author: UserBaseInfo,
|
||||
pub reply_to_comment_id: Option<Uuid>,
|
||||
pub body: String,
|
||||
pub created_at: DateTime<Utc>,
|
||||
pub updated_at: DateTime<Utc>,
|
||||
pub deleted_at: Option<DateTime<Utc>>,
|
||||
}
|
||||
|
||||
impl IssueComment {
|
||||
pub fn into_detail(self, author: UserBaseInfo) -> IssueCommentDetail {
|
||||
IssueCommentDetail {
|
||||
id: self.id,
|
||||
issue_id: self.issue_id,
|
||||
author,
|
||||
reply_to_comment_id: self.reply_to_comment_id,
|
||||
body: self.body,
|
||||
created_at: self.created_at,
|
||||
updated_at: self.updated_at,
|
||||
deleted_at: self.deleted_at,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,9 +15,9 @@ pub mod issue_stats;
|
||||
pub mod issue_subscribers;
|
||||
pub mod issue_templates;
|
||||
|
||||
pub use issue::Issue;
|
||||
pub use issue::{Issue, IssueDetail};
|
||||
pub use issue_assignees::IssueAssignee;
|
||||
pub use issue_comments::IssueComment;
|
||||
pub use issue_comments::{IssueComment, IssueCommentDetail};
|
||||
pub use issue_commit_relations::IssueCommitRelation;
|
||||
pub use issue_events::IssueEvent;
|
||||
pub use issue_label_relations::IssueLabelRelation;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
pub mod agents;
|
||||
pub mod ais;
|
||||
pub mod base_info;
|
||||
pub mod channels;
|
||||
pub mod common;
|
||||
pub mod conversations;
|
||||
|
||||
@@ -4,7 +4,7 @@ pub mod notification_deliveries;
|
||||
pub mod notification_subscriptions;
|
||||
pub mod notification_templates;
|
||||
|
||||
pub use notification::Notification;
|
||||
pub use notification::{Notification, NotificationDetail};
|
||||
pub use notification_blocks::NotificationBlock;
|
||||
pub use notification_deliveries::NotificationDelivery;
|
||||
pub use notification_subscriptions::NotificationSubscription;
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
use crate::models::base_info::{RepoBaseInfo, UserBaseInfo, WorkspaceBaseInfo};
|
||||
use crate::models::common::{NotificationType, Priority, TargetType};
|
||||
use crate::models::json_types::{NotificationMetadata, TypedJson};
|
||||
use chrono::{DateTime, Utc};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use uuid::Uuid;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, sqlx::FromRow)]
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, sqlx::FromRow, utoipa::ToSchema)]
|
||||
pub struct Notification {
|
||||
pub id: Uuid,
|
||||
pub user_id: Uuid,
|
||||
@@ -24,8 +25,70 @@ pub struct Notification {
|
||||
pub priority: Priority,
|
||||
pub read_at: Option<DateTime<Utc>>,
|
||||
pub dismissed_at: Option<DateTime<Utc>>,
|
||||
#[schema(value_type = serde_json::Value)]
|
||||
pub metadata: Option<TypedJson<NotificationMetadata>>,
|
||||
pub created_at: DateTime<Utc>,
|
||||
pub updated_at: DateTime<Utc>,
|
||||
pub deleted_at: Option<DateTime<Utc>>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, utoipa::ToSchema)]
|
||||
pub struct NotificationDetail {
|
||||
pub id: Uuid,
|
||||
pub user_id: Uuid,
|
||||
pub actor: Option<UserBaseInfo>,
|
||||
pub workspace: Option<WorkspaceBaseInfo>,
|
||||
pub repo: Option<RepoBaseInfo>,
|
||||
pub issue_id: Option<Uuid>,
|
||||
pub pull_request_id: Option<Uuid>,
|
||||
pub channel_id: Option<Uuid>,
|
||||
pub message_id: Option<Uuid>,
|
||||
pub notification_type: NotificationType,
|
||||
pub title: String,
|
||||
pub body: Option<String>,
|
||||
pub target_type: Option<TargetType>,
|
||||
pub target_id: Option<Uuid>,
|
||||
pub action_url: Option<String>,
|
||||
pub priority: Priority,
|
||||
pub read_at: Option<DateTime<Utc>>,
|
||||
pub dismissed_at: Option<DateTime<Utc>>,
|
||||
#[schema(value_type = serde_json::Value)]
|
||||
pub metadata: Option<TypedJson<NotificationMetadata>>,
|
||||
pub created_at: DateTime<Utc>,
|
||||
pub updated_at: DateTime<Utc>,
|
||||
pub deleted_at: Option<DateTime<Utc>>,
|
||||
}
|
||||
|
||||
impl Notification {
|
||||
pub fn into_detail(
|
||||
self,
|
||||
actor: Option<UserBaseInfo>,
|
||||
workspace: Option<WorkspaceBaseInfo>,
|
||||
repo: Option<RepoBaseInfo>,
|
||||
) -> NotificationDetail {
|
||||
NotificationDetail {
|
||||
id: self.id,
|
||||
user_id: self.user_id,
|
||||
actor,
|
||||
workspace,
|
||||
repo,
|
||||
issue_id: self.issue_id,
|
||||
pull_request_id: self.pull_request_id,
|
||||
channel_id: self.channel_id,
|
||||
message_id: self.message_id,
|
||||
notification_type: self.notification_type,
|
||||
title: self.title,
|
||||
body: self.body,
|
||||
target_type: self.target_type,
|
||||
target_id: self.target_id,
|
||||
action_url: self.action_url,
|
||||
priority: self.priority,
|
||||
read_at: self.read_at,
|
||||
dismissed_at: self.dismissed_at,
|
||||
metadata: self.metadata,
|
||||
created_at: self.created_at,
|
||||
updated_at: self.updated_at,
|
||||
deleted_at: self.deleted_at,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ use chrono::{DateTime, Utc};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use uuid::Uuid;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, sqlx::FromRow)]
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, sqlx::FromRow, utoipa::ToSchema)]
|
||||
pub struct NotificationBlock {
|
||||
pub id: Uuid,
|
||||
pub user_id: Uuid,
|
||||
|
||||
@@ -3,7 +3,7 @@ use chrono::{DateTime, Utc};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use uuid::Uuid;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, sqlx::FromRow)]
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, sqlx::FromRow, utoipa::ToSchema)]
|
||||
pub struct NotificationDelivery {
|
||||
pub id: Uuid,
|
||||
pub notification_id: Uuid,
|
||||
|
||||
@@ -3,7 +3,7 @@ use chrono::{DateTime, Utc};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use uuid::Uuid;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, sqlx::FromRow)]
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, sqlx::FromRow, utoipa::ToSchema)]
|
||||
pub struct NotificationSubscription {
|
||||
pub id: Uuid,
|
||||
pub user_id: Uuid,
|
||||
|
||||
@@ -3,7 +3,7 @@ use chrono::{DateTime, Utc};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use uuid::Uuid;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, sqlx::FromRow)]
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, sqlx::FromRow, utoipa::ToSchema)]
|
||||
pub struct NotificationTemplate {
|
||||
pub id: Uuid,
|
||||
pub key: String,
|
||||
|
||||
+6
-2
@@ -9,8 +9,10 @@ pub mod pr_merge_strategy;
|
||||
pub mod pr_reactions;
|
||||
pub mod pr_review;
|
||||
pub mod pr_review_comment;
|
||||
pub mod pr_review_requests;
|
||||
pub mod pr_status;
|
||||
pub mod pr_subscriptions;
|
||||
pub mod pr_templates;
|
||||
pub mod pull_request;
|
||||
pub mod pull_request_queries;
|
||||
|
||||
@@ -23,8 +25,10 @@ pub use pr_label_relations::PrLabelRelation;
|
||||
pub use pr_labels::PrLabel;
|
||||
pub use pr_merge_strategy::PrMergeStrategy;
|
||||
pub use pr_reactions::PrReaction;
|
||||
pub use pr_review::PrReview;
|
||||
pub use pr_review::{PrReview, PrReviewDetail};
|
||||
pub use pr_review_comment::PrReviewComment;
|
||||
pub use pr_review_requests::PrReviewRequest;
|
||||
pub use pr_status::PrStatus;
|
||||
pub use pr_subscriptions::PrSubscription;
|
||||
pub use pull_request::PullRequest;
|
||||
pub use pr_templates::PrTemplate;
|
||||
pub use pull_request::{PullRequest, PullRequestDetail};
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
use crate::models::base_info::UserBaseInfo;
|
||||
use chrono::{DateTime, Utc};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use uuid::Uuid;
|
||||
@@ -17,3 +18,34 @@ pub struct PrReview {
|
||||
pub created_at: DateTime<Utc>,
|
||||
pub updated_at: DateTime<Utc>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, utoipa::ToSchema)]
|
||||
pub struct PrReviewDetail {
|
||||
pub id: Uuid,
|
||||
pub pull_request_id: Uuid,
|
||||
pub author: UserBaseInfo,
|
||||
pub state: String,
|
||||
pub body: Option<String>,
|
||||
pub dismissed: bool,
|
||||
pub dismissed_by: Option<Uuid>,
|
||||
pub dismissed_at: Option<DateTime<Utc>>,
|
||||
pub created_at: DateTime<Utc>,
|
||||
pub updated_at: DateTime<Utc>,
|
||||
}
|
||||
|
||||
impl PrReview {
|
||||
pub fn into_detail(self, author: UserBaseInfo) -> PrReviewDetail {
|
||||
PrReviewDetail {
|
||||
id: self.id,
|
||||
pull_request_id: self.pull_request_id,
|
||||
author,
|
||||
state: self.state,
|
||||
body: self.body,
|
||||
dismissed: self.dismissed_at.is_some(),
|
||||
dismissed_by: self.dismissed_by,
|
||||
dismissed_at: self.dismissed_at,
|
||||
created_at: self.created_at,
|
||||
updated_at: self.updated_at,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
use uuid::Uuid;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, sqlx::FromRow, utoipa::ToSchema)]
|
||||
pub struct PrReviewRequest {
|
||||
pub id: Uuid,
|
||||
pub pull_request_id: Uuid,
|
||||
pub reviewer_id: Uuid,
|
||||
pub requested_by: Uuid,
|
||||
pub created_at: chrono::DateTime<chrono::Utc>,
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
use uuid::Uuid;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, sqlx::FromRow, utoipa::ToSchema)]
|
||||
pub struct PrTemplate {
|
||||
pub id: Uuid,
|
||||
pub repo_id: Uuid,
|
||||
pub name: String,
|
||||
pub description: Option<String>,
|
||||
pub title_template: Option<String>,
|
||||
pub body_template: String,
|
||||
pub labels: Vec<String>,
|
||||
pub active: bool,
|
||||
pub created_by: Option<Uuid>,
|
||||
pub created_at: chrono::DateTime<chrono::Utc>,
|
||||
pub updated_at: chrono::DateTime<chrono::Utc>,
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
use crate::models::base_info::UserBaseInfo;
|
||||
use crate::models::common::State;
|
||||
use chrono::{DateTime, Utc};
|
||||
use serde::{Deserialize, Serialize};
|
||||
@@ -29,3 +30,60 @@ pub struct PullRequest {
|
||||
pub updated_at: DateTime<Utc>,
|
||||
pub deleted_at: Option<DateTime<Utc>>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, utoipa::ToSchema)]
|
||||
pub struct PullRequestDetail {
|
||||
pub id: Uuid,
|
||||
pub repo_id: Uuid,
|
||||
pub author: UserBaseInfo,
|
||||
pub number: i64,
|
||||
pub title: String,
|
||||
pub body: Option<String>,
|
||||
pub state: State,
|
||||
pub source_repo_id: Uuid,
|
||||
pub source_branch: String,
|
||||
pub target_repo_id: Uuid,
|
||||
pub target_branch: String,
|
||||
pub base_commit_sha: Option<String>,
|
||||
pub head_commit_sha: String,
|
||||
pub merge_commit_sha: Option<String>,
|
||||
pub draft: bool,
|
||||
pub locked: bool,
|
||||
pub merged_by: Option<Uuid>,
|
||||
pub merged_at: Option<DateTime<Utc>>,
|
||||
pub closed_by: Option<Uuid>,
|
||||
pub closed_at: Option<DateTime<Utc>>,
|
||||
pub created_at: DateTime<Utc>,
|
||||
pub updated_at: DateTime<Utc>,
|
||||
pub deleted_at: Option<DateTime<Utc>>,
|
||||
}
|
||||
|
||||
impl PullRequest {
|
||||
pub fn into_detail(self, author: UserBaseInfo) -> PullRequestDetail {
|
||||
PullRequestDetail {
|
||||
id: self.id,
|
||||
repo_id: self.repo_id,
|
||||
author,
|
||||
number: self.number,
|
||||
title: self.title,
|
||||
body: self.body,
|
||||
state: self.state,
|
||||
source_repo_id: self.source_repo_id,
|
||||
source_branch: self.source_branch,
|
||||
target_repo_id: self.target_repo_id,
|
||||
target_branch: self.target_branch,
|
||||
base_commit_sha: self.base_commit_sha,
|
||||
head_commit_sha: self.head_commit_sha,
|
||||
merge_commit_sha: self.merge_commit_sha,
|
||||
draft: self.draft,
|
||||
locked: self.locked,
|
||||
merged_by: self.merged_by,
|
||||
merged_at: self.merged_at,
|
||||
closed_by: self.closed_by,
|
||||
closed_at: self.closed_at,
|
||||
created_at: self.created_at,
|
||||
updated_at: self.updated_at,
|
||||
deleted_at: self.deleted_at,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+3
-1
@@ -10,6 +10,7 @@ pub mod repo_members;
|
||||
pub mod repo_push_commit;
|
||||
pub mod repo_push_lock;
|
||||
pub mod repo_queries;
|
||||
pub mod repo_release_assets;
|
||||
pub mod repo_releases;
|
||||
pub mod repo_stars;
|
||||
pub mod repo_stats;
|
||||
@@ -18,7 +19,7 @@ pub mod repo_watches;
|
||||
pub mod repo_webhooks;
|
||||
|
||||
pub use branch_protection_rule::BranchProtectionRule;
|
||||
pub use repo::Repo;
|
||||
pub use repo::{Repo, RepoDetail};
|
||||
pub use repo_branches::RepoBranch;
|
||||
pub use repo_commit_comments::RepoCommitComment;
|
||||
pub use repo_commit_statuses::RepoCommitStatus;
|
||||
@@ -28,6 +29,7 @@ pub use repo_invitations::RepoInvitation;
|
||||
pub use repo_members::RepoMember;
|
||||
pub use repo_push_commit::RepoPushCommit;
|
||||
pub use repo_push_lock::RepoPushLock;
|
||||
pub use repo_release_assets::RepoReleaseAsset;
|
||||
pub use repo_releases::RepoRelease;
|
||||
pub use repo_stars::RepoStar;
|
||||
pub use repo_stats::RepoStats;
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
use crate::models::base_info::{UserBaseInfo, WorkspaceBaseInfo};
|
||||
use crate::models::common::{GitService, Status, Visibility};
|
||||
use chrono::{DateTime, Utc};
|
||||
use serde::{Deserialize, Serialize};
|
||||
@@ -23,4 +24,91 @@ pub struct Repo {
|
||||
pub created_at: DateTime<Utc>,
|
||||
pub updated_at: DateTime<Utc>,
|
||||
pub deleted_at: Option<DateTime<Utc>>,
|
||||
#[sqlx(default)]
|
||||
pub topics: Vec<String>,
|
||||
#[sqlx(default)]
|
||||
pub homepage: Option<String>,
|
||||
#[sqlx(default)]
|
||||
pub has_issues: bool,
|
||||
#[sqlx(default)]
|
||||
pub has_wiki: bool,
|
||||
#[sqlx(default)]
|
||||
pub has_pull_requests: bool,
|
||||
#[sqlx(default)]
|
||||
pub allow_forking: bool,
|
||||
#[sqlx(default)]
|
||||
pub allow_merge_commit: bool,
|
||||
#[sqlx(default)]
|
||||
pub allow_squash_merge: bool,
|
||||
#[sqlx(default)]
|
||||
pub allow_rebase_merge: bool,
|
||||
#[sqlx(default)]
|
||||
pub delete_branch_on_merge: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, utoipa::ToSchema)]
|
||||
pub struct RepoDetail {
|
||||
pub id: Uuid,
|
||||
pub workspace: WorkspaceBaseInfo,
|
||||
pub owner: UserBaseInfo,
|
||||
pub name: String,
|
||||
pub description: Option<String>,
|
||||
pub default_branch: String,
|
||||
pub visibility: Visibility,
|
||||
pub status: Status,
|
||||
pub is_fork: bool,
|
||||
pub forked_from_repo_id: Option<Uuid>,
|
||||
pub storage_node_ids: Vec<Uuid>,
|
||||
pub primary_storage_node_id: Uuid,
|
||||
pub storage_path: String,
|
||||
pub git_service: GitService,
|
||||
pub archived_at: Option<DateTime<Utc>>,
|
||||
pub created_at: DateTime<Utc>,
|
||||
pub updated_at: DateTime<Utc>,
|
||||
pub deleted_at: Option<DateTime<Utc>>,
|
||||
pub topics: Vec<String>,
|
||||
pub homepage: Option<String>,
|
||||
pub has_issues: bool,
|
||||
pub has_wiki: bool,
|
||||
pub has_pull_requests: bool,
|
||||
pub allow_forking: bool,
|
||||
pub allow_merge_commit: bool,
|
||||
pub allow_squash_merge: bool,
|
||||
pub allow_rebase_merge: bool,
|
||||
pub delete_branch_on_merge: bool,
|
||||
}
|
||||
|
||||
impl Repo {
|
||||
pub fn into_detail(self, owner: UserBaseInfo, workspace: WorkspaceBaseInfo) -> RepoDetail {
|
||||
RepoDetail {
|
||||
id: self.id,
|
||||
workspace,
|
||||
owner,
|
||||
name: self.name,
|
||||
description: self.description,
|
||||
default_branch: self.default_branch,
|
||||
visibility: self.visibility,
|
||||
status: self.status,
|
||||
is_fork: self.is_fork,
|
||||
forked_from_repo_id: self.forked_from_repo_id,
|
||||
storage_node_ids: self.storage_node_ids,
|
||||
primary_storage_node_id: self.primary_storage_node_id,
|
||||
storage_path: self.storage_path,
|
||||
git_service: self.git_service,
|
||||
archived_at: self.archived_at,
|
||||
created_at: self.created_at,
|
||||
updated_at: self.updated_at,
|
||||
deleted_at: self.deleted_at,
|
||||
topics: self.topics,
|
||||
homepage: self.homepage,
|
||||
has_issues: self.has_issues,
|
||||
has_wiki: self.has_wiki,
|
||||
has_pull_requests: self.has_pull_requests,
|
||||
allow_forking: self.allow_forking,
|
||||
allow_merge_commit: self.allow_merge_commit,
|
||||
allow_squash_merge: self.allow_squash_merge,
|
||||
allow_rebase_merge: self.allow_rebase_merge,
|
||||
delete_branch_on_merge: self.delete_branch_on_merge,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
use chrono::{DateTime, Utc};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use uuid::Uuid;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, sqlx::FromRow, utoipa::ToSchema)]
|
||||
pub struct RepoReleaseAsset {
|
||||
pub id: Uuid,
|
||||
pub release_id: Uuid,
|
||||
pub filename: String,
|
||||
pub size_bytes: i64,
|
||||
pub mime_type: String,
|
||||
pub storage_path: String,
|
||||
pub url: Option<String>,
|
||||
pub download_count: i64,
|
||||
pub uploaded_by: Option<Uuid>,
|
||||
pub created_at: DateTime<Utc>,
|
||||
pub updated_at: DateTime<Utc>,
|
||||
pub deleted_at: Option<DateTime<Utc>>,
|
||||
}
|
||||
@@ -19,4 +19,8 @@ pub struct User {
|
||||
pub created_at: DateTime<Utc>,
|
||||
pub updated_at: DateTime<Utc>,
|
||||
pub deleted_at: Option<DateTime<Utc>>,
|
||||
#[sqlx(default)]
|
||||
pub restore_token_hash: Option<String>,
|
||||
#[sqlx(default)]
|
||||
pub restore_token_expires_at: Option<DateTime<Utc>>,
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ use chrono::{DateTime, Utc};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use uuid::Uuid;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, sqlx::FromRow)]
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, sqlx::FromRow, utoipa::ToSchema)]
|
||||
pub struct UserBlock {
|
||||
pub blocker_id: Uuid,
|
||||
pub blocked_id: Uuid,
|
||||
|
||||
@@ -2,7 +2,7 @@ use chrono::{DateTime, Utc};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use uuid::Uuid;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, sqlx::FromRow)]
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, sqlx::FromRow, utoipa::ToSchema)]
|
||||
pub struct UserFollow {
|
||||
pub follower_id: Uuid,
|
||||
pub following_id: Uuid,
|
||||
|
||||
@@ -3,7 +3,7 @@ use chrono::{DateTime, Utc};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use uuid::Uuid;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, sqlx::FromRow)]
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, sqlx::FromRow, utoipa::ToSchema)]
|
||||
pub struct UserPresence {
|
||||
pub id: Uuid,
|
||||
pub user_id: Uuid,
|
||||
|
||||
@@ -12,7 +12,7 @@ pub mod workspace_settings;
|
||||
pub mod workspace_stats;
|
||||
pub mod workspace_webhooks;
|
||||
|
||||
pub use workspace::Workspace;
|
||||
pub use workspace::{Workspace, WorkspaceDetail};
|
||||
pub use workspace_audit_logs::WorkspaceAuditLog;
|
||||
pub use workspace_billing::WorkspaceBilling;
|
||||
pub use workspace_custom_branding::WorkspaceCustomBranding;
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
use crate::models::base_info::UserBaseInfo;
|
||||
use crate::models::common::{Status, Visibility};
|
||||
use chrono::{DateTime, Utc};
|
||||
use serde::{Deserialize, Serialize};
|
||||
@@ -20,3 +21,42 @@ pub struct Workspace {
|
||||
pub updated_at: DateTime<Utc>,
|
||||
pub deleted_at: Option<DateTime<Utc>>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, utoipa::ToSchema)]
|
||||
pub struct WorkspaceDetail {
|
||||
pub id: Uuid,
|
||||
pub owner: UserBaseInfo,
|
||||
pub name: String,
|
||||
pub description: Option<String>,
|
||||
pub avatar_url: Option<String>,
|
||||
pub visibility: Visibility,
|
||||
pub plan: String,
|
||||
pub status: Status,
|
||||
pub default_role: String,
|
||||
pub is_personal: bool,
|
||||
pub archived_at: Option<DateTime<Utc>>,
|
||||
pub created_at: DateTime<Utc>,
|
||||
pub updated_at: DateTime<Utc>,
|
||||
pub deleted_at: Option<DateTime<Utc>>,
|
||||
}
|
||||
|
||||
impl Workspace {
|
||||
pub fn into_detail(self, owner: UserBaseInfo) -> WorkspaceDetail {
|
||||
WorkspaceDetail {
|
||||
id: self.id,
|
||||
owner,
|
||||
name: self.name,
|
||||
description: self.description,
|
||||
avatar_url: self.avatar_url,
|
||||
visibility: self.visibility,
|
||||
plan: self.plan,
|
||||
status: self.status,
|
||||
default_role: self.default_role,
|
||||
is_personal: self.is_personal,
|
||||
archived_at: self.archived_at,
|
||||
created_at: self.created_at,
|
||||
updated_at: self.updated_at,
|
||||
deleted_at: self.deleted_at,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user