mirror of
https://github.com/harness/drone.git
synced 2025-05-05 05:01:46 +08:00
use useHistory inside MarkdownViewer (#358)
Co-authored-by: “Tan <“tan@harness.io”>
This commit is contained in:
parent
a96ed98e5d
commit
ba6645cdaa
5
.github/workflows/ci-lint.yml
vendored
5
.github/workflows/ci-lint.yml
vendored
@ -23,14 +23,15 @@ jobs:
|
|||||||
- uses: actions/setup-node@v3
|
- uses: actions/setup-node@v3
|
||||||
with:
|
with:
|
||||||
node-version: 16
|
node-version: 16
|
||||||
cache: 'npm'
|
cache: "npm"
|
||||||
- name: install and build web app
|
- name: install, lint, and build web app
|
||||||
working-directory: web
|
working-directory: web
|
||||||
run: |
|
run: |
|
||||||
echo "@harness:registry=https://npm.pkg.github.com
|
echo "@harness:registry=https://npm.pkg.github.com
|
||||||
//npm.pkg.github.com/:_authToken=${{ secrets.GH_TOKEN }}
|
//npm.pkg.github.com/:_authToken=${{ secrets.GH_TOKEN }}
|
||||||
always-auth=true" >> ~/.npmrc
|
always-auth=true" >> ~/.npmrc
|
||||||
yarn install
|
yarn install
|
||||||
|
yarn checks
|
||||||
yarn build
|
yarn build
|
||||||
- name: golangci-lint
|
- name: golangci-lint
|
||||||
uses: golangci/golangci-lint-action@v3
|
uses: golangci/golangci-lint-action@v3
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import { useHistory } from 'react-router-dom'
|
||||||
import React, { Suspense, useCallback } from 'react'
|
import React, { Suspense, useCallback } from 'react'
|
||||||
import { Container, Text } from '@harness/uicore'
|
import { Container, Text } from '@harness/uicore'
|
||||||
import MarkdownEditor from '@uiw/react-markdown-editor'
|
import MarkdownEditor from '@uiw/react-markdown-editor'
|
||||||
@ -10,13 +11,12 @@ import css from './SourceCodeViewer.module.scss'
|
|||||||
|
|
||||||
interface MarkdownViewerProps {
|
interface MarkdownViewerProps {
|
||||||
source: string
|
source: string
|
||||||
navigateTo: (url: string) => void
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function MarkdownViewer({ source, navigateTo }: MarkdownViewerProps) {
|
export function MarkdownViewer({ source }: MarkdownViewerProps) {
|
||||||
const { getString } = useStrings()
|
const { getString } = useStrings()
|
||||||
const interceptClickEventOnViewerContainer = useCallback(
|
const history = useHistory()
|
||||||
event => {
|
const interceptClickEventOnViewerContainer = useCallback(event => {
|
||||||
const { target } = event
|
const { target } = event
|
||||||
|
|
||||||
if (target?.tagName?.toLowerCase() === 'a') {
|
if (target?.tagName?.toLowerCase() === 'a') {
|
||||||
@ -25,13 +25,12 @@ export function MarkdownViewer({ source, navigateTo }: MarkdownViewerProps) {
|
|||||||
// Intercept click event on internal links and navigate to pages to avoid full page reload
|
// Intercept click event on internal links and navigate to pages to avoid full page reload
|
||||||
if (href && !href.startsWith('#')) {
|
if (href && !href.startsWith('#')) {
|
||||||
try {
|
try {
|
||||||
const origin = new URL(href).origin
|
const url = new URL(href)
|
||||||
|
|
||||||
if (origin === window.location.origin) {
|
if (url.origin === window.location.origin) {
|
||||||
// For some reason, history.push(href) does not work in the context of @uiw/react-markdown-editor library.
|
|
||||||
navigateTo?.(href)
|
|
||||||
event.stopPropagation()
|
event.stopPropagation()
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
|
history.push(url.pathname)
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// eslint-disable-next-line no-console
|
// eslint-disable-next-line no-console
|
||||||
@ -39,9 +38,7 @@ export function MarkdownViewer({ source, navigateTo }: MarkdownViewerProps) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
}, [])
|
||||||
[navigateTo]
|
|
||||||
)
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Container className={css.main} onClick={interceptClickEventOnViewerContainer}>
|
<Container className={css.main} onClick={interceptClickEventOnViewerContainer}>
|
||||||
|
@ -311,8 +311,7 @@ repoCloneHeader: Or you can clone this repository
|
|||||||
repoCloneLabel: Clone with HTTPS
|
repoCloneLabel: Clone with HTTPS
|
||||||
emptyRepoHeader: This repository is empty. Let's get started...
|
emptyRepoHeader: This repository is empty. Let's get started...
|
||||||
addNewFile: + New File
|
addNewFile: + New File
|
||||||
# emptyRepoInclude: We recommend every repository include a [README](README_URL), [LICENSE](LICENSE_URL), and [.gitignore](GITIGNORE_URL).
|
emptyRepoInclude: We recommend every repository include a {README}, {LICENSE}, and {GITIGNORE}.
|
||||||
emptyRepoInclude: We recommend every repository include a
|
|
||||||
readMe: README,
|
readMe: README,
|
||||||
license: LICENSE
|
license: LICENSE
|
||||||
gitIgnore: .gitignore
|
gitIgnore: .gitignore
|
||||||
|
@ -21,7 +21,6 @@ import cx from 'classnames'
|
|||||||
import { useGet, useMutate } from 'restful-react'
|
import { useGet, useMutate } from 'restful-react'
|
||||||
import ReactTimeago from 'react-timeago'
|
import ReactTimeago from 'react-timeago'
|
||||||
import { orderBy } from 'lodash-es'
|
import { orderBy } from 'lodash-es'
|
||||||
import { useHistory } from 'react-router-dom'
|
|
||||||
import { Render } from 'react-jsx-match'
|
import { Render } from 'react-jsx-match'
|
||||||
import { CodeIcon, GitInfoProps } from 'utils/GitUtils'
|
import { CodeIcon, GitInfoProps } from 'utils/GitUtils'
|
||||||
import { MarkdownViewer } from 'components/SourceCodeViewer/SourceCodeViewer'
|
import { MarkdownViewer } from 'components/SourceCodeViewer/SourceCodeViewer'
|
||||||
@ -275,7 +274,7 @@ export const Conversation: React.FC<ConversationProps> = ({
|
|||||||
{activityBlocks?.map((blocks, index) => {
|
{activityBlocks?.map((blocks, index) => {
|
||||||
const threadId = blocks[0].payload?.id
|
const threadId = blocks[0].payload?.id
|
||||||
const commentItems = blocks
|
const commentItems = blocks
|
||||||
let state = {
|
const state = {
|
||||||
label: getString('active'),
|
label: getString('active'),
|
||||||
value: commentState.ACTIVE
|
value: commentState.ACTIVE
|
||||||
} as SelectOption
|
} as SelectOption
|
||||||
@ -530,7 +529,6 @@ const generateReviewDecisionIcon = (
|
|||||||
}
|
}
|
||||||
|
|
||||||
const SystemBox: React.FC<SystemBoxProps> = ({ pullRequestMetadata, commentItems }) => {
|
const SystemBox: React.FC<SystemBoxProps> = ({ pullRequestMetadata, commentItems }) => {
|
||||||
const history = useHistory()
|
|
||||||
const { getString } = useStrings()
|
const { getString } = useStrings()
|
||||||
const payload = commentItems[0].payload
|
const payload = commentItems[0].payload
|
||||||
const type = payload?.type
|
const type = payload?.type
|
||||||
@ -694,7 +692,6 @@ const SystemBox: React.FC<SystemBoxProps> = ({ pullRequestMetadata, commentItems
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
.join('\n')}
|
.join('\n')}
|
||||||
navigateTo={history.push}
|
|
||||||
/>
|
/>
|
||||||
</Container>
|
</Container>
|
||||||
</Render>
|
</Render>
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import React, { useState } from 'react'
|
import React, { useState } from 'react'
|
||||||
import { Container, useToaster } from '@harness/uicore'
|
import { Container, useToaster } from '@harness/uicore'
|
||||||
import cx from 'classnames'
|
import cx from 'classnames'
|
||||||
import { useHistory } from 'react-router-dom'
|
|
||||||
import { useMutate } from 'restful-react'
|
import { useMutate } from 'restful-react'
|
||||||
import { MarkdownViewer } from 'components/SourceCodeViewer/SourceCodeViewer'
|
import { MarkdownViewer } from 'components/SourceCodeViewer/SourceCodeViewer'
|
||||||
import { useStrings } from 'framework/strings'
|
import { useStrings } from 'framework/strings'
|
||||||
@ -17,7 +16,6 @@ export const DescriptionBox: React.FC<ConversationProps> = ({
|
|||||||
pullRequestMetadata,
|
pullRequestMetadata,
|
||||||
onCommentUpdate: refreshPullRequestMetadata
|
onCommentUpdate: refreshPullRequestMetadata
|
||||||
}) => {
|
}) => {
|
||||||
const history = useHistory()
|
|
||||||
const [edit, setEdit] = useState(false)
|
const [edit, setEdit] = useState(false)
|
||||||
// const [updated, setUpdated] = useState(pullRequestMetadata.edited as number)
|
// const [updated, setUpdated] = useState(pullRequestMetadata.edited as number)
|
||||||
const [originalContent, setOriginalContent] = useState(pullRequestMetadata.description as string)
|
const [originalContent, setOriginalContent] = useState(pullRequestMetadata.description as string)
|
||||||
@ -65,7 +63,7 @@ export const DescriptionBox: React.FC<ConversationProps> = ({
|
|||||||
/>
|
/>
|
||||||
)) || (
|
)) || (
|
||||||
<Container className={css.mdWrapper}>
|
<Container className={css.mdWrapper}>
|
||||||
<MarkdownViewer source={content} navigateTo={history.push} />
|
<MarkdownViewer source={content} />
|
||||||
<Container className={css.menuWrapper}>
|
<Container className={css.menuWrapper}>
|
||||||
<OptionsMenuButton
|
<OptionsMenuButton
|
||||||
isDark={true}
|
isDark={true}
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import { noop } from 'lodash-es'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import {
|
import {
|
||||||
Container,
|
Container,
|
||||||
@ -18,7 +19,7 @@ import { useStrings } from 'framework/strings'
|
|||||||
import css from './PullRequestSideBar.module.scss'
|
import css from './PullRequestSideBar.module.scss'
|
||||||
|
|
||||||
interface PullRequestSideBarProps {
|
interface PullRequestSideBarProps {
|
||||||
reviewers?: any
|
reviewers?: Unknown
|
||||||
}
|
}
|
||||||
|
|
||||||
const PullRequestSideBar = (props: PullRequestSideBarProps) => {
|
const PullRequestSideBar = (props: PullRequestSideBarProps) => {
|
||||||
@ -99,17 +100,17 @@ const PullRequestSideBar = (props: PullRequestSideBarProps) => {
|
|||||||
items={[
|
items={[
|
||||||
{
|
{
|
||||||
text: getString('makeOptional'),
|
text: getString('makeOptional'),
|
||||||
onClick: () => {}
|
onClick: noop
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: getString('makeRequired'),
|
text: getString('makeRequired'),
|
||||||
onClick: () => {}
|
onClick: noop
|
||||||
},
|
},
|
||||||
'-',
|
'-',
|
||||||
{
|
{
|
||||||
isDanger: true,
|
isDanger: true,
|
||||||
text: getString('remove'),
|
text: getString('remove'),
|
||||||
onClick: () => {}
|
onClick: noop
|
||||||
}
|
}
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
@ -155,17 +156,17 @@ const PullRequestSideBar = (props: PullRequestSideBarProps) => {
|
|||||||
items={[
|
items={[
|
||||||
{
|
{
|
||||||
text: getString('makeOptional'),
|
text: getString('makeOptional'),
|
||||||
onClick: () => {}
|
onClick: noop
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: getString('makeRequired'),
|
text: getString('makeRequired'),
|
||||||
onClick: () => {}
|
onClick: noop
|
||||||
},
|
},
|
||||||
'-',
|
'-',
|
||||||
{
|
{
|
||||||
isDanger: true,
|
isDanger: true,
|
||||||
text: getString('remove'),
|
text: getString('remove'),
|
||||||
onClick: () => {}
|
onClick: noop
|
||||||
}
|
}
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
|
@ -29,9 +29,9 @@ import { UserPreference, useUserPreference } from 'hooks/useUserPreference'
|
|||||||
import { NoResultCard } from 'components/NoResultCard/NoResultCard'
|
import { NoResultCard } from 'components/NoResultCard/NoResultCard'
|
||||||
import { PullRequestStateLabel } from 'components/PullRequestStateLabel/PullRequestStateLabel'
|
import { PullRequestStateLabel } from 'components/PullRequestStateLabel/PullRequestStateLabel'
|
||||||
import { LoadingSpinner } from 'components/LoadingSpinner/LoadingSpinner'
|
import { LoadingSpinner } from 'components/LoadingSpinner/LoadingSpinner'
|
||||||
|
import { ExecutionStatusLabel } from 'components/ExecutionStatusLabel/ExecutionStatusLabel'
|
||||||
import { PullRequestsContentHeader } from './PullRequestsContentHeader/PullRequestsContentHeader'
|
import { PullRequestsContentHeader } from './PullRequestsContentHeader/PullRequestsContentHeader'
|
||||||
import css from './PullRequests.module.scss'
|
import css from './PullRequests.module.scss'
|
||||||
import { ExecutionStatusLabel } from 'components/ExecutionStatusLabel/ExecutionStatusLabel'
|
|
||||||
|
|
||||||
export default function PullRequests() {
|
export default function PullRequests() {
|
||||||
const { getString } = useStrings()
|
const { getString } = useStrings()
|
||||||
|
@ -14,12 +14,11 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.textContainer {
|
.textContainer {
|
||||||
display: flex;
|
a {
|
||||||
|
color: var(--primary-7) !important;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.clickableText {
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
.bannerContainer {
|
.bannerContainer {
|
||||||
padding: var(--spacing-small) var(--spacing-xsmall) !important;
|
padding: var(--spacing-small) var(--spacing-xsmall) !important;
|
||||||
background-color: var(--red-50) !important;
|
background-color: var(--red-50) !important;
|
||||||
|
@ -5,7 +5,6 @@ declare const styles: {
|
|||||||
readonly emptyRepo: string
|
readonly emptyRepo: string
|
||||||
readonly divContainer: string
|
readonly divContainer: string
|
||||||
readonly textContainer: string
|
readonly textContainer: string
|
||||||
readonly clickableText: string
|
|
||||||
readonly bannerContainer: string
|
readonly bannerContainer: string
|
||||||
}
|
}
|
||||||
export default styles
|
export default styles
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
import React, { useEffect, useState } from 'react'
|
import React, { useEffect, useState } from 'react'
|
||||||
import { useHistory } from 'react-router-dom'
|
import { Link, useHistory } from 'react-router-dom'
|
||||||
import {
|
import {
|
||||||
Button,
|
Button,
|
||||||
ButtonVariation,
|
ButtonVariation,
|
||||||
Color,
|
|
||||||
Container,
|
Container,
|
||||||
FontVariation,
|
FontVariation,
|
||||||
Layout,
|
Layout,
|
||||||
@ -143,40 +142,18 @@ const EmptyRepositoryInfo: React.FC<Pick<GitInfoProps, 'repoMetadata' | 'resourc
|
|||||||
<Button
|
<Button
|
||||||
variation={ButtonVariation.PRIMARY}
|
variation={ButtonVariation.PRIMARY}
|
||||||
text={getString('addNewFile')}
|
text={getString('addNewFile')}
|
||||||
onClick={() => {
|
onClick={() => history.push(newFileURL)}></Button>
|
||||||
history.push(newFileURL)
|
|
||||||
}}></Button>
|
|
||||||
|
|
||||||
<Container padding={{ left: 'medium', top: 'small' }}>
|
<Container padding={{ left: 'medium', top: 'small' }}>
|
||||||
<Text className={css.textContainer}>
|
<Text className={css.textContainer}>
|
||||||
{getString('emptyRepoInclude')}
|
<StringSubstitute
|
||||||
<Text
|
str={getString('emptyRepoInclude')}
|
||||||
onClick={() => {
|
vars={{
|
||||||
history.push(newFileURL + `?name=README.md`)
|
README: <Link to={newFileURL + `?name=README.md`}>README</Link>,
|
||||||
|
LICENSE: <Link to={newFileURL + `?name=LICENSE.md`}>LICENSE</Link>,
|
||||||
|
GITIGNORE: <Link to={newFileURL + `?name=.gitignore`}>.gitignore</Link>
|
||||||
}}
|
}}
|
||||||
className={css.clickableText}
|
/>
|
||||||
padding={{ left: 'small' }}
|
|
||||||
color={Color.PRIMARY_7}>
|
|
||||||
{getString('readMe')}
|
|
||||||
</Text>
|
|
||||||
<Text
|
|
||||||
onClick={() => {
|
|
||||||
history.push(newFileURL + `?name=LICENSE.md`)
|
|
||||||
}}
|
|
||||||
className={css.clickableText}
|
|
||||||
padding={{ left: 'small', right: 'small' }}
|
|
||||||
color={Color.PRIMARY_7}>
|
|
||||||
{getString('license')}
|
|
||||||
</Text>
|
|
||||||
<Text padding={{ right: 'small' }}>{getString('and')}</Text>
|
|
||||||
<Text
|
|
||||||
onClick={() => {
|
|
||||||
history.push(newFileURL + `?name=.gitignore`)
|
|
||||||
}}
|
|
||||||
className={css.clickableText}
|
|
||||||
color={Color.PRIMARY_7}>
|
|
||||||
{getString('gitIgnore')}
|
|
||||||
</Text>
|
|
||||||
</Text>
|
</Text>
|
||||||
</Container>
|
</Container>
|
||||||
</Layout.Horizontal>
|
</Layout.Horizontal>
|
||||||
@ -189,7 +166,6 @@ const EmptyRepositoryInfo: React.FC<Pick<GitInfoProps, 'repoMetadata' | 'resourc
|
|||||||
source={getString('repoEmptyMarkdownClone')
|
source={getString('repoEmptyMarkdownClone')
|
||||||
.replace(/REPO_URL/g, repoMetadata.git_url || '')
|
.replace(/REPO_URL/g, repoMetadata.git_url || '')
|
||||||
.replace(/REPO_NAME/g, repoMetadata.uid || '')}
|
.replace(/REPO_NAME/g, repoMetadata.uid || '')}
|
||||||
navigateTo={history.push}
|
|
||||||
/>
|
/>
|
||||||
</Container>
|
</Container>
|
||||||
<Container
|
<Container
|
||||||
@ -201,7 +177,6 @@ const EmptyRepositoryInfo: React.FC<Pick<GitInfoProps, 'repoMetadata' | 'resourc
|
|||||||
.replace(/REPO_URL/g, '...')
|
.replace(/REPO_URL/g, '...')
|
||||||
.replace(/REPO_NAME/g, repoMetadata.uid || '')
|
.replace(/REPO_NAME/g, repoMetadata.uid || '')
|
||||||
.replace(/CREATE_API_TOKEN_URL/g, currentUserProfileURL || '')}
|
.replace(/CREATE_API_TOKEN_URL/g, currentUserProfileURL || '')}
|
||||||
navigateTo={history.push}
|
|
||||||
/>
|
/>
|
||||||
</Container>
|
</Container>
|
||||||
</Container>
|
</Container>
|
||||||
|
@ -61,10 +61,7 @@ function ReadmeViewer({ metadata, gitRef, readmeInfo, contentOnly, maxWidth }: F
|
|||||||
|
|
||||||
<Render when={(data?.content as RepoFileContent)?.data}>
|
<Render when={(data?.content as RepoFileContent)?.data}>
|
||||||
<Container className={css.readmeContent}>
|
<Container className={css.readmeContent}>
|
||||||
<MarkdownViewer
|
<MarkdownViewer source={window.atob((data?.content as RepoFileContent)?.data || '')} />
|
||||||
source={window.atob((data?.content as RepoFileContent)?.data || '')}
|
|
||||||
navigateTo={history.push}
|
|
||||||
/>
|
|
||||||
</Container>
|
</Container>
|
||||||
</Render>
|
</Render>
|
||||||
</Container>
|
</Container>
|
||||||
|
Loading…
Reference in New Issue
Block a user