mirror of
https://github.com/harness/drone.git
synced 2025-05-21 19:39:59 +08:00
Added: [code-1533] feedback and settings framework for AIDA PR Description (#1087)
This commit is contained in:
parent
89dcee0b43
commit
bcc1845f0f
@ -26,7 +26,7 @@ import { currentUserAtom } from 'atoms/currentUser'
|
||||
import { newCacheStrategy } from 'utils/CacheStrategy'
|
||||
import { useGetSettingValue } from 'hooks/useGetSettingValue'
|
||||
import { useFeatureFlags } from 'hooks/useFeatureFlag'
|
||||
import { defaultUsefulOrNot } from 'utils/componentMocks/UsefulOrNot'
|
||||
import { defaultUsefulOrNot } from 'components/DefaultUsefulOrNot/UsefulOrNot'
|
||||
|
||||
interface AppContextProps extends AppProps {
|
||||
setAppContext: (value: Partial<AppProps>) => void
|
||||
|
@ -21,7 +21,7 @@ import { routes } from 'RouteDefinitions'
|
||||
import { defaultCurrentUser } from 'AppContext'
|
||||
import { useFeatureFlags } from 'hooks/useFeatureFlag'
|
||||
import { useGetSettingValue } from 'hooks/useGetSettingValue'
|
||||
import { defaultUsefulOrNot } from 'utils/componentMocks/UsefulOrNot'
|
||||
import { defaultUsefulOrNot } from 'components/DefaultUsefulOrNot/UsefulOrNot'
|
||||
import App from './App'
|
||||
import './bootstrap.scss'
|
||||
|
||||
|
@ -280,3 +280,11 @@
|
||||
background: var(--ai-purple-800) !important;
|
||||
font-weight: bold !important;
|
||||
}
|
||||
|
||||
.aidaFeedback {
|
||||
position: absolute !important;
|
||||
width: 100%;
|
||||
right: -4.5px;
|
||||
padding: 5px 10px !important;
|
||||
margin: 10px 5px !important;
|
||||
}
|
||||
|
@ -16,6 +16,7 @@
|
||||
|
||||
/* eslint-disable */
|
||||
// This is an auto-generated file
|
||||
export declare const aidaFeedback: string
|
||||
export declare const aidaGenText: string
|
||||
export declare const buttonsBar: string
|
||||
export declare const container: string
|
||||
|
@ -32,8 +32,9 @@ import cx from 'classnames'
|
||||
import { DecorationSet, EditorView, Decoration, keymap } from '@codemirror/view'
|
||||
import { undo, redo, history } from '@codemirror/commands'
|
||||
import { EditorSelection, StateEffect, StateField } from '@codemirror/state'
|
||||
import { isEmpty } from 'lodash-es'
|
||||
import { isEmpty, isString } from 'lodash-es'
|
||||
import { useMutate } from 'restful-react'
|
||||
import { useAppContext } from 'AppContext'
|
||||
import { Editor } from 'components/Editor/Editor'
|
||||
import { MarkdownViewer } from 'components/MarkdownViewer/MarkdownViewer'
|
||||
import { useStrings } from 'framework/strings'
|
||||
@ -46,6 +47,8 @@ import {
|
||||
removeSpecificTextOptimized
|
||||
} from 'utils/Utils'
|
||||
import { decodeGitContent, handleUpload, normalizeGitRef } from 'utils/GitUtils'
|
||||
import { defaultUsefulOrNot } from 'components/DefaultUsefulOrNot/UsefulOrNot'
|
||||
import { AidaClient } from 'utils/types'
|
||||
import type { TypesRepository } from 'services/code'
|
||||
import { useEventListener } from 'hooks/useEventListener'
|
||||
import css from './MarkdownEditorWithPreview.module.scss'
|
||||
@ -179,6 +182,8 @@ export function MarkdownEditorWithPreview({
|
||||
const [file, setFile] = useState<File>()
|
||||
const { showError } = useToaster()
|
||||
const [markdownContent, setMarkdownContent] = useState('')
|
||||
const { customComponents } = useAppContext()
|
||||
const AIDAFeedback = customComponents?.UsefulOrNot ? customComponents.UsefulOrNot : defaultUsefulOrNot
|
||||
const { mutate } = useMutate({
|
||||
verb: 'POST',
|
||||
path: `/api/v1/repos/${repoMetadata?.path}/+/genai/change-summary`
|
||||
@ -224,7 +229,7 @@ export function MarkdownEditorWithPreview({
|
||||
)
|
||||
|
||||
useEventListener('mousedown', handleMouseDown)
|
||||
|
||||
const [generating, setGenerating] = useState<boolean>(false)
|
||||
const dispatchContent = (content: string, userEvent: boolean, decoration = false) => {
|
||||
const view = viewRef.current
|
||||
const { from, to } = view?.state.selection.main ?? { from: 0, to: 0 }
|
||||
@ -256,12 +261,14 @@ export function MarkdownEditorWithPreview({
|
||||
useEffect(() => {
|
||||
if (flag) {
|
||||
if (handleCopilotClick) {
|
||||
setGenerating(true)
|
||||
dispatchContent(getString('aidaGenSummary'), false, true)
|
||||
mutate({
|
||||
head_ref: normalizeGitRef(sourceGitRef),
|
||||
base_ref: normalizeGitRef(targetGitRef)
|
||||
})
|
||||
.then(res => {
|
||||
setGenerating(false)
|
||||
setData(res.summary || '')
|
||||
})
|
||||
.catch(err => {
|
||||
@ -635,6 +642,20 @@ export function MarkdownEditorWithPreview({
|
||||
</Layout.Horizontal>
|
||||
</Container>
|
||||
)}
|
||||
{!isEmpty(data) && !generating && !standalone && (
|
||||
<AIDAFeedback
|
||||
className={css.aidaFeedback}
|
||||
allowCreateTicket={true}
|
||||
allowFeedback={true}
|
||||
telemetry={{
|
||||
aidaClient: AidaClient.CODE_PR_SUMMARY,
|
||||
metadata: {
|
||||
query: getString('generateSummary'),
|
||||
generatedResponse: isString(data) ? data : getString('invalidResponse')
|
||||
}
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</Container>
|
||||
)
|
||||
}
|
||||
|
@ -259,6 +259,8 @@ export interface StringsMap {
|
||||
emptyRepoInclude: string
|
||||
emptySpaceText: string
|
||||
enableAIDAMessage: string
|
||||
enableAIDAPRDescription: string
|
||||
enableAIDAPRMessange: string
|
||||
enableAISearch: string
|
||||
enableSSLVerification: string
|
||||
enableWebhookContent: string
|
||||
@ -344,6 +346,7 @@ export interface StringsMap {
|
||||
generateCloneCred: string
|
||||
generateCloneText: string
|
||||
generateHelptext: string
|
||||
generateSummary: string
|
||||
getMyCloneTitle: string
|
||||
gitIgnore: string
|
||||
gitness: string
|
||||
@ -411,6 +414,7 @@ export interface StringsMap {
|
||||
'importSpace.title': string
|
||||
in: string
|
||||
inactiveBranches: string
|
||||
invalidResponse: string
|
||||
isRequired: string
|
||||
key: string
|
||||
'keywordSearch.sampleQueries.searchForClass': string
|
||||
|
@ -735,6 +735,8 @@ viewFile: View File
|
||||
searchResult: 'Search Result {count}'
|
||||
aiSearch: AIDA SEARCH
|
||||
enableAISearch: Enable AI Search
|
||||
enableAIDAPRDescription: Auto generate PR description
|
||||
enableAIDAPRMessange: To generate a PR description using Harness AIDA, you need to enable it in the Project Settings.
|
||||
enableAIDAMessage: In order to use Harness AIDA Search, you will need to enable it in the Project Settings
|
||||
reviewProjectSettings: Review Project Settings
|
||||
turnOnSemanticSearch: Turn on semantic search
|
||||
@ -745,7 +747,6 @@ keywordSearch:
|
||||
searchForFilesWithCMD: Search for class in files starting with cmd
|
||||
searchForPattern: Include only results from file paths matching the given search pattern
|
||||
searchForInitialCommit: Search for exact phrase initial commit
|
||||
|
||||
keywordSearchPlaceholder: Search for code or files...
|
||||
codeSearch: Code Search
|
||||
codeSearchModal: Begin search by describing what you are looking for
|
||||
@ -1005,6 +1006,8 @@ reqChanges: 'Request changes'
|
||||
summary: Summary
|
||||
prGenSummary: AIDA generate PR summary, insert at the cursor or replace selected text only.
|
||||
aidaGenSummary: 'AIDA is generating a summary...'
|
||||
generateSummary: Generate PR Summary
|
||||
invalidResponse: Invalid summary response generated
|
||||
importFailed: Import Failed
|
||||
uploadAFileError: There is no image or video uploaded. Please upload an image or video.
|
||||
securitySettings:
|
||||
|
@ -33,7 +33,7 @@ import {
|
||||
import { Color, FontVariation } from '@harnessio/design-system'
|
||||
import { PopoverPosition } from '@blueprintjs/core'
|
||||
import cx from 'classnames'
|
||||
import { useHistory } from 'react-router-dom'
|
||||
import { Link, useHistory, useParams } from 'react-router-dom'
|
||||
import { useGet, useMutate } from 'restful-react'
|
||||
import { useAppContext } from 'AppContext'
|
||||
import { useGetRepositoryMetadata } from 'hooks/useGetRepositoryMetadata'
|
||||
@ -63,10 +63,21 @@ import { CompareContentHeader, PRCreationType } from './CompareContentHeader/Com
|
||||
import { CompareCommits } from './CompareCommits'
|
||||
import css from './Compare.module.scss'
|
||||
|
||||
interface Identifier {
|
||||
accountId: string
|
||||
orgIdentifier: string
|
||||
projectIdentifier: string
|
||||
}
|
||||
|
||||
export default function Compare() {
|
||||
const { routes, standalone, hooks, routingId } = useAppContext()
|
||||
const { routes, standalone, hooks, routingId, defaultSettingsURL } = useAppContext()
|
||||
const [flag, setFlag] = useState(false)
|
||||
const { SEMANTIC_SEARCH_ENABLED } = hooks?.useFeatureFlags()
|
||||
const { orgIdentifier, projectIdentifier } = useParams<Identifier>()
|
||||
const { data: aidaSettingResponse, loading: isAidaSettingLoading } = hooks?.useGetSettingValue({
|
||||
identifier: 'aida',
|
||||
queryParams: { accountIdentifier: routingId, orgIdentifier, projectIdentifier }
|
||||
})
|
||||
const { getString } = useStrings()
|
||||
const history = useHistory()
|
||||
const { repoMetadata, error, loading, diffRefs } = useGetRepositoryMetadata()
|
||||
@ -304,7 +315,10 @@ export default function Compare() {
|
||||
outlets={{
|
||||
[CommentBoxOutletPosition.START_OF_MARKDOWN_EDITOR_TOOLBAR]: (
|
||||
<>
|
||||
{SEMANTIC_SEARCH_ENABLED && !standalone ? (
|
||||
{!isAidaSettingLoading &&
|
||||
aidaSettingResponse?.data?.value == 'true' &&
|
||||
SEMANTIC_SEARCH_ENABLED &&
|
||||
!standalone ? (
|
||||
<Button
|
||||
size={ButtonSize.SMALL}
|
||||
variation={ButtonVariation.ICON}
|
||||
@ -338,6 +352,31 @@ export default function Compare() {
|
||||
)
|
||||
}}
|
||||
/>
|
||||
{aidaSettingResponse?.data?.value != 'true' &&
|
||||
SEMANTIC_SEARCH_ENABLED &&
|
||||
!isAidaSettingLoading && (
|
||||
<Container
|
||||
background={Color.AI_PURPLE_50}
|
||||
padding="small"
|
||||
margin={{ top: 'xsmall', right: 'small', left: 'xsmall' }}>
|
||||
<Text
|
||||
font={{ variation: FontVariation.BODY2 }}
|
||||
margin={{ bottom: 'small' }}
|
||||
icon="info-messaging"
|
||||
iconProps={{ size: 15 }}>
|
||||
{getString('enableAIDAPRDescription')}
|
||||
</Text>
|
||||
<Text
|
||||
font={{ variation: FontVariation.BODY2_SEMI }}
|
||||
margin={{ bottom: 'small' }}
|
||||
color={Color.GREY_450}>
|
||||
{getString('enableAIDAPRMessange')}
|
||||
</Text>
|
||||
<Link to={defaultSettingsURL} color={Color.AI_PURPLE_800}>
|
||||
{getString('reviewProjectSettings')}
|
||||
</Link>
|
||||
</Container>
|
||||
)}
|
||||
</Layout.Vertical>
|
||||
</Container>
|
||||
</Layout.Vertical>
|
||||
|
@ -49,7 +49,7 @@ import KeywordSearchbar from 'components/KeywordSearchbar/KeywordSearchbar'
|
||||
import { LoadingSpinner } from 'components/LoadingSpinner/LoadingSpinner'
|
||||
import { SEARCH_MODE } from 'components/CodeSearch/CodeSearch'
|
||||
import CodeSearchBar from 'components/CodeSearchBar/CodeSearchBar'
|
||||
import { defaultUsefulOrNot } from 'utils/componentMocks/UsefulOrNot'
|
||||
import { defaultUsefulOrNot } from 'components/DefaultUsefulOrNot/UsefulOrNot'
|
||||
import { AidaClient } from 'utils/types'
|
||||
import KeywordSearchFilters from './KeywordSearchFilters'
|
||||
import type { FileMatch, KeywordSearchResponse } from './CodeSearchPage.types'
|
||||
|
@ -27,7 +27,8 @@ export interface DiffFileEntry extends DiffFile {
|
||||
export type FCWithChildren<T> = React.FC<React.PropsWithChildren<T>>
|
||||
|
||||
export enum AidaClient {
|
||||
CODE_SEMANTIC_SEARCH = 'CODE_SEMANTIC_SEARCH'
|
||||
CODE_SEMANTIC_SEARCH = 'CODE_SEMANTIC_SEARCH',
|
||||
CODE_PR_SUMMARY = 'CODE_PR_SUMMARY'
|
||||
}
|
||||
export interface TelemeteryProps {
|
||||
aidaClient: AidaClient
|
||||
|
Loading…
Reference in New Issue
Block a user