diff --git a/src/common/copilot/assets/scripts/copilot.js b/src/common/copilot/assets/scripts/copilot.js index 328119ef4..4a10703d4 100644 --- a/src/common/copilot/assets/scripts/copilot.js +++ b/src/common/copilot/assets/scripts/copilot.js @@ -134,6 +134,7 @@ copyButton.classList.add("action-button"); copyButton.classList.add("copy-button"); copyButton.title = copilotStrings.COPY_TO_CLIPBOARD_MESSAGE; + copyButton.setAttribute("aria-label", copilotStrings.COPY_TO_CLIPBOARD_MESSAGE); copyButton.addEventListener("click", () => { copyCodeToClipboard(code); }); @@ -144,12 +145,12 @@ insertButton.classList.add("action-button"); insertButton.classList.add("insert-button"); insertButton.title = copilotStrings.INSERT_CODE_MESSAGE; + insertButton.setAttribute("aria-label", copilotStrings.INSERT_CODE_MESSAGE); insertButton.addEventListener("click", () => { insertCode(code); }); actionWrapper.appendChild(insertButton); - return actionWrapper; } @@ -160,7 +161,6 @@ return truncatedInitials.join("").toUpperCase(); } - function handleUserMessage(message) { const messageWrapper = document.createElement("div"); messageWrapper.classList.add("message-wrapper"); @@ -259,21 +259,21 @@ const listPrompt = copilotStrings.LIST_PROMPT; suggestedPrompt.innerHTML = `

${copilotStrings.SUGGESTIONS_MESSAGE}

- + ${starIconSvg} ${formPrompt}
- + ${starIconSvg} ${webApiPrompt}
- + ${starIconSvg} @@ -287,7 +287,7 @@ const walkthrough = document.createElement("div"); walkthrough.classList.add("walkthrough-div"); walkthrough.innerHTML = `

${copilotStrings.GETTING_STARTED_MESSAGE}

-
+ ${bookIconSvg} ${copilotStrings.LEARN_MORE_MESSAGE} `; @@ -317,6 +317,9 @@ const thinking = document.createElement("div"); thinking.classList.add("thinking"); thinking.innerText = thinkingMessage; + thinking.setAttribute("tabindex", "0"); // Make the element focusable + thinking.setAttribute("role", "status"); // Add ARIA role + thinking.setAttribute("aria-live", "polite"); // Ensure screen readers announce updates messageElement.appendChild(thinking); chatMessages.scrollTop = chatMessages.scrollHeight - chatMessages.clientHeight; @@ -341,6 +344,7 @@ messageIndex++; const apiResponseElement = parseCodeBlocks(apiResponse); + apiResponseElement.setAttribute("aria-live", "assertive"); // Add aria-live attribute to response messageElement.appendChild(apiResponseElement); messageWrapper.dataset.id = message.id; @@ -375,7 +379,7 @@ notLoggedIn.classList.add("not-loggedIn"); notLoggedIn.innerHTML = `

${copilotStrings.LOGIN_MESSAGE}

- `; + `; messageElement.appendChild(notLoggedIn); @@ -403,13 +407,18 @@ vscode.postMessage({ type: "openGitHubCopilotLink" }); }); - const suggestedPromptDiv = createSuggestedPromptDiv(); messageElement.appendChild(suggestedPromptDiv); const suggestedPrompts = document.querySelectorAll(".suggested-prompt"); suggestedPrompts.forEach((suggestedPrompt) => { suggestedPrompt.addEventListener("click", handleSuggestionsClick); + suggestedPrompt.addEventListener("keydown", (event) => { + if (event.key === "Enter" || event.key === " ") { + event.preventDefault(); + handleSuggestionsClick.call(suggestedPrompt); + } + }); }); const walkthroughDiv = createWalkthroughDiv(); @@ -417,7 +426,12 @@ const walkthroughContent = document.getElementById("walk-text"); walkthroughContent.addEventListener("click", handleWalkthroughClick); - + walkthroughContent.addEventListener("keydown", (event) => { + if (event.key === "Enter" || event.key === " ") { + event.preventDefault(); + handleWalkthroughClick.call(walkthroughContent); + } + }); } }; } @@ -443,7 +457,6 @@

${copilotStrings.DOCUMENTATION_LINK}

`; messageElement.appendChild(notAvailabel); - } // Handle messages sent from the extension to the webview diff --git a/src/web/client/dal/remoteFetchProvider.ts b/src/web/client/dal/remoteFetchProvider.ts index 4887b7138..8414b56da 100644 --- a/src/web/client/dal/remoteFetchProvider.ts +++ b/src/web/client/dal/remoteFetchProvider.ts @@ -246,11 +246,16 @@ async function createContentFiles( schemaEntityKey.LANGUAGE_FIELD ); + let languageCode = WebExtensionContext.websiteLanguageCode; + if (languageCodeAttribute && result[languageCodeAttribute] === null) { - throw new Error(ERROR_CONSTANTS.LANGUAGE_CODE_ID_VALUE_NULL); + if (entityName !== schemaEntityName.CONTENTSNIPPETS) { + throw new Error(ERROR_CONSTANTS.LANGUAGE_CODE_ID_VALUE_NULL); + } else { + languageCode = Constants.DEFAULT_LANGUAGE_CODE; // Handles the case where language code is null for content snippets + } } - let languageCode = WebExtensionContext.websiteLanguageCode; if (defaultFileInfo?.fileName === undefined && languageCodeAttribute && result[languageCodeAttribute]) { diff --git a/src/web/client/schema/portalSchema.ts b/src/web/client/schema/portalSchema.ts index c17092c06..5f34b7423 100644 --- a/src/web/client/schema/portalSchema.ts +++ b/src/web/client/schema/portalSchema.ts @@ -123,7 +123,7 @@ export const portal_schema_V1 = { _fetchQueryParameters: "?$filter=adx_contentsnippetid eq {entityId}&$select=adx_name,adx_value,_adx_contentsnippetlanguageid_value", _multiFileFetchQueryParameters: - "?$filter=_adx_websiteid_value eq {websiteId} and _adx_contentsnippetlanguageid_value ne null &$select=adx_name,adx_value,adx_contentsnippetid,_adx_contentsnippetlanguageid_value&$count=true", + "?$filter=_adx_websiteid_value eq {websiteId} &$select=adx_name,adx_value,adx_contentsnippetid,_adx_contentsnippetlanguageid_value&$count=true", _attributes: "adx_value", _attributesExtension: new Map([["adx_value", "html"]]), }, @@ -334,7 +334,7 @@ export const portal_schema_V2 = { _fetchQueryParameters: "?$filter=powerpagecomponentid eq {entityId}&$select=name,content", _multiFileFetchQueryParameters: - "?$filter=_powerpagesiteid_value eq {websiteId} and powerpagecomponenttype eq 7 and _powerpagesitelanguageid_value ne null &$select=name,content,_powerpagesitelanguageid_value&$count=true", + "?$filter=_powerpagesiteid_value eq {websiteId} and powerpagecomponenttype eq 7 &$select=name,content,_powerpagesitelanguageid_value&$count=true", _attributes: "content.value", _attributesExtension: new Map([["content.value", "html"]]), }, diff --git a/src/web/client/utilities/commonUtil.ts b/src/web/client/utilities/commonUtil.ts index c258429d9..b859f8450 100644 --- a/src/web/client/utilities/commonUtil.ts +++ b/src/web/client/utilities/commonUtil.ts @@ -24,6 +24,7 @@ import { doesFileExist, getFileAttributePath, getFileEntityName, updateEntityCol import { isWebFileV2 } from "./schemaHelperUtil"; import { ServiceEndpointCategory } from "../../../common/services/Constants"; import { PPAPIService } from "../../../common/services/PPAPIService"; +import * as Constants from "../common/constants"; // decodes file content to UTF-8 export function convertContentToUint8Array(content: string, isBase64Encoded: boolean): Uint8Array { @@ -42,15 +43,18 @@ export function GetFileNameWithExtension( languageCode: string, extension: string ) { - fileName = isLanguageCodeNeededInFileName(entity) ? `${fileName}.${languageCode}` : fileName; + if (entity === schemaEntityName.CONTENTSNIPPETS) { + fileName = languageCode && languageCode != Constants.DEFAULT_LANGUAGE_CODE ? `${fileName}.${languageCode}` : fileName; // Handle the case where language is not provided for content snippets + } else { + fileName = isLanguageCodeNeededInFileName(entity) ? `${fileName}.${languageCode}` : fileName; + } fileName = isExtensionNeededInFileName(entity) ? `${fileName}.${extension}` : fileName; return getSanitizedFileName(fileName); } export function isLanguageCodeNeededInFileName(entity: string) { - return entity === schemaEntityName.WEBPAGES || - entity === schemaEntityName.CONTENTSNIPPETS; + return entity === schemaEntityName.WEBPAGES ||entity === schemaEntityName.CONTENTSNIPPETS; } export function isExtensionNeededInFileName(entity: string) {