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

presentation/default units #657

Merged
merged 14 commits into from
Feb 5, 2021
Merged
Show file tree
Hide file tree
Changes from 5 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
2 changes: 1 addition & 1 deletion common/api/presentation-backend.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,7 @@ export interface PresentationManagerProps {
// @alpha (undocumented)
contentCacheSize?: number;
// @alpha
defaultFormatsMap?: {
defaultFormats?: {
[phenomenon: string]: {
unitSystems: string[];
grigasp marked this conversation as resolved.
Show resolved Hide resolved
format: FormatProps;
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"changes": [
{
"packageName": "@bentley/presentation-backend",
"comment": "added default units map",
"comment": "Added a way to set default property formatting",
"type": "none"
}
],
Expand Down
4 changes: 2 additions & 2 deletions full-stack-tests/presentation/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@
"@bentley/imodeljs-backend": "2.12.0-dev.10",
"@bentley/imodeljs-frontend": "2.12.0-dev.10",
"@bentley/oidc-signin-tool": "2.12.0-dev.10",
"@bentley/presentation-common": "2.12.0-dev.10",
"@bentley/presentation-backend": "2.12.0-dev.10",
"@bentley/presentation-common": "2.12.0-dev.10",
"@bentley/presentation-frontend": "2.12.0-dev.10",
"@bentley/presentation-components": "2.12.0-dev.10",
"@bentley/presentation-testing": "2.12.0-dev.10",
Expand Down Expand Up @@ -90,4 +90,4 @@
],
"extends": "plugin:@bentley/imodeljs-recommended"
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@ import { expect } from "chai";
import { ClientRequestContext, Guid } from "@bentley/bentleyjs-core";
import { IModelDb, SnapshotDb } from "@bentley/imodeljs-backend";
import { PresentationManager } from "@bentley/presentation-backend";
import { ContentSpecificationTypes, Field, KeySet, PresentationUnitSystem, Ruleset, RuleTypes } from "@bentley/presentation-common";
import {
ContentSpecificationTypes, DisplayValuesArray, DisplayValuesMap, KeySet, PresentationUnitSystem, Ruleset, RuleTypes,
} from "@bentley/presentation-common";
import { findFieldByLabel } from "../frontend/Content.test";
grigasp marked this conversation as resolved.
Show resolved Hide resolved
import { initialize, terminate } from "../IntegrationTests";

describe("PresentationManager", () => {
Expand All @@ -23,17 +26,18 @@ describe("PresentationManager", () => {
await terminate();
});

describe("Calculated Properties", () => {
describe("Property value formatting", () => {

const ruleset: Ruleset = {
id: Guid.createValue(),
rules: [{
ruleType: RuleTypes.Content,
specifications: [{ specType: ContentSpecificationTypes.SelectedNodeInstances }],
}],
};

const keys = KeySet.fromJSON({ instanceKeys: [["Generic:PhysicalObject", ["0x74"]]], nodeKeys: [] });
it("creates calculated fields without defaultMap", async () => {

it("formats property with default kind of quantity format when it doesn't have format for requested unit system", async () => {
const manager: PresentationManager = new PresentationManager();
const descriptor = await manager.getContentDescriptor({
imodel,
Expand All @@ -46,10 +50,13 @@ describe("PresentationManager", () => {
expect(descriptor).to.not.be.undefined;
const field = findFieldByLabel(descriptor!.fields, "cm2")!;
expect(field).not.to.be.undefined;
const allDistinctValues =await manager.getPagedDistinctValues({ imodel, rulesetOrId: ruleset, keys, descriptor: descriptor!, fieldDescriptor: field.getFieldDescriptor(), requestContext: new ClientRequestContext() });
expect(allDistinctValues.items[0].displayValue).to.eq("150.1235 cm²");
const content = await manager.getContent({ imodel, rulesetOrId: ruleset, keys, descriptor: descriptor!, requestContext: new ClientRequestContext(), unitSystem: PresentationUnitSystem.BritishImperial });
const displayValues = content!.contentSet[0].displayValues.rc_generic_PhysicalObject_ncc_MyProp_areaElementAspect as DisplayValuesArray;
expect(displayValues.length).is.eq(1);
expect(((displayValues[0] as DisplayValuesMap).displayValues as DisplayValuesMap)[field.name]!).to.eq("150.1235 cm²");
});
it("creates calculated fields with defaultMap", async () => {

it("formats property using default format when it doesn't have format for requested unit system", async () => {
const formatProps = {
composite:
{includeZero:true,
Expand All @@ -63,10 +70,10 @@ describe("PresentationManager", () => {

const map = {
// eslint-disable-next-line @typescript-eslint/naming-convention
AREA: {unitSystems: ["Undefined"], format: formatProps},
AREA: {unitSystems: [PresentationUnitSystem.BritishImperial], format: formatProps},
};

const manager: PresentationManager = new PresentationManager({defaultFormatsMap: map});
const manager: PresentationManager = new PresentationManager({defaultFormats: map});
const descriptor = await manager.getContentDescriptor({
imodel,
rulesetOrId: ruleset,
Expand All @@ -78,32 +85,46 @@ describe("PresentationManager", () => {
expect(descriptor).to.not.be.undefined;
const field = findFieldByLabel(descriptor!.fields, "cm2")!;
expect(field).not.to.be.undefined;
const allDistinctValues = await manager.getPagedDistinctValues({ imodel, rulesetOrId: ruleset, keys, descriptor: descriptor!, fieldDescriptor: field.getFieldDescriptor(), requestContext: new ClientRequestContext() });
expect(allDistinctValues.items[0].displayValue).to.eq("0.1616 ft²");
const content = await manager.getContent({ imodel, rulesetOrId: ruleset, keys, descriptor: descriptor!, requestContext: new ClientRequestContext(), unitSystem: PresentationUnitSystem.BritishImperial });
const displayValues = content!.contentSet[0].displayValues.rc_generic_PhysicalObject_ncc_MyProp_areaElementAspect as DisplayValuesArray;
expect(displayValues.length).is.eq(1);
expect(((displayValues[0] as DisplayValuesMap).displayValues as DisplayValuesMap)[field.name]!).to.eq("0.1616 ft²");
});

grigasp marked this conversation as resolved.
Show resolved Hide resolved
function findFieldByLabel(fields: Field[], label: string, allFields?: Field[]): Field | undefined {
const isTopLevel = (undefined === allFields);
if (!allFields)
allFields = new Array<Field>();
for (const field of fields) {
if (field.label === label)
return field;
it("formats property using provided format when it has provided format and default format for requested unit system", async () => {
const formatProps = {
composite:
{includeZero:true,
spacer:" ",
units:[{label:"ft²",name:"SQ_FT"}],
},
formatTraits:"KeepSingleZero|KeepDecimalPoint|ShowUnitLabel",
precision:4,
type:"Decimal",
uomSeparator:""};

if (field.isNestedContentField()) {
const nestedMatchingField = findFieldByLabel(field.nestedFields, label, allFields);
if (nestedMatchingField)
return nestedMatchingField;
}
const map = {
// eslint-disable-next-line @typescript-eslint/naming-convention
AREA: {unitSystems: [PresentationUnitSystem.Metric], format: formatProps},
};

allFields.push(field);
}
if (isTopLevel) {
// eslint-disable-next-line no-console
console.error(`Field '${label}' not found. Available fields: [${allFields.map((f) => `"${f.label}"`).join(", ")}]`);
}
return undefined;
}
const manager: PresentationManager = new PresentationManager({defaultFormats: map});
const descriptor = await manager.getContentDescriptor({
imodel,
rulesetOrId: ruleset,
keys,
displayType: "Grid",
requestContext: new ClientRequestContext(),
unitSystem: PresentationUnitSystem.Metric,
});
expect(descriptor).to.not.be.undefined;
const field = findFieldByLabel(descriptor!.fields, "cm2")!;
expect(field).not.to.be.undefined;
const content = await manager.getContent({ imodel, rulesetOrId: ruleset, keys, descriptor: descriptor!, requestContext: new ClientRequestContext(), unitSystem: PresentationUnitSystem.Metric });
const displayValues = content!.contentSet[0].displayValues.rc_generic_PhysicalObject_ncc_MyProp_areaElementAspect as DisplayValuesArray;
expect(displayValues.length).is.eq(1);
expect(((displayValues[0] as DisplayValuesMap).displayValues as DisplayValuesMap)[field.name]!).to.eq("150.1235 cm²");
grigasp marked this conversation as resolved.
Show resolved Hide resolved
});
});

});
Original file line number Diff line number Diff line change
Expand Up @@ -575,7 +575,7 @@ class ECClassHierarchy {
}
}

function findFieldByLabel(fields: Field[], label: string, allFields?: Field[]): Field | undefined {
export function findFieldByLabel(fields: Field[], label: string, allFields?: Field[]): Field | undefined {
const isTopLevel = (undefined === allFields);
if (!allFields)
allFields = new Array<Field>();
Expand Down
8 changes: 4 additions & 4 deletions presentation/backend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,17 +40,17 @@
"@bentley/bentleyjs-core": "^2.12.0-dev.10",
"@bentley/imodeljs-backend": "^2.12.0-dev.10",
"@bentley/imodeljs-common": "^2.12.0-dev.10",
"@bentley/presentation-common": "^2.12.0-dev.10",
"@bentley/imodeljs-quantity": "^2.12.0-dev.10"
"@bentley/imodeljs-quantity": "^2.12.0-dev.10",
"@bentley/presentation-common": "^2.12.0-dev.10"
},
"devDependencies": {
"@bentley/bentleyjs-core": "2.12.0-dev.10",
"@bentley/build-tools": "2.12.0-dev.10",
"@bentley/eslint-plugin": "2.12.0-dev.10",
"@bentley/imodeljs-backend": "2.12.0-dev.10",
"@bentley/imodeljs-common": "2.12.0-dev.10",
"@bentley/presentation-common": "2.12.0-dev.10",
"@bentley/imodeljs-quantity": "2.12.0-dev.10",
"@bentley/presentation-common": "2.12.0-dev.10",
"@types/chai": "^4.1.4",
"@types/chai-as-promised": "^7",
"@types/chai-jest-snapshot": "^1.3.0",
Expand Down Expand Up @@ -98,4 +98,4 @@
],
"extends": "plugin:@bentley/imodeljs-recommended"
}
}
}
16 changes: 5 additions & 11 deletions presentation/backend/src/presentation-backend/NativePlatform.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,10 @@

import { ClientRequestContext, IDisposable } from "@bentley/bentleyjs-core";
import { IModelDb, IModelHost, IModelJsNative } from "@bentley/imodeljs-backend";
import { FormatProps } from "@bentley/imodeljs-quantity";
import {
DiagnosticsScopeLogs, PresentationError, PresentationStatus, UpdateInfoJSON, VariableValueJSON, VariableValueTypes,
} from "@bentley/presentation-common";
import { HierarchyCacheMode, PresentationManagerMode } from "./PresentationManager";
import { HierarchyCacheMode, PresentationManagerMode, UnitSystemFormat } from "./PresentationManager";

/** @internal */
export enum NativePlatformRequestTypes {
Expand Down Expand Up @@ -69,12 +68,7 @@ export interface DefaultNativePlatformProps {
isChangeTrackingEnabled: boolean;
cacheConfig?: IModelJsNative.ECPresentationHierarchyCacheConfig;
contentCacheSize?: number;
defaultFormatsMap?: {
[phenomenon: string]: {
unitSystems: string[];
format: FormatProps;
};
};
defaultFormats?: { [phenomenon: string]: UnitSystemFormat };
}

/** @internal */
Expand All @@ -86,8 +80,8 @@ export const createDefaultNativePlatform = (props: DefaultNativePlatformProps):
public constructor() {
const mode = (props.mode === PresentationManagerMode.ReadOnly) ? IModelJsNative.ECPresentationManagerMode.ReadOnly : IModelJsNative.ECPresentationManagerMode.ReadWrite;
const cacheConfig = props.cacheConfig ?? { mode: HierarchyCacheMode.Disk, directory: "" };
const defaultFormatsMap = props.defaultFormatsMap ? this.getSerializedMap(props.defaultFormatsMap) : {};
this._nativeAddon = new IModelHost.platform.ECPresentationManager({ ...props, mode, cacheConfig, defaultFormatsMap});
const defaultFormats = props.defaultFormats ? this.getSerializedDefaultFormatsMap(props.defaultFormats) : {};
this._nativeAddon = new IModelHost.platform.ECPresentationManager({ ...props, mode, cacheConfig, defaultFormats});
grigasp marked this conversation as resolved.
Show resolved Hide resolved
}
private getStatus(responseStatus: IModelJsNative.ECPresentationStatus): PresentationStatus {
switch (responseStatus) {
Expand All @@ -96,7 +90,7 @@ export const createDefaultNativePlatform = (props: DefaultNativePlatformProps):
default: return PresentationStatus.Error;
}
}
private getSerializedMap(defaultMap: { [phenomenon: string]: { unitSystems: string[], format: FormatProps } }){
private getSerializedDefaultFormatsMap(defaultMap: { [phenomenon: string]: UnitSystemFormat }){
const res: {
[phenomenon: string]: {
unitSystems: string[];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,17 @@ export interface HybridCacheConfig extends HierarchyCacheConfigBase {
disk?: DiskHierarchyCacheConfig;
}

/**
* Map for setting up format to a number of UnitSystems.
* It is used in [[PresentationManager]] to setup DefaultFormats.
* DefaultFormats are constructed by mapping a phenomenon with UnitSystemFormat.
grigasp marked this conversation as resolved.
Show resolved Hide resolved
* @alpha
*/
export interface UnitSystemFormat {
unitSystems: PresentationUnitSystem[];
format: FormatProps;
};

/**
* Properties that can be used to configure [[PresentationManager]]
* @public
Expand Down Expand Up @@ -250,11 +261,8 @@ export interface PresentationManagerProps {
/**
* A map for setting up default formats.
grigasp marked this conversation as resolved.
Show resolved Hide resolved
* @alpha */
defaultFormatsMap?: {
[phenomenon: string]: {
unitSystems: string[];
format: FormatProps;
};
defaultFormats?: {
[phenomenon: string]: UnitSystemFormat;
};

/**
Expand Down Expand Up @@ -318,7 +326,7 @@ export class PresentationManager {
isChangeTrackingEnabled,
cacheConfig: createCacheConfig(this._props.cacheConfig),
contentCacheSize: this._props.contentCacheSize,
defaultFormatsMap: this._props.defaultFormatsMap,
defaultFormats: this._props.defaultFormats,
});
this._nativePlatform = new nativePlatformImpl();
}
Expand Down
12 changes: 6 additions & 6 deletions presentation/backend/src/test/PresentationManager.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ describe("PresentationManager", () => {
isChangeTrackingEnabled: false,
cacheConfig: { mode: HierarchyCacheMode.Disk, directory: "" },
contentCacheSize: undefined,
defaultFormatsMap: {},
defaultFormats: {},
});
});
});
Expand Down Expand Up @@ -128,7 +128,7 @@ describe("PresentationManager", () => {
isChangeTrackingEnabled: true,
cacheConfig: expectedCacheConfig,
contentCacheSize: 999,
defaultFormatsMap: {},
defaultFormats: {},
});
});
});
Expand All @@ -145,7 +145,7 @@ describe("PresentationManager", () => {
isChangeTrackingEnabled: false,
cacheConfig: { mode: HierarchyCacheMode.Disk, directory: "" },
contentCacheSize: undefined,
defaultFormatsMap: {},
defaultFormats: {},
});
});
constructorSpy.resetHistory();
Expand All @@ -164,7 +164,7 @@ describe("PresentationManager", () => {
isChangeTrackingEnabled: false,
cacheConfig: expectedConfig,
contentCacheSize: undefined,
defaultFormatsMap: {},
defaultFormats: {},
});
});
});
Expand All @@ -181,7 +181,7 @@ describe("PresentationManager", () => {
isChangeTrackingEnabled: false,
cacheConfig: { mode: HierarchyCacheMode.Hybrid, disk: undefined },
contentCacheSize: undefined,
defaultFormatsMap: {},
defaultFormats: {},
});
});
constructorSpy.resetHistory();
Expand All @@ -205,7 +205,7 @@ describe("PresentationManager", () => {
isChangeTrackingEnabled: false,
cacheConfig: expectedConfig,
contentCacheSize: undefined,
defaultFormatsMap: {},
defaultFormats: {},
});
});
});
Expand Down