This commit is contained in:
Ashwani Kumar 2024-11-05 02:52:35 +05:30
Родитель bd8598dae7
Коммит 27e0aa0d30
8 изменённых файлов: 91 добавлений и 50 удалений

Просмотреть файл

@ -40,16 +40,13 @@ import { ActiveOrgOutput } from "./pac/PacTypes";
import { desktopTelemetryEventNames } from "../common/OneDSLoggerTelemetry/client/desktopExtensionTelemetryEventNames";
import { ArtemisService } from "../common/services/ArtemisService";
import { workspaceContainsPortalConfigFolder } from "../common/utilities/PathFinderUtil";
import { getPortalsOrgURLs, getWebsiteRecordID } from "../common/utilities/WorkspaceInfoFinderUtil";
import { getPortalsOrgURLs } from "../common/utilities/WorkspaceInfoFinderUtil";
import { EXTENSION_ID, SUCCESS } from "../common/constants";
import { AadIdKey, EnvIdKey, TenantIdKey } from "../common/OneDSLoggerTelemetry/telemetryConstants";
import { PowerPagesAppName, PowerPagesClientName } from "../common/ecs-features/constants";
import { ECSFeaturesClient } from "../common/ecs-features/ecsFeatureClient";
import { getECSOrgLocationValue } from "../common/utilities/Utils";
import { PreviewSite } from "./runtimeSitePreview/PreviewSite";
import { PPAPIService } from "../common/services/PPAPIService";
import { ServiceEndpointCategory } from "../common/services/Constants";
import { EnableSiteRuntimePreview } from "../common/ecs-features/ecsFeatureGates";
let client: LanguageClient;
let _context: vscode.ExtensionContext;
@ -175,6 +172,7 @@ export async function activate(
_context.subscriptions.push(cli);
_context.subscriptions.push(pacTerminal);
let websiteURL = "";
_context.subscriptions.push(
orgChangeEvent(async (orgDetails: ActiveOrgOutput) => {
const orgID = orgDetails.OrgId;
@ -209,17 +207,18 @@ export async function activate(
}
oneDSLoggerWrapper.getLogger().traceInfo(desktopTelemetryEventNames.DESKTOP_EXTENSION_INIT_CONTEXT, initContext);
}
if(artemisResponse!==null && PreviewSite.isSiteRuntimePreviewEnabled()) {
websiteURL = await PreviewSite.getWebSiteURL(workspaceFolders, artemisResponse?.stamp, orgDetails.EnvironmentId, _telemetry);
}
})
);
let websiteURL: string | undefined;
const workspaceFolders =
vscode.workspace.workspaceFolders?.map(
(fl) => ({ ...fl, uri: fl.uri.fsPath } as WorkspaceFolder)
) || [];
// TODO: Handle for VSCode.dev also
if (workspaceContainsPortalConfigFolder(workspaceFolders)) {
websiteURL = await getWebSiteURL(workspaceFolders, pacTerminal, _telemetry);
let telemetryData = '';
let listOfActivePortals = [];
try {
@ -249,18 +248,18 @@ export async function activate(
}
const registerPreviewShowCommand = async () => {
const isEnabled = isSiteRuntimePreviewEnabled();
const isEnabled = PreviewSite.isSiteRuntimePreviewEnabled();
_telemetry.sendTelemetryEvent("EnableSiteRuntimePreview", {
isEnabled: isEnabled.toString(),
websiteURL: websiteURL? websiteURL: ""
websiteURL: websiteURL
});
oneDSLoggerWrapper.getLogger().traceInfo("EnableSiteRuntimePreview", {
isEnabled: isEnabled.toString(),
websiteURL: websiteURL? websiteURL: ""
websiteURL: websiteURL
});
if (!isEnabled || !websiteURL) {
if (!isEnabled) {
// portal web view panel
_context.subscriptions.push(
vscode.commands.registerCommand(
@ -317,37 +316,6 @@ export async function deactivate(): Promise<void> {
disposeNotificationPanel();
}
async function getWebSiteURL(workspaceFolders: WorkspaceFolder[], pacTerminal: PacTerminal, telemetry: ITelemetry): Promise<string | undefined> {
const envId = await getEnvId(pacTerminal);
const stamp = await getStamp(pacTerminal);
const websiteRecordId = getWebsiteRecordID(workspaceFolders, telemetry);
const websiteDetails = await PPAPIService.getWebsiteDetailsByWebsiteRecordId(stamp, envId, websiteRecordId, _telemetry);
return websiteDetails?.websiteUrl;
}
async function getStamp(pacTerminal: PacTerminal): Promise<ServiceEndpointCategory> {
const orgDetails = (await pacTerminal.getWrapper().activeOrg()).Results;
const artemisResponse = await ArtemisService.getArtemisResponse(orgDetails.OrgId, _telemetry, "");
return artemisResponse?.stamp || ServiceEndpointCategory.PROD;
}
async function getEnvId(pacTerminal: PacTerminal): Promise<string> {
const pacActiveAuth = await pacTerminal.getWrapper()?.activeAuth();
return pacActiveAuth.Results?.filter(obj => obj.Key === EnvIdKey)?.[0]?.Value;
}
function isSiteRuntimePreviewEnabled() {
const enableSiteRuntimePreview = ECSFeaturesClient.getConfig(EnableSiteRuntimePreview).enableSiteRuntimePreview
if(enableSiteRuntimePreview === undefined) {
return false;
}
return enableSiteRuntimePreview;
}
function didOpenTextDocument(document: vscode.TextDocument): void {
// The debug options for the server
// --inspect=6009: runs the server in Node's Inspector mode so VS Code can attach to the server for debugging

Просмотреть файл

@ -9,7 +9,8 @@ export async function updateLaunchJsonConfig(url: string): Promise<void> {
const workspaceFolders = vscode.workspace.workspaceFolders;
if (!workspaceFolders) {
vscode.window.showErrorMessage('No workspace folder is open.');
vscode.window.showErrorMessage(
vscode.l10n.t('No workspace folder is open.'));
return;
}
@ -82,7 +83,8 @@ export async function updateLaunchJsonConfig(url: string): Promise<void> {
await vscode.workspace.fs.writeFile(launchJsonPath, Buffer.from(launchJsonContent, 'utf8'));
} catch (e) {
if(e instanceof Error) {
vscode.window.showErrorMessage(`Failed to update launch.json: ${e.message}`);
vscode.window.showErrorMessage(
vscode.l10n.t(`Failed to update launch.json: ${e.message}`));
}
}
}

Просмотреть файл

@ -7,9 +7,33 @@ import * as vscode from 'vscode';
import * as path from 'path';
import * as fs from 'fs';
import { updateLaunchJsonConfig } from './LaunchJsonHelper';
import { ECSFeaturesClient } from '../../common/ecs-features/ecsFeatureClient';
import { EnableSiteRuntimePreview } from '../../common/ecs-features/ecsFeatureGates';
import { ITelemetry } from '../../common/OneDSLoggerTelemetry/telemetry/ITelemetry';
import { WorkspaceFolder } from 'vscode-languageclient/node';
import { getWebsiteRecordID } from '../../common/utilities/WorkspaceInfoFinderUtil';
import { ServiceEndpointCategory } from '../../common/services/Constants';
import { PPAPIService } from '../../common/services/PPAPIService';
export class PreviewSite {
static isSiteRuntimePreviewEnabled(): boolean {
const enableSiteRuntimePreview = ECSFeaturesClient.getConfig(EnableSiteRuntimePreview).enableSiteRuntimePreview
if(enableSiteRuntimePreview === undefined) {
return false;
}
return enableSiteRuntimePreview;
}
static async getWebSiteURL(workspaceFolders: WorkspaceFolder[], stamp: ServiceEndpointCategory, envId: string, telemetry: ITelemetry): Promise<string> {
const websiteRecordId = getWebsiteRecordID(workspaceFolders, telemetry);
const websiteDetails = await PPAPIService.getWebsiteDetailsByWebsiteRecordId(stamp, envId, websiteRecordId, telemetry);
return websiteDetails?.websiteUrl || "";
}
static async launchBrowserAndDevToolsWithinVsCode(webSitePreviewURL: string | undefined): Promise<void> {
// The desired website preview URL
@ -37,14 +61,20 @@ export class PreviewSite {
await updateLaunchJsonConfig(webSitePreviewURL);
try {
// Add a 2-second delay before executing the launchProject command
await new Promise(resolve => setTimeout(resolve, 2000));
// Polling mechanism to check if the launch.json file has been created
//await this.waitForFileCreation(launchJsonPath);
await vscode.commands.executeCommand('vscode-edge-devtools-view.launchProject');
} finally {
// Revert the changes made to the launch.json file and remove the .vscode folder if it was created
await new Promise(resolve => setTimeout(resolve, 2000));
// Event listener to detect when the Edge DevTools extension is closed
//await this.waitForExtensionClosure(edgeToolsExtensionId);
if (launchJsonPath) {
if (originalLaunchJsonContent !== null) {
fs.writeFileSync(launchJsonPath, originalLaunchJsonContent, 'utf8');
@ -62,9 +92,10 @@ export class PreviewSite {
}
} else {
const install = await vscode.window.showWarningMessage(
vscode.l10n.t(
`The extension "${edgeToolsExtensionId}" is required to run this command. Do you want to install it now?`,
'Install', 'Cancel'
);
));
if (install === 'Install') {
// Open the Extensions view with the specific extension
@ -74,4 +105,34 @@ export class PreviewSite {
return;
}
}
static async waitForFileCreation(filePath: string | null): Promise<void> {
if (!filePath) return;
const timeout = 10000; // 10 seconds
const interval = 100; // 100 milliseconds
let elapsed = 0;
while (elapsed < timeout) {
if (fs.existsSync(filePath)) {
return;
}
await new Promise(resolve => setTimeout(resolve, interval));
elapsed += interval;
}
throw new Error(`File ${filePath} was not created within the timeout period.`);
}
static async waitForExtensionClosure(extensionId: string): Promise<void> {
return new Promise<void>((resolve) => {
const checkInterval = setInterval(() => {
const extension = vscode.extensions.getExtension(extensionId);
if (!extension || !extension.isActive) {
clearInterval(checkInterval);
resolve();
}
}, 100);
});
}
}

Просмотреть файл

@ -53,4 +53,5 @@ export const ERROR_CONSTANTS = {
BULKHEAD_LIMITS_EXCEEDED: "Bulkhead queue limits exceeded",
NPS_FAILED_AUTH: "Failed to authenticate with NPS",
PAC_AUTH_FAILED : "Failed to fetch org details from PAC"
};

Просмотреть файл

@ -18,6 +18,7 @@ export const CleanupRelatedFilesEvent = 'CleanupRelatedFilesEvent';
export const UpdateEntityNameInYmlEvent = 'UpdateEntityNameInYmlEvent';
export const UserFileCreateEvent = 'UserFileCreateEvent';
export const FileCreateEvent = 'FileCreateEvent';
export const GetWebsiteRecordID = 'getWebsiteRecordID';
interface ITelemetryData {
eventName: string,

Просмотреть файл

@ -5,7 +5,7 @@
import { ITelemetry } from "../OneDSLoggerTelemetry/telemetry/ITelemetry";
import { getCommonHeaders, powerPlatformAPIAuthentication } from "./AuthenticationProvider";
import { VSCODE_EXTENSION_GET_CROSS_GEO_DATA_MOVEMENT_ENABLED_FLAG_FAILED, VSCODE_EXTENSION_GET_PPAPI_WEBSITES_ENDPOINT_UNSUPPORTED_REGION, VSCODE_EXTENSION_PPAPI_GET_WEBSITE_BY_ID_COMPLETED } from "./TelemetryConstants";
import { VSCODE_EXTENSION_SERVICE_STAMP_NOT_FOUND, VSCODE_EXTENSION_GET_CROSS_GEO_DATA_MOVEMENT_ENABLED_FLAG_FAILED, VSCODE_EXTENSION_GET_PPAPI_WEBSITES_ENDPOINT_UNSUPPORTED_REGION, VSCODE_EXTENSION_PPAPI_GET_WEBSITE_BY_ID_COMPLETED, VSCODE_EXTENSION_PPAPI_GET_WEBSITE_DETAILS_FAILED, VSCODE_EXTENSION_PPAPI_GET_WEBSITE_BY_RECORD_ID_COMPLETED } from "./TelemetryConstants";
import { ServiceEndpointCategory, PPAPI_WEBSITES_ENDPOINT, PPAPI_WEBSITES_API_VERSION } from "./Constants";
import { sendTelemetryEvent } from "../copilot/telemetry/copilotTelemetry";
import { IWebsiteDetails } from "./Interfaces";
@ -32,13 +32,18 @@ export class PPAPIService {
return null;
}
public static async getWebsiteDetailsByWebsiteRecordId(serviceEndpointStamp: ServiceEndpointCategory, environmentId: string, websiteRecordId: string, telemetry: ITelemetry): Promise<IWebsiteDetails | null> {
public static async getWebsiteDetailsByWebsiteRecordId(serviceEndpointStamp: ServiceEndpointCategory | undefined, environmentId: string, websiteRecordId: string, telemetry: ITelemetry): Promise<IWebsiteDetails | null> {
if (!serviceEndpointStamp) {
sendTelemetryEvent(telemetry, { eventName: VSCODE_EXTENSION_SERVICE_STAMP_NOT_FOUND, data: serviceEndpointStamp });
return null;
}
const websiteDetailsArray = await PPAPIService.getWebsiteDetails(serviceEndpointStamp, environmentId, telemetry);
const websiteDetails = websiteDetailsArray?.find((website) => website.websiteRecordId === websiteRecordId);
if (websiteDetails) {
sendTelemetryEvent(telemetry, { eventName: VSCODE_EXTENSION_PPAPI_GET_WEBSITE_BY_ID_COMPLETED, orgUrl: websiteDetails.dataverseInstanceUrl });
sendTelemetryEvent(telemetry, { eventName: VSCODE_EXTENSION_PPAPI_GET_WEBSITE_BY_RECORD_ID_COMPLETED, orgUrl: websiteDetails.dataverseInstanceUrl });
return websiteDetails;
}
return null;
@ -58,7 +63,7 @@ export class PPAPIService {
}
}
catch (error) {
sendTelemetryEvent(telemetry, { eventName: VSCODE_EXTENSION_GET_CROSS_GEO_DATA_MOVEMENT_ENABLED_FLAG_FAILED, errorMsg: (error as Error).message });
sendTelemetryEvent(telemetry, { eventName: VSCODE_EXTENSION_PPAPI_GET_WEBSITE_DETAILS_FAILED, errorMsg: (error as Error).message });
}
return null;
}

Просмотреть файл

@ -24,3 +24,6 @@ export const VSCODE_EXTENSION_GET_PPAPI_WEBSITES_ENDPOINT_UNSUPPORTED_REGION = "
export const VSCODE_EXTENSION_DECODE_JWT_TOKEN_FAILED = "VSCodeExtensionDecodeJWTTokenFailed";
export const VSCODE_EXTENSION_PPAPI_GET_WEBSITE_BY_ID_COMPLETED = "VSCodeExtensionPPAPIGetWebsiteByIdCompleted";
export const VSCODE_EXTENSION_PPAPI_GET_WEBSITE_BY_ID_FAILED = "VSCodeExtensionPPAPIGetWebsiteByIdFailed";
export const VSCODE_EXTENSION_SERVICE_STAMP_NOT_FOUND = "VSCodeExtensionServiceStampNotFound";
export const VSCODE_EXTENSION_PPAPI_GET_WEBSITE_DETAILS_FAILED = "VSCodeExtensionPPAPIGetWebsiteDetailsFailed";
export const VSCODE_EXTENSION_PPAPI_GET_WEBSITE_BY_RECORD_ID_COMPLETED = "VSCodeExtensionPPAPIGetWebsiteByRecordIdCompleted";

Просмотреть файл

@ -11,7 +11,7 @@ import * as path from 'path';
import * as fs from 'fs';
import { parse } from 'yaml';
import { ITelemetry } from '../OneDSLoggerTelemetry/telemetry/ITelemetry';
import { sendTelemetryEvent } from '../OneDSLoggerTelemetry/telemetry/telemetry';
import { GetWebsiteRecordID, sendTelemetryEvent } from '../OneDSLoggerTelemetry/telemetry/telemetry';
export function getPortalsOrgURLs(workspaceRootFolders: WorkspaceFolder[] | null, telemetry: ITelemetry) {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
@ -56,7 +56,7 @@ export function getWebsiteRecordID(workspaceFolders: { uri: string }[], telemetr
}
}
} catch (exception) {
sendTelemetryEvent(telemetry, { methodName: getWebsiteRecordID.name, eventName: 'getWebsiteRecordID', exception: exception as Error });
sendTelemetryEvent(telemetry, { methodName: getWebsiteRecordID.name, eventName: GetWebsiteRecordID, exception: exception as Error });
}
return "";
}