Skip to content

Commit

Permalink
added progress notifications (#304)
Browse files Browse the repository at this point in the history
* added progress notifications

* added debug telemetry logs

* removed extra quotes

* removed preview tag

* modified eventName for lcid and languageCode

* added api success telemetry for save calls

Co-authored-by: Ashish Choudhary <[email protected]>
  • Loading branch information
ashishchoudhary001 and Ashish-portalFxDev authored Oct 6, 2022
1 parent 4570f8f commit 422ec8c
Show file tree
Hide file tree
Showing 9 changed files with 116 additions and 99 deletions.
33 changes: 5 additions & 28 deletions loc/translations-export/vscode-powerplatform.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -257,17 +257,6 @@ The {2} represents Solution's Version number</note>
<source xml:lang="en">Unable to find that app</source>
</trans-unit>
</body></file>
<file original="./web/client/common/authenticationProvider" source-language="en" datatype="plaintext"><body>
<trans-unit id="microsoft-powerapps-portals.webExtension.init.error">
<source xml:lang="en">There was a problem opening the workspace</source>
</trans-unit>
<trans-unit id="microsoft-powerapps-portals.webExtension.init.error.desc">
<source xml:lang="en">Try refreshing the browser</source>
</trans-unit>
<trans-unit id="microsoft-powerapps-portals.webExtension.init.authorization.error">
<source xml:lang="en">Authorization Failed. Please run again to authorize it</source>
</trans-unit>
</body></file>
<file original="./web/client/common/errorHandler" source-language="en" datatype="plaintext"><body>
<trans-unit id="microsoft-powerapps-portals.webExtension.init.workspace.error">
<source xml:lang="en">There was a problem opening the workspace</source>
Expand All @@ -282,24 +271,12 @@ The {2} represents Solution's Version number</note>
<source xml:lang="en">Check the URL and verify the parameters are correct</source>
</trans-unit>
</body></file>
<file original="./web/client/common/localStore" source-language="en" datatype="plaintext"><body>
<trans-unit id="microsoft-powerapps-portals.webExtension.backend.error">
<source xml:lang="en">There’s a problem on the back end</source>
<file original="./web/client/common/fileSystemProvider" source-language="en" datatype="plaintext"><body>
<trans-unit id="microsoft-powerapps-portals.webExtension.fetch.file.message">
<source xml:lang="en">Fetching your file ...</source>
</trans-unit>
<trans-unit id="microsoft-powerapps-portals.webExtension.backend.desc">
<source xml:lang="en">Try again</source>
</trans-unit>
<trans-unit id="microsoft-powerapps-portals.webExtension.unauthorized.error">
<source xml:lang="en">Authorization Failed. Please run again to authorize it</source>
</trans-unit>
<trans-unit id="microsoft-powerapps-portals.webExtension.unauthorized.desc">
<source xml:lang="en">There was a permissions problem with the server</source>
</trans-unit>
<trans-unit id="microsoft-powerapps-portals.webExtension.parameter.error">
<source xml:lang="en">One or more commands are invalid or malformed</source>
</trans-unit>
<trans-unit id="microsoft-powerapps-portals.webExtension.parameter.desc">
<source xml:lang="en">Check the parameters and try again</source>
<trans-unit id="microsoft-powerapps-portals.webExtension.save.file.message">
<source xml:lang="en">Saving your file ...</source>
</trans-unit>
</body></file>
<file original="./web/client/common/remoteFetchProvider" source-language="en" datatype="plaintext"><body>
Expand Down
5 changes: 0 additions & 5 deletions src/web/client/common/authenticationProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,8 @@
import * as vscode from 'vscode';
import * as nls from 'vscode-nls';
nls.config({ messageFormat: nls.MessageFormat.bundle, bundleFormat: nls.BundleFormat.standalone })();
const localize: nls.LocalizeFunc = nls.loadMessageBundle();
import { sendErrorTelemetry } from '../telemetry/webExtensionTelemetry';
import { pathParamToSchema, PROVIDER_ID, telemetryEventNames } from './constants';
import { showErrorDialog } from './errorHandler';
import PowerPlatformExtensionContextManager from "./localStore";

export function getHeader(accessToken: string) {
Expand All @@ -30,13 +28,10 @@ export async function dataverseAuthentication(dataverseOrgURL: string): Promise<

if (!accessToken) {
{
showErrorDialog(localize("microsoft-powerapps-portals.webExtension.init.error", "There was a problem opening the workspace"), localize("microsoft-powerapps-portals.webExtension.init.error.desc", "Try refreshing the browser"));
sendErrorTelemetry(telemetryEventNames.WEB_EXTENSION_NO_ACCESS_TOKEN);
return '';
}
}
} catch (error) {
vscode.window.showErrorMessage(localize("microsoft-powerapps-portals.webExtension.init.authorization.error", "Authorization Failed. Please run again to authorize it"));
const authError = (error as Error)?.message;
sendErrorTelemetry(telemetryEventNames.WEB_EXTENSION_DATAVERSE_AUTHENTICATION_FAILED, authError);
}
Expand Down
5 changes: 4 additions & 1 deletion src/web/client/common/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,8 @@ export enum queryParameters {
SCHEMA = 'schema',
DATA_SOURCE = 'dataSource',
REFERRER_SESSION_ID = 'referrerSessionId',
REFERRER = 'referrer'
REFERRER = 'referrer',
SITE_VISIBILITY = 'siteVisibility'
}

export enum telemetryEventNames {
Expand All @@ -134,4 +135,6 @@ export enum telemetryEventNames {
WEB_EXTENSION_API_REQUEST_SUCCESS = 'WebExtensionApiRequestSuccess',
WEB_EXTENSION_EMPTY_FILE_NAME = 'WebExtensionEmptyFileName',
WEB_EXTENSION_SET_CONTEXT_PERF = 'WebExtensionSetContextPerf',
WEB_EXTENSION_EDIT_LCID = 'WebExtensionEditLcid',
WEB_EXTENSION_EDIT_LANGUAGE_CODE = 'WebExtensionEditLanguageCode',
}
32 changes: 26 additions & 6 deletions src/web/client/common/fileSystemProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ import PowerPlatformExtensionContextManager from "./localStore";
import { SaveEntityDetails } from './portalSchemaInterface';
import { fetchDataFromDataverseAndUpdateVFS } from './remoteFetchProvider';
import { saveData } from './remoteSaveProvider';
import * as nls from 'vscode-nls';
nls.config({ messageFormat: nls.MessageFormat.bundle, bundleFormat: nls.BundleFormat.standalone })();
const localize: nls.LocalizeFunc = nls.loadMessageBundle();

export class File implements vscode.FileStat {

Expand Down Expand Up @@ -79,7 +82,13 @@ export class PortalsFS implements vscode.FileSystemProvider {
if (castedError.code === vscode.FileSystemError.FileNotFound.name) {
const powerPlatformContext = await PowerPlatformExtensionContextManager.getPowerPlatformExtensionContext();
if (powerPlatformContext.rootDirectory && uri.toString().toLowerCase() === powerPlatformContext.rootDirectory.toString().toLowerCase()) {
await this._loadFromDataverseToVFS();
await vscode.window.withProgress({
location: vscode.ProgressLocation.Notification,
cancellable: true,
title: localize("microsoft-powerapps-portals.webExtension.fetch.file.message", "Fetching your file ...")
}, async () => {
await this._loadFromDataverseToVFS();
});
}
}
}
Expand All @@ -101,10 +110,15 @@ export class PortalsFS implements vscode.FileSystemProvider {
if (rootDirectory
&& uri.toString().includes(rootDirectory.toString())) {
if (PathHasEntityFolderName(uri.toString())) {
await this._loadFromDataverseToVFS();

const data = await this._lookupAsFile(uri, false);
return data.data;
await vscode.window.withProgress({
location: vscode.ProgressLocation.Notification,
cancellable: true,
title: localize("microsoft-powerapps-portals.webExtension.fetch.file.message", "Fetching your file ...")
}, async () => {
await this._loadFromDataverseToVFS();
const data = await this._lookupAsFile(uri, false);
return data.data;
});
}
}
}
Expand All @@ -131,7 +145,13 @@ export class PortalsFS implements vscode.FileSystemProvider {
this._fireSoon({ type: vscode.FileChangeType.Created, uri });
} else if (PowerPlatformExtensionContextManager.getPowerPlatformExtensionContext().saveDataMap.has(uri.fsPath)) {
// Save data to dataverse
await this._saveFileToDataverseFromVFS(uri, content);
await vscode.window.withProgress({
location: vscode.ProgressLocation.Notification,
cancellable: true,
title: localize("microsoft-powerapps-portals.webExtension.save.file.message", "Saving your file ...")
}, async () => {
await this._saveFileToDataverseFromVFS(uri, content);
});
}

entry.mtime = Date.now();
Expand Down
87 changes: 46 additions & 41 deletions src/web/client/common/localStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,8 @@ import * as vscode from "vscode";
import { dataverseAuthentication, getCustomRequestURL, getHeader } from "./authenticationProvider";
import { MULTI_ENTITY_URL_KEY, ORG_URL, pathParamToSchema, PORTALS_URI_SCHEME, PORTAL_LANGUAGES, PORTAL_LANGUAGE_DEFAULT, WEBSITES, WEBSITE_LANGUAGES, WEBSITE_NAME } from "./constants";
import { getDataSourcePropertiesMap, getEntitiesFolderNameMap, getEntitiesSchemaMap } from "./portalSchemaReader";
import { showErrorDialog } from "./errorHandler";
import * as nls from 'vscode-nls';
import { SaveEntityDetails } from "./portalSchemaInterface";
nls.config({ messageFormat: nls.MessageFormat.bundle, bundleFormat: nls.BundleFormat.standalone })();
const localize: nls.LocalizeFunc = nls.loadMessageBundle();
import { sendAPIFailureTelemetry, sendAPISuccessTelemetry, sendAPITelemetry } from "../telemetry/webExtensionTelemetry";

export interface IPowerPlatformExtensionContext {
dataSourcePropertiesMap: Map<string, string>; // dataSourceProperties in portal_schema_data
Expand Down Expand Up @@ -70,13 +67,15 @@ class PowerPlatformExtensionContextManager {
const dataverseOrgUrl = this.PowerPlatformExtensionContext.queryParamsMap.get(ORG_URL) as string;
const accessToken: string = await dataverseAuthentication(dataverseOrgUrl);

this.PowerPlatformExtensionContext = {
... this.PowerPlatformExtensionContext,
websiteIdToLanguage: await this.websiteIdToLanguageMap(accessToken, dataverseOrgUrl),
websiteLanguageIdToPortalLanguageMap: await this.websiteLanguageIdToPortalLanguage(accessToken, dataverseOrgUrl),
languageIdCodeMap: await this.languageIdToCode(accessToken, dataverseOrgUrl),
dataverseAccessToken: accessToken,
};
if (accessToken) {
this.PowerPlatformExtensionContext = {
... this.PowerPlatformExtensionContext,
websiteIdToLanguage: await this.websiteIdToLanguageMap(accessToken, dataverseOrgUrl),
websiteLanguageIdToPortalLanguageMap: await this.websiteLanguageIdToPortalLanguage(accessToken, dataverseOrgUrl),
languageIdCodeMap: await this.languageIdToCode(accessToken, dataverseOrgUrl),
dataverseAccessToken: accessToken,
};
}

return this.PowerPlatformExtensionContext;
}
Expand All @@ -100,16 +99,22 @@ class PowerPlatformExtensionContextManager {
}

private async languageIdToCode(accessToken: string, dataverseOrgUrl: string): Promise<Map<string, string>> {
let requestUrl = '';
let requestSentAtTime = new Date().getTime();
const languageIdCodeMap = new Map<string, string>();
try {
const requestUrl = getCustomRequestURL(dataverseOrgUrl, PORTAL_LANGUAGES, MULTI_ENTITY_URL_KEY);
requestUrl = getCustomRequestURL(dataverseOrgUrl, PORTAL_LANGUAGES, MULTI_ENTITY_URL_KEY);
sendAPITelemetry(requestUrl);

requestSentAtTime = new Date().getTime();
const response = await fetch(requestUrl, {
headers: getHeader(accessToken),
});
if (!response.ok) {
showErrorDialog(localize("microsoft-powerapps-portals.webExtension.backend.error", "There’s a problem on the back end"), localize("microsoft-powerapps-portals.webExtension.backend.desc", "Try again"));
if (!response?.ok) {
sendAPIFailureTelemetry(requestUrl, new Date().getTime() - requestSentAtTime, response?.statusText);
}
const result = await response.json();
sendAPISuccessTelemetry(requestUrl, new Date().getTime() - requestSentAtTime);
const result = await response?.json();
if (result) {
if (result.value?.length > 0) {
for (let counter = 0; counter < result.value.length; counter++) {
Expand All @@ -120,27 +125,29 @@ class PowerPlatformExtensionContextManager {
}
}
} catch (error) {
if (typeof error === "string" && error.includes("Unauthorized")) {
showErrorDialog(localize("microsoft-powerapps-portals.webExtension.unauthorized.error", "Authorization Failed. Please run again to authorize it"), localize("microsoft-powerapps-portals.webExtension.unauthorized.desc", "There was a permissions problem with the server"));
}
else {
showErrorDialog(localize("microsoft-powerapps-portals.webExtension.parameter.error", "One or more commands are invalid or malformed"), localize("microsoft-powerapps-portals.webExtension.parameter.desc", "Check the parameters and try again"));
}
const errorMsg = (error as Error)?.message;
sendAPIFailureTelemetry(requestUrl, new Date().getTime() - requestSentAtTime, errorMsg);
}
return languageIdCodeMap;
}

private async websiteLanguageIdToPortalLanguage(accessToken: string, dataverseOrgUrl: string): Promise<Map<string, string>> {
let requestUrl = '';
let requestSentAtTime = new Date().getTime();
const websiteLanguageIdToPortalLanguageMap = new Map<string, string>();
try {
const requestUrl = getCustomRequestURL(dataverseOrgUrl, WEBSITE_LANGUAGES, MULTI_ENTITY_URL_KEY);
requestUrl = getCustomRequestURL(dataverseOrgUrl, WEBSITE_LANGUAGES, MULTI_ENTITY_URL_KEY);
sendAPITelemetry(requestUrl);

requestSentAtTime = new Date().getTime();
const response = await fetch(requestUrl, {
headers: getHeader(accessToken),
});
if (!response.ok) {
showErrorDialog(localize("microsoft-powerapps-portals.webExtension.backend.error", "One or more commands are invalid or malformed"), localize("microsoft-powerapps-portals.webExtension.backend.desc", "Check the parameters and try again"));
if (!response?.ok) {
sendAPIFailureTelemetry(requestUrl, new Date().getTime() - requestSentAtTime, response?.statusText);
}
const result = await response.json();
sendAPISuccessTelemetry(requestUrl, new Date().getTime() - requestSentAtTime);
const result = await response?.json();
if (result) {
if (result.value?.length > 0) {
for (let counter = 0; counter < result.value.length; counter++) {
Expand All @@ -151,28 +158,30 @@ class PowerPlatformExtensionContextManager {
}
}
} catch (error) {
if (typeof error === "string" && error.includes("Unauthorized")) {
showErrorDialog(localize("microsoft-powerapps-portals.webExtension.unauthorized.error", "Authorization Failed. Please run again to authorize it"), localize("microsoft-powerapps-portals.webExtension.unauthorized.desc", "There was a permissions problem with the server"));
}
else {
showErrorDialog(localize("microsoft-powerapps-portals.webExtension.parameter.error", "One or more commands are invalid or malformed"), localize("microsoft-powerapps-portals.webExtension.parameter.desc", "Check the parameters and try again"));
}
const errorMsg = (error as Error)?.message;
sendAPIFailureTelemetry(requestUrl, new Date().getTime() - requestSentAtTime, errorMsg);
}
return websiteLanguageIdToPortalLanguageMap;
}

private async websiteIdToLanguageMap(accessToken: string, dataverseOrgUrl: string): Promise<Map<string, string>> {
let requestUrl = '';
let requestSentAtTime = new Date().getTime();
const websiteIdToLanguage = new Map<string, string>();
try {
const requestUrl = getCustomRequestURL(dataverseOrgUrl, WEBSITES, MULTI_ENTITY_URL_KEY);
requestUrl = getCustomRequestURL(dataverseOrgUrl, WEBSITES, MULTI_ENTITY_URL_KEY);
sendAPITelemetry(requestUrl);

requestSentAtTime = new Date().getTime();
const response = await fetch(requestUrl, {
headers: getHeader(accessToken),
});

if (!response.ok) {
showErrorDialog(localize("microsoft-powerapps-portals.webExtension.backend.error", "One or more commands are invalid or malformed"), localize("microsoft-powerapps-portals.webExtension.backend.desc", "Check the parameters and try again"));
if (!response?.ok) {
sendAPIFailureTelemetry(requestUrl, new Date().getTime() - requestSentAtTime, response?.statusText);
}
const result = await response.json();
sendAPISuccessTelemetry(requestUrl, new Date().getTime() - requestSentAtTime);
const result = await response?.json();

if (result) {
if (result.value?.length > 0) {
Expand All @@ -185,12 +194,8 @@ class PowerPlatformExtensionContextManager {
}

} catch (error) {
if (typeof error === "string" && error.includes("Unauthorized")) {
showErrorDialog(localize("microsoft-powerapps-portals.webExtension.unauthorized.error", "Authorization Failed. Please run again to authorize it"), localize("microsoft-powerapps-portals.webExtension.unauthorized.desc", "There was a permissions problem with the server"));
}
else {
showErrorDialog(localize("microsoft-powerapps-portals.webExtension.parameter.error", "One or more commands are invalid or malformed"), localize("microsoft-powerapps-portals.webExtension.parameter.desc", "Check the parameters and try again"));
}
const errorMsg = (error as Error)?.message;
sendAPIFailureTelemetry(requestUrl, new Date().getTime() - requestSentAtTime, errorMsg);
}
return websiteIdToLanguage;
}
Expand Down
Loading

0 comments on commit 422ec8c

Please sign in to comment.