From 3176d15ecf4ec5e624efb9a946ca52de4f082336 Mon Sep 17 00:00:00 2001 From: Calvin Lee Date: Mon, 27 Jan 2025 10:11:36 -0700 Subject: [PATCH 1/9] feat: [pipe-24078]: update design on deleted files and large files (#834) Signed-off-by: Calvin Lee Co-authored-by: Calvin Lee --- .../compare/components/pull-request-compare-diff-list.tsx | 8 ++++---- .../details/components/changes/pull-request-changes.tsx | 8 ++++---- .../repo-commit-details/components/commit-changes.tsx | 8 ++++---- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/packages/ui/src/views/repo/pull-request/compare/components/pull-request-compare-diff-list.tsx b/packages/ui/src/views/repo/pull-request/compare/components/pull-request-compare-diff-list.tsx index fb40b1f8c..4e1ca30c3 100644 --- a/packages/ui/src/views/repo/pull-request/compare/components/pull-request-compare-diff-list.tsx +++ b/packages/ui/src/views/repo/pull-request/compare/components/pull-request-compare-diff-list.tsx @@ -85,11 +85,11 @@ const PullRequestAccordion: FC = ({
{(fileDeleted || isDiffTooLarge || fileUnchanged || header?.isBinary) && !showHiddenDiff ? ( - + )} {err && {err}} - +
diff --git a/packages/ui/src/views/repo/pull-request/components/pull-request-item-title.tsx b/packages/ui/src/views/repo/pull-request/components/pull-request-item-title.tsx index 4d8984d9a..80d0a78e9 100644 --- a/packages/ui/src/views/repo/pull-request/components/pull-request-item-title.tsx +++ b/packages/ui/src/views/repo/pull-request/components/pull-request-item-title.tsx @@ -47,8 +47,8 @@ export const PullRequestItemTitle: FC = ({ merged }) => { return ( -
-
+
+
= ({ name={getPrState(isDraft, merged, state).icon} /> -

{title}

+

{title}

{labels?.map((l, l_idx) => { const { border, text, bg } = colorMapping[l.color] ? colorMapping[l.color] diff --git a/packages/ui/src/views/repo/pull-request/components/pull-request-list.tsx b/packages/ui/src/views/repo/pull-request/components/pull-request-list.tsx index ea562afa1..306a9d1d3 100644 --- a/packages/ui/src/views/repo/pull-request/components/pull-request-list.tsx +++ b/packages/ui/src/views/repo/pull-request/components/pull-request-list.tsx @@ -73,7 +73,7 @@ export const PullRequestList: FC = ({ {pullRequest.number && ( <> Details diff --git a/packages/ui/src/views/repo/webhooks/webhook-list/components/repo-webhook-list.tsx b/packages/ui/src/views/repo/webhooks/webhook-list/components/repo-webhook-list.tsx index df291cbf7..59409e681 100644 --- a/packages/ui/src/views/repo/webhooks/webhook-list/components/repo-webhook-list.tsx +++ b/packages/ui/src/views/repo/webhooks/webhook-list/components/repo-webhook-list.tsx @@ -1,4 +1,4 @@ -import { useNavigate } from 'react-router-dom' +import { Link, useNavigate } from 'react-router-dom' import { Badge, MoreActionsTooltip, NoData, PaginationComponent, Spacer, StackedList, Text } from '@/components' import { TranslationStore, WebhookType } from '@/views' @@ -97,38 +97,40 @@ export function RepoWebhookList({ <> {webhooks.map((webhook, webhook_idx) => ( - - {webhook.description}} - title={} - className="gap-1.5" - /> - <StackedList.Field - title={ - <MoreActionsTooltip - actions={[ - { - title: t('views:webhookData.edit', 'Edit webhook'), - to: `${webhook.id}` - }, - { - isDanger: true, - title: t('views:webhookData.delete', 'Delete webhook'), - onClick: () => openDeleteWebhookDialog(webhook.id) - } - ]} - /> - } - right - label - secondary - /> - </StackedList.Item> + <Link key={webhook.id} to={`${webhook.id}`}> + <StackedList.Item + key={webhook.createdAt} + className="py-3 pr-1.5 cursor-pointer" + isLast={webhooks.length - 1 === webhook_idx} + > + <StackedList.Field + primary + description={<span className="leading-none">{webhook.description}</span>} + title={<Title title={webhook.name} isEnabled={webhook.enabled} />} + className="gap-1.5" + /> + <StackedList.Field + title={ + <MoreActionsTooltip + actions={[ + { + title: t('views:webhookData.edit', 'Edit webhook'), + to: `${webhook.id}` + }, + { + isDanger: true, + title: t('views:webhookData.delete', 'Delete webhook'), + onClick: () => openDeleteWebhookDialog(webhook.id) + } + ]} + /> + } + right + label + secondary + /> + </StackedList.Item> + </Link> ))} </StackedList.Root> <PaginationComponent totalPages={totalPages} currentPage={page} goToPage={setPage} t={t} /> From 68c6db28a5f0747b1765f4794810a6eadbaf6950 Mon Sep 17 00:00:00 2001 From: Sanskar <c_sanskar.sehgal@harness.io> Date: Mon, 27 Jan 2025 11:32:03 -0800 Subject: [PATCH 3/9] feat: Adds the repo empty view (#836) * feat: add repo empty view * feat: add preview * fix: minor design fixes * fix: spacing --- .../src/pages/view-preview/view-preview.tsx | 6 + .../views/repo-empty/repo-empty-view.tsx | 12 ++ packages/ui/src/views/repo/index.ts | 1 + .../repo/repo-summary/repo-empty-view.tsx | 105 ++++++++++++++++++ .../views/repo/repo-summary/repo-summary.tsx | 12 +- 5 files changed, 130 insertions(+), 6 deletions(-) create mode 100644 apps/design-system/src/subjects/views/repo-empty/repo-empty-view.tsx create mode 100644 packages/ui/src/views/repo/repo-summary/repo-empty-view.tsx diff --git a/apps/design-system/src/pages/view-preview/view-preview.tsx b/apps/design-system/src/pages/view-preview/view-preview.tsx index 83ac18567..c48e54dd6 100644 --- a/apps/design-system/src/pages/view-preview/view-preview.tsx +++ b/apps/design-system/src/pages/view-preview/view-preview.tsx @@ -18,6 +18,7 @@ import { RepoBranchesView } from '@subjects/views/repo-branches' import { RepoCommitsView } from '@subjects/views/repo-commits' import { CreateRepoView } from '@subjects/views/repo-create' import { RepoCreateRule } from '@subjects/views/repo-create-rule' +import { RepoEmpty } from '@subjects/views/repo-empty/repo-empty-view' import { RepoFilesEditView } from '@subjects/views/repo-files/repo-files-edit-view' import { RepoFilesJsonView } from '@subjects/views/repo-files/repo-files-json-view' import { RepoFilesList } from '@subjects/views/repo-files/repo-files-list' @@ -62,6 +63,11 @@ export const viewPreviews: Record<string, ReactNode> = { <RepoSummaryViewWrapper /> </RepoViewWrapper> ), + 'repo-empty': ( + <RepoViewWrapper> + <RepoEmpty /> + </RepoViewWrapper> + ), 'repo-list': ( <RootViewWrapper> <RepoListWrapper /> diff --git a/apps/design-system/src/subjects/views/repo-empty/repo-empty-view.tsx b/apps/design-system/src/subjects/views/repo-empty/repo-empty-view.tsx new file mode 100644 index 000000000..ed7f3f839 --- /dev/null +++ b/apps/design-system/src/subjects/views/repo-empty/repo-empty-view.tsx @@ -0,0 +1,12 @@ +import { RepoEmptyView } from '@harnessio/ui/views' + +export const RepoEmpty = () => { + return ( + <RepoEmptyView + httpUrl="https://github.com/mock-repo" + repoName="mock-repo" + projName="mock-project" + sshUrl="git@github.com:mock-repo.git" + /> + ) +} diff --git a/packages/ui/src/views/repo/index.ts b/packages/ui/src/views/repo/index.ts index bd8e8e507..25c62b77c 100644 --- a/packages/ui/src/views/repo/index.ts +++ b/packages/ui/src/views/repo/index.ts @@ -13,6 +13,7 @@ export * from '@views/repo/repo-create' // repo summary export * from '@views/repo/repo-summary/repo-summary' +export * from '@views/repo/repo-summary/repo-empty-view' // repo types export * from '@views/repo/repo.types' diff --git a/packages/ui/src/views/repo/repo-summary/repo-empty-view.tsx b/packages/ui/src/views/repo/repo-summary/repo-empty-view.tsx new file mode 100644 index 000000000..fc7900b70 --- /dev/null +++ b/packages/ui/src/views/repo/repo-summary/repo-empty-view.tsx @@ -0,0 +1,105 @@ +import { + Button, + ButtonGroup, + ControlGroup, + CopyButton, + Fieldset, + FormSeparator, + Input, + MarkdownViewer, + NoData, + Spacer, + StyledLink, + Text +} from '@/components' +import { SandboxLayout } from '@/views' + +interface RepoEmptyViewProps { + repoName: string + projName: string + httpUrl: string + sshUrl: string +} + +export const RepoEmptyView: React.FC<RepoEmptyViewProps> = ({ repoName, projName, httpUrl, sshUrl }) => { + const getInitialCommitMarkdown = () => { + return ` +\`\`\`shell +cd ${repoName} +git branch -M main +echo '# Hello World' >> README.md +git add README.md +git commit -m 'Initial commit' +git push -u origin main +\`\`\` +` + } + + const getExistingRepoMarkdown = () => { + return ` +\`\`\`shell +git remote add origin http://localhost:3000/git/${projName}/${repoName}.git +git branch -M main +git push -u origin main +\`\`\` +` + } + return ( + <SandboxLayout.Main> + <SandboxLayout.Content className="max-w-[850px] mx-auto"> + <Text size={5} weight={'medium'}> + Repository + </Text> + <Spacer size={6} /> + <NoData + withBorder + iconName="no-repository" + title="This repository is empty" + description={['We recommend every repository include a', 'README, LICENSE, and .gitignore.']} + primaryButton={{ label: 'New file' }} + className="py-0 pb-0 min-h-[40vh]" + /> + <Spacer size={6} /> + + <Fieldset> + <Text size={4} weight="medium"> + Please Generate Git Cradentials if it’s your first time cloning the repository + </Text> + <Text size={3}>Git clone URL</Text> + <Input label="HTTP" value={httpUrl} readOnly rightElement={<CopyButton name={httpUrl} />} /> + <Input label="SSH" value={sshUrl} readOnly rightElement={<CopyButton name={sshUrl} />} /> + <ControlGroup> + <ButtonGroup> + <Button>Generate Clone Credentials</Button> + </ButtonGroup> + <p className="mt-2"> + You can also manage your git credential{' '} + <StyledLink to="/" relative="path"> + here + </StyledLink> + </p> + </ControlGroup> + + <FormSeparator /> + <Text size={4} weight="medium"> + Then push some content into it + </Text> + <MarkdownViewer source={getInitialCommitMarkdown()} /> + <Text size={4} weight="medium"> + Or you can push an existing repository + </Text> + <ControlGroup> + <MarkdownViewer source={getExistingRepoMarkdown()} /> + <p> + You might need to{' '} + <StyledLink to="/" relative="path"> + create an API token + </StyledLink>{' '} + In order to pull from or push into this repository. + </p> + </ControlGroup> + </Fieldset> + </SandboxLayout.Content> + </SandboxLayout.Main> + ) +} diff --git a/packages/ui/src/views/repo/repo-summary/repo-summary.tsx b/packages/ui/src/views/repo/repo-summary/repo-summary.tsx index c321e22a2..f4b093c5d 100644 --- a/packages/ui/src/views/repo/repo-summary/repo-summary.tsx +++ b/packages/ui/src/views/repo/repo-summary/repo-summary.tsx @@ -28,6 +28,7 @@ import { formatDate } from '@utils/utils' import { CloneRepoDialog } from './components/clone-repo-dialog' import SummaryPanel from './components/summary-panel' +import { RepoEmptyView } from './repo-empty-view' interface RoutingProps { toRepoFiles: () => string @@ -119,12 +120,11 @@ export function RepoSummaryView({ if (!repoEntryPathToFileTypeMap.size) { return ( - <NoData - iconName="no-data-folder" - title="No files yet" - description={['There are no files in this repository yet.', 'Create new or import an existing file.']} - primaryButton={{ label: 'Create file' }} - secondaryButton={{ label: 'Import file' }} + <RepoEmptyView + sshUrl={repository?.git_ssh_url ?? 'could not fetch url'} + httpUrl={repository?.git_url ?? 'could not fetch url'} + repoName={repoId} + projName={spaceId} /> ) } From a0aa052d7ea4141d749633f8de79609fd07a0bbe Mon Sep 17 00:00:00 2001 From: Calvin Lee <calvin.lee@harness.io> Date: Mon, 27 Jan 2025 13:41:56 -0700 Subject: [PATCH 4/9] feat: [pipe-24076]: fix text on compare page (#842) * feat: [pipe-24076]: fix text on compare page Signed-off-by: Calvin Lee <cjlee@ualberta.ca> * feat: [pipe-24076]: fix api on branch get Signed-off-by: Calvin Lee <cjlee@ualberta.ca> * feat: [pipe-24076]: fix api on branch get Signed-off-by: Calvin Lee <cjlee@ualberta.ca> --------- Signed-off-by: Calvin Lee <cjlee@ualberta.ca> Co-authored-by: Calvin Lee <cjlee@ualberta.ca> --- .../src/pages-v2/pull-request/pull-request-compare.tsx | 9 ++++++++- apps/gitness/src/pages-v2/repo/repo-sidebar.tsx | 2 +- apps/gitness/src/pages-v2/repo/repo-summary.tsx | 2 +- packages/ui/locales/en/views.json | 4 ++-- .../pull-request/compare/pull-request-compare-page.tsx | 2 +- 5 files changed, 13 insertions(+), 6 deletions(-) diff --git a/apps/gitness/src/pages-v2/pull-request/pull-request-compare.tsx b/apps/gitness/src/pages-v2/pull-request/pull-request-compare.tsx index a359bd829..04bd065fb 100644 --- a/apps/gitness/src/pages-v2/pull-request/pull-request-compare.tsx +++ b/apps/gitness/src/pages-v2/pull-request/pull-request-compare.tsx @@ -244,7 +244,14 @@ export const CreatePullRequest = () => { } const { data: { body: branches } = {} } = useListBranchesQuery({ repo_ref: repoRef, - queryParams: { page: 0, limit: 10, query: sourceQuery || targetQuery || '', include_pullreqs: true } + queryParams: { + page: 0, + sort: 'date', + order: 'desc', + limit: 10, + query: sourceQuery || targetQuery || '', + include_pullreqs: true + } }) useEffect(() => { diff --git a/apps/gitness/src/pages-v2/repo/repo-sidebar.tsx b/apps/gitness/src/pages-v2/repo/repo-sidebar.tsx index da658c96b..0e5085435 100644 --- a/apps/gitness/src/pages-v2/repo/repo-sidebar.tsx +++ b/apps/gitness/src/pages-v2/repo/repo-sidebar.tsx @@ -57,7 +57,7 @@ export const RepoSidebar = () => { queryParams: { include_commit: false, sort: 'date', - order: orderSortDate.ASC, + order: orderSortDate.DESC, limit: 50, query: searchQuery } diff --git a/apps/gitness/src/pages-v2/repo/repo-summary.tsx b/apps/gitness/src/pages-v2/repo/repo-summary.tsx index 2b1f61f7c..6c3d49c82 100644 --- a/apps/gitness/src/pages-v2/repo/repo-summary.tsx +++ b/apps/gitness/src/pages-v2/repo/repo-summary.tsx @@ -73,7 +73,7 @@ export default function RepoSummaryPage() { const { data: { body: branches } = {} } = useListBranchesQuery({ repo_ref: repoRef, - queryParams: { include_commit: false, sort: 'date', order: orderSortDate.ASC, limit: 50, query: branchTagQuery } + queryParams: { include_commit: false, sort: 'date', order: orderSortDate.DESC, limit: 50, query: branchTagQuery } }) const { data: { body: branchDivergence = [] } = {}, mutate: calculateDivergence } = diff --git a/packages/ui/locales/en/views.json b/packages/ui/locales/en/views.json index 1d7d3babb..c7e178b96 100644 --- a/packages/ui/locales/en/views.json +++ b/packages/ui/locales/en/views.json @@ -172,7 +172,7 @@ "noCommitsYet": "No commits yet", "noCommitsYetDescription": "Your commits will appear here once they're made. Start committing to see your changes reflected.", "compareChanges": "Compare and review just about anything", - "compareChangesDescription": "Branches, tags, commit ranges, and time ranges. In the same repository and across forks.", + "compareChangesDescription": "Branches and commit ranges can be reviewed within the same repository.", "clearFilters": "Clear filters", "noPullRequests": "There are no pull requests in this project yet.", "createNewPullRequest": "Create a new pull request.", @@ -231,7 +231,7 @@ "compareChangesCantMergeDesciption": "You can still create the pull request.", "compareChangesDiscussChanges": "Discuss and review the changes in this comparison with others.", "compareChangesDiscussChangesLink": "Learn about pull requests.", - "compareChangesChooseDifferent": "Choose different branches or forks above to discuss and review changes.", + "compareChangesChooseDifferent": "Choose different branches above to discuss and review changes.", "compareChangesViewPRLink": "View pull request", "compareChangesTabOverview": "Overview", "compareChangesTabCommits": "Commits", diff --git a/packages/ui/src/views/repo/pull-request/compare/pull-request-compare-page.tsx b/packages/ui/src/views/repo/pull-request/compare/pull-request-compare-page.tsx index 7881a1134..8771fc165 100644 --- a/packages/ui/src/views/repo/pull-request/compare/pull-request-compare-page.tsx +++ b/packages/ui/src/views/repo/pull-request/compare/pull-request-compare-page.tsx @@ -283,7 +283,7 @@ export const PullRequestComparePage: FC<PullRequestComparePageProps> = ({ ) : ( t( 'views:pullRequests.compareChangesChooseDifferent', - 'Choose different branches or forks above to discuss and review changes.' + 'Choose different branches above to discuss and review changes.' ) )} </p> From ad6eaff797c7af8e8c3c23676f8c798090767e66 Mon Sep 17 00:00:00 2001 From: Andrew Golovanov <spacewebdeveloper@gmail.com> Date: Tue, 28 Jan 2025 00:45:16 +0300 Subject: [PATCH 5/9] feat: improving the styles and functionality of the PR detail page (#820) Co-authored-by: Calvin Lee <calvin.lee@harness.io> --- .../pages/view-preview/repo-view-wrapper.tsx | 2 +- .../pull-request-conversation.tsx | 1 - .../pull-request-panelData.ts | 138 ++++++++++ apps/gitness/src/components-v2/app-shell.tsx | 2 +- .../pull-request-conversation.tsx | 2 - packages/ui/src/components/badge.tsx | 2 +- packages/ui/src/components/button.tsx | 2 +- packages/ui/src/components/icon.tsx | 10 +- .../src/components/markdown-viewer/index.tsx | 10 +- packages/ui/src/components/node-group.tsx | 8 +- packages/ui/src/icons/attachment-image.svg | 12 + packages/ui/src/icons/attachment.svg | 10 +- packages/ui/src/icons/bold.svg | 5 +- packages/ui/src/icons/code.svg | 12 +- packages/ui/src/icons/collapse-comment.svg | 16 ++ packages/ui/src/icons/expand-comment.svg | 16 ++ packages/ui/src/icons/suggestion.svg | 13 + .../src/views/layouts/PullRequestLayout.tsx | 31 ++- .../pull-request-compare-tab-trigger-item.tsx | 24 +- .../components/pull-request-diff-viewer.tsx | 48 ++-- .../changes/pull-request-changes.tsx | 2 - .../conversation/pull-request-comment-box.tsx | 246 ++++++++++-------- .../pull-request-description-box.tsx | 21 +- .../conversation/pull-request-overview.tsx | 59 ++--- .../pull-request-system-comments.tsx | 22 +- .../pull-request-timeline-item.tsx | 208 +++++++++------ .../sections/pull-request-changes-section.tsx | 2 +- 27 files changed, 582 insertions(+), 342 deletions(-) create mode 100644 packages/ui/src/icons/attachment-image.svg create mode 100644 packages/ui/src/icons/collapse-comment.svg create mode 100644 packages/ui/src/icons/expand-comment.svg create mode 100644 packages/ui/src/icons/suggestion.svg diff --git a/apps/design-system/src/pages/view-preview/repo-view-wrapper.tsx b/apps/design-system/src/pages/view-preview/repo-view-wrapper.tsx index 7dc7963ce..69b3a70d7 100644 --- a/apps/design-system/src/pages/view-preview/repo-view-wrapper.tsx +++ b/apps/design-system/src/pages/view-preview/repo-view-wrapper.tsx @@ -13,7 +13,7 @@ const RepoViewWrapper: FC<PropsWithChildren<React.HTMLAttributes<HTMLElement>>> path="*" element={ <> - <div className="layer-high sticky top-[55px] bg-background-1"> + <div className="layer-high bg-background-1 sticky top-[55px]"> <RepoSubheader useTranslationStore={useTranslationsStore} /> </div> {children} diff --git a/apps/design-system/src/subjects/views/pull-request-conversation/pull-request-conversation.tsx b/apps/design-system/src/subjects/views/pull-request-conversation/pull-request-conversation.tsx index 638fdb989..f033d8633 100644 --- a/apps/design-system/src/subjects/views/pull-request-conversation/pull-request-conversation.tsx +++ b/apps/design-system/src/subjects/views/pull-request-conversation/pull-request-conversation.tsx @@ -201,7 +201,6 @@ const PullRequestConversation: FC<PullRequestConversationProps> = ({ state }) => handleSaveComment={noop} currentUser={{ display_name: currentUserData?.display_name, uid: currentUserData?.uid }} onCopyClick={noop} - onCommentSaveAndStatusChange={noop} toggleConversationStatus={noop} onCommitSuggestion={noop} addSuggestionToBatch={noop} diff --git a/apps/design-system/src/subjects/views/pull-request-conversation/pull-request-panelData.ts b/apps/design-system/src/subjects/views/pull-request-conversation/pull-request-panelData.ts index 6edd0c9ca..b5901e8ee 100644 --- a/apps/design-system/src/subjects/views/pull-request-conversation/pull-request-panelData.ts +++ b/apps/design-system/src/subjects/views/pull-request-conversation/pull-request-panelData.ts @@ -164,6 +164,144 @@ export const mockPullRequestActions = [ ] export const mockActivities = [ + { + id: 795, + created: 1737660580605, + updated: 1737660580605, + edited: 1737660580605, + parent_id: null, + repo_id: 22, + pullreq_id: 174, + order: 2, + sub_order: 0, + type: 'code-comment', + kind: 'change-comment', + text: 'We should add type checking for this function to improve type safety', + payload: { + title: '@@ -0,0 +1,4 @@', + lines: [ + "+import tailwindcssAnimate from 'tailwindcss-animate'", + "+import { PluginAPI } from 'tailwindcss/types/config'", + '+', + '+export default {' + ], + line_start_new: true, + line_end_new: true + }, + author: { + id: 3, + uid: 'admin', + display_name: 'Administrator', + email: 'admin@gitness.io', + type: 'user', + created: 1699863416002, + updated: 1699863416002 + }, + resolved: 1737660580605, + resolver: { + id: 3, + uid: 'admin', + display_name: 'Administrator', + email: 'admin@gitness.io', + type: 'user', + created: 1699863416002, + updated: 1699863416002 + }, + code_comment: { + outdated: false, + merge_base_sha: '12421f51a7cca90376cba8de0fe9b3289eb6e218', + source_sha: '34f4d7bbfeda153e4965395ac6a20e80dec63e57', + path: 'packages/canary/configs/tailwind.ts', + line_new: 2, + span_new: 1, + line_old: 0, + span_old: 0 + } + }, + { + id: 796, + created: 1737660580605, + updated: 1737660580605, + edited: 1737660580605, + parent_id: null, + repo_id: 22, + pullreq_id: 174, + order: 2, + sub_order: 0, + type: 'comment', + kind: 'comment', + text: 'Should we consider adding unit tests for the new animation components?', + payload: {}, + author: { + id: 3, + uid: 'admin', + display_name: 'Administrator', + email: 'admin@gitness.io', + type: 'user', + created: 1699863416002, + updated: 1699863416002 + }, + resolved: 1737660580607, + resolver: { + id: 3, + uid: 'admin', + display_name: 'Administrator', + email: 'admin@gitness.io', + type: 'user', + created: 1699863416002, + updated: 1699863416002 + } + }, + + { + id: 797, + created: 1737660580606, + updated: 1737660580606, + edited: 1737660580606, + parent_id: 796, + repo_id: 22, + pullreq_id: 174, + order: 2, + sub_order: 1, + type: 'comment', + kind: 'comment', + text: 'Yes, I agree. I will add tests for basic animations first.', + payload: {}, + author: { + id: 3, + uid: 'admin', + display_name: 'Administrator', + email: 'admin@gitness.io', + type: 'user', + created: 1699863416002, + updated: 1699863416002 + } + }, + + { + id: 798, + created: 1737660580607, + updated: 1737660580607, + edited: 1737660580607, + parent_id: 796, + repo_id: 22, + pullreq_id: 174, + order: 2, + sub_order: 2, + type: 'comment', + kind: 'comment', + text: 'Tests have been added in PR #123. We can close this discussion.', + payload: {}, + author: { + id: 3, + uid: 'admin', + display_name: 'Administrator', + email: 'admin@gitness.io', + type: 'user', + created: 1699863416002, + updated: 1699863416002 + } + }, { id: 792, created: 1737660563002, diff --git a/apps/gitness/src/components-v2/app-shell.tsx b/apps/gitness/src/components-v2/app-shell.tsx index 46ca226f0..ab104f5bd 100644 --- a/apps/gitness/src/components-v2/app-shell.tsx +++ b/apps/gitness/src/components-v2/app-shell.tsx @@ -216,7 +216,7 @@ export const AppShellMFE = () => { function BreadcrumbsAndOutlet({ className }: { className?: string }) { return ( <div className={cn('flex flex-col', className)}> - <div className="layer-high bg-background-1 sticky top-0"> + <div className="layer-high sticky top-0 bg-background-1"> <Breadcrumbs /> </div> <Outlet /> diff --git a/apps/gitness/src/pages-v2/pull-request/pull-request-conversation.tsx b/apps/gitness/src/pages-v2/pull-request/pull-request-conversation.tsx index 95f9d1ec0..0fbc2a662 100644 --- a/apps/gitness/src/pages-v2/pull-request/pull-request-conversation.tsx +++ b/apps/gitness/src/pages-v2/pull-request/pull-request-conversation.tsx @@ -526,7 +526,6 @@ export default function PullRequestConversationPage() { onCommitSuggestionsBatch, suggestionsBatch, suggestionToCommit, - onCommentSaveAndStatusChange, toggleConversationStatus, handleUpload } = usePRCommonInteractions({ @@ -662,7 +661,6 @@ export default function PullRequestConversationPage() { handleSaveComment={handleSaveComment} currentUser={{ display_name: currentUserData?.display_name, uid: currentUserData?.uid }} onCopyClick={onCopyClick} - onCommentSaveAndStatusChange={onCommentSaveAndStatusChange} toggleConversationStatus={toggleConversationStatus} onCommitSuggestion={onCommitSuggestion} addSuggestionToBatch={addSuggestionToBatch} diff --git a/packages/ui/src/components/badge.tsx b/packages/ui/src/components/badge.tsx index 9b4f18d80..0bc3775df 100644 --- a/packages/ui/src/components/badge.tsx +++ b/packages/ui/src/components/badge.tsx @@ -34,7 +34,7 @@ const badgeVariants = cva( lg: 'px-3 py-1 text-xs font-normal', md: 'h-6 px-2.5', sm: 'h-5 px-1.5 text-12', - xs: 'px-1.5 py-0 text-11 font-light' + xs: 'h-[18px] px-1.5 text-11 font-light' }, borderRadius: { default: 'rounded-md', diff --git a/packages/ui/src/components/button.tsx b/packages/ui/src/components/button.tsx index 43cb9f19d..20a9cb096 100644 --- a/packages/ui/src/components/button.tsx +++ b/packages/ui/src/components/button.tsx @@ -6,7 +6,7 @@ import { cn } from '@utils/cn' import { cva, type VariantProps } from 'class-variance-authority' const buttonVariants = cva( - 'inline-flex items-center justify-center whitespace-nowrap rounded text-sm font-medium transition-colors disabled:pointer-events-none disabled:cursor-not-allowed', + 'inline-flex items-center justify-center whitespace-nowrap rounded text-14 font-medium transition-colors disabled:pointer-events-none disabled:cursor-not-allowed', { variants: { variant: { diff --git a/packages/ui/src/components/icon.tsx b/packages/ui/src/components/icon.tsx index 97cf4ad85..be10506d0 100644 --- a/packages/ui/src/components/icon.tsx +++ b/packages/ui/src/components/icon.tsx @@ -9,6 +9,7 @@ import AppleShortcut from '../icons/apple-shortcut.svg' import ArrowLong from '../icons/arrow-long.svg' import ArtifactsGradient from '../icons/artifacts-gradient.svg' import Artifacts from '../icons/artifacts-icon.svg' +import AttachmentImage from '../icons/attachment-image.svg' import Attachment from '../icons/attachment.svg' import BitrisePlugin from '../icons/bitrise-plugin.svg' import Bold from '../icons/bold.svg' @@ -45,6 +46,7 @@ import CloudCosts from '../icons/cloud-costs-icon.svg' import CodeBrackets from '../icons/code-brackets.svg' import Code from '../icons/code.svg' import Cog6 from '../icons/cog-6.svg' +import CollapseComment from '../icons/collapse-comment.svg' import CollapseDiff from '../icons/collapse-diff.svg' import Comments from '../icons/comments.svg' import Compare from '../icons/compare.svg' @@ -67,6 +69,7 @@ import Edit from '../icons/edit-icon.svg' import Environment from '../icons/environment-icon.svg' import ExecutionGradient from '../icons/execution-gradient.svg' import Execution from '../icons/execution-icon.svg' +import ExpandComment from '../icons/expand-comment.svg' import ExpandDiff from '../icons/expand-diff.svg' import Eye from '../icons/eye-icon.svg' import Fail from '../icons/fail.svg' @@ -159,6 +162,7 @@ import Stack from '../icons/stack-icon.svg' import Star from '../icons/star-icon.svg' import SubMenuEllipse from '../icons/sub-menu-ellipse.svg' import Success from '../icons/success.svg' +import Suggestion from '../icons/suggestion.svg' import SupplyChainGradient from '../icons/supply-chain-gradient.svg' import SupplyChain from '../icons/supply-chain-icon.svg' import Tag from '../icons/tag.svg' @@ -359,7 +363,11 @@ const IconNameMap = { 'collapse-diff': CollapseDiff, 'expand-diff': ExpandDiff, 'circle-plus': CirclePlus, - 'code-brackets': CodeBrackets + 'code-brackets': CodeBrackets, + 'attachment-image': AttachmentImage, + 'collapse-comment': CollapseComment, + 'expand-comment': ExpandComment, + suggestion: Suggestion } satisfies Record<string, React.FunctionComponent<React.SVGProps<SVGSVGElement>>> export interface IconProps { diff --git a/packages/ui/src/components/markdown-viewer/index.tsx b/packages/ui/src/components/markdown-viewer/index.tsx index 1ef96f5d9..bf5a0be4f 100644 --- a/packages/ui/src/components/markdown-viewer/index.tsx +++ b/packages/ui/src/components/markdown-viewer/index.tsx @@ -10,6 +10,8 @@ import rehypeVideo from 'rehype-video' import './style.css' +import { cn } from '@utils/cn' + import { CodeSuggestionBlock, SuggestionBlock } from './CodeSuggestionBlock' // TODO: add ai stuff at a later point for code suggestions @@ -36,6 +38,7 @@ interface MarkdownViewerProps { suggestionBlock?: SuggestionBlock suggestionCheckSum?: string isSuggestion?: boolean + markdownClassName?: string } export function MarkdownViewer({ @@ -44,7 +47,8 @@ export function MarkdownViewer({ withBorderWrapper = false, suggestionBlock, suggestionCheckSum, - isSuggestion + isSuggestion, + markdownClassName }: MarkdownViewerProps) { const navigate = useNavigate() const [isOpen, setIsOpen] = useState(false) @@ -151,10 +155,10 @@ export function MarkdownViewer({ return ( <Wrapper> - <div className="m-auto max-w-[836px]" ref={ref} style={styles}> + <div ref={ref} style={styles}> <MarkdownPreview source={source} - className="prose prose-invert" + className={cn('prose prose-invert', markdownClassName)} rehypeRewrite={rehypeRewrite} rehypePlugins={[ rehypeSanitize, diff --git a/packages/ui/src/components/node-group.tsx b/packages/ui/src/components/node-group.tsx index dabd6c196..b587479f8 100644 --- a/packages/ui/src/components/node-group.tsx +++ b/packages/ui/src/components/node-group.tsx @@ -59,12 +59,8 @@ function Content({ children }: { children: ReactNode }) { function Connector({ first, last, className }: { first?: boolean; last?: boolean; className?: string }) { return ( <div - className={cn( - 'absolute bottom-0 left-[11px] top-0 z-10 w-1', - { 'top-3': first }, - { 'bottom-8': last }, - className - )} + className={cn('absolute bottom-0 left-2.5 top-0 z-10 w-1', { 'top-3': first }, { 'bottom-8': last }, className)} + data-connector > <span className="absolute inset-y-0 left-1/2 w-px -translate-x-1/2 bg-borders-4" /> </div> diff --git a/packages/ui/src/icons/attachment-image.svg b/packages/ui/src/icons/attachment-image.svg new file mode 100644 index 000000000..adc55501d --- /dev/null +++ b/packages/ui/src/icons/attachment-image.svg @@ -0,0 +1,12 @@ +<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg"> +<g clip-path="url(#clip0_24053_167006)"> +<path d="M0.5 12.5L3.5 9.5L5.5 11.5L10.5 6.5L15.5 11.5" stroke="currentColor" style="stroke:currentColor;stroke:color(display-p3 0.5760 0.5760 0.6240);stroke-opacity:1;" stroke-linecap="round" stroke-linejoin="round"/> +<path d="M14 15.5H2C1.60218 15.5 1.22064 15.342 0.93934 15.0607C0.658035 14.7794 0.5 14.3978 0.5 14V2C0.5 1.60218 0.658035 1.22064 0.93934 0.93934C1.22064 0.658035 1.60218 0.5 2 0.5H14C14.3978 0.5 14.7794 0.658035 15.0607 0.93934C15.342 1.22064 15.5 1.60218 15.5 2V14C15.5 14.3978 15.342 14.7794 15.0607 15.0607C14.7794 15.342 14.3978 15.5 14 15.5Z" stroke="currentColor" style="stroke:currentColor;stroke:color(display-p3 0.5760 0.5760 0.6240);stroke-opacity:1;" stroke-linecap="round" stroke-linejoin="round"/> +<path d="M5 6.5C5.82843 6.5 6.5 5.82843 6.5 5C6.5 4.17157 5.82843 3.5 5 3.5C4.17157 3.5 3.5 4.17157 3.5 5C3.5 5.82843 4.17157 6.5 5 6.5Z" stroke="currentColor" style="stroke:currentColor;stroke:color(display-p3 0.5760 0.5760 0.6240);stroke-opacity:1;" stroke-linecap="round" stroke-linejoin="round"/> +</g> +<defs> +<clipPath id="clip0_24053_167006"> +<rect width="16" height="16" fill="currentColor"/> +</clipPath> +</defs> +</svg> diff --git a/packages/ui/src/icons/attachment.svg b/packages/ui/src/icons/attachment.svg index da66fdcf2..0f8d07b6f 100644 --- a/packages/ui/src/icons/attachment.svg +++ b/packages/ui/src/icons/attachment.svg @@ -1,10 +1,10 @@ -<svg viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"> -<g clip-path="url(#clip0_17619_89256)"> -<path d="M8.85683 5.35812L5.85183 8.36312C5.16883 9.04612 5.16883 10.1541 5.85183 10.8381C6.53483 11.5211 7.64283 11.5211 8.32683 10.8381L12.3928 6.77212C13.7598 5.40512 13.7598 3.18912 12.3928 1.82212C11.0258 0.455125 8.80983 0.455125 7.44283 1.82212L3.02383 6.24212C0.973828 8.29212 0.973828 11.6161 3.02383 13.6671C5.07383 15.7171 8.39783 15.7171 10.4488 13.6671L14.5138 9.60113" stroke="#AEAEB7" stroke-width="1.14286" stroke-linecap="round" stroke-linejoin="round"/> +<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg"> +<g clip-path="url(#clip0_23746_174254)"> +<path d="M8.85683 5.35812L5.85183 8.36312C5.16883 9.04612 5.16883 10.1541 5.85183 10.8381C6.53483 11.5211 7.64283 11.5211 8.32683 10.8381L12.3928 6.77212C13.7598 5.40512 13.7598 3.18912 12.3928 1.82212C11.0258 0.455125 8.80983 0.455125 7.44283 1.82212L3.02383 6.24212C0.973828 8.29212 0.973828 11.6161 3.02383 13.6671C5.07383 15.7171 8.39783 15.7171 10.4488 13.6671L14.5138 9.60113" stroke="currentColor" style="stroke:currentColor;stroke:color(display-p3 0.6820 0.6820 0.7180);stroke-opacity:1;" stroke-width="1.14286" stroke-linecap="round" stroke-linejoin="round"/> </g> <defs> -<clipPath id="clip0_17619_89256"> -<rect width="16" height="16" /> +<clipPath id="clip0_23746_174254"> +<rect width="16" height="16" fill="currentColor" style="fill:currentColor;fill-opacity:1;"/> </clipPath> </defs> </svg> diff --git a/packages/ui/src/icons/bold.svg b/packages/ui/src/icons/bold.svg index 4f972d6a2..6d773b8af 100644 --- a/packages/ui/src/icons/bold.svg +++ b/packages/ui/src/icons/bold.svg @@ -1 +1,4 @@ -<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.714" d="M3.502 1.492h5a3.001 3.001 0 0 1 0 6h-5zM3.502 7.492h5.5c1.932 0 3.5 1.568 3.5 3.5s-1.568 3.5-3.5 3.5h-5.5z"/></svg> \ No newline at end of file +<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg"> +<path d="M3.50195 1.49219H8.50195C10.158 1.49219 11.502 2.83619 11.502 4.49219C11.502 6.14819 10.158 7.49219 8.50195 7.49219H3.50195V1.49219Z" stroke="currentColor" style="stroke:currentColor;stroke-opacity:1;" stroke-width="1.71429" stroke-linecap="round" stroke-linejoin="round"/> +<path d="M3.50195 7.49219H9.00195C10.934 7.49219 12.502 9.06019 12.502 10.9922C12.502 12.9242 10.934 14.4922 9.00195 14.4922H3.50195V7.49219Z" stroke="currentColor" style="stroke:currentColor;stroke-opacity:1;" stroke-width="1.71429" stroke-linecap="round" stroke-linejoin="round"/> +</svg> diff --git a/packages/ui/src/icons/code.svg b/packages/ui/src/icons/code.svg index 71d93961e..9e13fb000 100644 --- a/packages/ui/src/icons/code.svg +++ b/packages/ui/src/icons/code.svg @@ -1,11 +1,11 @@ -<svg viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"> -<g clip-path="url(#clip0_17619_89259)"> -<path d="M5.5 2.99219L0.5 7.99219L5.5 12.9922" stroke="#AEAEB7" stroke-width="1.14286" stroke-linecap="round" stroke-linejoin="round"/> -<path d="M10.5 12.9922L15.5 7.99219L10.5 2.99219" stroke="#AEAEB7" stroke-width="1.14286" stroke-linecap="round" stroke-linejoin="round"/> +<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg"> +<g clip-path="url(#clip0_23746_174257)"> +<path d="M5.5 2.99219L0.5 7.99219L5.5 12.9922" stroke="currentColor" style="stroke:currentColor;stroke:color(display-p3 0.6820 0.6820 0.7180);stroke-opacity:1;" stroke-width="1.14286" stroke-linecap="round" stroke-linejoin="round"/> +<path d="M10.5 12.9922L15.5 7.99219L10.5 2.99219" stroke="currentColor" style="stroke:currentColor;stroke:color(display-p3 0.6820 0.6820 0.7180);stroke-opacity:1;" stroke-width="1.14286" stroke-linecap="round" stroke-linejoin="round"/> </g> <defs> -<clipPath id="clip0_17619_89259"> -<rect width="16" height="16" fill="currentColor"/> +<clipPath id="clip0_23746_174257"> +<rect width="16" height="16" fill="currentColor" style="fill:currentColor;fill-opacity:1;"/> </clipPath> </defs> </svg> diff --git a/packages/ui/src/icons/collapse-comment.svg b/packages/ui/src/icons/collapse-comment.svg new file mode 100644 index 000000000..0a8c44f47 --- /dev/null +++ b/packages/ui/src/icons/collapse-comment.svg @@ -0,0 +1,16 @@ +<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg"> +<g clip-path="url(#clip0_23746_175034)"> +<path d="M8 1V5.5M8 5.5L10 3.5M8 5.5L6 3.5" stroke="currentColor" style="stroke:currentColor;stroke-opacity:1;" stroke-linecap="round" stroke-linejoin="round"/> +<path d="M8 15V10.5M8 10.5L10 12.5M8 10.5L6 12.5" stroke="currentColor" style="stroke:currentColor;stroke-opacity:1;" stroke-linecap="round" stroke-linejoin="round"/> +<path d="M1 8H2.25" stroke="currentColor" style="stroke:currentColor;stroke-opacity:1;" stroke-linecap="round"/> +<path d="M4.1875 8H5.4375" stroke="currentColor" style="stroke:currentColor;stroke-opacity:1;" stroke-linecap="round"/> +<path d="M7.375 8H8.625" stroke="currentColor" style="stroke:currentColor;stroke-opacity:1;" stroke-linecap="round"/> +<path d="M10.5625 8H11.8125" stroke="currentColor" style="stroke:currentColor;stroke-opacity:1;" stroke-linecap="round"/> +<path d="M13.75 8H15" stroke="currentColor" style="stroke:currentColor;stroke-opacity:1;" stroke-linecap="round"/> +</g> +<defs> +<clipPath id="clip0_23746_175034"> +<rect width="16" height="16" fill="currentColor" style="fill:currentColor;fill-opacity:1;"/> +</clipPath> +</defs> +</svg> diff --git a/packages/ui/src/icons/expand-comment.svg b/packages/ui/src/icons/expand-comment.svg new file mode 100644 index 000000000..d83db819f --- /dev/null +++ b/packages/ui/src/icons/expand-comment.svg @@ -0,0 +1,16 @@ +<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg"> +<g clip-path="url(#clip0_23746_175137)"> +<path d="M8 5.5V1M8 1L10 3M8 1L6 3" stroke="currentColor" style="stroke:currentColor;stroke-opacity:1;" stroke-linecap="round" stroke-linejoin="round"/> +<path d="M8 10.5V15M8 15L10 13M8 15L6 13" stroke="currentColor" style="stroke:currentColor;stroke-opacity:1;" stroke-linecap="round" stroke-linejoin="round"/> +<path d="M1 8H2.25" stroke="currentColor" style="stroke:currentColor;stroke-opacity:1;" stroke-linecap="round"/> +<path d="M4.1875 8H5.4375" stroke="currentColor" style="stroke:currentColor;stroke-opacity:1;" stroke-linecap="round"/> +<path d="M7.375 8H8.625" stroke="currentColor" style="stroke:currentColor;stroke-opacity:1;" stroke-linecap="round"/> +<path d="M10.5625 8H11.8125" stroke="currentColor" style="stroke:currentColor;stroke-opacity:1;" stroke-linecap="round"/> +<path d="M13.75 8H15" stroke="currentColor" style="stroke:currentColor;stroke-opacity:1;" stroke-linecap="round"/> +</g> +<defs> +<clipPath id="clip0_23746_175137"> +<rect width="16" height="16" fill="currentColor" style="fill:currentColor;fill-opacity:1;"/> +</clipPath> +</defs> +</svg> diff --git a/packages/ui/src/icons/suggestion.svg b/packages/ui/src/icons/suggestion.svg new file mode 100644 index 000000000..c2c132f21 --- /dev/null +++ b/packages/ui/src/icons/suggestion.svg @@ -0,0 +1,13 @@ +<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg"> +<g clip-path="url(#clip0_23746_174295)"> +<path d="M5.5 11.5H10.5" stroke="currentColor" style="stroke:currentColor;stroke-opacity:1;" stroke-linecap="round" stroke-linejoin="round"/> +<path d="M5.5 6.5H10.5" stroke="currentColor" style="stroke:currentColor;stroke-opacity:1;" stroke-linecap="round" stroke-linejoin="round"/> +<path d="M8 4L8 9" stroke="currentColor" style="stroke:currentColor;stroke-opacity:1;" stroke-linecap="round" stroke-linejoin="round"/> +<path d="M9.5 0.5H1.5V15.5H14.5V5.5L9.5 0.5Z" stroke="currentColor" style="stroke:currentColor;stroke-opacity:1;" stroke-linecap="round" stroke-linejoin="round"/> +</g> +<defs> +<clipPath id="clip0_23746_174295"> +<rect width="16" height="16" fill="currentColor" style="fill:currentColor;fill-opacity:1;"/> +</clipPath> +</defs> +</svg> \ No newline at end of file diff --git a/packages/ui/src/views/layouts/PullRequestLayout.tsx b/packages/ui/src/views/layouts/PullRequestLayout.tsx index d58ab5ca2..78580b956 100644 --- a/packages/ui/src/views/layouts/PullRequestLayout.tsx +++ b/packages/ui/src/views/layouts/PullRequestLayout.tsx @@ -62,28 +62,29 @@ const PullRequestLayout: React.FC<PullRequestLayoutProps> = ({ <NavLink to={PullRequestTabsKeys.CONVERSATION}> {({ isActive }) => ( <TabsTrigger - className="gap-x-1" + className="gap-x-1.5" value={PullRequestTabsKeys.CONVERSATION} data-state={isActive ? 'active' : 'inactive'} > - <Icon size={14} name="comments" /> - {t('views:pullRequests.conversation')} - <Badge variant="outline" size="xs"> - {pullRequest?.stats?.conversations || 0} - </Badge> + <div className="flex items-center gap-x-1"> + <Icon size={14} name="comments" /> + {t('views:pullRequests.conversation')} + </div> </TabsTrigger> )} </NavLink> <NavLink to={PullRequestTabsKeys.COMMITS}> {({ isActive }) => ( <TabsTrigger - className="gap-x-1" + className="gap-x-1.5" value={PullRequestTabsKeys.COMMITS} data-state={isActive ? 'active' : 'inactive'} > - <Icon size={14} name="tube-sign" /> - {t('views:repos.commits')} - <Badge variant="outline" size="xs"> + <div className="flex items-center gap-x-1"> + <Icon size={14} name="tube-sign" /> + {t('views:repos.commits')} + </div> + <Badge variant="outline" size="xs" borderRadius="base"> {pullRequest?.stats?.commits} </Badge> </TabsTrigger> @@ -92,13 +93,15 @@ const PullRequestLayout: React.FC<PullRequestLayoutProps> = ({ <NavLink to={PullRequestTabsKeys.CHANGES}> {({ isActive }) => ( <TabsTrigger - className="gap-x-1" + className="gap-x-1.5" value={PullRequestTabsKeys.CHANGES} data-state={isActive ? 'active' : 'inactive'} > - <Icon size={14} name="changes" /> - {t('views:pullRequests.changes')} - <Badge variant="outline" size="xs"> + <div className="flex items-center gap-x-1"> + <Icon size={14} name="changes" /> + {t('views:pullRequests.changes')} + </div> + <Badge variant="outline" size="xs" borderRadius="base"> {pullRequest?.stats?.files_changed} </Badge> </TabsTrigger> diff --git a/packages/ui/src/views/repo/pull-request/compare/components/pull-request-compare-tab-trigger-item.tsx b/packages/ui/src/views/repo/pull-request/compare/components/pull-request-compare-tab-trigger-item.tsx index 6a0ac2c50..7caa92f4d 100644 --- a/packages/ui/src/views/repo/pull-request/compare/components/pull-request-compare-tab-trigger-item.tsx +++ b/packages/ui/src/views/repo/pull-request/compare/components/pull-request-compare-tab-trigger-item.tsx @@ -3,8 +3,6 @@ import { FC } from 'react' import { Badge } from '@components/badge' import { Icon, IconProps } from '@components/icon' import { TabsTrigger } from '@components/tabs' -import { Text } from '@components/text' -import { Layout } from '@views/layouts/layout' interface TabTriggerItemProps { value: string @@ -15,18 +13,16 @@ interface TabTriggerItemProps { const TabTriggerItem: FC<TabTriggerItemProps> = ({ value, icon, label, badgeCount }) => { return ( - <TabsTrigger value={value} className="data-[state=active]:bg-background-1"> - <Layout.Horizontal className="items-center" gap="gap-x-1.5"> - <div> - <Icon size={16} name={icon as IconProps['name']} /> - </div> - <Text size={2}>{label}</Text> - {badgeCount !== undefined && ( - <Badge variant="outline" size="xs"> - {badgeCount} - </Badge> - )} - </Layout.Horizontal> + <TabsTrigger value={value} className="gap-x-1.5"> + <div className="flex items-center gap-x-1"> + <Icon size={14} name={icon as IconProps['name']} /> + <span>{label}</span> + </div> + {badgeCount !== undefined && ( + <Badge variant="outline" size="xs" borderRadius="base"> + {badgeCount} + </Badge> + )} </TabsTrigger> ) } diff --git a/packages/ui/src/views/repo/pull-request/components/pull-request-diff-viewer.tsx b/packages/ui/src/views/repo/pull-request/components/pull-request-diff-viewer.tsx index 6ab3a73bc..8cb4dd52a 100644 --- a/packages/ui/src/views/repo/pull-request/components/pull-request-diff-viewer.tsx +++ b/packages/ui/src/views/repo/pull-request/components/pull-request-diff-viewer.tsx @@ -8,7 +8,7 @@ import { TranslationStore, TypesPullReqActivity } from '@/views' -import { Avatar, AvatarFallback, Layout, Text } from '@components/index' +import { Avatar, AvatarFallback, Layout } from '@components/index' import { DiffFile, DiffModeEnum, DiffView, DiffViewProps, SplitSide } from '@git-diff-view/react' import { getInitials, timeAgo } from '@utils/utils' import { DiffBlock } from 'diff2html/lib/types' @@ -49,7 +49,6 @@ interface PullRequestDiffviewerProps { useTranslationStore: () => TranslationStore commentId?: string onCopyClick?: (commentId?: number) => void - onCommentSaveAndStatusChange?: (comment: string, status: string, parentId?: number) => void suggestionsBatch?: CommitSuggestion[] onCommitSuggestion?: (suggestion: CommitSuggestion) => void addSuggestionToBatch?: (suggestion: CommitSuggestion) => void @@ -79,7 +78,6 @@ const PullRequestDiffViewer = ({ useTranslationStore, commentId, onCopyClick, - onCommentSaveAndStatusChange, suggestionsBatch, onCommitSuggestion, addSuggestionToBatch, @@ -342,7 +340,7 @@ const PullRequestDiffViewer = ({ if (!threads) return <></> return ( - <div className="w- rounded border bg-background"> + <div className="rounded border bg-background"> {threads.map(thread => { const parent = thread.parent const componentId = `activity-code-${parent?.id}` @@ -356,20 +354,28 @@ const PullRequestDiffViewer = ({ parentCommentId={parent.id} handleSaveComment={handleSaveComment} isLast={true} - contentClassName="px-4 py-2 w-[calc(100%-38px)]" + contentClassName="w-[calc(100%-38px)]" header={[]} currentUser={currentUser} isComment - replyBoxClassName="py-4" + replyBoxClassName="p-4" hideReplyHere={hideReplyHeres[parent?.id]} setHideReplyHere={state => toggleReplyBox(state, parent?.id)} isResolved={!!parent.payload?.resolved} toggleConversationStatus={toggleConversationStatus} - onCommentSaveAndStatusChange={onCommentSaveAndStatusChange} onQuoteReply={handleQuoteReply} quoteReplyText={quoteReplies[parent.id]?.text || ''} + contentHeader={ + !!parent.payload?.resolved && ( + <div className="flex items-center gap-x-1"> + {/* TODO: need to identify the author who resolved the conversation */} + <span className="font-medium text-foreground-8">{parent.author}</span> + <span className="text-foreground-4">marked this conversation as resolved</span> + </div> + ) + } content={ - <div className="flex-col"> + <div className="flex-col px-4 pt-4"> <PullRequestTimelineItem titleClassName="!flex max-w-full" parentCommentId={parent.id} @@ -389,9 +395,7 @@ const PullRequestDiffViewer = ({ icon={ <Avatar className="size-6 rounded-full p-0"> <AvatarFallback> - <Text size={1} color="tertiaryBackground"> - {parentInitials} - </Text> + <span className="text-12 text-foreground-3">{parentInitials}</span> </AvatarFallback> </Avatar> } @@ -399,12 +403,12 @@ const PullRequestDiffViewer = ({ { name: parent.author, description: ( - <Layout.Horizontal> - <span className="text-foreground-3">{timeAgo(parent?.created as number)}</span> + <Layout.Horizontal className="text-foreground-4"> + <span>{timeAgo(parent?.created as number)}</span> {parent?.deleted ? ( <> - <span className="text-foreground-3"> | </span> - <span className="text-foreground-3">{t('views:pullRequests.deleted')} </span> + <span> | </span> + <span>{t('views:pullRequests.deleted')} </span> </> ) : null} </Layout.Horizontal> @@ -474,9 +478,7 @@ const PullRequestDiffViewer = ({ icon={ <Avatar className="size-6 rounded-full p-0"> <AvatarFallback> - <Text size={1} color="tertiaryBackground"> - {replyInitials} - </Text> + <span className="text-12 text-foreground-3">{replyInitials}</span> </AvatarFallback> </Avatar> } @@ -484,12 +486,12 @@ const PullRequestDiffViewer = ({ { name: reply.author, description: ( - <Layout.Horizontal> - <span className="text-foreground-3">{timeAgo(reply?.created as number)}</span> + <Layout.Horizontal className="text-foreground-4"> + <span>{timeAgo(reply?.created as number)}</span> {reply?.deleted ? ( <> - <span className="text-foreground-3"> | </span> - <span className="text-foreground-3">{t('views:pullRequests.deleted')} </span> + <span> | </span> + <span>{t('views:pullRequests.deleted')} </span> </> ) : null} </Layout.Horizontal> @@ -505,7 +507,6 @@ const PullRequestDiffViewer = ({ <PullRequestCommentBox handleUpload={handleUpload} isEditMode - isResolved={!!parent?.payload?.resolved} onSaveComment={() => { if (reply?.id) { updateComment?.(reply?.id, editComments[replyComponentId]) @@ -520,7 +521,6 @@ const PullRequestDiffViewer = ({ setComment={text => setEditComments(prev => ({ ...prev, [replyComponentId]: text })) } - onCommentSaveAndStatusChange={onCommentSaveAndStatusChange} /> ) : ( <PRCommentView diff --git a/packages/ui/src/views/repo/pull-request/details/components/changes/pull-request-changes.tsx b/packages/ui/src/views/repo/pull-request/details/components/changes/pull-request-changes.tsx index 82c845aca..2992b4cd1 100644 --- a/packages/ui/src/views/repo/pull-request/details/components/changes/pull-request-changes.tsx +++ b/packages/ui/src/views/repo/pull-request/details/components/changes/pull-request-changes.tsx @@ -208,7 +208,6 @@ const PullRequestAccordion: React.FC<{ commentId, autoExpand, onCopyClick, - onCommentSaveAndStatusChange, suggestionsBatch, onCommitSuggestion, addSuggestionToBatch, @@ -384,7 +383,6 @@ const PullRequestAccordion: React.FC<{ useTranslationStore={useTranslationStore} commentId={commentId} onCopyClick={onCopyClick} - onCommentSaveAndStatusChange={onCommentSaveAndStatusChange} onCommitSuggestion={onCommitSuggestion} addSuggestionToBatch={addSuggestionToBatch} suggestionsBatch={suggestionsBatch} diff --git a/packages/ui/src/views/repo/pull-request/details/components/conversation/pull-request-comment-box.tsx b/packages/ui/src/views/repo/pull-request/details/components/conversation/pull-request-comment-box.tsx index 46ab1c50e..ac2946391 100644 --- a/packages/ui/src/views/repo/pull-request/details/components/conversation/pull-request-comment-box.tsx +++ b/packages/ui/src/views/repo/pull-request/details/components/conversation/pull-request-comment-box.tsx @@ -1,9 +1,11 @@ -import { useMemo, useState } from 'react' +import { Fragment, useMemo, useRef, useState } from 'react' import { Avatar, AvatarFallback, Button, + Icon, + IconProps, MarkdownViewer, Tabs, TabsContent, @@ -14,16 +16,17 @@ import { import { cn } from '@utils/cn' import { getInitials } from '@utils/stringUtils' +import { ToolbarAction } from '../../pull-request-details-types' import { handleFileDrop, handlePaste } from '../../pull-request-utils' -// TODO: add back when functionality is added -// import { ToolbarAction } from '../../pull-request-details-types' -// interface ToolbarItem { -// icon: IconProps['name'] -// action: ToolbarAction -// title?: string -// size?: number -// } +interface ToolbarItem { + icon: IconProps['name'] + action: ToolbarAction + title?: string + size?: number + onClick?: () => void +} + interface PullRequestCommentBoxProps { onSaveComment: (comment: string) => void comment: string @@ -36,14 +39,15 @@ interface PullRequestCommentBoxProps { onCommentSubmit?: () => void inReplyMode?: boolean isEditMode?: boolean - hideAvatar?: boolean onCancelClick?: () => void - isResolved?: boolean - onCommentSaveAndStatusChange?: (comment: string, status: string, parentId?: number) => void - parentCommentId?: number handleUpload?: (blob: File, setMarkdownContent: (data: string) => void) => void } +const TABS_KEYS = { + WRITE: 'write', + PREVIEW: 'preview' +} + // TODO: will have to eventually implement a commenting and reply system similiar to gitness const PullRequestCommentBox = ({ onSaveComment, @@ -53,13 +57,13 @@ const PullRequestCommentBox = ({ comment, setComment, isEditMode, - hideAvatar, - isResolved, - onCommentSaveAndStatusChange, - parentCommentId, handleUpload }: PullRequestCommentBoxProps) => { const [__file, setFile] = useState<File>() + const [activeTab, setActiveTab] = useState<typeof TABS_KEYS.WRITE | typeof TABS_KEYS.PREVIEW>(TABS_KEYS.WRITE) + const fileInputRef = useRef<HTMLInputElement | null>(null) + const [isDragging, setIsDragging] = useState(false) + const dropZoneRef = useRef<HTMLDivElement>(null) const handleSaveComment = () => { if (comment.trim()) { @@ -71,7 +75,6 @@ const PullRequestCommentBox = ({ const avatar = useMemo(() => { return ( <Avatar size="6"> - {/* <AvatarImage src={AvatarUrl} /> */} <AvatarFallback> <span className="text-12 text-foreground-3">{getInitials(currentUser || '')}</span> </AvatarFallback> @@ -79,138 +82,177 @@ const PullRequestCommentBox = ({ ) }, [currentUser]) - // TODO: add back when functionality is added - // const toolbar: ToolbarItem[] = useMemo(() => { - // const initial: ToolbarItem[] = [] - // return [ - // ...initial, - // { icon: 'header', action: ToolbarAction.HEADER }, - // { icon: 'bold', action: ToolbarAction.BOLD }, - // { icon: 'italicize', action: ToolbarAction.ITALIC }, - // { icon: 'attachment', action: ToolbarAction.UPLOAD }, - // { icon: 'list', action: ToolbarAction.UNORDER_LIST }, - // { icon: 'checklist', action: ToolbarAction.CHECK_LIST }, - // { icon: 'code', action: ToolbarAction.CODE_BLOCK } - // ] - // }, []) const handleUploadCallback = (file: File) => { setFile(file) handleUpload?.(file, setComment) } + + const handleFileSelect = () => { + fileInputRef.current?.click() + } + + const handleFileChange = (event: React.ChangeEvent<HTMLInputElement>) => { + const file = event.target.files?.[0] + if (file) { + handleUploadCallback(file) + } + } + + const handleDragEnter = (e: React.DragEvent) => { + e.preventDefault() + e.stopPropagation() + + if (e.currentTarget === dropZoneRef.current) { + setIsDragging(true) + } + } + + const handleDragLeave = (e: React.DragEvent) => { + e.preventDefault() + e.stopPropagation() + + if (e.currentTarget === dropZoneRef.current && !e.currentTarget.contains(e.relatedTarget as Node)) { + setIsDragging(false) + } + } + + const handleDrop = (e: React.DragEvent) => { + e.preventDefault() + e.stopPropagation() + setIsDragging(false) + handleDropForUpload(e) + } + // eslint-disable-next-line @typescript-eslint/no-explicit-any const handleDropForUpload = async (event: any) => { handleFileDrop(event, handleUploadCallback) } - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const handlePasteForUpload = (event: { preventDefault: () => void; clipboardData: any }) => { + + const handlePasteForUpload = (event: React.ClipboardEvent) => { handlePaste(event, handleUploadCallback) } + // TODO: add the remaining required logic for the toolbar + const toolbar: ToolbarItem[] = useMemo(() => { + const initial: ToolbarItem[] = [] + return [ + ...initial, + { icon: 'suggestion', action: ToolbarAction.SUGGESTION }, + { icon: 'header', action: ToolbarAction.HEADER }, + { icon: 'bold', action: ToolbarAction.BOLD }, + { icon: 'italicize', action: ToolbarAction.ITALIC }, + { icon: 'attachment', action: ToolbarAction.UPLOAD, onClick: handleFileSelect }, + { icon: 'list', action: ToolbarAction.UNORDER_LIST }, + { icon: 'checklist', action: ToolbarAction.CHECK_LIST }, + { icon: 'code', action: ToolbarAction.CODE_BLOCK } + ] + }, []) + + const handleTabChange = (tab: typeof TABS_KEYS.WRITE | typeof TABS_KEYS.PREVIEW) => { + setActiveTab(tab) + } + return ( - <div className="flex items-start space-x-4"> - {(!isEditMode || !hideAvatar) && avatar} + <div className="flex items-start gap-x-3"> + {!inReplyMode && avatar} + <div - className={cn('min-w-0 flex-1 px-4 pb-5 pt-1.5', { + className={cn('pb-5 pt-1.5 px-4 flex-1 bg-background-2 border-border-1', { 'border rounded-md': !inReplyMode || isEditMode, - 'border-t ': inReplyMode + 'border-t': inReplyMode })} > - <Tabs variant="tabnav" defaultValue="write"> + <Tabs variant="tabnav" defaultValue={TABS_KEYS.WRITE} value={activeTab} onValueChange={handleTabChange}> <TabsList className="relative left-1/2 w-[calc(100%+32px)] -translate-x-1/2 px-4"> - <TabsTrigger value="write">Write</TabsTrigger> - <TabsTrigger value="preview">Preview</TabsTrigger> + <TabsTrigger className="data-[state=active]:bg-background-2" value={TABS_KEYS.WRITE}> + Write + </TabsTrigger> + <TabsTrigger className="data-[state=active]:bg-background-2" value={TABS_KEYS.PREVIEW}> + Preview + </TabsTrigger> </TabsList> - <TabsContent className="mt-4" value="write"> + <TabsContent className="mt-4" value={TABS_KEYS.WRITE}> <div - onDrop={e => { - handleDropForUpload(e) - }} - onPaste={handlePasteForUpload} - className="relative gap-y-1" - onDragOver={event => { - event.preventDefault() - }} + className="relative" + onDrop={handleDrop} + onDragOver={e => e.preventDefault()} + onDragEnter={handleDragEnter} + onDragLeave={handleDragLeave} + ref={dropZoneRef} > <Textarea - onDrop={e => { - handleDropForUpload(e) - }} - onPaste={e => { - if (e.clipboardData.files.length > 0) { - handlePasteForUpload(e) - } else { - const pastedText = e.clipboardData.getData('Text') - setComment(comment + pastedText) - } - }} className="min-h-24 p-3 pb-10" autoFocus={!!inReplyMode} placeholder="Add your comment here" value={comment} onChange={e => setComment(e.target.value)} + onPaste={e => { + if (e.clipboardData.files.length > 0) { + handlePasteForUpload(e) + } + }} resizable /> - <p className="pt-1 text-foreground-4"> - Attach images & videos by dragging and dropping,selecting or pasting them. - </p> + {isDragging && ( + <div className="absolute inset-1 cursor-copy rounded-sm border border-dashed border-borders-2" /> + )} - {/* TODO: add back when functionality is implemented */} - {/* <div className="absolute pb-2 pt-1 px-1 bottom-px bg-background-1 left-1/2 w-[calc(100%-2px)] -translate-x-1/2 rounded"> + <div className="absolute -ml-0.5 bottom-px flex left-1/2 w-[calc(100%-16px)] -translate-x-1/2 bg-background-2 items-center pb-2 pt-1"> {toolbar.map((item, index) => { + const isFirst = index === 0 return ( - <Button key={`${comment}-${index}`} size="icon" variant="ghost"> - <Icon name={item.icon} /> - </Button> + <Fragment key={`${comment}-${index}`}> + <Button size="icon" variant="ghost" onClick={item?.onClick}> + <Icon className="text-icons-9" name={item.icon} /> + </Button> + {isFirst && <div className="h-4 w-px bg-borders-2" />} + </Fragment> ) })} - </div> */} + </div> </div> </TabsContent> - <TabsContent className="mt-4" value="preview"> + <TabsContent className="mt-4" value={TABS_KEYS.PREVIEW}> <div className="min-h-24"> - {comment ? <MarkdownViewer source={comment} /> : <span>Nothing to preview</span>} + {comment ? ( + <MarkdownViewer markdownClassName="!bg-background-2" source={comment} /> + ) : ( + <span>Nothing to preview</span> + )} </div> </TabsContent> </Tabs> - <div className="mt-4 flex items-center gap-x-3"> - {!inReplyMode && !isEditMode ? ( - <Button onClick={handleSaveComment}>Comment</Button> - ) : isEditMode ? ( - <> - <Button onClick={handleSaveComment}>Save</Button> - <Button variant="outline" onClick={onCancelClick}> - Cancel - </Button> - </> - ) : ( - <></> - )} - {inReplyMode && ( - <> - {isEditMode ? ( - <Button onClick={handleSaveComment}>Save</Button> - ) : ( - <Button onClick={handleSaveComment}>Reply</Button> - )} + <div className="mt-4 flex items-center justify-between"> + {activeTab === TABS_KEYS.WRITE && ( + <div> + <input type="file" ref={fileInputRef} className="hidden" onChange={handleFileChange} /> <Button - variant={'outline'} - onClick={() => { - if (comment.trim()) { - onCommentSaveAndStatusChange?.(comment.trim(), isResolved ? 'active' : 'resolved', parentCommentId) - onCancelClick?.() - } - }} + className="gap-x-2 px-2.5 font-normal text-foreground-3 hover:bg-background-8" + variant="custom" + onClick={handleFileSelect} > - {isResolved ? 'Reply & Reactivate' : 'Reply & Resolve'} + <Icon size={16} name="attachment-image" /> + <span>Drag & drop, select, or paste to attach files</span> </Button> + </div> + )} + + <div className="flex gap-x-3 ml-auto"> + {(inReplyMode || isEditMode) && ( <Button variant="outline" onClick={onCancelClick}> Cancel </Button> - </> - )} + )} + + {isEditMode ? ( + <Button onClick={handleSaveComment}>Save</Button> + ) : ( + <Button onClick={handleSaveComment}>Comment</Button> + )} + </div> </div> </div> </div> diff --git a/packages/ui/src/views/repo/pull-request/details/components/conversation/pull-request-description-box.tsx b/packages/ui/src/views/repo/pull-request/details/components/conversation/pull-request-description-box.tsx index 163532217..aed895b67 100644 --- a/packages/ui/src/views/repo/pull-request/details/components/conversation/pull-request-description-box.tsx +++ b/packages/ui/src/views/repo/pull-request/details/components/conversation/pull-request-description-box.tsx @@ -63,24 +63,19 @@ const PullRequestDescBox: React.FC<PullRequestDescBoxProps> = ({ { avatar: ( <Avatar size="6"> - {/* <AvatarImage src={AvatarUrl} /> */} <AvatarFallback> - <Text size={0} color="tertiaryBackground"> - {getInitials(author || '')} - </Text> + <span className="text-12 text-foreground-3">{getInitials(author || '')}</span> </AvatarFallback> </Avatar> ), name: author, - // TODO: make pr num clickable? + // TODO: pr number must be a link description: ( - <Text size={2} className="gap-x-2" color="tertiaryBackground"> - {`created pull request`} - <Text size={2} className="pl-1"> - {`${prNum} `} - </Text> + <span className="flex gap-x-1"> + created pull request + <span className="text-foreground-8">{prNum}</span> {formattedTime} - </Text> + </span> ) } ]} @@ -93,21 +88,17 @@ const PullRequestDescBox: React.FC<PullRequestDescBoxProps> = ({ <PullRequestCommentBox isEditMode handleUpload={handleUpload} - isResolved={undefined} onSaveComment={() => { if (title && description) { handleUpdateDescription(title, comment || '') setEdit(false) } }} - currentUser={undefined} onCancelClick={() => { setEdit(false) }} comment={comment} setComment={setComment} - onCommentSaveAndStatusChange={undefined} - parentCommentId={undefined} /> ) : ( <Text size={2} color="primary"> diff --git a/packages/ui/src/views/repo/pull-request/details/components/conversation/pull-request-overview.tsx b/packages/ui/src/views/repo/pull-request/details/components/conversation/pull-request-overview.tsx index 9d48354ba..4bc0f498b 100644 --- a/packages/ui/src/views/repo/pull-request/details/components/conversation/pull-request-overview.tsx +++ b/packages/ui/src/views/repo/pull-request/details/components/conversation/pull-request-overview.tsx @@ -1,6 +1,6 @@ import { useCallback, useMemo, useState } from 'react' -import { Avatar, AvatarFallback, Icon, Layout, Text } from '@components/index' +import { Avatar, AvatarFallback, Icon, Layout } from '@components/index' import { DiffModeEnum } from '@git-diff-view/react' import { getInitials } from '@utils/stringUtils' import { timeAgo } from '@utils/utils' @@ -50,7 +50,6 @@ interface PullRequestOverviewProps extends RoutingProps { repoId: string diffData?: { text: string; numAdditions?: number; numDeletions?: number; data?: string; title: string; lang: string } onCopyClick: (commentId?: number) => void - onCommentSaveAndStatusChange?: (comment: string, status: string, parentId?: number) => void suggestionsBatch: CommitSuggestion[] onCommitSuggestion: (suggestion: CommitSuggestion) => void addSuggestionToBatch: (suggestion: CommitSuggestion) => void @@ -82,7 +81,6 @@ const PullRequestOverview: React.FC<PullRequestOverviewProps> = ({ useTranslationStore, onCopyClick, handleUpload, - onCommentSaveAndStatusChange, suggestionsBatch, onCommitSuggestion, addSuggestionToBatch, @@ -93,7 +91,6 @@ const PullRequestOverview: React.FC<PullRequestOverviewProps> = ({ toCommitDetails }) => { const { t } = useTranslationStore() - const { // mode, // setMode, @@ -254,7 +251,6 @@ const PullRequestOverview: React.FC<PullRequestOverviewProps> = ({ currentUser={currentUser?.display_name} replyBoxClassName="p-4" toggleConversationStatus={toggleConversationStatus} - onCommentSaveAndStatusChange={onCommentSaveAndStatusChange} isResolved={!!payload?.resolved} icon={<Icon name="pr-review" size={12} />} isLast={(data && data?.length - 1 === index) ?? false} @@ -264,13 +260,11 @@ const PullRequestOverview: React.FC<PullRequestOverviewProps> = ({ { avatar: ( <Avatar className="size-6 rounded-full p-0"> - {/* <AvatarImage src={AvatarUrl} /> */} - <AvatarFallback> - <Text size={1} color="tertiaryBackground"> + <span className="text-12 text-foreground-3"> {/* TODO: fix fallback string */} {getInitials((payload?.author as PayloadAuthor)?.display_name || '')} - </Text> + </span> </AvatarFallback> </Avatar> ), @@ -279,13 +273,9 @@ const PullRequestOverview: React.FC<PullRequestOverviewProps> = ({ description: payload?.created && `reviewed ${timeAgo(payload?.created)}` } ]} + contentHeader={<span>{(payload?.code_comment as PayloadCodeComment)?.path}</span>} content={ - <div className="flex flex-col pt-2"> - <div className="flex w-full items-center justify-between px-4 pb-2"> - <Text size={3} color="primary"> - {(payload?.code_comment as PayloadCodeComment)?.path} - </Text> - </div> + <div className="flex flex-col"> {startingLine ? ( <div className="bg-[--diff-hunk-lineNumber--]"> <div className="ml-16 w-full px-8 py-1">{startingLine}</div> @@ -334,13 +324,10 @@ const PullRequestOverview: React.FC<PullRequestOverviewProps> = ({ contentClassName="border-transparent" replyBoxClassName="p-4" toggleConversationStatus={toggleConversationStatus} - onCommentSaveAndStatusChange={onCommentSaveAndStatusChange} icon={ <Avatar className="size-6 rounded-full p-0"> - {/* <AvatarImage src={AvatarUrl} /> */} - <AvatarFallback> - <Text size={1} color="tertiaryBackground"> + <span className="text-12 text-foreground-3"> {/* TODO: fix fallback string */} {getInitials( ( @@ -348,7 +335,7 @@ const PullRequestOverview: React.FC<PullRequestOverviewProps> = ({ ?.author as PayloadAuthor )?.display_name || '' )} - </Text> + </span> </AvatarFallback> </Avatar> } @@ -360,16 +347,12 @@ const PullRequestOverview: React.FC<PullRequestOverviewProps> = ({ )?.display_name, // TODO: fix comment to tell between comment or code comment? description: ( - <Layout.Horizontal> - <span className="text-foreground-3"> - {timeAgo((commentItem as unknown as PayloadCreated)?.created)} - </span> + <Layout.Horizontal className="text-foreground-4"> + <span>{timeAgo((commentItem as unknown as PayloadCreated)?.created)}</span> {commentItem?.deleted ? ( <> - <span className="text-foreground-3"> | </span> - <span className="text-foreground-3"> - {t('views:pullRequests.deleted')}{' '} - </span> + <span> | </span> + <span>{t('views:pullRequests.deleted')}</span> </> ) : null} </Layout.Horizontal> @@ -385,7 +368,6 @@ const PullRequestOverview: React.FC<PullRequestOverviewProps> = ({ <PullRequestCommentBox isEditMode handleUpload={handleUpload} - isResolved={!!payload?.resolved} onSaveComment={() => { if (commentItem?.id) { handleUpdateComment?.(commentItem?.id, editComments[componentId]) @@ -400,8 +382,6 @@ const PullRequestOverview: React.FC<PullRequestOverviewProps> = ({ setComment={text => setEditComments(prev => ({ ...prev, [componentId]: text })) } - onCommentSaveAndStatusChange={onCommentSaveAndStatusChange} - parentCommentId={payload?.id} /> ) : ( <PRCommentView @@ -442,18 +422,15 @@ const PullRequestOverview: React.FC<PullRequestOverviewProps> = ({ replyBoxClassName="p-4" isResolved={!!payload?.resolved} toggleConversationStatus={toggleConversationStatus} - onCommentSaveAndStatusChange={onCommentSaveAndStatusChange} header={[ { avatar: ( <Avatar className="size-6 rounded-full p-0"> - {/* <AvatarImage src={AvatarUrl} /> */} - <AvatarFallback> - <Text size={1} color="tertiaryBackground"> + <span className="text-12 text-foreground-3"> {/* TODO: fix fallback string */} {getInitials((payload?.author as PayloadAuthor)?.display_name || '')} - </Text> + </span> </AvatarFallback> </Avatar> ), @@ -485,7 +462,6 @@ const PullRequestOverview: React.FC<PullRequestOverviewProps> = ({ onQuoteReply={handleQuoteReply} parentCommentId={payload?.id} toggleConversationStatus={toggleConversationStatus} - onCommentSaveAndStatusChange={onCommentSaveAndStatusChange} titleClassName="!flex max-w-full" currentUser={currentUser?.display_name} isLast={commentItems.length - 1 === idx} @@ -502,10 +478,8 @@ const PullRequestOverview: React.FC<PullRequestOverviewProps> = ({ key={`${commentItem.id}-${commentItem.author}-pr-comment`} icon={ <Avatar className="size-6 rounded-full p-0"> - {/* <AvatarImage src={AvatarUrl} /> */} - <AvatarFallback> - <Text size={1} color="tertiaryBackground"> + <span className="text-12 text-foreground-3"> {/* TODO: fix fallback string */} {getInitials( ( @@ -513,7 +487,7 @@ const PullRequestOverview: React.FC<PullRequestOverviewProps> = ({ ?.author as PayloadAuthor ).display_name || '' )} - </Text> + </span> </AvatarFallback> </Avatar> } @@ -549,7 +523,6 @@ const PullRequestOverview: React.FC<PullRequestOverviewProps> = ({ <PullRequestCommentBox handleUpload={handleUpload} isEditMode - isResolved={!!payload?.resolved} onSaveComment={() => { if (commentItem?.id) { handleUpdateComment?.(commentItem?.id, editComments[componentId]) @@ -562,8 +535,6 @@ const PullRequestOverview: React.FC<PullRequestOverviewProps> = ({ }} comment={editComments[componentId]} setComment={text => setEditComments(prev => ({ ...prev, [componentId]: text }))} - onCommentSaveAndStatusChange={onCommentSaveAndStatusChange} - parentCommentId={payload?.id} /> ) : ( <PRCommentView diff --git a/packages/ui/src/views/repo/pull-request/details/components/conversation/pull-request-system-comments.tsx b/packages/ui/src/views/repo/pull-request/details/components/conversation/pull-request-system-comments.tsx index c15b5d106..992b97fe7 100644 --- a/packages/ui/src/views/repo/pull-request/details/components/conversation/pull-request-system-comments.tsx +++ b/packages/ui/src/views/repo/pull-request/details/components/conversation/pull-request-system-comments.tsx @@ -66,13 +66,11 @@ const PullRequestSystemComments: React.FC<SystemCommentProps> = ({ { avatar: ( <Avatar className="size-6 rounded-full p-0"> - {/* <AvatarImage src={AvatarUrl} /> */} - <AvatarFallback> - <Text size={1} color="tertiaryBackground"> + <span className="text-12 text-foreground-3"> {/* TODO: fix fallback string */} {getInitials((payload?.author as PayloadAuthor)?.display_name || '')} - </Text> + </span> </AvatarFallback> </Avatar> ), @@ -101,9 +99,7 @@ const PullRequestSystemComments: React.FC<SystemCommentProps> = ({ const authorAvatar = ( <Avatar className="size-6 rounded-full p-0"> <AvatarFallback> - <Text size={1} color="tertiaryBackground"> - {getInitials(author?.display_name || '')} - </Text> + <span className="text-12 text-foreground-3">{getInitials(author?.display_name || '')}</span> </AvatarFallback> </Avatar> ) @@ -145,13 +141,11 @@ const PullRequestSystemComments: React.FC<SystemCommentProps> = ({ { avatar: ( <Avatar className="size-6 rounded-full p-0"> - {/* <AvatarImage src={AvatarUrl} /> */} - <AvatarFallback> - <Text size={1} color="tertiaryBackground"> + <span className="text-12 text-foreground-3"> {/* TODO: fix fallback string */} {getInitials((payload?.author as PayloadAuthor)?.display_name || '')} - </Text> + </span> </AvatarFallback> </Avatar> ), @@ -192,13 +186,11 @@ const PullRequestSystemComments: React.FC<SystemCommentProps> = ({ { avatar: ( <Avatar className="size-6 rounded-full p-0"> - {/* <AvatarImage src={AvatarUrl} /> */} - <AvatarFallback> - <Text size={1} color="tertiaryBackground"> + <span className="text-12 text-foreground-3"> {/* TODO: fix fallback string */} {getInitials((payload?.author as PayloadAuthor)?.display_name || '')} - </Text> + </span> </AvatarFallback> </Avatar> ), diff --git a/packages/ui/src/views/repo/pull-request/details/components/conversation/pull-request-timeline-item.tsx b/packages/ui/src/views/repo/pull-request/details/components/conversation/pull-request-timeline-item.tsx index 9fd217d12..84e9135f1 100644 --- a/packages/ui/src/views/repo/pull-request/details/components/conversation/pull-request-timeline-item.tsx +++ b/packages/ui/src/views/repo/pull-request/details/components/conversation/pull-request-timeline-item.tsx @@ -1,4 +1,4 @@ -import { FC, memo, ReactNode, useEffect, useState } from 'react' +import { Children, FC, memo, ReactElement, ReactNode, useEffect, useState } from 'react' import { Avatar, AvatarFallback, Button, Card, DropdownMenu, Icon, Input, NodeGroup, Text } from '@/components' import { cn } from '@utils/cn' @@ -16,6 +16,7 @@ interface TimelineItemProps { parentCommentId?: number commentId?: number currentUser?: string + contentHeader?: ReactNode content?: ReactNode icon?: ReactNode isLast: boolean @@ -37,7 +38,6 @@ interface TimelineItemProps { id?: string isResolved?: boolean toggleConversationStatus?: (status: string, parentId?: number) => void - onCommentSaveAndStatusChange?: (comment: string, status: string, parentId?: number) => void data?: string handleUpload?: (blob: File, setMarkdownContent: (data: string) => void) => void onQuoteReply?: (parentId: number, rawText: string) => void @@ -125,16 +125,8 @@ const ItemHeader: FC<ItemHeaderProps> = memo( <div className="inline-flex w-full items-center justify-between gap-1.5"> <div className="inline-flex items-center gap-1.5"> {avatar && <div>{avatar}</div>} - {name && ( - <Text size={2} color="primary" weight="medium"> - {name} - </Text> - )} - {description && ( - <Text size={2} color="tertiaryBackground"> - {description} - </Text> - )} + {name && <span className="text-14 font-medium text-foreground-8">{name}</span>} + {description && <span className="text-14 text-foreground-4">{description}</span>} </div> {selectStatus && ( <div className="justify-end"> @@ -152,6 +144,7 @@ ItemHeader.displayName = 'ItemHeader' const PullRequestTimelineItem: FC<TimelineItemProps> = ({ header, + contentHeader, content, icon, isLast, @@ -175,7 +168,6 @@ const PullRequestTimelineItem: FC<TimelineItemProps> = ({ id, isResolved, toggleConversationStatus, - onCommentSaveAndStatusChange, isNotCodeComment, data, handleUpload, @@ -183,10 +175,42 @@ const PullRequestTimelineItem: FC<TimelineItemProps> = ({ quoteReplyText }) => { const [comment, setComment] = useState('') + const [isExpanded, setIsExpanded] = useState(!isResolved) + useEffect(() => { if (quoteReplyText) setComment(quoteReplyText) }, [quoteReplyText]) + useEffect(() => { + if (isResolved) { + setIsExpanded(false) + } + }, [isResolved]) + + const renderContent = () => { + if (!content) return null + + // Show full content if not resolved or expanded + if (!isResolved || isExpanded) { + return content + } + + // For resolved comments with contentHeader, hide all content when collapsed + if (contentHeader) { + return null + } + + // For resolved comments without contentHeader, show only the first comment + const contentElement = content as ReactElement + if (contentElement.props?.children?.length) { + // If content is an array of comments, take the first one + const [firstComment] = Children.toArray(contentElement.props.children) + return <div className="px-4 pt-4 [&_[data-connector]]:hidden">{firstComment}</div> + } + // If content is a single element, return as is + return content + } + return ( <div id={id}> <NodeGroup.Root> @@ -194,102 +218,122 @@ const PullRequestTimelineItem: FC<TimelineItemProps> = ({ <NodeGroup.Title className={titleClassName}> {/* Ensure that header has at least one item */} {header.length > 0 && ( - <ItemHeader - isDeleted={isDeleted} - onEditClick={onEditClick} - onCopyClick={onCopyClick} - isComment={isComment} - isNotCodeComment={isNotCodeComment} - handleDeleteComment={handleDeleteComment} - commentId={commentId} - {...header[0]} - onQuoteReply={() => { - setHideReplyHere?.(true) - if (parentCommentId) onQuoteReply?.(parentCommentId, data ?? '') - }} - /> + <div className="flex w-full items-center justify-between gap-x-2"> + <ItemHeader + isDeleted={isDeleted} + onEditClick={onEditClick} + onCopyClick={onCopyClick} + isComment={isComment} + isNotCodeComment={isNotCodeComment} + handleDeleteComment={handleDeleteComment} + commentId={commentId} + {...header[0]} + onQuoteReply={() => { + setHideReplyHere?.(true) + if (parentCommentId) onQuoteReply?.(parentCommentId, data ?? '') + }} + /> + {isResolved && !contentHeader && ( + <Button + className="h-auto gap-x-1.5 px-4 font-normal text-foreground-2 hover:text-foreground-8" + variant="custom" + onClick={() => setIsExpanded(prev => !prev)} + > + <Icon name={isExpanded ? 'collapse-comment' : 'expand-comment'} size={14} /> + {isExpanded ? 'Hide resolved' : 'Show resolved'} + </Button> + )} + </div> )} </NodeGroup.Title> {content && ( <NodeGroup.Content> - <Card.Root className={cn('rounded-md bg-transparent', contentClassName)}> + <Card.Root className={cn('rounded-md bg-transparent overflow-hidden shadow-none', contentClassName)}> + {contentHeader && ( + <div + className={cn('flex w-full items-center justify-between p-4 bg-background-2', { + 'pr-1.5': isResolved + })} + > + {contentHeader} + {isResolved && ( + <Button + className="h-auto gap-x-1.5 px-2.5 font-normal text-foreground-2 hover:text-foreground-8" + variant="custom" + onClick={() => setIsExpanded(prev => !prev)} + > + <Icon name={isExpanded ? 'collapse-comment' : 'expand-comment'} size={14} /> + {isExpanded ? 'Hide resolved' : 'Show resolved'} + </Button> + )} + </div> + )} + {isEditMode ? ( <PullRequestCommentBox handleUpload={handleUpload} isEditMode + currentUser={currentUser} onSaveComment={() => { handleSaveComment?.(comment, parentCommentId) setComment('') }} - currentUser={currentUser} onCancelClick={() => { setComment('') }} - isResolved={isResolved} comment={comment} setComment={setComment} /> ) : ( - content + renderContent() )} - {!hideReplySection && ( + {!hideReplySection && (!isResolved || isExpanded) && ( <> {hideReplyHere ? ( - <div className="flex w-full flex-col px-4"> - <PullRequestCommentBox - handleUpload={handleUpload} - inReplyMode - hideAvatar - onSaveComment={() => { - handleSaveComment?.(comment, parentCommentId) - setHideReplyHere?.(false) + <PullRequestCommentBox + handleUpload={handleUpload} + inReplyMode + onSaveComment={() => { + handleSaveComment?.(comment, parentCommentId) + setHideReplyHere?.(false) + }} + onCancelClick={() => { + setHideReplyHere?.(false) + }} + comment={comment} + setComment={setComment} + /> + ) : ( + <div className={cn('flex items-center gap-3 border-t bg-background-2', replyBoxClassName)}> + {currentUser ? ( + <Avatar className="size-6 rounded-full p-0"> + <AvatarFallback> + <span className="text-12 text-foreground-3">{getInitials(currentUser ?? '', 2)}</span> + </AvatarFallback> + </Avatar> + ) : null} + <Input + placeholder="Reply here" + size="md" + onClick={() => { + setHideReplyHere?.(true) }} - currentUser={currentUser} - onCancelClick={() => { - setHideReplyHere?.(false) + onChange={e => { + setComment(e.target.value) }} - comment={comment} - isResolved={isResolved} - setComment={setComment} - parentCommentId={parentCommentId} - onCommentSaveAndStatusChange={onCommentSaveAndStatusChange} /> </div> - ) : ( - <> - <div className={cn('flex items-center gap-3 border-t', replyBoxClassName)}> - {currentUser ? ( - <Avatar className="size-6 rounded-full p-0"> - <AvatarFallback> - <Text size={1} color="tertiaryBackground"> - {getInitials(currentUser ?? '', 2)} - </Text> - </AvatarFallback> - </Avatar> - ) : null} - <Input - placeholder="Reply here" - size="md" - onClick={() => { - setHideReplyHere?.(true) - }} - onChange={e => { - setComment(e.target.value) - }} - /> - </div> - <div className={cn('flex gap-3 border-t', replyBoxClassName)}> - <Button - variant={'outline'} - onClick={() => { - toggleConversationStatus?.(isResolved ? 'active' : 'resolved', parentCommentId) - }} - > - {isResolved ? 'Reactivate' : 'Resolve Conversation'} - </Button> - </div> - </> )} + <div className={cn('flex gap-3 border-t', replyBoxClassName)}> + <Button + variant="outline" + onClick={() => { + toggleConversationStatus?.(isResolved ? 'active' : 'resolved', parentCommentId) + }} + > + {isResolved ? 'Unresolve conversation' : 'Resolve conversation'} + </Button> + </div> </> )} </Card.Root> diff --git a/packages/ui/src/views/repo/pull-request/details/components/conversation/sections/pull-request-changes-section.tsx b/packages/ui/src/views/repo/pull-request/details/components/conversation/sections/pull-request-changes-section.tsx index e1cb1a625..8ae816628 100644 --- a/packages/ui/src/views/repo/pull-request/details/components/conversation/sections/pull-request-changes-section.tsx +++ b/packages/ui/src/views/repo/pull-request/details/components/conversation/sections/pull-request-changes-section.tsx @@ -73,7 +73,7 @@ const AvatarItem: React.FC<AvatarItemProps> = ({ evaluations }: AvatarItemProps) return ( <Avatar key={owner?.id} className="size-6 rounded-full"> <AvatarFallback> - <span className="text-12 text-foreground-4"> + <span className="text-12 text-foreground-3"> {owner?.display_name && getInitials(owner?.display_name)} </span> </AvatarFallback> From d9c8a5e9084f1c4db18f97e61b28ee2aafcacff8 Mon Sep 17 00:00:00 2001 From: Calvin Lee <calvin.lee@harness.io> Date: Mon, 27 Jan 2025 14:53:12 -0700 Subject: [PATCH 6/9] feat: [pipe-24076]: fix closed issue on filter (#844) Signed-off-by: Calvin Lee <cjlee@ualberta.ca> Co-authored-by: Calvin Lee <cjlee@ualberta.ca> --- .../ui/src/views/repo/pull-request/pull-request-list-page.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/ui/src/views/repo/pull-request/pull-request-list-page.tsx b/packages/ui/src/views/repo/pull-request/pull-request-list-page.tsx index 736d3065a..a9cfe732a 100644 --- a/packages/ui/src/views/repo/pull-request/pull-request-list-page.tsx +++ b/packages/ui/src/views/repo/pull-request/pull-request-list-page.tsx @@ -68,7 +68,7 @@ const PullRequestList: FC<PullRequestPageProps> = ({ const noData = !(sortedPullReqs && sortedPullReqs.length > 0) const handleCloseClick = () => { - filterHandlers.setActiveFilters([{ type: 'type', condition: 'is', selectedValues: ['disabled'] }]) + filterHandlers.handleResetFilters() } const handleOpenClick = () => { From bb4ca36b04c3060a8b58cf291e7c3926bc511212 Mon Sep 17 00:00:00 2001 From: vivek-harness <c_vivek.patel@harness.io> Date: Tue, 28 Jan 2025 11:18:39 +0530 Subject: [PATCH 7/9] Fixed breadcrumb failing API issue for MFE (#841) * Fixed breadcrumb failing API issue for MFE * Removed empty line --- apps/gitness/src/AppMFE.tsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/apps/gitness/src/AppMFE.tsx b/apps/gitness/src/AppMFE.tsx index e0765ff78..3fcecfd92 100644 --- a/apps/gitness/src/AppMFE.tsx +++ b/apps/gitness/src/AppMFE.tsx @@ -29,7 +29,7 @@ export interface MFERouteRendererProps { const filteredRoutes = extractRedirectRouteObjects(repoRoutes) const isRouteMatchingRedirectRoutes = (pathToValidate: string) => { - return filteredRoutes.every(route => !matchPath(`/${route.path}` as string, pathToValidate)) + return filteredRoutes.some(route => matchPath(`/${route.path}` as string, pathToValidate)) } function MFERouteRenderer({ renderUrl, parentLocationPath, onRouteChange }: MFERouteRendererProps) { @@ -50,7 +50,6 @@ function MFERouteRenderer({ renderUrl, parentLocationPath, onRouteChange }: MFER ) // Handle location change detected from parent route - useEffect(() => { if (canNavigate) { const pathToNavigate = parentLocationPath.replace(renderUrl, '') From e75b7e53bc6393b6de8fb9e40f5d5cf134dd5336 Mon Sep 17 00:00:00 2001 From: praneshg239 <95267551+praneshg239@users.noreply.github.com> Date: Tue, 28 Jan 2025 12:46:25 +0530 Subject: [PATCH 8/9] Fix create repo API call plus portal and PR svg icons fill issue (#847) --- .../src/pages-v2/repo/repo-create-page.tsx | 4 +- packages/ui/src/components/select.tsx | 5 ++- packages/ui/src/components/sheet.tsx | 42 ++++++++++--------- packages/ui/src/icons/pr-closed.svg | 2 +- packages/ui/src/icons/pr-comment.svg | 2 +- packages/ui/src/icons/pr-merge.svg | 2 +- packages/ui/src/icons/pr-open.svg | 2 +- packages/ui/src/icons/pr-review.svg | 2 +- 8 files changed, 35 insertions(+), 26 deletions(-) diff --git a/apps/gitness/src/pages-v2/repo/repo-create-page.tsx b/apps/gitness/src/pages-v2/repo/repo-create-page.tsx index 48c1a766a..bc187674e 100644 --- a/apps/gitness/src/pages-v2/repo/repo-create-page.tsx +++ b/apps/gitness/src/pages-v2/repo/repo-create-page.tsx @@ -35,7 +35,9 @@ export const CreateRepo = () => { createRepositoryMutation.mutate( { - queryParams: {}, + queryParams: { + space_path: spaceURL + }, body: repositoryRequest }, { diff --git a/packages/ui/src/components/select.tsx b/packages/ui/src/components/select.tsx index 99baab42d..ec9bc651b 100644 --- a/packages/ui/src/components/select.tsx +++ b/packages/ui/src/components/select.tsx @@ -1,6 +1,7 @@ import { Children, ComponentPropsWithoutRef, ElementRef, FC, forwardRef, PropsWithChildren, ReactNode } from 'react' import { Caption, Label, Message, MessageTheme, SearchBox } from '@/components' +import { usePortal } from '@/context' import { useDebounceSearch } from '@hooks/use-debounce-search' import { CheckIcon, ChevronDownIcon } from '@radix-ui/react-icons' import * as SelectPrimitive from '@radix-ui/react-select' @@ -114,8 +115,10 @@ const SelectContent = forwardRef< searchValue: searchProps?.searchValue }) + const { portalContainer } = usePortal() + return ( - <SelectPrimitive.Portal> + <SelectPrimitive.Portal container={portalContainer}> <SelectPrimitive.Content ref={ref} className={cn( diff --git a/packages/ui/src/components/sheet.tsx b/packages/ui/src/components/sheet.tsx index fb9bc4c52..8deafa405 100644 --- a/packages/ui/src/components/sheet.tsx +++ b/packages/ui/src/components/sheet.tsx @@ -1,5 +1,6 @@ import * as React from 'react' +import { usePortal } from '@/context' import * as SheetPrimitive from '@radix-ui/react-dialog' import { cn } from '@utils/cn' import { cva, type VariantProps } from 'class-variance-authority' @@ -85,25 +86,28 @@ const SheetContent = React.forwardRef<React.ElementRef<typeof SheetPrimitive.Con ...props }, ref - ) => ( - <SheetPortal> - <SheetOverlay modal={modal} className={overlayClassName} handleClose={handleClose || props.onClick} /> - <SheetPrimitive.Content ref={ref} className={cn(sheetVariants({ side }), className)} {...props}> - {children} - {!hideCloseButton && ( - <SheetPrimitive.Close - asChild - className="absolute right-[0.1875rem] top-2 flex items-center justify-center transition-colors disabled:pointer-events-none" - > - <Button className="text-icons-4 hover:text-icons-2" variant="custom" size="icon" onClick={handleClose}> - <Icon name="close" size={16} /> - <span className="sr-only">Close</span> - </Button> - </SheetPrimitive.Close> - )} - </SheetPrimitive.Content> - </SheetPortal> - ) + ) => { + const { portalContainer } = usePortal() + return ( + <SheetPortal container={portalContainer}> + <SheetOverlay modal={modal} className={overlayClassName} handleClose={handleClose || props.onClick} /> + <SheetPrimitive.Content ref={ref} className={cn(sheetVariants({ side }), className)} {...props}> + {children} + {!hideCloseButton && ( + <SheetPrimitive.Close + asChild + className="absolute right-[0.1875rem] top-2 flex items-center justify-center transition-colors disabled:pointer-events-none" + > + <Button className="text-icons-4 hover:text-icons-2" variant="custom" size="icon" onClick={handleClose}> + <Icon name="close" size={16} /> + <span className="sr-only">Close</span> + </Button> + </SheetPrimitive.Close> + )} + </SheetPrimitive.Content> + </SheetPortal> + ) + } ) SheetContent.displayName = SheetPrimitive.Content.displayName diff --git a/packages/ui/src/icons/pr-closed.svg b/packages/ui/src/icons/pr-closed.svg index 146760b15..bfc633888 100644 --- a/packages/ui/src/icons/pr-closed.svg +++ b/packages/ui/src/icons/pr-closed.svg @@ -1 +1 @@ -<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 12 12"><circle cx="2.57" cy="2.57" r="1.714" stroke="currentColor" stroke-linecap="round"/><circle cx="9.427" cy="9.425" r="1.714" stroke="currentColor" stroke-linecap="round"/><path stroke="currentColor" stroke-linecap="round" d="M9.428 5.14v2.358"/><path fill="currentColor" fill-rule="evenodd" d="M7.824 1.725a.5.5 0 1 1 .707-.707l.895.894.895-.894a.5.5 0 1 1 .707.707l-.895.894.895.895a.5.5 0 1 1-.707.707l-.895-.895-.895.895a.5.5 0 1 1-.707-.707l.895-.895z" clip-rule="evenodd"/><circle cx="2.57" cy="9.425" r="1.714" stroke="currentColor" stroke-linecap="round"/><path stroke="currentColor" stroke-linecap="round" d="M2.57 4.285v3.429"/></svg> \ No newline at end of file +<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 12 12"><circle cx="2.57" cy="2.57" r="1.714" stroke="currentColor" stroke-linecap="round"/><circle cx="9.427" cy="9.425" r="1.714" stroke="currentColor" stroke-linecap="round"/><path stroke="currentColor" stroke-linecap="round" d="M9.428 5.14v2.358"/><path fill="currentColor" fill-rule="evenodd" d="M7.824 1.725a.5.5 0 1 1 .707-.707l.895.894.895-.894a.5.5 0 1 1 .707.707l-.895.894.895.895a.5.5 0 1 1-.707.707l-.895-.895-.895.895a.5.5 0 1 1-.707-.707l.895-.895z" clip-rule="evenodd"/><circle cx="2.57" cy="9.425" r="1.714" stroke="currentColor" stroke-linecap="round"/><path stroke="currentColor" stroke-linecap="round" d="M2.57 4.285v3.429"/></svg> \ No newline at end of file diff --git a/packages/ui/src/icons/pr-comment.svg b/packages/ui/src/icons/pr-comment.svg index 99cf4c7e0..9f26f8c69 100644 --- a/packages/ui/src/icons/pr-comment.svg +++ b/packages/ui/src/icons/pr-comment.svg @@ -1 +1 @@ -<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 12 12"><g clip-path="url(#a)"><g clip-path="url(#b)"><path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" d="M.5 2v5A1.5 1.5 0 0 0 2 8.5h2l2 3 2-3h2A1.5 1.5 0 0 0 11.5 7V2A1.5 1.5 0 0 0 10 .5H2A1.5 1.5 0 0 0 .5 2"/></g></g><defs><clipPath id="a"><path fill="#fff" d="M0 0h12v12H0z"/></clipPath><clipPath id="b"><path fill="#fff" d="M0 0h12v12H0z"/></clipPath></defs></svg> \ No newline at end of file +<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 12 12"><g clip-path="url(#a)"><g clip-path="url(#b)"><path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" d="M.5 2v5A1.5 1.5 0 0 0 2 8.5h2l2 3 2-3h2A1.5 1.5 0 0 0 11.5 7V2A1.5 1.5 0 0 0 10 .5H2A1.5 1.5 0 0 0 .5 2"/></g></g><defs><clipPath id="a"><path fill="#fff" d="M0 0h12v12H0z"/></clipPath><clipPath id="b"><path fill="#fff" d="M0 0h12v12H0z"/></clipPath></defs></svg> \ No newline at end of file diff --git a/packages/ui/src/icons/pr-merge.svg b/packages/ui/src/icons/pr-merge.svg index 14da165a0..8b718a086 100644 --- a/packages/ui/src/icons/pr-merge.svg +++ b/packages/ui/src/icons/pr-merge.svg @@ -1 +1 @@ -<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 12 12"><g stroke="currentColor" stroke-linecap="round" clip-path="url(#a)"><circle cx="2.57" cy="2.57" r="1.714"/><circle cx="9.427" cy="6.425" r="1.714"/><circle cx="2.57" cy="9.425" r="1.714"/><path d="M2.57 4.285v3.429M2.57 4.285C4.285 6 5.57 6.428 7.713 6.428"/></g><defs><clipPath id="a"><path fill="#fff" d="M0 0h12v12H0z"/></clipPath></defs></svg> \ No newline at end of file +<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 12 12"><g stroke="currentColor" stroke-linecap="round" clip-path="url(#a)"><circle cx="2.57" cy="2.57" r="1.714"/><circle cx="9.427" cy="6.425" r="1.714"/><circle cx="2.57" cy="9.425" r="1.714"/><path d="M2.57 4.285v3.429M2.57 4.285C4.285 6 5.57 6.428 7.713 6.428"/></g><defs><clipPath id="a"><path fill="#fff" d="M0 0h12v12H0z"/></clipPath></defs></svg> \ No newline at end of file diff --git a/packages/ui/src/icons/pr-open.svg b/packages/ui/src/icons/pr-open.svg index 31f0b9292..2b0b09581 100644 --- a/packages/ui/src/icons/pr-open.svg +++ b/packages/ui/src/icons/pr-open.svg @@ -1 +1 @@ -<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 12 12"><g stroke="currentColor" stroke-linecap="round" clip-path="url(#a)"><ellipse cx="2.622" cy="2.621" rx="1.622" ry="1.621"/><ellipse cx="9.378" cy="9.379" rx="1.622" ry="1.621"/><ellipse cx="2.622" cy="9.379" rx="1.622" ry="1.621"/><path d="M2.62 4.309v3.377M9.378 7.688V3.466a.845.845 0 0 0-.845-.845H6"/><path stroke-linejoin="round" d="M7.266 1.355 6 2.622 7.266 3.89"/></g><defs><clipPath id="a"><path fill="#fff" d="M0 0h12v12H0z"/></clipPath></defs></svg> \ No newline at end of file +<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 12 12"><g stroke="currentColor" stroke-linecap="round" clip-path="url(#a)"><ellipse cx="2.622" cy="2.621" rx="1.622" ry="1.621"/><ellipse cx="9.378" cy="9.379" rx="1.622" ry="1.621"/><ellipse cx="2.622" cy="9.379" rx="1.622" ry="1.621"/><path d="M2.62 4.309v3.377M9.378 7.688V3.466a.845.845 0 0 0-.845-.845H6"/><path stroke-linejoin="round" d="M7.266 1.355 6 2.622 7.266 3.89"/></g><defs><clipPath id="a"><path fill="#fff" d="M0 0h12v12H0z"/></clipPath></defs></svg> \ No newline at end of file diff --git a/packages/ui/src/icons/pr-review.svg b/packages/ui/src/icons/pr-review.svg index 38b4f5d58..94e390a62 100644 --- a/packages/ui/src/icons/pr-review.svg +++ b/packages/ui/src/icons/pr-review.svg @@ -1 +1 @@ -<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 12 12"><g clip-path="url(#a)"><g stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" clip-path="url(#b)"><path d="M.375 6S2.625 1.875 6 1.875 11.625 6 11.625 6 9.375 10.125 6 10.125.375 6 .375 6"/><path d="M6 7.875a1.875 1.875 0 1 0 0-3.75 1.875 1.875 0 0 0 0 3.75"/></g></g><defs><clipPath id="a"><path fill="#fff" d="M0 0h12v12H0z"/></clipPath><clipPath id="b"><path fill="#fff" d="M0 0h12v12H0z"/></clipPath></defs></svg> \ No newline at end of file +<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 12 12"><g clip-path="url(#a)"><g stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" clip-path="url(#b)"><path d="M.375 6S2.625 1.875 6 1.875 11.625 6 11.625 6 9.375 10.125 6 10.125.375 6 .375 6"/><path d="M6 7.875a1.875 1.875 0 1 0 0-3.75 1.875 1.875 0 0 0 0 3.75"/></g></g><defs><clipPath id="a"><path fill="#fff" d="M0 0h12v12H0z"/></clipPath><clipPath id="b"><path fill="#fff" d="M0 0h12v12H0z"/></clipPath></defs></svg> \ No newline at end of file From d1b64016f3019aa1361f9a6dd614df20769d5f95 Mon Sep 17 00:00:00 2001 From: vivek-harness <c_vivek.patel@harness.io> Date: Tue, 28 Jan 2025 13:17:45 +0530 Subject: [PATCH 9/9] Breadcrumb api call fix (#848) * Fixed failing api call for repos in MFE * Changed retry limit to 5 instead of the default 3 * Renamed function * Changed variable name * Changed location to location.pathname in dependency array --- apps/gitness/src/AppMFE.tsx | 15 +++++++-------- apps/gitness/src/pages-v2/repo/repo-list.tsx | 2 +- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/apps/gitness/src/AppMFE.tsx b/apps/gitness/src/AppMFE.tsx index 3fcecfd92..b72f85e50 100644 --- a/apps/gitness/src/AppMFE.tsx +++ b/apps/gitness/src/AppMFE.tsx @@ -27,16 +27,16 @@ export interface MFERouteRendererProps { onRouteChange: (updatedLocationPathname: string) => void } -const filteredRoutes = extractRedirectRouteObjects(repoRoutes) -const isRouteMatchingRedirectRoutes = (pathToValidate: string) => { - return filteredRoutes.some(route => matchPath(`/${route.path}` as string, pathToValidate)) +const filteredRedirectRoutes = extractRedirectRouteObjects(repoRoutes) +const isRouteNotMatchingRedirectRoutes = (pathToValidate: string) => { + return filteredRedirectRoutes.every(route => !matchPath(`/${route.path}` as string, pathToValidate)) } function MFERouteRenderer({ renderUrl, parentLocationPath, onRouteChange }: MFERouteRendererProps) { const navigate = useNavigate() const location = useLocation() const parentPath = parentLocationPath.replace(renderUrl, '') - const isNotRedirectPath = isRouteMatchingRedirectRoutes(location.pathname) + const isNotRedirectPath = isRouteNotMatchingRedirectRoutes(location.pathname) /** * renderUrl ==> base URL of parent application @@ -52,17 +52,16 @@ function MFERouteRenderer({ renderUrl, parentLocationPath, onRouteChange }: MFER // Handle location change detected from parent route useEffect(() => { if (canNavigate) { - const pathToNavigate = parentLocationPath.replace(renderUrl, '') - navigate(pathToNavigate, { replace: true }) + navigate(parentPath, { replace: true }) } - }, [parentLocationPath]) + }, [parentPath]) // Notify parent about route change useEffect(() => { if (canNavigate) { onRouteChange?.(`${renderUrl}${location.pathname}`) } - }, [location]) + }, [location.pathname]) return null } diff --git a/apps/gitness/src/pages-v2/repo/repo-list.tsx b/apps/gitness/src/pages-v2/repo/repo-list.tsx index 8927208d1..a94ff3e16 100644 --- a/apps/gitness/src/pages-v2/repo/repo-list.tsx +++ b/apps/gitness/src/pages-v2/repo/repo-list.tsx @@ -39,7 +39,7 @@ export default function ReposListPage() { space_ref: `${spaceURL}/+` }, { - retry: false + retry: 5 } )