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
471 changes: 338 additions & 133 deletions moon/apps/web/components/Issues/IssueDetailPage.tsx

Large diffs are not rendered by default.

34 changes: 34 additions & 0 deletions moon/apps/web/components/Issues/IssueList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,40 @@ export const DropdownOrder = ({
</>
)
}
export const DropdownReview = ({
name,
dropdownArr,
dropdownItem,
onOpen,
open
}: {
name: string
dropdownArr: MenuItem[]
dropdownItem?: MenuItem[]
onOpen?: (open: boolean) => void
open?: boolean
inside?: React.ReactNode
}) => {
return (
<>
<DropdownMenu
open={open}
onOpenChange={onOpen}
key={name}
align='end'
desktop={{ width: 'w-72 max-h-[50vh] overflow-auto bg-white' }}
items={[...dropdownArr, ...(dropdownItem as MenuItem[])]}
trigger={
<Button size='sm' variant={'plain'} tooltipShortcut={name}>
<div className='flex items-center'>
{name} <ChevronDownIcon />
</div>
</Button>
}
/>
</>
)
}

// dropdownArr是不一样的,其他一样
export const Dropdown = ({
Expand Down
4 changes: 2 additions & 2 deletions moon/apps/web/components/Issues/IssueNewPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -310,7 +310,7 @@ type SelectPanelExcludedProps =
| 'renderAnchor'
| 'variant'

const BadgeItem = ({
export const BadgeItem = ({
title,
selectPannelProps,
items,
Expand Down Expand Up @@ -376,7 +376,7 @@ const BadgeItem = ({
)
}

const SideBarItem = ({ emptyState }: { emptyState: string }) => {
export const SideBarItem = ({ emptyState }: { emptyState: string }) => {
return (
<>
<div className='mx-4 text-sm text-gray-500'>
Expand Down
2 changes: 1 addition & 1 deletion moon/apps/web/components/Issues/IssuesContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -430,7 +430,7 @@ export const RightAvatar = ({ member, commentNum }: { member?: Member; commentNu
<div className='mr-10 flex items-center justify-between gap-10'>
<div className='flex items-center gap-2 text-sm text-gray-500'>
<ChatBubbleIcon />
<span>{commentNum}</span>
{commentNum !== 0 && <span>{commentNum}</span>}
</div>
{member && (
<MemberHovercard username={member.user.display_name} side='top' align='end' member={member}>
Expand Down
2 changes: 2 additions & 0 deletions moon/apps/web/components/Issues/utils/consts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ export const tags: LabelItem[] = [

export const orderTags = ['Created on', 'Last updated', 'Total comments', 'Best match', 'Oldest', 'Newest']

export const reviewTags = ['No reviews', 'Review required', 'Approved review', 'Changes requested']

export const searchList: SearchType = [
{
type: 'item',
Expand Down
52 changes: 50 additions & 2 deletions moon/apps/web/components/MrView/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import {
DropdownItemwithAvatar,
DropdownItemwithLabel,
DropdownOrder,
DropdownReview,
ListBanner,
ListItem as MrItem,
IssueList as MrList
Expand All @@ -29,7 +30,7 @@ import { atomWithWebStorage } from '@/utils/atomWithWebStorage'
import { IndexPageContainer, IndexPageContent } from '../IndexPages/components'
import { AdditionType, RightAvatar } from '../Issues/IssuesContent'
import { Pagination } from '../Issues/Pagenation'
import { orderTags, tags } from '../Issues/utils/consts'
import { orderTags, reviewTags, tags } from '../Issues/utils/consts'
import { generateAllMenuItems, MenuConfig } from '../Issues/utils/generateAllMenuItems'
import { filterAtom, sortAtom } from '../Issues/utils/store'
import { Heading } from './catalyst/heading'
Expand Down Expand Up @@ -63,12 +64,16 @@ export default function MrView() {
[scope]
)

const reviewAtom = useMemo(() => atomWithWebStorage(`${scope}:mr-review`, ''), [scope])

const labelAtom = useMemo(() => atomWithWebStorage<string[]>(`${scope}:mr-label`, []), [scope])

const [order, setOrder] = useAtom(orderAtom)

const [label, setLabel] = useAtom(labelAtom)

const [review, setReview] = useAtom(reviewAtom)

const additions = useCallback(
(labels: number[]): AdditionType => {
const additional: AdditionType = { status, asc: false }
Expand Down Expand Up @@ -240,6 +245,29 @@ export default function MrView() {
}
]

const ReviewConfig: MenuConfig<string>[] = [
{
key: 'Review',
isChosen: () => true,

onSelectFactory: (item) => (e: Event) => {
e.preventDefault()
if (item === review) {
setReview('')
} else {
setReview(item)
}
},
className: 'overflow-hidden',
labelFactory: (item) => (
<div className='flex items-center gap-2'>
<div className='h-4 w-4'>{review === item && <CheckIcon />}</div>
<span className='flex-1'>{item}</span>
</div>
)
}
]

const OrderConfig: MenuConfig<string>[] = [
{
key: 'Order',
Expand Down Expand Up @@ -292,6 +320,8 @@ export default function MrView() {

const orders = generateAllMenuItems(orderTags, OrderConfig)

const reviews = generateAllMenuItems(reviewTags, ReviewConfig)

const ListHeaderItem = (p: string) => {
switch (p) {
case 'Author':
Expand All @@ -314,6 +344,15 @@ export default function MrView() {
dropdownItem={member?.get('Assignees').chosen}
/>
)
case 'Reviews':
return (
<DropdownReview
key={p}
name={p}
dropdownArr={reviews?.get('Review').all}
dropdownItem={reviews?.get('Review').chosen}
/>
)
case 'Labels':
return (
<Dropdown
Expand Down Expand Up @@ -367,7 +406,16 @@ export default function MrView() {
Issuelists={mrList}
header={
<ListBanner
pickerTypes={['Author', 'Labels', 'Projects', 'Milestones', 'Assignees', 'Types', `${order.sort}`]}
pickerTypes={[
'Author',
'Labels',
'Projects',
'Milestones',
'Reviews',
'Assignees',
'Types',
`${order.sort}`
]}
tabfilter={<MRIndexTabFilter part='mr' />}
>
{(p) => ListHeaderItem(p)}
Expand Down
31 changes: 29 additions & 2 deletions moon/apps/web/components/SimpleNoteEditor/SimpleNoteContent.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,14 @@
import { DragEvent, forwardRef, KeyboardEvent, memo, MouseEvent, useImperativeHandle, useRef, useState } from 'react'
import {
DragEvent,
forwardRef,
KeyboardEvent,
memo,
MouseEvent,
useEffect,
useImperativeHandle,
useRef,
useState
} from 'react'
import { Editor as TTEditor } from '@tiptap/core'
import { EditorContent } from '@tiptap/react'

Expand Down Expand Up @@ -28,6 +38,7 @@ interface Props {
content: string
onBlurAtTop?: BlurAtTopOptions['onBlur']
onKeyDown?: (event: KeyboardEvent) => void
onChange?: (html: string) => void
}

export interface SimpleNoteContentRef {
Expand All @@ -42,7 +53,7 @@ export interface SimpleNoteContentRef {

export const SimpleNoteContent = memo(
forwardRef<SimpleNoteContentRef, Props>((props, ref) => {
const { commentId, editable = 'viewer', autofocus = false, onBlurAtTop, content } = props
const { commentId, editable = 'viewer', autofocus = false, onBlurAtTop, content, onChange } = props

const [activeComment, setActiveComment] = useState<ActiveEditorComment | null>(null)
const [hoverComment, setHoverComment] = useState<ActiveEditorComment | null>(null)
Expand Down Expand Up @@ -120,6 +131,22 @@ export const SimpleNoteContent = memo(
enabled: true
})

useEffect(() => {
if (!editor || !onChange) return

const handleUpdate = () => {
const html = editor.getHTML()

onChange?.(html)

Copilot AI Jul 12, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] The optional chaining is unnecessary here since there's already a null check for onChange at line 135. Consider using onChange(html) directly for cleaner code.

Suggested change
onChange?.(html)
onChange(html)

Copilot uses AI. Check for mistakes.
}

editor.on('update', handleUpdate)

return () => {
editor.off('update', handleUpdate)
}
}, [editor, onChange])

return (
<div ref={containerRef} className='relative mb-2 h-[95%] min-h-[100px] overflow-auto'>
<LayeredHotkeys
Expand Down
7 changes: 6 additions & 1 deletion moon/apps/web/pages/[org]/issue/[id]/index.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { BaseStyles, ThemeProvider } from '@primer/react'
import { GetServerSideProps } from 'next'

import IssueDetailPage from '@/components/Issues/IssueDetailPage'
Expand All @@ -24,7 +25,11 @@ export const getServerSideProps: GetServerSideProps = async ({ query }) => {
const OrganizationIssueDetailPage: PageWithLayout<any> = ({ id }) => {
return (
<>
<IssueDetailPage id={id} key={id} />
<ThemeProvider>
<BaseStyles>
<IssueDetailPage id={id} key={id} />
</BaseStyles>
</ThemeProvider>
</>
)
}
Expand Down
8 changes: 4 additions & 4 deletions moon/apps/web/pages/[org]/issue/new/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@ const OrganizationIssueNewPage: PageWithLayout<any> = () => {
return (
<>
<ThemeProvider>
<BaseStyles>
<IssueNewPage key={router.pathname} />
</BaseStyles>
</ThemeProvider>
<BaseStyles>
<IssueNewPage key={router.pathname} />
</BaseStyles>
</ThemeProvider>
</>
)
}
Expand Down