From bcc1845f0f459b1f9e5c9d4b108cd2c8bed248d4 Mon Sep 17 00:00:00 2001 From: Ritik Kapoor Date: Tue, 16 Apr 2024 09:51:42 +0000 Subject: [PATCH] Added: [code-1533] feedback and settings framework for AIDA PR Description (#1087) --- web/src/AppContext.tsx | 2 +- web/src/bootstrap.tsx | 2 +- .../DefaultUsefulOrNot}/UsefulOrNot.tsx | 0 .../MarkdownEditorWithPreview.module.scss | 8 ++++ ...MarkdownEditorWithPreview.module.scss.d.ts | 1 + .../MarkdownEditorWithPreview.tsx | 25 ++++++++++- web/src/framework/strings/stringTypes.ts | 4 ++ web/src/i18n/strings.en.yaml | 5 ++- web/src/pages/Compare/Compare.tsx | 45 +++++++++++++++++-- web/src/pages/Search/CodeSearchPage.tsx | 2 +- web/src/utils/types.ts | 3 +- 11 files changed, 87 insertions(+), 10 deletions(-) rename web/src/{utils/componentMocks => components/DefaultUsefulOrNot}/UsefulOrNot.tsx (100%) diff --git a/web/src/AppContext.tsx b/web/src/AppContext.tsx index c92f6a130..230324972 100644 --- a/web/src/AppContext.tsx +++ b/web/src/AppContext.tsx @@ -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) => void diff --git a/web/src/bootstrap.tsx b/web/src/bootstrap.tsx index c3bb812b2..a712f307c 100644 --- a/web/src/bootstrap.tsx +++ b/web/src/bootstrap.tsx @@ -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' diff --git a/web/src/utils/componentMocks/UsefulOrNot.tsx b/web/src/components/DefaultUsefulOrNot/UsefulOrNot.tsx similarity index 100% rename from web/src/utils/componentMocks/UsefulOrNot.tsx rename to web/src/components/DefaultUsefulOrNot/UsefulOrNot.tsx diff --git a/web/src/components/MarkdownEditorWithPreview/MarkdownEditorWithPreview.module.scss b/web/src/components/MarkdownEditorWithPreview/MarkdownEditorWithPreview.module.scss index 550d99121..3489caee4 100644 --- a/web/src/components/MarkdownEditorWithPreview/MarkdownEditorWithPreview.module.scss +++ b/web/src/components/MarkdownEditorWithPreview/MarkdownEditorWithPreview.module.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; +} diff --git a/web/src/components/MarkdownEditorWithPreview/MarkdownEditorWithPreview.module.scss.d.ts b/web/src/components/MarkdownEditorWithPreview/MarkdownEditorWithPreview.module.scss.d.ts index 553f41302..89900c670 100644 --- a/web/src/components/MarkdownEditorWithPreview/MarkdownEditorWithPreview.module.scss.d.ts +++ b/web/src/components/MarkdownEditorWithPreview/MarkdownEditorWithPreview.module.scss.d.ts @@ -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 diff --git a/web/src/components/MarkdownEditorWithPreview/MarkdownEditorWithPreview.tsx b/web/src/components/MarkdownEditorWithPreview/MarkdownEditorWithPreview.tsx index 492f6ffec..451997874 100644 --- a/web/src/components/MarkdownEditorWithPreview/MarkdownEditorWithPreview.tsx +++ b/web/src/components/MarkdownEditorWithPreview/MarkdownEditorWithPreview.tsx @@ -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() 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(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({ )} + {!isEmpty(data) && !generating && !standalone && ( + + )} ) } diff --git a/web/src/framework/strings/stringTypes.ts b/web/src/framework/strings/stringTypes.ts index 12c858bbf..705f378fc 100644 --- a/web/src/framework/strings/stringTypes.ts +++ b/web/src/framework/strings/stringTypes.ts @@ -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 diff --git a/web/src/i18n/strings.en.yaml b/web/src/i18n/strings.en.yaml index d95380057..d192f04e9 100644 --- a/web/src/i18n/strings.en.yaml +++ b/web/src/i18n/strings.en.yaml @@ -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: diff --git a/web/src/pages/Compare/Compare.tsx b/web/src/pages/Compare/Compare.tsx index 16d5f8663..f96ad0bce 100644 --- a/web/src/pages/Compare/Compare.tsx +++ b/web/src/pages/Compare/Compare.tsx @@ -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() + 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 ? (