Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
92 changes: 80 additions & 12 deletions src/api/builders/mapagent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { RequestBuilder, ICreateRuntimeMapOptions, IQueryMapFeaturesOptions, IDe
import { RuntimeMap } from '../contracts/runtime-map';
import { QueryMapFeaturesResponse } from '../contracts/query';
import { ResourceIdentifier, ResourceBase, SiteVersionResponse } from '../contracts/common';
import { parseSiteVersion } from '../../utils/site-version';

const MG_MAPAGENT_ERROR_CODE = 559;

Expand Down Expand Up @@ -39,11 +40,58 @@ export function serialize(data: any, uppercase: boolean = true): string {
*/
export class MapAgentRequestBuilder extends RequestBuilder {
private locale: string;
private static siteVersionCache = new Map<string, Promise<SiteVersionResponse>>();
constructor(agentUri: string, locale: string = DEFAULT_LOCALE) {
super(agentUri);
this.locale = locale;
}

private async getRawJson(url: string): Promise<any> {
const response = await fetch(url, {
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
} as any,
method: "GET"
});
if (isErrorResponse(response)) {
throw new MgError(response.statusText);
}
return await response.json();
}

private extractCleanResourceJson(json: any): any {
if (json?.ApplicationDefinition) {
return json.ApplicationDefinition;
}
if (json?.WebLayout) {
return json.WebLayout;
}
if (json?.MapDefinition) {
return json.MapDefinition;
}
if (json?.TileSetDefinition) {
return json.TileSetDefinition;
}
return json;
}

private extractCleanRuntimeMapJson(json: any): any {
if (json?.RuntimeMap) {
return json.RuntimeMap;
}
if (json?.Map) {
return json.Map;
}
return json;
}

private async canUseCleanResourceContent(): Promise<boolean> {
const sv = await this.getSiteVersion();
const [major] = parseSiteVersion(sv.Version);
return major >= 4;
}

public async get<T>(url: string): Promise<T> {
const response = await fetch(url, {
headers: {
Expand Down Expand Up @@ -141,21 +189,39 @@ export class MapAgentRequestBuilder extends RequestBuilder {
}
}

public getResource<T extends ResourceBase>(resourceId: ResourceIdentifier, args?: any): Promise<T> {
public async getResource<T extends ResourceBase>(resourceId: ResourceIdentifier, args?: any): Promise<T> {
if (args != null) {
const isAppDef = typeof resourceId === "string" && /applicationdefinition$/i.test(resourceId.trim());
if (isAppDef && await this.canUseCleanResourceContent()) {
const p1 = { operation: "GETRESOURCECONTENT", resourceId: resourceId, version: "4.0.0", clean: 1 };
const url = this.stringifyGetUrl({ ...args, ...p1 });
const json = await this.getRawJson(url);
return this.extractCleanResourceJson(json) as T;
}

const p1 = { operation: "GETRESOURCECONTENT", resourceId: resourceId };
const url = this.stringifyGetUrl({ ...args, ...p1 });
return this.get<T>(url);
return await this.get<T>(url);
} else {
const url = this.stringifyGetUrl({ operation: "GETRESOURCE", resourceId: resourceId });
return this.get<T>(url);
return await this.get<T>(url);
}
}

public getSiteVersion(): Promise<SiteVersionResponse> {
const p1 = { operation: "GETSITEVERSION", version: "1.0.0", username: "Anonymous" };
const url = this.stringifyGetUrl({ ...p1 });
return this.get<SiteVersionResponse>(url);
const cached = MapAgentRequestBuilder.siteVersionCache.get(this.agentUri);
if (cached) {
return cached;
}

const p1 = { operation: "GETSITEVERSION", version: "1.0.0", username: "Anonymous" };
const url = this.stringifyGetUrl({ ...p1 });
const pending = this.get<SiteVersionResponse>(url).catch((error) => {
MapAgentRequestBuilder.siteVersionCache.delete(this.agentUri);
throw error;
});
MapAgentRequestBuilder.siteVersionCache.set(this.agentUri, pending);
return pending;
}

public createRuntimeMap(options: ICreateRuntimeMapOptions): Promise<RuntimeMap> {
Expand All @@ -164,10 +230,11 @@ export class MapAgentRequestBuilder extends RequestBuilder {
return this.get<RuntimeMap>(url);
}

public createRuntimeMap_v4(options: ICreateRuntimeMapOptions): Promise<RuntimeMap> {
const p1 = { operation: "CREATERUNTIMEMAP", version: "4.0.0" };
public async createRuntimeMap_v4(options: ICreateRuntimeMapOptions): Promise<RuntimeMap> {
const p1 = { operation: "CREATERUNTIMEMAP", version: "4.0.0", clean: 1 };
const url = this.stringifyGetUrl({ ...options, ...p1 });
return this.get<RuntimeMap>(url);
const json = await this.getRawJson(url);
return this.extractCleanRuntimeMapJson(json) as RuntimeMap;
}

public queryMapFeatures(options: IQueryMapFeaturesOptions): Promise<QueryMapFeaturesResponse> {
Expand All @@ -186,10 +253,11 @@ export class MapAgentRequestBuilder extends RequestBuilder {
return this.get<RuntimeMap>(url);
}

public describeRuntimeMap_v4(options: IDescribeRuntimeMapOptions): Promise<RuntimeMap> {
const p1 = { operation: "DESCRIBERUNTIMEMAP", version: "4.0.0" };
public async describeRuntimeMap_v4(options: IDescribeRuntimeMapOptions): Promise<RuntimeMap> {
const p1 = { operation: "DESCRIBERUNTIMEMAP", version: "4.0.0", clean: 1 };
const url = this.stringifyGetUrl({ ...options, ...p1 });
return this.get<RuntimeMap>(url);
const json = await this.getRawJson(url);
return this.extractCleanRuntimeMapJson(json) as RuntimeMap;
}

public getTileTemplateUrl(resourceId: string, groupName: string, xPlaceholder: string, yPlaceholder: string, zPlaceholder: string, isXYZ: boolean): string {
Expand Down
5 changes: 3 additions & 2 deletions src/api/registry/command-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ function isCommandSpec(cmd: ICommandSpec | IUnknownCommandSpec): cmd is ICommand
}

export function isUIWidget(widget: any): widget is UIWidget {
return widget.WidgetType === "UiWidgetType";
return widget.WidgetType === "UiWidgetType"
|| widget["@xsi:type"] === "UiWidgetType";
}

/**
Expand Down Expand Up @@ -189,7 +190,7 @@ function convertWidget(widget: UIWidget, locale: string, noToolbarLabels: boolea
* @returns
*/
export function convertFlexLayoutUIItems(isStateless: boolean, items: ContainerItem[], widgetsByKey: Dictionary<Widget>, locale: string, noToolbarLabels = false): (IFlyoutSpec | ISeparatorSpec | IUnknownCommandSpec | ICommandSpec)[] {
const converted = items.map(item => {
const converted = (items || []).map(item => {
switch (item.Function) {
case "Widget":
{
Expand Down
Loading
Loading