diff --git a/ceres/src/api_service/mono_api_service.rs b/ceres/src/api_service/mono_api_service.rs index 889c9db1b..d1f1ef031 100644 --- a/ceres/src/api_service/mono_api_service.rs +++ b/ceres/src/api_service/mono_api_service.rs @@ -207,7 +207,6 @@ impl MonoApiService { vec![MergeStatus::Closed, MergeStatus::Merged] } else { vec![MergeStatus::Open, MergeStatus::Closed, MergeStatus::Merged] - // return Err(MegaError::with_message("Invalid status name")); }; let storage = self.context.services.mono_storage.clone(); let mr_list = storage.get_mr_by_status(status).await.unwrap(); @@ -301,7 +300,7 @@ impl MonoApiService { // add conversation storage - .add_mr_conversation(&mr.mr_link, 0, ConvType::Merged) + .add_mr_conversation(&mr.mr_link, 0, ConvType::Merged, None) .await .unwrap(); if mr.path != "/" { diff --git a/ceres/src/model/mr.rs b/ceres/src/model/mr.rs index c02228fa8..f441b257a 100644 --- a/ceres/src/model/mr.rs +++ b/ceres/src/model/mr.rs @@ -40,6 +40,7 @@ pub struct MRDetail { pub struct MRConversion { pub user_id: i64, pub conv_type: String, + pub comment: Option, pub created_at: i64, pub updated_at: i64, } @@ -49,7 +50,7 @@ impl From for MRDetail { Self { id: value.id, mr_link: value.mr_link, - title: String::new(), + title: value.title, status: value.status.to_string(), open_timestamp: value.created_at.and_utc().timestamp(), merge_timestamp: value.merge_date.map(|dt| dt.and_utc().timestamp()), @@ -63,6 +64,7 @@ impl From for MRConversion { Self { user_id: value.user_id, conv_type: value.conv_type.to_string(), + comment: value.comment, created_at: value.created_at.and_utc().timestamp(), updated_at: value.updated_at.and_utc().timestamp(), } diff --git a/ceres/src/pack/monorepo.rs b/ceres/src/pack/monorepo.rs index 61946046c..db1d41948 100644 --- a/ceres/src/pack/monorepo.rs +++ b/ceres/src/pack/monorepo.rs @@ -15,10 +15,10 @@ use rand::{distributions::Alphanumeric, thread_rng, Rng}; use tokio::sync::mpsc; use tokio_stream::wrappers::ReceiverStream; -use callisto::raw_blob; +use callisto::{db_enums::ConvType, raw_blob}; use common::{errors::MegaError, utils::MEGA_BRANCH_NAME}; use jupiter::{context::Context, storage::mono_storage::MonoStorage}; -use mercury::internal::pack::encode::PackEncoder; +use mercury::internal::{object::ObjectTrait, pack::encode::PackEncoder}; use mercury::{ errors::GitError, hash::SHA1, @@ -123,30 +123,33 @@ impl PackHandler for MonoRepo { async fn handle_receiver(&self, receiver: Receiver) -> Result<(), GitError> { let storage = self.context.services.mono_storage.clone(); let path_str = self.path.to_str().unwrap(); - match storage.get_open_mr_by_path(path_str).await.unwrap() { - Some(mr) => { - let mut mr = mr.into(); - self.handle_existing_mr(&mut mr, &storage, receiver).await - } - None => { - let mr_link: String = thread_rng() - .sample_iter(&Alphanumeric) - .take(8) - .map(char::from) - .collect(); - let mr = MergeRequest { - path: path_str.to_owned(), - from_hash: self.from_hash.clone(), - to_hash: self.to_hash.clone(), - mr_link: mr_link.to_uppercase(), - ..Default::default() - }; - let unpack_res = self.save_entry(receiver).await; - if unpack_res.is_ok() { + + let unpack_res = self.save_entry(receiver).await; + match unpack_res { + Ok(title) => match storage.get_open_mr_by_path(path_str).await.unwrap() { + Some(mr) => { + let mut mr = mr.into(); + self.handle_existing_mr(&mut mr, &storage).await + } + None => { + let mr_link: String = thread_rng() + .sample_iter(&Alphanumeric) + .take(8) + .map(char::from) + .collect(); + let mr = MergeRequest { + path: path_str.to_owned(), + from_hash: self.from_hash.clone(), + to_hash: self.to_hash.clone(), + mr_link: mr_link.to_uppercase(), + title, + ..Default::default() + }; storage.save_mr(mr.clone().into()).await.unwrap(); + Ok(()) } - unpack_res - } + }, + Err(err) => Err(err), } } @@ -332,38 +335,25 @@ impl MonoRepo { &self, mr: &mut MergeRequest, storage: &MonoStorage, - receiver: Receiver, ) -> Result<(), GitError> { if mr.from_hash == self.from_hash { if mr.to_hash != self.to_hash { let comment = self.comment_for_force_update(&mr.to_hash, &self.to_hash); mr.to_hash = self.to_hash.clone(); storage - .add_mr_comment(&mr.mr_link, 0, Some(comment)) + .add_mr_conversation(&mr.mr_link, 0, ConvType::Comment, Some(comment)) .await .unwrap(); - - let unpack_res = self.save_entry(receiver).await; - if unpack_res.is_err() { - mr.close(); - storage - .add_mr_comment( - &mr.mr_link, - 0, - Some("Mega closed MR due to multi commit detected".to_string()), - ) - .await - .unwrap(); - } } else { tracing::info!("repeat commit with mr: {}, do nothing", mr.id); } } else { mr.close(); storage - .add_mr_comment( + .add_mr_conversation( &mr.mr_link, 0, + ConvType::Comment, Some("Mega closed MR due to conflict".to_string()), ) .await @@ -382,15 +372,18 @@ impl MonoRepo { ) } - async fn save_entry(&self, receiver: Receiver) -> Result<(), GitError> { + async fn save_entry(&self, receiver: Receiver) -> Result { let storage = self.context.services.mono_storage.clone(); let mut entry_list = Vec::new(); let mut join_tasks = vec![]; let mut current_commit_id = String::new(); + let mut mr_title = String::new(); for entry in receiver { if current_commit_id.is_empty() { if entry.obj_type == ObjectType::Commit { current_commit_id = entry.hash.to_plain_str(); + let commit = Commit::from_bytes(&entry.data, entry.hash).unwrap(); + mr_title = commit.format_message(); } } else { if entry.obj_type == ObjectType::Commit { @@ -415,6 +408,6 @@ impl MonoRepo { .save_entry(¤t_commit_id, entry_list) .await .unwrap(); - Ok(()) + Ok(mr_title) } } diff --git a/ceres/src/protocol/mr.rs b/ceres/src/protocol/mr.rs index 7c74f7ed4..cd8b611e1 100644 --- a/ceres/src/protocol/mr.rs +++ b/ceres/src/protocol/mr.rs @@ -7,6 +7,7 @@ use common::utils::generate_id; pub struct MergeRequest { pub id: i64, pub mr_link: String, + pub title: String, pub status: MergeStatus, pub merge_date: Option, pub path: String, @@ -19,6 +20,7 @@ impl Default for MergeRequest { Self { id: generate_id(), mr_link: String::new(), + title: String::new(), status: MergeStatus::Open, merge_date: None, path: String::new(), @@ -44,6 +46,7 @@ impl From for mega_mr::Model { Self { id: value.id, mr_link: value.mr_link, + title: value.title, status: value.status, merge_date: value.merge_date, path: value.path, @@ -60,6 +63,7 @@ impl From for MergeRequest { Self { id: value.id, mr_link: value.mr_link, + title: value.title, status: value.status, merge_date: value.merge_date, path: value.path, diff --git a/docker/start-moon.sh b/docker/start-moon.sh index 6bb3a597e..75b8029b5 100755 --- a/docker/start-moon.sh +++ b/docker/start-moon.sh @@ -1,6 +1,6 @@ #!/bin/bash -# user must set the MEGA_HOST,MEGA_INTERNAL_HOST +# user must set the MEGA_HOST, MEGA_INTERNAL_HOST if [ -z "$MEGA_HOST" ]; then echo "MEGA_HOST is not set" exit 1 diff --git a/jupiter/callisto/src/lib.rs b/jupiter/callisto/src/lib.rs index 1250d6e9d..3884c3c73 100644 --- a/jupiter/callisto/src/lib.rs +++ b/jupiter/callisto/src/lib.rs @@ -18,7 +18,6 @@ pub mod mega_blob; pub mod mega_commit; pub mod mega_issue; pub mod mega_mr; -pub mod mega_mr_comment; pub mod mega_mr_conv; pub mod mega_refs; pub mod mega_tag; diff --git a/jupiter/callisto/src/mega_mr.rs b/jupiter/callisto/src/mega_mr.rs index 419c807cd..570b053ec 100644 --- a/jupiter/callisto/src/mega_mr.rs +++ b/jupiter/callisto/src/mega_mr.rs @@ -10,6 +10,7 @@ pub struct Model { #[sea_orm(primary_key, auto_increment = false)] pub id: i64, pub mr_link: String, + pub title: String, pub merge_date: Option, pub status: MergeStatus, #[sea_orm(column_type = "Text")] diff --git a/jupiter/callisto/src/mega_mr_comment.rs b/jupiter/callisto/src/mega_mr_comment.rs deleted file mode 100644 index c63f714ff..000000000 --- a/jupiter/callisto/src/mega_mr_comment.rs +++ /dev/null @@ -1,19 +0,0 @@ -//! `SeaORM` Entity, @generated by sea-orm-codegen 1.0.0 - -use sea_orm::entity::prelude::*; - -#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] -#[sea_orm(table_name = "mega_mr_comment")] -pub struct Model { - #[sea_orm(primary_key, auto_increment = false)] - pub id: i64, - pub conv_id: i64, - #[sea_orm(column_type = "Text", nullable)] - pub comment: Option, - pub edited: bool, -} - -#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] -pub enum Relation {} - -impl ActiveModelBehavior for ActiveModel {} diff --git a/jupiter/callisto/src/mega_mr_conv.rs b/jupiter/callisto/src/mega_mr_conv.rs index 63b0b4064..1f564804c 100644 --- a/jupiter/callisto/src/mega_mr_conv.rs +++ b/jupiter/callisto/src/mega_mr_conv.rs @@ -12,6 +12,8 @@ pub struct Model { pub mr_link: String, pub user_id: i64, pub conv_type: ConvType, + #[sea_orm(column_type = "Text", nullable)] + pub comment: Option, pub created_at: DateTime, pub updated_at: DateTime, } diff --git a/jupiter/callisto/src/prelude.rs b/jupiter/callisto/src/prelude.rs index c29eb6397..4f4791176 100644 --- a/jupiter/callisto/src/prelude.rs +++ b/jupiter/callisto/src/prelude.rs @@ -15,7 +15,6 @@ pub use crate::mega_blob::Entity as MegaBlob; pub use crate::mega_commit::Entity as MegaCommit; pub use crate::mega_issue::Entity as MegaIssue; pub use crate::mega_mr::Entity as MegaMr; -pub use crate::mega_mr_comment::Entity as MegaMrComment; pub use crate::mega_mr_conv::Entity as MegaMrConv; pub use crate::mega_refs::Entity as MegaRefs; pub use crate::mega_tag::Entity as MegaTag; diff --git a/jupiter/src/storage/init.rs b/jupiter/src/storage/init.rs index a04dd7bee..2a96fcca8 100644 --- a/jupiter/src/storage/init.rs +++ b/jupiter/src/storage/init.rs @@ -51,7 +51,7 @@ async fn setup_sql(conn: &DatabaseConnection) -> Result<(), TransactionError, ) -> Result { let conversation = mega_mr_conv::Model { id: generate_id(), mr_link: mr_link.to_owned(), user_id, conv_type, + comment, created_at: chrono::Utc::now().naive_utc(), updated_at: chrono::Utc::now().naive_utc(), }; @@ -192,27 +194,6 @@ impl MonoStorage { Ok(res.id) } - pub async fn add_mr_comment( - &self, - mr_link: &str, - user_id: i64, - comment: Option, - ) -> Result<(), MegaError> { - let conv_id = self - .add_mr_conversation(mr_link, user_id, ConvType::Comment) - .await - .unwrap(); - let comment = mega_mr_comment::Model { - id: generate_id(), - conv_id, - comment, - edited: false, - }; - let comment = comment.into_active_model(); - comment.insert(self.get_connection()).await.unwrap(); - Ok(()) - } - pub async fn save_entry( &self, commit_id: &str, diff --git a/mercury/src/internal/pack/decode.rs b/mercury/src/internal/pack/decode.rs index c1f7e6968..bd7e3c712 100644 --- a/mercury/src/internal/pack/decode.rs +++ b/mercury/src/internal/pack/decode.rs @@ -492,7 +492,7 @@ impl Pack { // DO NOT use thread::spawn, because it will block tokio runtime (if single-threaded runtime, like in tests) tokio::task::spawn_blocking(move || { self.decode(&mut reader, move |entry, _| { - sender.send(entry).unwrap(); + if sender.send(entry).is_ok() {} }).unwrap(); self }).await.unwrap() diff --git a/mono/src/api/api_router.rs b/mono/src/api/api_router.rs index 8f8fbc549..a2b01e091 100644 --- a/mono/src/api/api_router.rs +++ b/mono/src/api/api_router.rs @@ -1,3 +1,5 @@ +use std::path::PathBuf; + use axum::{ body::Body, extract::{Path, Query, State}, @@ -5,6 +7,7 @@ use axum::{ routing::{get, post}, Json, Router, }; +use http::StatusCode; use ceres::{ api_service::ApiHandler, @@ -15,7 +18,6 @@ use ceres::{ }, }; use common::{errors::ProtocolError, model::CommonResult}; -use http::StatusCode; use taurus::event::api_request::{ApiRequestEvent, ApiType}; use crate::api::error::ApiError; @@ -29,11 +31,11 @@ pub fn routers() -> Router { .route("/create-file", post(create_file)) .route("/latest-commit", get(get_latest_commit)) .route("/tree/commit-info", get(get_tree_commit_info)) + .route("/tree/path-can-clone", get(path_can_be_cloned)) .route("/tree", get(get_tree_info)) .route("/blob", get(get_blob_string)) .route("/file/blob/:object_id", get(get_blob_file)) - .route("/file/tree", get(get_tree_file)) - .route("/path-can-clone", get(path_can_be_cloned)); + .route("/file/tree", get(get_tree_file)); Router::new() .merge(router) .merge(mr_router::routers()) @@ -179,6 +181,20 @@ async fn path_can_be_cloned( Query(query): Query, state: State, ) -> Result>, ApiError> { - let res = state.api_handler(query.path.clone().into()).await.is_ok(); + let path: PathBuf = query.path.clone().into(); + let import_dir = state.context.config.monorepo.import_dir.clone(); + let res = if path.starts_with(&import_dir) { + state + .context + .services + .git_db_storage + .find_git_repo_exact_match(path.to_str().unwrap()) + .await + .unwrap() + .is_some() + } else { + // any path under monorepo can be cloned + true + }; Ok(Json(CommonResult::success(Some(res)))) } diff --git a/moon/src/app/(dashboard)/mr/[id]/page.tsx b/moon/src/app/(dashboard)/mr/[id]/page.tsx index 975e3d51e..5dabba8c2 100644 --- a/moon/src/app/(dashboard)/mr/[id]/page.tsx +++ b/moon/src/app/(dashboard)/mr/[id]/page.tsx @@ -1,27 +1,135 @@ 'use client' -import MergeDetail from "@/components/MergeDetail"; import { useEffect, useState } from "react"; +import { Card, Button, List, Tabs, TabsProps, Space, Timeline } from 'antd/lib'; +import { useRouter } from 'next/navigation'; +import { CommentOutlined, MergeOutlined } from '@ant-design/icons'; +import { formatDistance, fromUnixTime } from 'date-fns'; +interface MRDetail { + status: string, + conversions: Conversation[], + title: string, +} +interface Conversation { + user_id: number, + conv_type: String, + comment: String, + created_at: number, +} + +export default function MRDetailPage({ params }: { params: { id: string } }) { + const [mrDetail, setMrDetail] = useState( + { + status: "", + conversions: [], + title: "", + } + ); + const router = useRouter(); + const [filedata, setFileData] = useState([]); + const [loadings, setLoadings] = useState([]); -export default function MRDetailPage( { params }: { params: { id: string } }) { - const [mrDetail, setMrDetail] = useState([]); useEffect(() => { - const fetchData = async () => { + const fetchFileList = async () => { + set_to_loading(2) try { - const res = await fetch(`/api/mr/${params.id}/detail`); - const response = await res.json(); - const data = response.data.data; - setMrDetail(data); - } catch (error) { - console.error('Error fetching data:', error); + const detail = await fetch(`/api/mr/${params.id}/detail`); + const detail_json = await detail.json(); + setMrDetail(detail_json.data.data); + const res = await fetch(`/api/mr/${params.id}/files`); + const result = await res.json(); + setFileData(result.data.data); + } finally { + cancel_loading(2) } }; - fetchData(); + fetchFileList(); }, [params.id]); + const set_to_loading = (index: number) => { + setLoadings((prevLoadings) => { + const newLoadings = [...prevLoadings]; + newLoadings[index] = true; + return newLoadings; + }); + } + + const cancel_loading = (index: number) => { + setLoadings((prevLoadings) => { + const newLoadings = [...prevLoadings]; + newLoadings[index] = false; + return newLoadings; + }); + } + + const approve_mr = async (index: number, mr_link: string) => { + set_to_loading(index); + const res = await fetch(`/api/mr/${mr_link}/merge`, { + method: 'POST', + }); + if (res) { + cancel_loading(index); + } + }; + + let conv_items = mrDetail?.conversions.map(conv => { + let icon; + let children; + switch (conv.conv_type) { + case "Comment": icon = ; children = conv.comment; break; + case "Merged": icon = ; children = "Merged via the queue into main " + formatDistance(fromUnixTime(conv.created_at), new Date(), { addSuffix: true }); break; + // default: icon = ; children = conv.comment; + }; + + const element = { + dot: icon, + // color: 'red', + children: children + } + return element + }); + + const tab_items: TabsProps['items'] = [ + { + key: '1', + label: 'Conversation', + children: + + + + }, + { + key: '2', + label: 'Files Changed', + children: + Change File List} + bordered + dataSource={filedata} + loading={loadings[2]} + renderItem={(item) => ( + + {item} + + )} + /> + + } + ]; + return ( -
- -
+ + {mrDetail && mrDetail.status === "open" && + + } + + ) } diff --git a/moon/src/app/(dashboard)/tree/[...path]/page.tsx b/moon/src/app/(dashboard)/tree/[...path]/page.tsx index 52d7a514d..cad0831bd 100644 --- a/moon/src/app/(dashboard)/tree/[...path]/page.tsx +++ b/moon/src/app/(dashboard)/tree/[...path]/page.tsx @@ -10,6 +10,8 @@ import { Flex, Layout } from "antd/lib"; export default function Page({ params }: { params: { path: string[] } }) { const [directory, setDirectory] = useState([]); const [readmeContent, setReadmeContent] = useState(""); + const [cloneBtn, setCloneBtn] = useState(true); + const [endpoint, setEndPoint] = useState(""); let path = '/' + params.path.join('/'); useEffect(() => { const fetchData = async () => { @@ -18,6 +20,10 @@ export default function Page({ params }: { params: { path: string[] } }) { setDirectory(directory); let readmeContent = await getReadmeContent(path, directory); setReadmeContent(readmeContent); + let shown_clone_btn = await pathCanClone(path); + setCloneBtn(shown_clone_btn); + let endpoint = await getEndpoint(); + setEndPoint(endpoint); } catch (error) { console.error('Error fetching data:', error); } @@ -52,9 +58,12 @@ export default function Page({ params }: { params: { path: string[] } }) { - - - + { + cloneBtn && + + + + } @@ -85,3 +94,18 @@ async function getReadmeContent(pathname, directory) { } return readmeContent } + +async function pathCanClone(pathname: string) { + const res = await fetch(`/api/tree/path-can-clone?path=${pathname}`); + const response = await res.json(); + const shown_clone_btn = response.data.data; + return shown_clone_btn +} + + +async function getEndpoint() { + const res = await fetch(`/host`); + const response = await res.json(); + const data = response.endpoint; + return data +} \ No newline at end of file diff --git a/moon/src/app/api/tree/path-can-clone/route.ts b/moon/src/app/api/tree/path-can-clone/route.ts new file mode 100644 index 000000000..d58531e66 --- /dev/null +++ b/moon/src/app/api/tree/path-can-clone/route.ts @@ -0,0 +1,16 @@ +import { type NextRequest } from 'next/server' +export const revalidate = 0 +export const dynamic = 'force-dynamic' // defaults to auto + +export async function GET(request: NextRequest) { + const endpoint = process.env.MEGA_INTERNAL_HOST; + + const searchParams = request.nextUrl.searchParams + const path = searchParams.get('path') + + const res = await fetch(`${endpoint}/api/v1/tree/path-can-clone?path=${path}`, { + }) + const data = await res.json() + + return Response.json({ data }) +} \ No newline at end of file diff --git a/moon/src/app/host/route.ts b/moon/src/app/host/route.ts new file mode 100644 index 000000000..5e1c8dc2e --- /dev/null +++ b/moon/src/app/host/route.ts @@ -0,0 +1,5 @@ + +export async function GET() { + const endpoint = process.env.MEGA_HOST; + return Response.json({ endpoint }) +} \ No newline at end of file diff --git a/moon/src/components/CloneTabs.tsx b/moon/src/components/CloneTabs.tsx index 754a5cc63..5bdf353c9 100644 --- a/moon/src/components/CloneTabs.tsx +++ b/moon/src/components/CloneTabs.tsx @@ -1,14 +1,11 @@ import React, { useEffect, useState } from 'react'; import { Tabs, TabsProps, Button, Space, Popover, Input } from 'antd'; -import { - CodeBracketIcon, -} from '@heroicons/react/16/solid' import copy from 'copy-to-clipboard'; import { CopyOutlined, CheckOutlined, DownloadOutlined } from '@ant-design/icons'; import { usePathname } from 'next/navigation'; -const CloneTabs: React.FC = () => { +const CloneTabs = ({ endpoint }) => { const pathname = usePathname(); const [text, setText] = useState(pathname); const [copied, setCopied] = useState(false); @@ -19,15 +16,15 @@ const CloneTabs: React.FC = () => { }; useEffect(() => { - if (typeof window !== 'undefined') { - const domain = window.location.origin; + if (endpoint) { + const url = new URL(endpoint); if (active_tab === '1') { - setText(`${domain}${pathname.replace('/tree', '')}.git`); + setText(`${url.href}${pathname.replace('/tree/', '')}.git`); } else { - setText(`ssh://git@${window.location.hostname}:${pathname.replace('/tree', '')}.git`); + setText(`ssh://git@${url.host}${pathname.replace('/tree', '')}.git`); } } - }, [pathname, active_tab]); + }, [pathname, active_tab, endpoint]); diff --git a/moon/src/components/MergeDetail.tsx b/moon/src/components/MergeDetail.tsx deleted file mode 100644 index f2bf2ae56..000000000 --- a/moon/src/components/MergeDetail.tsx +++ /dev/null @@ -1,98 +0,0 @@ -'use client' -import React, { useEffect, useState } from 'react'; -import { Card, Button, List, Typography } from 'antd/lib'; -import { useRouter } from 'next/navigation'; - -const MRDetailPage = ({ mrDetail }) => { - const router = useRouter(); - const [filedata, setFileData] = useState([]); - const [loadings, setLoadings] = useState([]); - const [error, setError] = useState(null); - - useEffect(() => { - const fetchFileList = async () => { - set_to_loading(2) - try { - const res = await fetch(`/api/mr/${mrDetail.mr_link}/files`); - const result = await res.json(); - setFileData(result.data.data); - } catch (err) { - setError(err); - } finally { - cancel_loading(2) - } - }; - if (!mrDetail || !mrDetail.mr_link) { - return; - } - fetchFileList(); - }, [mrDetail]); - - - const set_to_loading = (index: number) => { - setLoadings((prevLoadings) => { - const newLoadings = [...prevLoadings]; - newLoadings[index] = true; - return newLoadings; - }); - } - - const cancel_loading = (index: number) => { - setLoadings((prevLoadings) => { - const newLoadings = [...prevLoadings]; - newLoadings[index] = false; - return newLoadings; - }); - } - - const approve_mr = async (index: number, mr_link: string) => { - set_to_loading(index); - const res = await fetch(`/api/mr/${mr_link}/merge`,{ - method: 'POST', - }); - if (res) { - cancel_loading(index); - } - - if (res.ok) { - router.refresh(); - } - }; - - - return ( - - {mrDetail.status === "open" && - - } - - More} - > - Change File List} - bordered - dataSource={filedata} - loading = {loadings[2]} - renderItem={(item) => ( - - {item} - - )} - /> - - - ) -} - -export default MRDetailPage; \ No newline at end of file diff --git a/sql/postgres/pg_20240912__init.sql b/sql/postgres/pg_20240923__init.sql similarity index 97% rename from sql/postgres/pg_20240912__init.sql rename to sql/postgres/pg_20240923__init.sql index 13875622b..e03c2d673 100644 --- a/sql/postgres/pg_20240912__init.sql +++ b/sql/postgres/pg_20240923__init.sql @@ -42,6 +42,7 @@ CREATE TABLE IF NOT EXISTS "mega_tag" ( CREATE TABLE IF NOT EXISTS "mega_mr" ( "id" BIGINT PRIMARY KEY, "mr_link" VARCHAR(40) NOT NULL, + "title" VARCHAR(80) NOT NULL, "merge_date" TIMESTAMP, "status" VARCHAR(20) NOT NULL, "path" TEXT NOT NULL, @@ -57,20 +58,13 @@ CREATE TABLE IF NOT EXISTS "mega_mr_conv" ( "mr_link" VARCHAR(20) NOT NULL, "user_id" BIGINT NOT NULL, "conv_type" VARCHAR(20) NOT NULL, + "comment" TEXT, "created_at" TIMESTAMP NOT NULL, "updated_at" TIMESTAMP NOT NULL ); CREATE INDEX "idx_conversation" ON "mega_mr_conv" ("mr_link"); -CREATE TABLE IF NOT EXISTS "mega_mr_comment" ( - "id" BIGINT PRIMARY KEY, - "conv_id" BIGINT NOT NULL, - "comment" TEXT, - "edited" BOOLEAN NOT NULL -); -CREATE INDEX "idx_comment_id" ON "mega_mr_comment" ("conv_id"); - CREATE TABLE IF NOT EXISTS "mega_issue" ( "id" BIGINT PRIMARY KEY, "number" BIGINT NOT NULL, diff --git a/sql/sqlite/sqlite_20240912_init.sql b/sql/sqlite/sqlite_20240923_init.sql similarity index 97% rename from sql/sqlite/sqlite_20240912_init.sql rename to sql/sqlite/sqlite_20240923_init.sql index 8e0e30e42..29fa615e9 100644 --- a/sql/sqlite/sqlite_20240912_init.sql +++ b/sql/sqlite/sqlite_20240923_init.sql @@ -42,6 +42,7 @@ CREATE TABLE IF NOT EXISTS "mega_tag" ( CREATE TABLE IF NOT EXISTS "mega_mr" ( "id" INTEGER PRIMARY KEY, "mr_link" TEXT NOT NULL, + "title" TEXT NOT NULL, "merge_date" TEXT, "status" TEXT NOT NULL, "path" TEXT NOT NULL, @@ -57,20 +58,12 @@ CREATE TABLE IF NOT EXISTS "mega_mr_conv" ( "mr_link" INTEGER NOT NULL, "user_id" INTEGER NOT NULL, "conv_type" TEXT NOT NULL, + "comment" TEXT, "created_at" TEXT NOT NULL, "updated_at" TEXT NOT NULL ); CREATE INDEX "idx_conversation" ON "mega_mr_conv" ("mr_link"); - -CREATE TABLE IF NOT EXISTS "mega_mr_comment" ( - "id" INTEGER PRIMARY KEY, - "conv_id" INTEGER NOT NULL, - "comment" TEXT, - "edited" INTEGER NOT NULL -); -CREATE INDEX "idx_comment_id" ON "mega_mr_comment" ("conv_id"); - CREATE TABLE IF NOT EXISTS "mega_issue" ( "id" INTEGER PRIMARY KEY, "number" INTEGER NOT NULL,