Skip to content
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
74 changes: 62 additions & 12 deletions moon/apps/web/components/Issues/IssueDetailPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@

import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'
import { IssueClosedIcon, IssueOpenedIcon, IssueReopenedIcon } from '@primer/octicons-react'
import { Stack } from '@primer/react'
import { Stack, TextInput } from '@primer/react'
import { useAtom } from 'jotai'
import { useRouter } from 'next/router'
import toast from 'react-hot-toast'

import { CommonResultIssueDetailRes } from '@gitmono/types'
import { Button, LoadingSpinner, PicturePlusIcon } from '@gitmono/ui'
import { Button, LoadingSpinner, PicturePlusIcon, UIText } from '@gitmono/ui'

import { EMPTY_HTML } from '@/atoms/markdown'
import { useHandleBottomScrollOffset } from '@/components/NoteEditor/useHandleBottomScrollOffset'
Expand All @@ -19,6 +19,7 @@ import { usePostIssueAssignees } from '@/hooks/issues/usePostIssueAssignees'
import { usePostIssueClose } from '@/hooks/issues/usePostIssueClose'
import { usePostIssueComment } from '@/hooks/issues/usePostIssueComment'
import { usePostIssueReopen } from '@/hooks/issues/usePostIssueReopen'
import { usePostIssueTitle } from '@/hooks/issues/usePostIssueTitle'
import { useGetCurrentUser } from '@/hooks/useGetCurrentUser'
import { useGetOrganizationMember } from '@/hooks/useGetOrganizationMember'
import { usePostIssueLabels } from '@/hooks/usePostIssueLabels'
Expand All @@ -42,15 +43,6 @@ import {
} from './utils/sideEffect'
import { idAtom } from './utils/store'

// interface IssueDetail {
// status: string
// conversations: Conversation[]
// title: string
// assignees?: string[]
// }

// let needComment = false

export default function IssueDetailPage({ link }: { link: string }) {
const [id] = useAtom(idAtom)
const [login, setLogin] = useState(false)
Expand Down Expand Up @@ -88,6 +80,10 @@ export default function IssueDetailPage({ link }: { link: string }) {

const issueDetail = issueDetailObj?.data as CommonResultIssueDetailRes['data'] | undefined

const [isEdit, setIsEdit] = useState(false)
const [editTitle, setEditTitle] = useState(issueDetail?.title)
const [titleloading, setTitleLoading] = useState(false)

const applyDetailData = (detail: CommonResultIssueDetailRes | undefined) => {
if (!detail || !detail.req_result || !detail.data) return
setInfo({
Expand Down Expand Up @@ -285,12 +281,66 @@ export default function IssueDetailPage({ link }: { link: string }) {
}
})

const { mutate: modifyTitle } = usePostIssueTitle()
const handleSave = () => {
if (editTitle === issueDetail?.title || editTitle === '') {
apiErrorToast(new Error('Nothing Changed or is Empty'))
return
}
setTitleLoading(true)
modifyTitle(
{ link, data: { content: editTitle as string } },
{
onError: (err) => apiErrorToast(err),
onSuccess: async () => await refetch({ throwOnError: true }),
onSettled: () => {
setIsEdit(false)
setTitleLoading(false)
}
}
)
}

return (
<>
<div className='h-screen overflow-auto pt-10'>
{info?.title && (
<div className='px-10 pb-4 text-xl'>
<div className='mb-4'>{info.title}</div>
<div className='mb-4 w-[70%]'>
{!isEdit && (
<>
<div className='flex w-full items-center justify-between'>
<UIText size='text-2xl' weight='font-bold' className='-tracking-[1px] lg:flex'>
{`${issueDetail?.title || ''}`}
</UIText>
<Button
onClick={() => {
setEditTitle(issueDetail?.title)
setIsEdit(true)
}}
>
Edit
</Button>
</div>
</>
)}
{isEdit && (
<>
<div className='flex w-full items-center justify-between gap-2'>
<TextInput
value={editTitle || ''}
onChange={(e) => setEditTitle(e.target.value)}
className='new-issue-input no-border-input w-[80%]'
trailingVisual={() => (titleloading ? <LoadingSpinner /> : '')}
/>
<div className='flex gap-4'>
<Button onClick={handleSave}>Save</Button>
<Button onClick={() => setIsEdit(false)}>Cancel</Button>
</div>
</div>
</>
)}
</div>
{info.status === 'open' ? (
<>
<span className='flex w-fit items-center gap-2 rounded-full bg-[#1f883d] px-3 py-1 text-sm text-[#fff]'>
Expand Down
55 changes: 55 additions & 0 deletions moon/apps/web/components/MrView/components/Checks/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { memo, useEffect, useRef, useState } from 'react'
import { LazyLog } from '@melloware/react-logviewer'

import { useSSM } from '../../hook/useSSM'

enum Status {
Pending = 'pending',
Fullfilled = 'fullfilled',
Rejected = 'rejected'
}

const Checks = () => {
const serverStream = useRef('')
const es = useRef<EventSource | null>()
const baseUrl = useRef('http://47.79.95.33:3000/logs?follow=true')
const status = useRef(Status.Pending)
const [displayTest, setDisplayText] = useState('')
const { createEventSource } = useSSM()

// 页面初始化时建立连接
useEffect(() => {
if (status.current !== Status.Fullfilled) {
createEventSource(baseUrl.current)
.then((res) => {
es.current = res
status.current = Status.Fullfilled
es.current.onmessage = (event) => {
serverStream.current += event.data + '\n'
setDisplayText(serverStream.current)
}
})
.catch(() => (status.current = Status.Rejected))
}

return () => {
// 关闭连接
status.current = Status.Pending
es.current?.close()
es.current = null
serverStream.current = ''
setDisplayText('')
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [])

return (
<>
<div style={{ height: `calc(100vh - 104px)` }}>
{displayTest && <LazyLog extraLines={1} text={displayTest} stream enableSearch caseInsensitive follow />}
</div>
</>
)
}

export default memo(Checks)
18 changes: 18 additions & 0 deletions moon/apps/web/components/MrView/hook/useSSM.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
export const useSSM = () => {
const createEventSource = (baseUrl: string): Promise<EventSource> => {
return new Promise<EventSource>((res, rej) => {
const es = new EventSource(baseUrl)

es.onopen = () => {
res(es)
}
es.onerror = () => {
rej('eventsource建立失败')
}
})
}

return {
createEventSource
}
}
11 changes: 11 additions & 0 deletions moon/apps/web/hooks/MR/usePostMrTitle.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { useMutation } from '@tanstack/react-query'

import { ContentPayload, PostApiMrTitleData, RequestParams } from '@gitmono/types/generated'

import { legacyApiClient } from '@/utils/queryClient'

export function usePostMrTitle() {
return useMutation<PostApiMrTitleData, Error, { link: string; data: ContentPayload; params?: RequestParams }>({
mutationFn: ({ link, data, params }) => legacyApiClient.v1.postApiMrTitle().request(link, data, params)
})
}
11 changes: 11 additions & 0 deletions moon/apps/web/hooks/issues/usePostIssueTitle.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { useMutation } from '@tanstack/react-query'

import { ContentPayload, PostApiIssueTitleData, RequestParams } from '@gitmono/types/generated'

import { legacyApiClient } from '@/utils/queryClient'

export function usePostIssueTitle() {
return useMutation<PostApiIssueTitleData, Error, { link: string; data: ContentPayload; params?: RequestParams }>({
mutationFn: ({ link, data, params }) => legacyApiClient.v1.postApiIssueTitle().request(link, data, params)
})
}
3 changes: 2 additions & 1 deletion moon/apps/web/next.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,8 @@ const cspResourcesByDirective = {
'https://gitmono.imgix.net',
process.env.NODE_ENV !== 'production' && 'https://campsite-dev.imgix.net',
'https://react-tweet.vercel.app', // for react-tweet embeds
'https://media.tenor.com' // used for Tenor gifs
'https://media.tenor.com', // used for Tenor gifs
'http://47.79.95.33:3000'
],
'font-src': ["'self'"],
'img-src': [
Expand Down
1 change: 1 addition & 0 deletions moon/apps/web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
"@heroicons/react": "catalog:",
"@hocuspocus/provider": "catalog:",
"@hookform/resolvers": "catalog:",
"@melloware/react-logviewer": "^6.3.2",
"@mui/icons-material": "catalog:",
"@mui/material": "catalog:",
"@mui/x-tree-view": "catalog:",
Expand Down
Loading