Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Showing co-presence on Power Pages Action TreeView #746

Closed
wants to merge 47 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
d4739ad
added gulp file and webpack config file to compile copresence worker …
ritikramuka Sep 19, 2023
b28a5f0
dependencies installed
ritikramuka Sep 20, 2023
79e8acc
Merge branch 'main' of https://github.com/microsoft/powerplatform-vsc…
ritikramuka Oct 18, 2023
c316aba
updated gulp file and webpack file to compile webworker script
ritikramuka Oct 18, 2023
1a1641c
passed entity id while loading container & few nit changes
ritikramuka Oct 19, 2023
a2602e3
creating web worker instance get or create sharedworkspace for copres…
ritikramuka Oct 19, 2023
b397ddf
showing dummy data of active users in treeview
ritikramuka Oct 19, 2023
64f087b
Merge branch 'main' into users/ramukaritik/treeview-for-copresence
ritikramuka Oct 19, 2023
b38c232
added action items icons for teams chat and mail
ritikramuka Oct 20, 2023
e57e131
Merge branch 'main' into users/ramukaritik/treeview-for-copresence
ritikramuka Oct 20, 2023
2c02358
extra conditions removed
ritikramuka Oct 20, 2023
63099d6
Merge branch 'users/ramukaritik/treeview-for-copresence' of https://g…
ritikramuka Oct 20, 2023
046a9c2
sending message to worker on tab change rather than open active text …
ritikramuka Oct 23, 2023
59e45ae
Merge branch 'main' into users/ramukaritik/creating-webworker-instance
ritikramuka Oct 24, 2023
43f883c
moved co-presence on vscode for web related parameters to a single place
ritikramuka Oct 26, 2023
ad6d855
Merge branch 'main' into users/ramukaritik/creating-webworker-instance
ritikramuka Oct 26, 2023
a2922d0
disabled co-presence feature for users as under development
ritikramuka Oct 26, 2023
64f0fa3
update in way of joining path
ritikramuka Oct 26, 2023
618928a
added const for worker event messages
ritikramuka Oct 26, 2023
1fcfe2e
renamed a worker event mesages
ritikramuka Oct 26, 2023
1bcf192
Merge branch 'main' into users/ramukaritik/creating-webworker-instance
ritikramuka Oct 27, 2023
6df6477
remove redundant event registery of onDidChangeTabs
ritikramuka Oct 27, 2023
0555759
Merge branch 'users/ramukaritik/creating-webworker-instance' of https…
ritikramuka Oct 27, 2023
474ee5d
moved populateSharedWorkSpace to authenticateAndUpdateDataverseProper…
ritikramuka Oct 27, 2023
b4e9319
disabling co-presence feature hard coded
ritikramuka Oct 27, 2023
b2568e6
added worker in webextension context
ritikramuka Oct 27, 2023
5d9d994
used concurrency handler to make fetch call worker script
ritikramuka Oct 27, 2023
eacad21
eslint error fixed
ritikramuka Oct 27, 2023
1e6e2bf
Merge branch 'main' into users/ramukaritik/creating-webworker-instance
ritikramuka Oct 30, 2023
231efe4
adding telemetry and moving api path in constant
ritikramuka Oct 30, 2023
aa1f530
removed console log
ritikramuka Oct 30, 2023
ea971cf
updating telemetry log
ritikramuka Oct 30, 2023
5ac8a0a
Merge branch 'main' into users/ramukaritik/creating-webworker-instance
ritikramuka Oct 30, 2023
f937bb7
Merge branch 'main' into users/ramukaritik/creating-webworker-instance
ritikramuka Nov 2, 2023
9a98b11
Merge branch 'main' into users/ramukaritik/creating-webworker-instance
ritikramuka Nov 3, 2023
699aba9
Merge branch 'main' into users/ramukaritik/creating-webworker-instance
ritikramuka Nov 7, 2023
663530a
Merge branch 'main' into users/ramukaritik/treeview-for-copresence
ritikramuka Nov 8, 2023
bb095fa
showing dummy data of active users in treeview
ritikramuka Oct 19, 2023
8f8d4cd
added action items icons for teams chat and mail
ritikramuka Oct 20, 2023
4aac88f
extra conditions removed
ritikramuka Oct 20, 2023
3e9051f
Localization for copilot webview strings (#762)
amitjoshi438 Nov 8, 2023
61d18c7
Merge branch 'users/ramukaritik/treeview-for-copresence' of https://g…
ritikramuka Nov 8, 2023
65498f7
resolving bug of correct api call
ritikramuka Nov 8, 2023
1a13ba8
Merge branch 'main' into users/ramukaritik/creating-webworker-instance
ritikramuka Nov 8, 2023
f31e0bb
Merge branch 'users/ramukaritik/creating-webworker-instance' of https…
ritikramuka Nov 8, 2023
a40a4ae
reading data from container to show in PowerPagesNavigation
ritikramuka Nov 8, 2023
7dc4f28
restructuring call process in order to create worker instance before …
ritikramuka Nov 9, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,16 @@
}
],
"commands": [
{
"command": "powerpages.powerPagesFileExplorer.openTeamsChat",
"title": "Open Teams Chat",
"icon": "$(person)"
},
{
"command": "powerpages.powerPagesFileExplorer.openMail",
"title": "Open Mail",
"icon": "$(mail)"
},
{
"command": "powerpages.powerPagesFileExplorer.powerPagesRuntimePreview",
"title": "Preview site",
Expand Down Expand Up @@ -852,6 +862,16 @@
{
"command": "pacCLI.envAndSolutionsPanel.copyOrganizationId",
"when": "!virtualWorkspace && view == pacCLI.envAndSolutionsPanel && viewItem == ENVIRONMENT"
},
{
"command": "powerpages.powerPagesFileExplorer.openTeamsChat",
"group": "inline",
"when": "viewItem == userNode"
},
{
"command": "powerpages.powerPagesFileExplorer.openMail",
"group": "inline",
"when": "viewItem == userNode"
}
]
},
Expand Down
128 changes: 127 additions & 1 deletion src/web/client/WebExtensionContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,15 @@ import {
getWebsiteIdToLcidMap,
getWebsiteLanguageIdToPortalLanguageIdMap,
} from "./utilities/schemaHelperUtil";
import { getCustomRequestURL } from "./utilities/urlBuilderUtil";
import { getCustomRequestURL, getOrCreateSharedWorkspace } from "./utilities/urlBuilderUtil";
import { schemaKey } from "./schema/constants";
import { telemetryEventNames } from "./telemetry/constants";
import { EntityDataMap } from "./context/entityDataMap";
import { FileDataMap } from "./context/fileDataMap";
import { IAttributePath, IEntityInfo } from "./common/interfaces";
import { ConcurrencyHandler } from "./dal/concurrencyHandler";
import { isMultifileEnabled } from "./utilities/commonUtil";
import { UserDataMap } from "./context/userDataMap";

export interface IWebExtensionContext {
// From portalSchema properties
Expand Down Expand Up @@ -102,6 +103,11 @@ class WebExtensionContext implements IWebExtensionContext {
private _userId: string;
private _formsProEligibilityId: string;
private _concurrencyHandler: ConcurrencyHandler
// Co-Presence for Power Pages Vscode for web
private _worker: Worker | undefined;
private _sharedWorkSpaceMap: Map<string, string>;
private _containerId: string;
private _connectedUsers: UserDataMap;

public get schemaDataSourcePropertiesMap() {
return this._schemaDataSourcePropertiesMap;
Expand Down Expand Up @@ -184,6 +190,21 @@ class WebExtensionContext implements IWebExtensionContext {
public get concurrencyHandler() {
return this._concurrencyHandler;
}
public get worker() {
return this._worker;
}
public get sharedWorkSpaceMap() {
return this._sharedWorkSpaceMap;
}
public get connectedUsers() {
return this._connectedUsers;
}
public get containerId() {
return this._containerId;
}
public set containerId(containerId: string) {
this._containerId = containerId;
}

constructor() {
this._schemaDataSourcePropertiesMap = new Map<string, string>();
Expand Down Expand Up @@ -213,6 +234,9 @@ class WebExtensionContext implements IWebExtensionContext {
this._userId = "";
this._formsProEligibilityId = "";
this._concurrencyHandler = new ConcurrencyHandler();
this._sharedWorkSpaceMap = new Map<string, string>();
this._containerId = "";
this._connectedUsers = new UserDataMap();
}

public setWebExtensionContext(
Expand Down Expand Up @@ -301,6 +325,16 @@ class WebExtensionContext implements IWebExtensionContext {
);

await this.setWebsiteLanguageCode();

// Getting website Id to populate shared workspace for Co-Presence
const websiteid = this.urlParametersMap.get(
Constants.queryParameters.WEBSITE_ID
) as string;

const headers = getCommonHeaders(this._dataverseAccessToken);

// Populate shared workspace for Co-Presence
await this.populateSharedworkspace(headers, dataverseOrgUrl, websiteid);
}

public async dataverseAuthentication(firstTimeAuth = false) {
Expand Down Expand Up @@ -629,6 +663,98 @@ class WebExtensionContext implements IWebExtensionContext {
public getVscodeWorkspaceState(key: string): IEntityInfo | undefined {
return this._vscodeWorkspaceState.get(key);
}

// eslint-disable-next-line @typescript-eslint/no-explicit-any
public async getWorkerScript(workerUrl : URL) : Promise<any> {
try {
this.telemetry.sendInfoTelemetry(
telemetryEventNames.WEB_EXTENSION_FETCH_WORKER_SCRIPT
);

const response = await this.concurrencyHandler.handleRequest(
workerUrl
)

if (!response.ok) {
throw new Error(
`Failed to fetch worker script '${workerUrl.toString()}': ${response.statusText}`
);
}

this.telemetry.sendInfoTelemetry(
telemetryEventNames.WEB_EXTENSION_FETCH_WORKER_SCRIPT_SUCCESS,
{ workerUrl: workerUrl.toString() }
);

return await response.text();
} catch (error) {
this.telemetry.sendErrorTelemetry(
telemetryEventNames.WEB_EXTENSION_FETCH_WORKER_SCRIPT_FAILED,
this.getWorkerScript.name,
(error as Error)?.message,
error as Error
);
}
}

public setWorker(worker: Worker) {
this._worker = worker;
}

private async populateSharedworkspace(
// eslint-disable-next-line @typescript-eslint/no-explicit-any
headers: any,
dataverseOrgUrl: string,
websiteid: string
) {
try {
const sharedworkspace = await getOrCreateSharedWorkspace({
headers,
dataverseOrgUrl,
websiteid,
});

const sharedWorkSpaceParamsMap = new Map<string, string>();
for (const key in sharedworkspace) {
sharedWorkSpaceParamsMap.set(
String(key).trim().toLocaleLowerCase(),
String(sharedworkspace[key]).trim()
);
}

this._sharedWorkSpaceMap = sharedWorkSpaceParamsMap;

this.telemetry.sendInfoTelemetry(
telemetryEventNames.WEB_EXTENSION_POPULATE_SHARED_WORKSPACE_SUCCESS,
{ count: this._sharedWorkSpaceMap.size.toString() }
);
} catch (error) {
this.telemetry.sendErrorTelemetry(
telemetryEventNames.WEB_EXTENSION_POPULATE_SHARED_WORKSPACE_SYSTEM_ERROR,
this.populateSharedworkspace.name,
(error as Error)?.message,
error as Error
);
}
}

public async updateConnectedUsersInContext(
containerId: string,
userName: string,
userId: string,
entityId: string[]
) {
this.connectedUsers.setUserData(
containerId,
userName,
userId,
entityId
);
}

public async removeConnectedUserInContext(userId: string) {
this.connectedUsers.removeUser(userId);
}
}

export default new WebExtensionContext();
15 changes: 15 additions & 0 deletions src/web/client/common/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,21 @@ export const MULTI_FILE_FEATURE_SETTING_NAME = "enableMultiFileFeature";
// Co-presence feature constants
export const CO_PRESENCE_FEATURE_SETTING_NAME = "enableCoPresenceFeature";

// Co-presence constants
export const GET_OR_CREATE_SHARED_WORK_SPACE = "/api/data/v9.2/GetOrCreateSharedWorkspace";

export enum sharedWorkspaceParameters {
SHAREWORKSPACE_ID = "sharedworkspaceid",
TENANT_ID = "tenantid",
ACCESS_TOKEN = "accesstoken",
DISCOVERY_ENDPOINT = "discoveryendpoint",
}

export enum workerEventMessages {
UPDATE_CONNECTED_USERS = "client-data",
REMOVE_CONNECTED_USER = "member-removed",
}

export enum initializationEntityName {
WEBSITE = "websites",
WEBSITELANGUAGE = "websitelanguages",
Expand Down
25 changes: 13 additions & 12 deletions src/web/client/common/worker/webworker.js
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ class AzureFluidClient {
}
}

async function loadContainer(config, id, swpId) {
async function loadContainer(config, swpId, entityInfo) {
try {
const { container, audience, map } =
await AzureFluidClient.fetchContainerAndService(config, swpId);
Expand All @@ -101,22 +101,23 @@ async function loadContainer(config, id, swpId) {
if (!initial) {
existingMembers.forEach(async (value, key) => {
const otherUser = value;
const connectionArray = otherUser.connections;

const entityId = [];
const userConnections = otherUser.connections;

const userEntityIdArray = [];

const connectionIdInContainer = await (container.initialObjects.sharedState.get('selection').get());

connectionArray.forEach((connectionId) => {
entityId.push(connectionIdInContainer.get(connectionId));
userConnections.forEach((connection) => {
userEntityIdArray.push(connectionIdInContainer.get(connection.id));
});

self.postMessage({
type: "client-data",
userName: otherUser.userName,
userId: key,
containerId: swpId,
entityId: entityId,
entityId: userEntityIdArray,
});
});
initial = true;
Expand All @@ -127,14 +128,14 @@ async function loadContainer(config, id, swpId) {
return;
} else {
const otherUser = map.get(changed.key);
const connectionArray = otherUser.connections;
const userConnections = otherUser.connections;

const entityId = [];
const userEntityIdArray = [];

const connectionIdInContainer = await (container.initialObjects.sharedState.get('selection').get());

connectionArray.forEach((connectionId) => {
entityId.push(connectionIdInContainer.get(connectionId));
userConnections.forEach((connection) => {
userEntityIdArray.push(connectionIdInContainer.get(connection.id));
});

// eslint-disable-next-line no-undef
Expand All @@ -143,7 +144,7 @@ async function loadContainer(config, id, swpId) {
userId: changed.key,
userName: otherUser.userName,
containerId: swpId,
entityId: entityId,
entityId: userEntityIdArray,
});
}
});
Expand All @@ -160,8 +161,8 @@ function runFluidApp() {

await loadContainer(
message.afrConfig,
message.containerId,
message.afrConfig.swpId,
message.entityInfo
);
});
}
Expand Down
Loading