From 2d1d8ab72eeafd6c64b1ec3c4cad045de2d6c588 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A5kon=20Flatval?= Date: Fri, 21 Jun 2024 15:55:49 +0200 Subject: [PATCH 01/19] feat(react-components): initial support for Observations --- react-components/package.json | 4 +- .../src/architecture/base/views/BaseView.ts | 8 +- .../architecture/base/views/GroupThreeView.ts | 6 +- .../src/architecture/base/views/ThreeView.ts | 6 +- .../ObservationsDomainObject.ts | 27 ++++ .../ObservationsTool.ts | 115 ++++++++++++++++++ .../ObservationsView.ts | 24 ++++ .../observationsDomainObject/models.ts | 54 ++++++++ .../components/Architecture/CommandButton.tsx | 9 +- .../components/Architecture/RevealButtons.tsx | 45 +++++-- .../components/RevealToolbar/HelpButton.tsx | 6 +- .../src/components/RuleBasedOutputs/types.ts | 7 +- react-components/src/utilities/FdmSDK.ts | 24 ++-- react-components/stories/Toolbar.stories.tsx | 2 + react-components/yarn.lock | 12 +- 15 files changed, 304 insertions(+), 45 deletions(-) create mode 100644 react-components/src/architecture/concrete/observationsDomainObject/ObservationsDomainObject.ts create mode 100644 react-components/src/architecture/concrete/observationsDomainObject/ObservationsTool.ts create mode 100644 react-components/src/architecture/concrete/observationsDomainObject/ObservationsView.ts create mode 100644 react-components/src/architecture/concrete/observationsDomainObject/models.ts diff --git a/react-components/package.json b/react-components/package.json index 3b15d39c271..29b0b98a2fe 100644 --- a/react-components/package.json +++ b/react-components/package.json @@ -30,7 +30,7 @@ }, "peerDependencies": { "@cognite/cogs.js": ">=9.84.3", - "@cognite/reveal": "4.14.7", + "@cognite/reveal": "4.15.0", "react": ">=18", "react-dom": ">=18", "styled-components": ">=5" @@ -44,7 +44,7 @@ "@cognite/cdf-i18n-utils": "^0.7.5", "@cognite/cdf-utilities": "^3.6.0", "@cognite/cogs.js": "^9.84.3", - "@cognite/reveal": "^4.14.7", + "@cognite/reveal": "^4.15.0", "@cognite/sdk": "^9.13.0", "@playwright/test": "^1.43.1", "@storybook/addon-essentials": "^8.0.9", diff --git a/react-components/src/architecture/base/views/BaseView.ts b/react-components/src/architecture/base/views/BaseView.ts index dfe435a3489..8361d6b0037 100644 --- a/react-components/src/architecture/base/views/BaseView.ts +++ b/react-components/src/architecture/base/views/BaseView.ts @@ -9,12 +9,12 @@ import { type DomainObjectChange } from '../domainObjectsHelpers/DomainObjectCha * Represents the observer in the Observer pattern * It provides common functionality for all types of views. */ -export abstract class BaseView { +export abstract class BaseView { // ================================================== // INSTANCE FIELDS // ================================================== - private _domainObject: DomainObject | undefined = undefined; + private _domainObject: DomainObjectType | undefined = undefined; // ================================================== // INSTANCE PROPERTIES @@ -24,7 +24,7 @@ export abstract class BaseView { return this._domainObject !== undefined; } - public get domainObject(): DomainObject { + public get domainObject(): DomainObjectType { if (this._domainObject === undefined) { throw Error('The DomainObject is missing in the view'); } @@ -92,7 +92,7 @@ export abstract class BaseView { // INSTANCE METHODS // ================================================== - public setDomainObject(domainObject: DomainObject): void { + public setDomainObject(domainObject: DomainObjectType): void { this._domainObject = domainObject; } } diff --git a/react-components/src/architecture/base/views/GroupThreeView.ts b/react-components/src/architecture/base/views/GroupThreeView.ts index afcde5e5f04..7cb4c603b52 100644 --- a/react-components/src/architecture/base/views/GroupThreeView.ts +++ b/react-components/src/architecture/base/views/GroupThreeView.ts @@ -13,6 +13,7 @@ import { } from '@cognite/reveal'; import { type DomainObjectIntersection } from '../domainObjectsHelpers/DomainObjectIntersection'; import { VisualDomainObject } from '../domainObjects/VisualDomainObject'; +import { DomainObject } from '../domainObjects/DomainObject'; /** * Represents an abstract class for a Three.js view that renders an Object3D. @@ -24,7 +25,10 @@ import { VisualDomainObject } from '../domainObjects/VisualDomainObject'; * - calculateBoundingBox() to calculate the bounding box if you don not relay on three.js. */ -export abstract class GroupThreeView extends ThreeView implements ICustomObject { +export abstract class GroupThreeView + extends ThreeView + implements ICustomObject +{ // ================================================== // INSTANCE FIELDS // ================================================== diff --git a/react-components/src/architecture/base/views/ThreeView.ts b/react-components/src/architecture/base/views/ThreeView.ts index 2cb0d6d26fe..dfee635291c 100644 --- a/react-components/src/architecture/base/views/ThreeView.ts +++ b/react-components/src/architecture/base/views/ThreeView.ts @@ -17,7 +17,9 @@ import { type PerspectiveCamera, type Box3 } from 'three'; * It can for instance be a view that changes something on another view, dor instance texture on a surface or whatever. * I just wanted to make it ready for some corner cases I have seen during a long time as 3D developer. */ -export abstract class ThreeView extends BaseView { +export abstract class ThreeView< + DomainObjectType extends DomainObject = DomainObject +> extends BaseView { // ================================================== // INSTANCE FIELDS // ================================================== @@ -112,7 +114,7 @@ export abstract class ThreeView extends BaseView { this._boundingBox = undefined; } - public attach(domainObject: DomainObject, renderTarget: RevealRenderTarget): void { + public attach(domainObject: DomainObjectType, renderTarget: RevealRenderTarget): void { super.setDomainObject(domainObject); this._renderTarget = renderTarget; } diff --git a/react-components/src/architecture/concrete/observationsDomainObject/ObservationsDomainObject.ts b/react-components/src/architecture/concrete/observationsDomainObject/ObservationsDomainObject.ts new file mode 100644 index 00000000000..a0ab0e9f60f --- /dev/null +++ b/react-components/src/architecture/concrete/observationsDomainObject/ObservationsDomainObject.ts @@ -0,0 +1,27 @@ +import { Overlay3DCollection } from '@cognite/reveal'; +import { Observation } from './models'; +import { VisualDomainObject } from '../../base/domainObjects/VisualDomainObject'; +import { ThreeView } from '../../base/views/ThreeView'; +import { ObservationsView } from './ObservationsView'; +import { TranslateKey } from '../../base/utilities/TranslateKey'; + +export class ObservationsDomainObject extends VisualDomainObject { + private _collection: Overlay3DCollection; + + public override get typeName(): TranslateKey { + return { fallback: ObservationsDomainObject.name }; + } + + constructor(collection: Overlay3DCollection) { + super(); + this._collection = collection; + } + + public get overlayCollection(): Overlay3DCollection { + return this._collection; + } + + protected override createThreeView(): ThreeView | undefined { + return new ObservationsView(this._collection); + } +} diff --git a/react-components/src/architecture/concrete/observationsDomainObject/ObservationsTool.ts b/react-components/src/architecture/concrete/observationsDomainObject/ObservationsTool.ts new file mode 100644 index 00000000000..d9412b78eee --- /dev/null +++ b/react-components/src/architecture/concrete/observationsDomainObject/ObservationsTool.ts @@ -0,0 +1,115 @@ +import { IconType } from '@cognite/cogs.js'; +import { TranslateKey } from '../../base/utilities/TranslateKey'; +import { FdmSDK, InstanceFilter } from '../../../utilities/FdmSDK'; +import { OBSERVATION_SOURCE, Observation, ObservationProperties } from './models'; +import { ObservationsDomainObject } from './ObservationsDomainObject'; +import { Color, Vector2, Vector3 } from 'three'; +import { CDF_TO_VIEWER_TRANSFORMATION, Overlay3D, Overlay3DCollection } from '@cognite/reveal'; +import { NavigationTool } from '../../base/concreteCommands/NavigationTool'; +import { RevealRenderTarget } from '../../base/renderTarget/RevealRenderTarget'; + +const DEFAULT_OVERLAY_COLOR = new Color('lightblue'); +const SELECTED_OVERLAY_COLOR = new Color('red'); + +export class ObservationsTool extends NavigationTool { + // private _domainObjects: ObservationsDomainObject[] = []; + private _domainObjectPromise: Promise; + + private _selectedOverlay: Overlay3D | undefined; + + constructor(fdmSdk: FdmSDK) { + super(); + this._domainObjectPromise = fetchObservations(fdmSdk).then((observations) => + this.initializeDomainObjects(observations) + ); + } + + private async initializeDomainObjects( + observations: Observation[] + ): Promise { + const observationOverlays = observations.map((observation) => { + const position = new Vector3( + observation.properties.positionX, + observation.properties.positionY, + observation.properties.positionZ + ).applyMatrix4(CDF_TO_VIEWER_TRANSFORMATION); + + return { + position, + content: observation + }; + }); + + console.log('Observation overlays: ', observationOverlays); + + const collection = new Overlay3DCollection(observationOverlays, { + defaultOverlayColor: DEFAULT_OVERLAY_COLOR + }); + + const observationDomainObject = new ObservationsDomainObject(collection); + + return observationDomainObject; + } + + public override get icon(): IconType { + return 'Location'; + } + + public override get tooltip(): TranslateKey { + return { fallback: 'Show observations' }; + } + + public override attach(renderTarget: RevealRenderTarget) { + super.attach(renderTarget); + this._domainObjectPromise.then((domainObject) => + renderTarget.rootDomainObject.addChildInteractive(domainObject) + ); + } + + public override onActivate() { + this._domainObjectPromise.then((domainObject) => + domainObject.setVisibleInteractive(true, this.renderTarget) + ); + } + + public override onDeactivate() { + this._domainObjectPromise.then((domainObject) => { + domainObject.setVisibleInteractive(false, this.renderTarget); + }); + } + + public override async onClick(event: PointerEvent) { + const domainObject = await this._domainObjectPromise; + domainObject.overlayCollection + .getOverlays() + .forEach((overlay) => overlay.setColor(DEFAULT_OVERLAY_COLOR)); + + const normalizedCoord = this.getNormalizedPixelCoordinates(event); + const intersection = domainObject.overlayCollection.intersectOverlays( + normalizedCoord, + this.renderTarget.camera + ); + + if (intersection !== undefined) { + this.handleIntersectedOverlay(intersection); + } + } + + private handleIntersectedOverlay(overlay: Overlay3D) { + overlay.setColor(SELECTED_OVERLAY_COLOR); + this.renderTarget.viewer.requestRedraw(); + this._selectedOverlay = overlay; + } +} + +const observationsFilter: InstanceFilter = {}; + +async function fetchObservations(fdmSdk: FdmSDK): Promise { + const observationResult = await fdmSdk.filterAllInstances( + observationsFilter, + 'node', + OBSERVATION_SOURCE + ); + + return observationResult.instances; +} diff --git a/react-components/src/architecture/concrete/observationsDomainObject/ObservationsView.ts b/react-components/src/architecture/concrete/observationsDomainObject/ObservationsView.ts new file mode 100644 index 00000000000..d60afdc8984 --- /dev/null +++ b/react-components/src/architecture/concrete/observationsDomainObject/ObservationsView.ts @@ -0,0 +1,24 @@ +import { Box3 } from 'three'; +import { ObservationsDomainObject } from './ObservationsDomainObject'; +import { GroupThreeView } from '../../base/views/GroupThreeView'; +import { Overlay3DCollection } from '@cognite/reveal'; +import { Observation } from './models'; + +export class ObservationsView extends GroupThreeView { + private _collection: Overlay3DCollection; + + constructor(collection: Overlay3DCollection) { + super(); + this._collection = collection; + } + + protected override calculateBoundingBox(): Box3 { + return this._collection + .getOverlays() + .reduce((box, overlay) => box.expandByPoint(overlay.getPosition()), new Box3()); + } + + protected override addChildren(): void { + this.addChild(this._collection); + } +} diff --git a/react-components/src/architecture/concrete/observationsDomainObject/models.ts b/react-components/src/architecture/concrete/observationsDomainObject/models.ts new file mode 100644 index 00000000000..e910327bd59 --- /dev/null +++ b/react-components/src/architecture/concrete/observationsDomainObject/models.ts @@ -0,0 +1,54 @@ +import { DmsUniqueIdentifier, FdmNode, Source } from '../../../utilities/FdmSDK'; + +export type ObservationProperties = { + // "ID as the node appears in the Source system" + sourceId: string; + // "Name of the source system node comes from" + source: string; + // "Title or name of the node" + title: string; + // "Long description of the node" + description: string; + // "Text based labels for generic use" + labels: string[]; + // "Visibility of node (PUBLIC, PRIVATE, PROTECTED)" + visibility: String; + // "Who created this node?" + createdBy: String; + // "Who was the last person to update this node?" + updatedBy: String; + // "Is this item archived, and therefore hidden from most UIs?" + isArchived: Boolean; + // "The status of the observation (draft, completed, sent)" + status: string; + // "External ID of the associated CDF Asset" + asset: DmsUniqueIdentifier; + // "List of associated files" + files: DmsUniqueIdentifier[]; + // "description of how the observation was troubleshooted" + troubleshooting: string; + // "Priority of the observation (Urgent, High ...)" + priority: string; + // "The observation type (Malfunction report, Maintenance request, etc.)" + type: string; + // "3D position" + positionX: number; + positionY: number; + positionZ: number; + // "Comments" + comments: [CommentProperties]; +}; + +export type CommentProperties = { + createdBy: string; + text: string; +}; + +export type Observation = FdmNode; + +export const OBSERVATION_SOURCE: Source = { + type: 'view', + version: '3c207ca2355dbb', + externalId: 'Observation', + space: 'observations' +}; diff --git a/react-components/src/components/Architecture/CommandButton.tsx b/react-components/src/components/Architecture/CommandButton.tsx index 4d25779a93b..508a58fb64e 100644 --- a/react-components/src/components/Architecture/CommandButton.tsx +++ b/react-components/src/components/Architecture/CommandButton.tsx @@ -32,7 +32,14 @@ export const CommandButtons = ({ ); }; -export const CreateCommandButton = (command: BaseCommand, isHorizontal = false): ReactElement => { +export const CommandButtonFromCommand = ({ + commandConstructor, + isHorizontal = false +}: { + commandConstructor: () => BaseCommand; + isHorizontal?: boolean; +}): ReactElement => { + const command = useMemo(commandConstructor, [commandConstructor]); return ; }; diff --git a/react-components/src/components/Architecture/RevealButtons.tsx b/react-components/src/components/Architecture/RevealButtons.tsx index 41cab519f34..0860261fabb 100644 --- a/react-components/src/components/Architecture/RevealButtons.tsx +++ b/react-components/src/components/Architecture/RevealButtons.tsx @@ -4,24 +4,49 @@ import { type ReactElement } from 'react'; import { NavigationTool } from '../../architecture/base/concreteCommands/NavigationTool'; -import { CreateCommandButton } from './CommandButton'; +import { CommandButtonFromCommand } from './CommandButton'; import { FitViewCommand } from '../../architecture/base/concreteCommands/FitViewCommand'; import { FlexibleControlsType } from '@cognite/reveal'; import { SetFlexibleControlsTypeCommand } from '../../architecture/base/concreteCommands/SetFlexibleControlsTypeCommand'; import { SetAxisVisibleCommand } from '../../architecture/concrete/axis/SetAxisVisibleCommand'; import { ClipTool } from '../../architecture/concrete/clipping/ClipTool'; import { MeasurementTool } from '../../architecture/concrete/measurements/MeasurementTool'; +import { useFdmSdk } from '../RevealCanvas/SDKProvider'; +import { ObservationsTool } from '../../architecture/concrete/observationsDomainObject/ObservationsTool'; export class RevealButtons { - static FitView = (): ReactElement => CreateCommandButton(new FitViewCommand()); - static NavigationTool = (): ReactElement => CreateCommandButton(new NavigationTool()); - static SetAxisVisible = (): ReactElement => CreateCommandButton(new SetAxisVisibleCommand()); - static Measurement = (): ReactElement => CreateCommandButton(new MeasurementTool()); - static Clip = (): ReactElement => CreateCommandButton(new ClipTool()); + static FitView = (): ReactElement => ( + new FitViewCommand()} /> + ); + static NavigationTool = (): ReactElement => ( + new NavigationTool()} /> + ); + static SetAxisVisible = (): ReactElement => ( + new SetAxisVisibleCommand()} /> + ); + static Measurement = (): ReactElement => ( + new MeasurementTool()} /> + ); + static Clip = (): ReactElement => ( + new ClipTool()} /> + ); - static SetFlexibleControlsTypeOrbit = (): ReactElement => - CreateCommandButton(new SetFlexibleControlsTypeCommand(FlexibleControlsType.Orbit)); + static SetFlexibleControlsTypeOrbit = (): ReactElement => ( + new SetFlexibleControlsTypeCommand(FlexibleControlsType.Orbit)} + /> + ); - static SetFlexibleControlsTypeFirstPerson = (): ReactElement => - CreateCommandButton(new SetFlexibleControlsTypeCommand(FlexibleControlsType.FirstPerson)); + static SetFlexibleControlsTypeFirstPerson = (): ReactElement => ( + + new SetFlexibleControlsTypeCommand(FlexibleControlsType.FirstPerson) + } + /> + ); + + static Observations = (): ReactElement => { + const fdmSdk = useFdmSdk(); + return new ObservationsTool(fdmSdk)} />; + }; } diff --git a/react-components/src/components/RevealToolbar/HelpButton.tsx b/react-components/src/components/RevealToolbar/HelpButton.tsx index ff5b812893f..c4a2d579494 100644 --- a/react-components/src/components/RevealToolbar/HelpButton.tsx +++ b/react-components/src/components/RevealToolbar/HelpButton.tsx @@ -23,9 +23,11 @@ export const HelpButton = ({ fallbackLanguage }: HelpButtonProps): ReactElement { + onHide={() => setHelpActive(false)} + hideOnSelect={{ hideOnContentClick: true, hideOnOutsideClick: true }} + /* onClickOutside={() => { setHelpActive(false); - }} + }} */ content={ diff --git a/react-components/src/components/RuleBasedOutputs/types.ts b/react-components/src/components/RuleBasedOutputs/types.ts index a3fb33c0314..fab522de7dd 100644 --- a/react-components/src/components/RuleBasedOutputs/types.ts +++ b/react-components/src/components/RuleBasedOutputs/types.ts @@ -3,7 +3,7 @@ */ import { type TreeIndexNodeCollection, type NumericRange } from '@cognite/reveal'; -import { type FdmNode, type EdgeItem } from '../../utilities/FdmSDK'; +import { type FdmNode, type EdgeItem, DmsUniqueIdentifier } from '../../utilities/FdmSDK'; import { type AssetStylingGroup, type FdmPropertyType } from '../Reveal3DResources/types'; import { type Datapoints, type Asset, type Timeseries, type ExternalId } from '@cognite/sdk'; @@ -220,11 +220,6 @@ export type SimpleSource = { version: string; } & DmsUniqueIdentifier; -export type DmsUniqueIdentifier = { - space: Space; - externalId: ExternalId; -}; - export type ViewQueryFilter = { view: Source; }; diff --git a/react-components/src/utilities/FdmSDK.ts b/react-components/src/utilities/FdmSDK.ts index 25ac69aa581..afaaeade356 100644 --- a/react-components/src/utilities/FdmSDK.ts +++ b/react-components/src/utilities/FdmSDK.ts @@ -283,12 +283,6 @@ export class FdmSDK { filter?: InstanceFilter, properties?: string[] ): Promise<{ instances: Array | NodeItem> }> { - function makeSureNonEmptyFilterForRequest( - filter: InstanceFilter | undefined - ): InstanceFilter | undefined { - return filter !== undefined && Object.keys(filter).length === 0 ? undefined : filter; - } - filter = makeSureNonEmptyFilterForRequest(filter); const data: any = { @@ -315,7 +309,7 @@ export class FdmSDK { // eslint-disable-next-line no-dupe-class-members public async filterInstances>( - filter: InstanceFilter, + filter: InstanceFilter | undefined, instanceType: InstanceType, source?: Source, cursor?: string @@ -326,7 +320,7 @@ export class FdmSDK { // eslint-disable-next-line no-dupe-class-members public async filterInstances>( - filter: InstanceFilter, + filter: InstanceFilter | undefined, instanceType: 'node', source?: Source, cursor?: string @@ -334,7 +328,7 @@ export class FdmSDK { // eslint-disable-next-line no-dupe-class-members public async filterInstances>( - filter: InstanceFilter, + filter: InstanceFilter | undefined, instanceType: 'edge', source?: Source, cursor?: string @@ -342,7 +336,7 @@ export class FdmSDK { // eslint-disable-next-line no-dupe-class-members public async filterInstances>( - filter: InstanceFilter, + filter: InstanceFilter | undefined, instanceType: InstanceType, source: Source, cursor?: string @@ -399,10 +393,12 @@ export class FdmSDK { // eslint-disable-next-line no-dupe-class-members public async filterAllInstances>( - filter: InstanceFilter, + filter: InstanceFilter | undefined, instanceType: InstanceType, source?: Source ): Promise<{ instances: Array | FdmNode> }> { + filter = makeSureNonEmptyFilterForRequest(filter); + let mappings = await this.filterInstances(filter, instanceType, source); while (mappings.nextCursor !== undefined) { @@ -558,3 +554,9 @@ function hoistInstanceProperties( } }); } + +function makeSureNonEmptyFilterForRequest( + filter: InstanceFilter | undefined +): InstanceFilter | undefined { + return filter !== undefined && Object.keys(filter).length === 0 ? undefined : filter; +} diff --git a/react-components/stories/Toolbar.stories.tsx b/react-components/stories/Toolbar.stories.tsx index cbf5dab9eca..534c7b8d734 100644 --- a/react-components/stories/Toolbar.stories.tsx +++ b/react-components/stories/Toolbar.stories.tsx @@ -20,6 +20,7 @@ import { signalStoryReadyForScreenshot } from './utilities/signalStoryReadyForSc import { RevealStoryContainer } from './utilities/RevealStoryContainer'; import { getAddModelOptionsFromUrl } from './utilities/getAddModelOptionsFromUrl'; import { SetOrbitOrFirstPersonControlsType } from '../src/components/RevealToolbar/SetFlexibleControlsType'; +import { ObservationsButton } from '../src/components/Observations/ObservationsButton'; const meta = { title: 'Example/Toolbar', @@ -109,6 +110,7 @@ export const Main: Story = { + ) diff --git a/react-components/yarn.lock b/react-components/yarn.lock index bff68112989..c030f37e6b9 100644 --- a/react-components/yarn.lock +++ b/react-components/yarn.lock @@ -1747,7 +1747,7 @@ __metadata: "@cognite/cdf-i18n-utils": "npm:^0.7.5" "@cognite/cdf-utilities": "npm:^3.6.0" "@cognite/cogs.js": "npm:^9.84.3" - "@cognite/reveal": "npm:^4.14.7" + "@cognite/reveal": "npm:^4.15.0" "@cognite/sdk": "npm:^9.13.0" "@playwright/test": "npm:^1.43.1" "@storybook/addon-essentials": "npm:^8.0.9" @@ -1802,16 +1802,16 @@ __metadata: vitest: "npm:^1.5.3" peerDependencies: "@cognite/cogs.js": ">=9.84.3" - "@cognite/reveal": 4.14.7 + "@cognite/reveal": 4.15.0 react: ">=18" react-dom: ">=18" styled-components: ">=5" languageName: unknown linkType: soft -"@cognite/reveal@npm:^4.14.7": - version: 4.14.7 - resolution: "@cognite/reveal@npm:4.14.7" +"@cognite/reveal@npm:^4.15.0": + version: 4.15.0 + resolution: "@cognite/reveal@npm:4.15.0" dependencies: "@rajesh896/broprint.js": "npm:^2.1.1" "@tweenjs/tween.js": "npm:^23.1.1" @@ -1831,7 +1831,7 @@ __metadata: peerDependencies: "@cognite/sdk": ^7.16.0 || ^8.0.0 three: 0.165.0 - checksum: 10/095b8d02ec9a66dc3f28974f95fcac959b854b0504774b1c3b4bc837e66026aa5d58d01c0f9adb7cc8a09e389c05d9091226f9b2533dc97e513e3fb5143cbb34 + checksum: 10/5d8111cf3cc5a2424a643fd0d743764a90b56ffb7602fccc3dc07aace1f9857eb514abe765a6fc2cd6ba8fdbe069dea22a1ba46a00526b6800bf8f947f64f3b0 languageName: node linkType: hard From 35d301643cc2d1cf7d04973d27d3647212dfef82 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A5kon=20Flatval?= Date: Fri, 21 Jun 2024 16:09:14 +0200 Subject: [PATCH 02/19] chore: lint fix --- .../architecture/base/views/GroupThreeView.ts | 2 +- .../ObservationsDomainObject.ts | 13 +++-- .../ObservationsTool.ts | 53 ++++++++++--------- .../ObservationsView.ts | 11 ++-- .../observationsDomainObject/models.ts | 13 +++-- .../components/Architecture/RevealButtons.tsx | 4 ++ .../components/RevealToolbar/HelpButton.tsx | 4 +- .../src/components/RuleBasedOutputs/types.ts | 4 +- 8 files changed, 61 insertions(+), 43 deletions(-) diff --git a/react-components/src/architecture/base/views/GroupThreeView.ts b/react-components/src/architecture/base/views/GroupThreeView.ts index 7cb4c603b52..3913af54377 100644 --- a/react-components/src/architecture/base/views/GroupThreeView.ts +++ b/react-components/src/architecture/base/views/GroupThreeView.ts @@ -13,7 +13,7 @@ import { } from '@cognite/reveal'; import { type DomainObjectIntersection } from '../domainObjectsHelpers/DomainObjectIntersection'; import { VisualDomainObject } from '../domainObjects/VisualDomainObject'; -import { DomainObject } from '../domainObjects/DomainObject'; +import { type DomainObject } from '../domainObjects/DomainObject'; /** * Represents an abstract class for a Three.js view that renders an Object3D. diff --git a/react-components/src/architecture/concrete/observationsDomainObject/ObservationsDomainObject.ts b/react-components/src/architecture/concrete/observationsDomainObject/ObservationsDomainObject.ts index a0ab0e9f60f..85ec7f888a3 100644 --- a/react-components/src/architecture/concrete/observationsDomainObject/ObservationsDomainObject.ts +++ b/react-components/src/architecture/concrete/observationsDomainObject/ObservationsDomainObject.ts @@ -1,12 +1,15 @@ -import { Overlay3DCollection } from '@cognite/reveal'; -import { Observation } from './models'; +/*! + * Copyright 2024 Cognite AS + */ +import { type Overlay3DCollection } from '@cognite/reveal'; +import { type Observation } from './models'; import { VisualDomainObject } from '../../base/domainObjects/VisualDomainObject'; -import { ThreeView } from '../../base/views/ThreeView'; +import { type ThreeView } from '../../base/views/ThreeView'; import { ObservationsView } from './ObservationsView'; -import { TranslateKey } from '../../base/utilities/TranslateKey'; +import { type TranslateKey } from '../../base/utilities/TranslateKey'; export class ObservationsDomainObject extends VisualDomainObject { - private _collection: Overlay3DCollection; + private readonly _collection: Overlay3DCollection; public override get typeName(): TranslateKey { return { fallback: ObservationsDomainObject.name }; diff --git a/react-components/src/architecture/concrete/observationsDomainObject/ObservationsTool.ts b/react-components/src/architecture/concrete/observationsDomainObject/ObservationsTool.ts index d9412b78eee..46890898167 100644 --- a/react-components/src/architecture/concrete/observationsDomainObject/ObservationsTool.ts +++ b/react-components/src/architecture/concrete/observationsDomainObject/ObservationsTool.ts @@ -1,26 +1,29 @@ -import { IconType } from '@cognite/cogs.js'; -import { TranslateKey } from '../../base/utilities/TranslateKey'; -import { FdmSDK, InstanceFilter } from '../../../utilities/FdmSDK'; -import { OBSERVATION_SOURCE, Observation, ObservationProperties } from './models'; +/*! + * Copyright 2024 Cognite AS + */ +import { type IconType } from '@cognite/cogs.js'; +import { type TranslateKey } from '../../base/utilities/TranslateKey'; +import { type FdmSDK, type InstanceFilter } from '../../../utilities/FdmSDK'; +import { OBSERVATION_SOURCE, type Observation, type ObservationProperties } from './models'; import { ObservationsDomainObject } from './ObservationsDomainObject'; -import { Color, Vector2, Vector3 } from 'three'; -import { CDF_TO_VIEWER_TRANSFORMATION, Overlay3D, Overlay3DCollection } from '@cognite/reveal'; +import { Color, Vector3 } from 'three'; +import { CDF_TO_VIEWER_TRANSFORMATION, type Overlay3D, Overlay3DCollection } from '@cognite/reveal'; import { NavigationTool } from '../../base/concreteCommands/NavigationTool'; -import { RevealRenderTarget } from '../../base/renderTarget/RevealRenderTarget'; +import { type RevealRenderTarget } from '../../base/renderTarget/RevealRenderTarget'; const DEFAULT_OVERLAY_COLOR = new Color('lightblue'); const SELECTED_OVERLAY_COLOR = new Color('red'); export class ObservationsTool extends NavigationTool { // private _domainObjects: ObservationsDomainObject[] = []; - private _domainObjectPromise: Promise; + private readonly _domainObjectPromise: Promise; private _selectedOverlay: Overlay3D | undefined; constructor(fdmSdk: FdmSDK) { super(); - this._domainObjectPromise = fetchObservations(fdmSdk).then((observations) => - this.initializeDomainObjects(observations) + this._domainObjectPromise = fetchObservations(fdmSdk).then( + async (observations) => await this.initializeDomainObjects(observations) ); } @@ -40,8 +43,6 @@ export class ObservationsTool extends NavigationTool { }; }); - console.log('Observation overlays: ', observationOverlays); - const collection = new Overlay3DCollection(observationOverlays, { defaultOverlayColor: DEFAULT_OVERLAY_COLOR }); @@ -59,30 +60,28 @@ export class ObservationsTool extends NavigationTool { return { fallback: 'Show observations' }; } - public override attach(renderTarget: RevealRenderTarget) { + public override attach(renderTarget: RevealRenderTarget): void { super.attach(renderTarget); - this._domainObjectPromise.then((domainObject) => - renderTarget.rootDomainObject.addChildInteractive(domainObject) - ); + void this._domainObjectPromise.then((domainObject) => { + renderTarget.rootDomainObject.addChildInteractive(domainObject); + }); } - public override onActivate() { - this._domainObjectPromise.then((domainObject) => + public override onActivate(): void { + void this._domainObjectPromise.then((domainObject) => domainObject.setVisibleInteractive(true, this.renderTarget) ); } - public override onDeactivate() { - this._domainObjectPromise.then((domainObject) => { + public override onDeactivate(): void { + void this._domainObjectPromise.then((domainObject) => { domainObject.setVisibleInteractive(false, this.renderTarget); }); } - public override async onClick(event: PointerEvent) { + public override async onClick(event: PointerEvent): Promise { const domainObject = await this._domainObjectPromise; - domainObject.overlayCollection - .getOverlays() - .forEach((overlay) => overlay.setColor(DEFAULT_OVERLAY_COLOR)); + this._selectedOverlay?.setColor(DEFAULT_OVERLAY_COLOR); const normalizedCoord = this.getNormalizedPixelCoordinates(event); const intersection = domainObject.overlayCollection.intersectOverlays( @@ -92,10 +91,14 @@ export class ObservationsTool extends NavigationTool { if (intersection !== undefined) { this.handleIntersectedOverlay(intersection); + } else { + this._selectedOverlay = undefined; } + + this.renderTarget.viewer.requestRedraw(); } - private handleIntersectedOverlay(overlay: Overlay3D) { + private handleIntersectedOverlay(overlay: Overlay3D): void { overlay.setColor(SELECTED_OVERLAY_COLOR); this.renderTarget.viewer.requestRedraw(); this._selectedOverlay = overlay; diff --git a/react-components/src/architecture/concrete/observationsDomainObject/ObservationsView.ts b/react-components/src/architecture/concrete/observationsDomainObject/ObservationsView.ts index d60afdc8984..b36e5d7f2e7 100644 --- a/react-components/src/architecture/concrete/observationsDomainObject/ObservationsView.ts +++ b/react-components/src/architecture/concrete/observationsDomainObject/ObservationsView.ts @@ -1,11 +1,14 @@ +/*! + * Copyright 2024 Cognite AS + */ import { Box3 } from 'three'; -import { ObservationsDomainObject } from './ObservationsDomainObject'; +import { type ObservationsDomainObject } from './ObservationsDomainObject'; import { GroupThreeView } from '../../base/views/GroupThreeView'; -import { Overlay3DCollection } from '@cognite/reveal'; -import { Observation } from './models'; +import { type Overlay3DCollection } from '@cognite/reveal'; +import { type Observation } from './models'; export class ObservationsView extends GroupThreeView { - private _collection: Overlay3DCollection; + private readonly _collection: Overlay3DCollection; constructor(collection: Overlay3DCollection) { super(); diff --git a/react-components/src/architecture/concrete/observationsDomainObject/models.ts b/react-components/src/architecture/concrete/observationsDomainObject/models.ts index e910327bd59..f402f148667 100644 --- a/react-components/src/architecture/concrete/observationsDomainObject/models.ts +++ b/react-components/src/architecture/concrete/observationsDomainObject/models.ts @@ -1,4 +1,7 @@ -import { DmsUniqueIdentifier, FdmNode, Source } from '../../../utilities/FdmSDK'; +/*! + * Copyright 2024 Cognite AS + */ +import { type DmsUniqueIdentifier, type FdmNode, type Source } from '../../../utilities/FdmSDK'; export type ObservationProperties = { // "ID as the node appears in the Source system" @@ -12,13 +15,13 @@ export type ObservationProperties = { // "Text based labels for generic use" labels: string[]; // "Visibility of node (PUBLIC, PRIVATE, PROTECTED)" - visibility: String; + visibility: string; // "Who created this node?" - createdBy: String; + createdBy: string; // "Who was the last person to update this node?" - updatedBy: String; + updatedBy: string; // "Is this item archived, and therefore hidden from most UIs?" - isArchived: Boolean; + isArchived: boolean; // "The status of the observation (draft, completed, sent)" status: string; // "External ID of the associated CDF Asset" diff --git a/react-components/src/components/Architecture/RevealButtons.tsx b/react-components/src/components/Architecture/RevealButtons.tsx index 0860261fabb..a4a5b82b920 100644 --- a/react-components/src/components/Architecture/RevealButtons.tsx +++ b/react-components/src/components/Architecture/RevealButtons.tsx @@ -18,15 +18,19 @@ export class RevealButtons { static FitView = (): ReactElement => ( new FitViewCommand()} /> ); + static NavigationTool = (): ReactElement => ( new NavigationTool()} /> ); + static SetAxisVisible = (): ReactElement => ( new SetAxisVisibleCommand()} /> ); + static Measurement = (): ReactElement => ( new MeasurementTool()} /> ); + static Clip = (): ReactElement => ( new ClipTool()} /> ); diff --git a/react-components/src/components/RevealToolbar/HelpButton.tsx b/react-components/src/components/RevealToolbar/HelpButton.tsx index c4a2d579494..38f59d48b70 100644 --- a/react-components/src/components/RevealToolbar/HelpButton.tsx +++ b/react-components/src/components/RevealToolbar/HelpButton.tsx @@ -23,7 +23,9 @@ export const HelpButton = ({ fallbackLanguage }: HelpButtonProps): ReactElement setHelpActive(false)} + onHide={() => { + setHelpActive(false); + }} hideOnSelect={{ hideOnContentClick: true, hideOnOutsideClick: true }} /* onClickOutside={() => { setHelpActive(false); diff --git a/react-components/src/components/RuleBasedOutputs/types.ts b/react-components/src/components/RuleBasedOutputs/types.ts index fab522de7dd..a4fa20cbedc 100644 --- a/react-components/src/components/RuleBasedOutputs/types.ts +++ b/react-components/src/components/RuleBasedOutputs/types.ts @@ -3,9 +3,9 @@ */ import { type TreeIndexNodeCollection, type NumericRange } from '@cognite/reveal'; -import { type FdmNode, type EdgeItem, DmsUniqueIdentifier } from '../../utilities/FdmSDK'; +import { type FdmNode, type EdgeItem, type DmsUniqueIdentifier } from '../../utilities/FdmSDK'; import { type AssetStylingGroup, type FdmPropertyType } from '../Reveal3DResources/types'; -import { type Datapoints, type Asset, type Timeseries, type ExternalId } from '@cognite/sdk'; +import { type Datapoints, type Asset, type Timeseries } from '@cognite/sdk'; // =========== RULE BASED OUTPUT DATA MODEL From 683f598f657c7f6946d797245745121fba2b65c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A5kon=20Flatval?= Date: Fri, 21 Jun 2024 16:22:55 +0200 Subject: [PATCH 03/19] chore: Add shameful type cast to please compiler --- react-components/src/architecture/base/commands/BaseTool.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/react-components/src/architecture/base/commands/BaseTool.ts b/react-components/src/architecture/base/commands/BaseTool.ts index 5f7b5f3099f..f90cf9edf0a 100644 --- a/react-components/src/architecture/base/commands/BaseTool.ts +++ b/react-components/src/architecture/base/commands/BaseTool.ts @@ -150,7 +150,7 @@ export abstract class BaseTool extends RenderTargetCommand { if (!(customObject instanceof ThreeView)) { return false; } - return domainObjectPredicate(customObject.domainObject); + return domainObjectPredicate(customObject.domainObject as DomainObject); }; return await viewer.getAnyIntersectionFromPixel(point, { predicate }); } From fefd8376acdb366dd94642310ea10a071898aa79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A5kon=20Flatval?= Date: Mon, 24 Jun 2024 14:59:04 +0200 Subject: [PATCH 04/19] chore: use RevealButtons import in Toolbar story --- react-components/stories/Toolbar.stories.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/react-components/stories/Toolbar.stories.tsx b/react-components/stories/Toolbar.stories.tsx index 534c7b8d734..8fb4d023942 100644 --- a/react-components/stories/Toolbar.stories.tsx +++ b/react-components/stories/Toolbar.stories.tsx @@ -10,7 +10,8 @@ import { withSuppressRevealEvents, withCameraStateUrlParam, useGetCameraStateFromUrlParam, - useCameraNavigation + useCameraNavigation, + RevealButtons } from '../src'; import { Color } from 'three'; import styled from 'styled-components'; @@ -20,7 +21,6 @@ import { signalStoryReadyForScreenshot } from './utilities/signalStoryReadyForSc import { RevealStoryContainer } from './utilities/RevealStoryContainer'; import { getAddModelOptionsFromUrl } from './utilities/getAddModelOptionsFromUrl'; import { SetOrbitOrFirstPersonControlsType } from '../src/components/RevealToolbar/SetFlexibleControlsType'; -import { ObservationsButton } from '../src/components/Observations/ObservationsButton'; const meta = { title: 'Example/Toolbar', @@ -110,7 +110,7 @@ export const Main: Story = { - + ) From bd8e9354899cc55426d80885f5ca26e5fab2efb9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A5kon=20Flatval?= Date: Mon, 24 Jun 2024 15:00:58 +0200 Subject: [PATCH 05/19] chore: revert irrelevant change --- .../src/components/RevealToolbar/HelpButton.tsx | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/react-components/src/components/RevealToolbar/HelpButton.tsx b/react-components/src/components/RevealToolbar/HelpButton.tsx index 38f59d48b70..ff5b812893f 100644 --- a/react-components/src/components/RevealToolbar/HelpButton.tsx +++ b/react-components/src/components/RevealToolbar/HelpButton.tsx @@ -23,13 +23,9 @@ export const HelpButton = ({ fallbackLanguage }: HelpButtonProps): ReactElement { + onClickOutside={() => { setHelpActive(false); }} - hideOnSelect={{ hideOnContentClick: true, hideOnOutsideClick: true }} - /* onClickOutside={() => { - setHelpActive(false); - }} */ content={ From 77c21444e1585349f6d266a414b3b4f06c190ae9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A5kon=20Flatval?= Date: Mon, 24 Jun 2024 15:36:09 +0200 Subject: [PATCH 06/19] chore: remove some "as"-es As promised --- .../architecture/concrete/exampleDomainObject/ExampleView.ts | 4 ++-- .../src/architecture/concrete/primitives/box/BoxView.ts | 4 ++-- .../src/architecture/concrete/primitives/line/LineView.ts | 4 ++-- .../src/architecture/concrete/primitives/plane/PlaneView.ts | 4 ++-- .../concrete/terrainDomainObject/TerrainThreeView.ts | 4 ++-- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/react-components/src/architecture/concrete/exampleDomainObject/ExampleView.ts b/react-components/src/architecture/concrete/exampleDomainObject/ExampleView.ts index 8df8fd2e8f1..d12e77addc9 100644 --- a/react-components/src/architecture/concrete/exampleDomainObject/ExampleView.ts +++ b/react-components/src/architecture/concrete/exampleDomainObject/ExampleView.ts @@ -16,13 +16,13 @@ import { import { type DomainObjectIntersection } from '../../base/domainObjectsHelpers/DomainObjectIntersection'; import { WHITE_COLOR } from '../../base/utilities/colors/colorExtensions'; -export class ExampleView extends GroupThreeView { +export class ExampleView extends GroupThreeView { // ================================================== // INSTANCE PROPERTIES // ================================================== public override get domainObject(): ExampleDomainObject { - return super.domainObject as ExampleDomainObject; + return super.domainObject; } protected override get style(): ExampleRenderStyle { diff --git a/react-components/src/architecture/concrete/primitives/box/BoxView.ts b/react-components/src/architecture/concrete/primitives/box/BoxView.ts index ca4dc586a8d..565684a9ccf 100644 --- a/react-components/src/architecture/concrete/primitives/box/BoxView.ts +++ b/react-components/src/architecture/concrete/primitives/box/BoxView.ts @@ -55,7 +55,7 @@ const TOP_FACE = new BoxFace(2); const CIRCULAR_SEGMENTS = 32; const RENDER_ORDER = 100; -export class BoxView extends GroupThreeView { +export class BoxView extends GroupThreeView { // ================================================== // INSTANCE FIELDS // ================================================== @@ -68,7 +68,7 @@ export class BoxView extends GroupThreeView { // ================================================== public override get domainObject(): BoxDomainObject { - return super.domainObject as BoxDomainObject; + return super.domainObject; } protected override get style(): BoxRenderStyle { diff --git a/react-components/src/architecture/concrete/primitives/line/LineView.ts b/react-components/src/architecture/concrete/primitives/line/LineView.ts index 6b198f5b571..569b28a2559 100644 --- a/react-components/src/architecture/concrete/primitives/line/LineView.ts +++ b/react-components/src/architecture/concrete/primitives/line/LineView.ts @@ -41,13 +41,13 @@ import { BoxView } from '../box/BoxView'; const CYLINDER_DEFAULT_AXIS = new Vector3(0, 1, 0); const RENDER_ORDER = 100; -export class LineView extends GroupThreeView { +export class LineView extends GroupThreeView { // ================================================== // INSTANCE PROPERTIES // ================================================== public override get domainObject(): LineDomainObject { - return super.domainObject as LineDomainObject; + return super.domainObject; } protected override get style(): LineRenderStyle { diff --git a/react-components/src/architecture/concrete/primitives/plane/PlaneView.ts b/react-components/src/architecture/concrete/primitives/plane/PlaneView.ts index 020a95ab9c6..d51ded18a1b 100644 --- a/react-components/src/architecture/concrete/primitives/plane/PlaneView.ts +++ b/react-components/src/architecture/concrete/primitives/plane/PlaneView.ts @@ -32,7 +32,7 @@ import { FocusType } from '../../../base/domainObjectsHelpers/FocusType'; import { type DomainObjectIntersection } from '../../../base/domainObjectsHelpers/DomainObjectIntersection'; import { PrimitiveType } from '../PrimitiveType'; -export class PlaneView extends GroupThreeView { +export class PlaneView extends GroupThreeView { // ================================================== // INSTANCE FIELDS // ================================================== @@ -45,7 +45,7 @@ export class PlaneView extends GroupThreeView { // ================================================== public override get domainObject(): PlaneDomainObject { - return super.domainObject as PlaneDomainObject; + return super.domainObject; } protected override get style(): PlaneRenderStyle { diff --git a/react-components/src/architecture/concrete/terrainDomainObject/TerrainThreeView.ts b/react-components/src/architecture/concrete/terrainDomainObject/TerrainThreeView.ts index 04d0cf777c8..d54129e7da5 100644 --- a/react-components/src/architecture/concrete/terrainDomainObject/TerrainThreeView.ts +++ b/react-components/src/architecture/concrete/terrainDomainObject/TerrainThreeView.ts @@ -35,13 +35,13 @@ import { type RegularGrid2 } from './geometry/RegularGrid2'; const SOLID_NAME = 'Solid'; const CONTOURS_NAME = 'Contour'; -export class TerrainThreeView extends GroupThreeView { +export class TerrainThreeView extends GroupThreeView { // ================================================== // INSTANCE PROPERTIES // ================================================== public override get domainObject(): TerrainDomainObject { - return super.domainObject as TerrainDomainObject; + return super.domainObject; } protected override get style(): TerrainRenderStyle { From e6ec4ff1545f1ac0a792bf2de0dd65b7b7d676f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A5kon=20Flatval?= Date: Tue, 25 Jun 2024 10:21:20 +0200 Subject: [PATCH 07/19] chore: refactor a bit to conform better to architecture --- .../architecture/base/commands/BaseTool.ts | 3 +- .../base/renderTarget/RevealRenderTarget.ts | 16 ++- .../ObservationsDomainObject.ts | 54 +++++++- .../ObservationsTool.ts | 116 ++++++------------ .../ObservationsView.ts | 60 +++++++-- .../RevealContext/RevealContext.tsx | 4 +- .../utilities/RevealStoryContainer.tsx | 5 +- 7 files changed, 157 insertions(+), 101 deletions(-) diff --git a/react-components/src/architecture/base/commands/BaseTool.ts b/react-components/src/architecture/base/commands/BaseTool.ts index f90cf9edf0a..4e4679f74aa 100644 --- a/react-components/src/architecture/base/commands/BaseTool.ts +++ b/react-components/src/architecture/base/commands/BaseTool.ts @@ -133,8 +133,7 @@ export abstract class BaseTool extends RenderTargetCommand { event: PointerEvent | WheelEvent, domainObjectPredicate?: (domainObject: DomainObject) => boolean ): Promise { - const { renderTarget } = this; - const { viewer } = renderTarget; + const viewer = this.renderTarget.viewer; const point = viewer.getPixelCoordinatesFromEvent(event); diff --git a/react-components/src/architecture/base/renderTarget/RevealRenderTarget.ts b/react-components/src/architecture/base/renderTarget/RevealRenderTarget.ts index eafa130b3f6..175034dc855 100644 --- a/react-components/src/architecture/base/renderTarget/RevealRenderTarget.ts +++ b/react-components/src/architecture/base/renderTarget/RevealRenderTarget.ts @@ -30,6 +30,8 @@ import { CommandsUpdater } from '../reactUpdaters/CommandsUpdater'; import { Range3 } from '../utilities/geometry/Range3'; import { getBoundingBoxFromPlanes } from '../utilities/geometry/getBoundingBoxFromPlanes'; import { Changes } from '../domainObjectsHelpers/Changes'; +import { CogniteClient } from '@cognite/sdk/dist/src'; +import { FdmSDK } from '../../../utilities/FdmSDK'; const DIRECTIONAL_LIGHT_NAME = 'DirectionalLight'; @@ -39,6 +41,8 @@ export class RevealRenderTarget { // ================================================== private readonly _viewer: Cognite3DViewer; + private readonly _sdk: CogniteClient; + private readonly _fdmSdk: FdmSDK; private readonly _commandsController: CommandsController; private readonly _rootDomainObject: RootDomainObject; private _ambientLight: AmbientLight | undefined; @@ -52,8 +56,10 @@ export class RevealRenderTarget { // CONSTRUCTOR // ================================================== - constructor(viewer: Cognite3DViewer) { + constructor(viewer: Cognite3DViewer, sdk: CogniteClient) { this._viewer = viewer; + this._sdk = sdk; + this._fdmSdk = new FdmSDK(sdk); const cameraManager = this.cameraManager; if (!isFlexibleCameraManager(cameraManager)) { @@ -77,6 +83,14 @@ export class RevealRenderTarget { return this._viewer; } + public get sdk(): CogniteClient { + return this._sdk; + } + + public get fdmSdk(): FdmSDK { + return this._fdmSdk; + } + public get config(): BaseRevealConfig | undefined { return this._config; } diff --git a/react-components/src/architecture/concrete/observationsDomainObject/ObservationsDomainObject.ts b/react-components/src/architecture/concrete/observationsDomainObject/ObservationsDomainObject.ts index 85ec7f888a3..2fc2aae94a2 100644 --- a/react-components/src/architecture/concrete/observationsDomainObject/ObservationsDomainObject.ts +++ b/react-components/src/architecture/concrete/observationsDomainObject/ObservationsDomainObject.ts @@ -1,23 +1,53 @@ /*! * Copyright 2024 Cognite AS */ -import { type Overlay3DCollection } from '@cognite/reveal'; -import { type Observation } from './models'; +import { CDF_TO_VIEWER_TRANSFORMATION, Overlay3DCollection } from '@cognite/reveal'; +import { OBSERVATION_SOURCE, ObservationProperties, type Observation } from './models'; import { VisualDomainObject } from '../../base/domainObjects/VisualDomainObject'; import { type ThreeView } from '../../base/views/ThreeView'; import { ObservationsView } from './ObservationsView'; import { type TranslateKey } from '../../base/utilities/TranslateKey'; +import { FdmSDK, InstanceFilter } from '../../../utilities/FdmSDK'; +import { Vector3 } from 'three'; +import { DEFAULT_OVERLAY_COLOR } from './constants'; +import { Changes } from '../../base/domainObjectsHelpers/Changes'; export class ObservationsDomainObject extends VisualDomainObject { - private readonly _collection: Overlay3DCollection; + private readonly _collection: Overlay3DCollection = new Overlay3DCollection( + undefined, + { + defaultOverlayColor: DEFAULT_OVERLAY_COLOR + } + ); public override get typeName(): TranslateKey { return { fallback: ObservationsDomainObject.name }; } - constructor(collection: Overlay3DCollection) { + constructor(fdmSdk: FdmSDK) { super(); - this._collection = collection; + fetchObservations(fdmSdk).then((observations) => { + this.initializeCollection(observations); + this.notify(Changes.geometry); + }); + } + + private initializeCollection(observations: Observation[]): void { + const observationOverlays = observations.map((observation) => { + const position = new Vector3( + observation.properties.positionX, + observation.properties.positionY, + observation.properties.positionZ + ).applyMatrix4(CDF_TO_VIEWER_TRANSFORMATION); + + return { + position, + content: observation + }; + }); + + console.log('Observations: ', observationOverlays); + this._collection.addOverlays(observationOverlays); } public get overlayCollection(): Overlay3DCollection { @@ -25,6 +55,18 @@ export class ObservationsDomainObject extends VisualDomainObject { } protected override createThreeView(): ThreeView | undefined { - return new ObservationsView(this._collection); + return new ObservationsView(); } } + +const observationsFilter: InstanceFilter = {}; + +async function fetchObservations(fdmSdk: FdmSDK): Promise { + const observationResult = await fdmSdk.filterAllInstances( + observationsFilter, + 'node', + OBSERVATION_SOURCE + ); + + return observationResult.instances; +} diff --git a/react-components/src/architecture/concrete/observationsDomainObject/ObservationsTool.ts b/react-components/src/architecture/concrete/observationsDomainObject/ObservationsTool.ts index 46890898167..34472580d65 100644 --- a/react-components/src/architecture/concrete/observationsDomainObject/ObservationsTool.ts +++ b/react-components/src/architecture/concrete/observationsDomainObject/ObservationsTool.ts @@ -3,53 +3,19 @@ */ import { type IconType } from '@cognite/cogs.js'; import { type TranslateKey } from '../../base/utilities/TranslateKey'; -import { type FdmSDK, type InstanceFilter } from '../../../utilities/FdmSDK'; -import { OBSERVATION_SOURCE, type Observation, type ObservationProperties } from './models'; +import { type Observation } from './models'; import { ObservationsDomainObject } from './ObservationsDomainObject'; -import { Color, Vector3 } from 'three'; -import { CDF_TO_VIEWER_TRANSFORMATION, type Overlay3D, Overlay3DCollection } from '@cognite/reveal'; -import { NavigationTool } from '../../base/concreteCommands/NavigationTool'; -import { type RevealRenderTarget } from '../../base/renderTarget/RevealRenderTarget'; - -const DEFAULT_OVERLAY_COLOR = new Color('lightblue'); -const SELECTED_OVERLAY_COLOR = new Color('red'); - -export class ObservationsTool extends NavigationTool { - // private _domainObjects: ObservationsDomainObject[] = []; - private readonly _domainObjectPromise: Promise; +import { type Overlay3D } from '@cognite/reveal'; +import { DEFAULT_OVERLAY_COLOR, SELECTED_OVERLAY_COLOR } from './constants'; +import { BaseEditTool } from '../../base/commands/BaseEditTool'; +import { VisualDomainObject } from '../../base/domainObjects/VisualDomainObject'; +export class ObservationsTool extends BaseEditTool { private _selectedOverlay: Overlay3D | undefined; + private _observationsDomainObject: ObservationsDomainObject | undefined; - constructor(fdmSdk: FdmSDK) { + constructor() { super(); - this._domainObjectPromise = fetchObservations(fdmSdk).then( - async (observations) => await this.initializeDomainObjects(observations) - ); - } - - private async initializeDomainObjects( - observations: Observation[] - ): Promise { - const observationOverlays = observations.map((observation) => { - const position = new Vector3( - observation.properties.positionX, - observation.properties.positionY, - observation.properties.positionZ - ).applyMatrix4(CDF_TO_VIEWER_TRANSFORMATION); - - return { - position, - content: observation - }; - }); - - const collection = new Overlay3DCollection(observationOverlays, { - defaultOverlayColor: DEFAULT_OVERLAY_COLOR - }); - - const observationDomainObject = new ObservationsDomainObject(collection); - - return observationDomainObject; } public override get icon(): IconType { @@ -60,59 +26,55 @@ export class ObservationsTool extends NavigationTool { return { fallback: 'Show observations' }; } - public override attach(renderTarget: RevealRenderTarget): void { - super.attach(renderTarget); - void this._domainObjectPromise.then((domainObject) => { - renderTarget.rootDomainObject.addChildInteractive(domainObject); - }); - } - public override onActivate(): void { - void this._domainObjectPromise.then((domainObject) => - domainObject.setVisibleInteractive(true, this.renderTarget) - ); + if (this._observationsDomainObject === undefined) { + this._observationsDomainObject = new ObservationsDomainObject(this.renderTarget.fdmSdk); + this.renderTarget.rootDomainObject.addChild(this._observationsDomainObject); + } + this._observationsDomainObject.setVisibleInteractive(true, this.renderTarget); } public override onDeactivate(): void { - void this._domainObjectPromise.then((domainObject) => { - domainObject.setVisibleInteractive(false, this.renderTarget); - }); + this._observationsDomainObject?.setVisibleInteractive(false, this.renderTarget); } public override async onClick(event: PointerEvent): Promise { - const domainObject = await this._domainObjectPromise; - this._selectedOverlay?.setColor(DEFAULT_OVERLAY_COLOR); + const intersection = await this.getIntersection(event); + if (intersection === undefined) { + await super.onClick(event); + return; + } + + const domainObject = this.getIntersectedSelectableDomainObject(intersection); + if (!(domainObject instanceof ObservationsDomainObject)) { + return; + } - const normalizedCoord = this.getNormalizedPixelCoordinates(event); - const intersection = domainObject.overlayCollection.intersectOverlays( - normalizedCoord, + const normalizedCoords = this.getNormalizedPixelCoordinates(event); + + const intersectedIcon = domainObject.overlayCollection.intersectOverlays( + normalizedCoords, this.renderTarget.camera ); - if (intersection !== undefined) { - this.handleIntersectedOverlay(intersection); - } else { - this._selectedOverlay = undefined; - } + this.handleIntersectedOverlay(intersectedIcon); this.renderTarget.viewer.requestRedraw(); } - private handleIntersectedOverlay(overlay: Overlay3D): void { + private handleIntersectedOverlay(overlay: Overlay3D | undefined): void { + this._selectedOverlay?.setColor(DEFAULT_OVERLAY_COLOR); + this._selectedOverlay = undefined; + + if (overlay === undefined) { + return; + } overlay.setColor(SELECTED_OVERLAY_COLOR); this.renderTarget.viewer.requestRedraw(); this._selectedOverlay = overlay; } -} -const observationsFilter: InstanceFilter = {}; - -async function fetchObservations(fdmSdk: FdmSDK): Promise { - const observationResult = await fdmSdk.filterAllInstances( - observationsFilter, - 'node', - OBSERVATION_SOURCE - ); - - return observationResult.instances; + protected override canBeSelected(domainObject: VisualDomainObject): boolean { + return domainObject instanceof ObservationsDomainObject; + } } diff --git a/react-components/src/architecture/concrete/observationsDomainObject/ObservationsView.ts b/react-components/src/architecture/concrete/observationsDomainObject/ObservationsView.ts index b36e5d7f2e7..18476c586fc 100644 --- a/react-components/src/architecture/concrete/observationsDomainObject/ObservationsView.ts +++ b/react-components/src/architecture/concrete/observationsDomainObject/ObservationsView.ts @@ -4,24 +4,62 @@ import { Box3 } from 'three'; import { type ObservationsDomainObject } from './ObservationsDomainObject'; import { GroupThreeView } from '../../base/views/GroupThreeView'; -import { type Overlay3DCollection } from '@cognite/reveal'; -import { type Observation } from './models'; +import { DomainObject } from '../../base/domainObjects/DomainObject'; +import { + AnyIntersection, + CustomObjectIntersectInput, + CustomObjectIntersection, + ICustomObject +} from '@cognite/reveal'; +import { ThreeView } from '../../base/views/ThreeView'; +import { DomainObjectIntersection } from '../../base/domainObjectsHelpers/DomainObjectIntersection'; export class ObservationsView extends GroupThreeView { - private readonly _collection: Overlay3DCollection; - - constructor(collection: Overlay3DCollection) { - super(); - this._collection = collection; - } - protected override calculateBoundingBox(): Box3 { - return this._collection + return this.domainObject.overlayCollection .getOverlays() .reduce((box, overlay) => box.expandByPoint(overlay.getPosition()), new Box3()); } protected override addChildren(): void { - this.addChild(this._collection); + this.addChild(this.domainObject.overlayCollection); + } + + public override intersectIfCloser( + intersectInput: CustomObjectIntersectInput, + closestDistance: number | undefined + ): undefined | CustomObjectIntersection { + const { domainObject } = this; + + const intersection = this.domainObject.overlayCollection.intersectOverlays( + intersectInput.normalizedCoords, + intersectInput.camera + ); + + if (intersection === undefined) { + return undefined; + } + + const point = intersection.getPosition(); + + const distanceToCamera = point.distanceTo(intersectInput.raycaster.ray.origin); + if (closestDistance !== undefined && closestDistance < distanceToCamera) { + return undefined; + } + if (domainObject.useClippingInIntersection && !intersectInput.isVisible(point)) { + return undefined; + } + const customObjectIntersection: DomainObjectIntersection = { + type: 'customObject', + point, + distanceToCamera, + customObject: this, + domainObject + }; + + if (this.shouldPickBoundingBox) { + customObjectIntersection.boundingBox = this.boundingBox; + } + return customObjectIntersection; } } diff --git a/react-components/src/components/RevealContext/RevealContext.tsx b/react-components/src/components/RevealContext/RevealContext.tsx index c76929d5bb5..744842c25f9 100644 --- a/react-components/src/components/RevealContext/RevealContext.tsx +++ b/react-components/src/components/RevealContext/RevealContext.tsx @@ -11,7 +11,7 @@ import { NodeCacheProvider } from '../CacheProvider/NodeCacheProvider'; import { AssetMappingCacheProvider } from '../CacheProvider/AssetMappingCacheProvider'; import { PointCloudAnnotationCacheProvider } from '../CacheProvider/PointCloudAnnotationCacheProvider'; import { Reveal3DResourcesCountContextProvider } from '../Reveal3DResources/Reveal3DResourcesCountContext'; -import { SDKProvider } from '../RevealCanvas/SDKProvider'; +import { SDKProvider, useFdmSdk } from '../RevealCanvas/SDKProvider'; import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; import { useRevealKeepAlive } from '../RevealKeepAlive/RevealKeepAliveContext'; import { Image360AnnotationCacheProvider } from '../CacheProvider/Image360AnnotationCacheProvider'; @@ -106,7 +106,7 @@ const useRevealFromKeepAlive = ({ useFlexibleCameraManager: true, hasEventListeners: false }); - renderTarget = new RevealRenderTarget(viewer); + renderTarget = new RevealRenderTarget(viewer, sdk); if (revealKeepAliveData !== undefined) { revealKeepAliveData.renderTargetRef.current = renderTarget; } diff --git a/react-components/stories/utilities/RevealStoryContainer.tsx b/react-components/stories/utilities/RevealStoryContainer.tsx index d232733b117..a77d4ee7a4b 100644 --- a/react-components/stories/utilities/RevealStoryContainer.tsx +++ b/react-components/stories/utilities/RevealStoryContainer.tsx @@ -18,6 +18,7 @@ import { type Image360AnnotationCache } from '../../src/components/CacheProvider import { type SceneIdentifiers } from '../../src/components/SceneContainer/sceneTypes'; import { RevealRenderTarget } from '../../src/architecture/base/renderTarget/RevealRenderTarget'; import { StoryBookConfig } from '../../src/architecture/concrete/config/StoryBookConfig'; +import { useFdmSdk } from '../../src/components/RevealCanvas/SDKProvider'; type RevealStoryContainerProps = Omit & { sdk?: CogniteClient; @@ -41,7 +42,7 @@ export const RevealStoryContext = ({ const renderTarget = useMemo(() => { if (viewer !== undefined) { - return new RevealRenderTarget(viewer); + return new RevealRenderTarget(viewer, sdkInstance); } else if (isLocal) { const newViewer = new Cognite3DViewer({ ...rest.viewerOptions, @@ -51,7 +52,7 @@ export const RevealStoryContext = ({ hasEventListeners: false, useFlexibleCameraManager: true }); - const renderTarget = new RevealRenderTarget(newViewer); + const renderTarget = new RevealRenderTarget(newViewer, sdkInstance); renderTarget.setConfig(new StoryBookConfig()); return renderTarget; } From 33c019f48afbb2183a814e9de70dad93354ef05f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A5kon=20Flatval?= Date: Tue, 25 Jun 2024 10:21:45 +0200 Subject: [PATCH 08/19] chore: add missing file --- .../concrete/observationsDomainObject/constants.ts | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 react-components/src/architecture/concrete/observationsDomainObject/constants.ts diff --git a/react-components/src/architecture/concrete/observationsDomainObject/constants.ts b/react-components/src/architecture/concrete/observationsDomainObject/constants.ts new file mode 100644 index 00000000000..471e98cede9 --- /dev/null +++ b/react-components/src/architecture/concrete/observationsDomainObject/constants.ts @@ -0,0 +1,4 @@ +import { Color } from 'three'; + +export const DEFAULT_OVERLAY_COLOR = new Color('lightblue'); +export const SELECTED_OVERLAY_COLOR = new Color('red'); From 3d8d673efa96e97486ee1dd29f56e5b003fca9d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A5kon=20Flatval?= Date: Tue, 25 Jun 2024 10:48:34 +0200 Subject: [PATCH 09/19] chore: lint fix --- .../base/renderTarget/RevealRenderTarget.ts | 2 +- .../ObservationsDomainObject.ts | 16 ++++++---------- .../observationsDomainObject/ObservationsTool.ts | 14 +++++--------- .../observationsDomainObject/ObservationsView.ts | 13 ++++--------- .../observationsDomainObject/constants.ts | 3 +++ .../components/RevealContext/RevealContext.tsx | 2 +- .../stories/utilities/RevealStoryContainer.tsx | 1 - 7 files changed, 20 insertions(+), 31 deletions(-) diff --git a/react-components/src/architecture/base/renderTarget/RevealRenderTarget.ts b/react-components/src/architecture/base/renderTarget/RevealRenderTarget.ts index 175034dc855..55a1e3a9561 100644 --- a/react-components/src/architecture/base/renderTarget/RevealRenderTarget.ts +++ b/react-components/src/architecture/base/renderTarget/RevealRenderTarget.ts @@ -30,7 +30,7 @@ import { CommandsUpdater } from '../reactUpdaters/CommandsUpdater'; import { Range3 } from '../utilities/geometry/Range3'; import { getBoundingBoxFromPlanes } from '../utilities/geometry/getBoundingBoxFromPlanes'; import { Changes } from '../domainObjectsHelpers/Changes'; -import { CogniteClient } from '@cognite/sdk/dist/src'; +import { type CogniteClient } from '@cognite/sdk/dist/src'; import { FdmSDK } from '../../../utilities/FdmSDK'; const DIRECTIONAL_LIGHT_NAME = 'DirectionalLight'; diff --git a/react-components/src/architecture/concrete/observationsDomainObject/ObservationsDomainObject.ts b/react-components/src/architecture/concrete/observationsDomainObject/ObservationsDomainObject.ts index 2fc2aae94a2..8218c2d2c59 100644 --- a/react-components/src/architecture/concrete/observationsDomainObject/ObservationsDomainObject.ts +++ b/react-components/src/architecture/concrete/observationsDomainObject/ObservationsDomainObject.ts @@ -2,23 +2,20 @@ * Copyright 2024 Cognite AS */ import { CDF_TO_VIEWER_TRANSFORMATION, Overlay3DCollection } from '@cognite/reveal'; -import { OBSERVATION_SOURCE, ObservationProperties, type Observation } from './models'; +import { OBSERVATION_SOURCE, type ObservationProperties, type Observation } from './models'; import { VisualDomainObject } from '../../base/domainObjects/VisualDomainObject'; import { type ThreeView } from '../../base/views/ThreeView'; import { ObservationsView } from './ObservationsView'; import { type TranslateKey } from '../../base/utilities/TranslateKey'; -import { FdmSDK, InstanceFilter } from '../../../utilities/FdmSDK'; +import { type FdmSDK, type InstanceFilter } from '../../../utilities/FdmSDK'; import { Vector3 } from 'three'; import { DEFAULT_OVERLAY_COLOR } from './constants'; import { Changes } from '../../base/domainObjectsHelpers/Changes'; export class ObservationsDomainObject extends VisualDomainObject { - private readonly _collection: Overlay3DCollection = new Overlay3DCollection( - undefined, - { - defaultOverlayColor: DEFAULT_OVERLAY_COLOR - } - ); + private readonly _collection = new Overlay3DCollection(undefined, { + defaultOverlayColor: DEFAULT_OVERLAY_COLOR + }); public override get typeName(): TranslateKey { return { fallback: ObservationsDomainObject.name }; @@ -26,7 +23,7 @@ export class ObservationsDomainObject extends VisualDomainObject { constructor(fdmSdk: FdmSDK) { super(); - fetchObservations(fdmSdk).then((observations) => { + void fetchObservations(fdmSdk).then((observations) => { this.initializeCollection(observations); this.notify(Changes.geometry); }); @@ -46,7 +43,6 @@ export class ObservationsDomainObject extends VisualDomainObject { }; }); - console.log('Observations: ', observationOverlays); this._collection.addOverlays(observationOverlays); } diff --git a/react-components/src/architecture/concrete/observationsDomainObject/ObservationsTool.ts b/react-components/src/architecture/concrete/observationsDomainObject/ObservationsTool.ts index 34472580d65..18c2d3d7001 100644 --- a/react-components/src/architecture/concrete/observationsDomainObject/ObservationsTool.ts +++ b/react-components/src/architecture/concrete/observationsDomainObject/ObservationsTool.ts @@ -8,16 +8,12 @@ import { ObservationsDomainObject } from './ObservationsDomainObject'; import { type Overlay3D } from '@cognite/reveal'; import { DEFAULT_OVERLAY_COLOR, SELECTED_OVERLAY_COLOR } from './constants'; import { BaseEditTool } from '../../base/commands/BaseEditTool'; -import { VisualDomainObject } from '../../base/domainObjects/VisualDomainObject'; +import { type VisualDomainObject } from '../../base/domainObjects/VisualDomainObject'; export class ObservationsTool extends BaseEditTool { private _selectedOverlay: Overlay3D | undefined; private _observationsDomainObject: ObservationsDomainObject | undefined; - constructor() { - super(); - } - public override get icon(): IconType { return 'Location'; } @@ -62,6 +58,10 @@ export class ObservationsTool extends BaseEditTool { this.renderTarget.viewer.requestRedraw(); } + protected override canBeSelected(domainObject: VisualDomainObject): boolean { + return domainObject instanceof ObservationsDomainObject; + } + private handleIntersectedOverlay(overlay: Overlay3D | undefined): void { this._selectedOverlay?.setColor(DEFAULT_OVERLAY_COLOR); this._selectedOverlay = undefined; @@ -73,8 +73,4 @@ export class ObservationsTool extends BaseEditTool { this.renderTarget.viewer.requestRedraw(); this._selectedOverlay = overlay; } - - protected override canBeSelected(domainObject: VisualDomainObject): boolean { - return domainObject instanceof ObservationsDomainObject; - } } diff --git a/react-components/src/architecture/concrete/observationsDomainObject/ObservationsView.ts b/react-components/src/architecture/concrete/observationsDomainObject/ObservationsView.ts index 18476c586fc..3eaec67c248 100644 --- a/react-components/src/architecture/concrete/observationsDomainObject/ObservationsView.ts +++ b/react-components/src/architecture/concrete/observationsDomainObject/ObservationsView.ts @@ -4,15 +4,8 @@ import { Box3 } from 'three'; import { type ObservationsDomainObject } from './ObservationsDomainObject'; import { GroupThreeView } from '../../base/views/GroupThreeView'; -import { DomainObject } from '../../base/domainObjects/DomainObject'; -import { - AnyIntersection, - CustomObjectIntersectInput, - CustomObjectIntersection, - ICustomObject -} from '@cognite/reveal'; -import { ThreeView } from '../../base/views/ThreeView'; -import { DomainObjectIntersection } from '../../base/domainObjectsHelpers/DomainObjectIntersection'; +import { type CustomObjectIntersectInput, type CustomObjectIntersection } from '@cognite/reveal'; +import { type DomainObjectIntersection } from '../../base/domainObjectsHelpers/DomainObjectIntersection'; export class ObservationsView extends GroupThreeView { protected override calculateBoundingBox(): Box3 { @@ -46,9 +39,11 @@ export class ObservationsView extends GroupThreeView { if (closestDistance !== undefined && closestDistance < distanceToCamera) { return undefined; } + if (domainObject.useClippingInIntersection && !intersectInput.isVisible(point)) { return undefined; } + const customObjectIntersection: DomainObjectIntersection = { type: 'customObject', point, diff --git a/react-components/src/architecture/concrete/observationsDomainObject/constants.ts b/react-components/src/architecture/concrete/observationsDomainObject/constants.ts index 471e98cede9..bab3e2c3073 100644 --- a/react-components/src/architecture/concrete/observationsDomainObject/constants.ts +++ b/react-components/src/architecture/concrete/observationsDomainObject/constants.ts @@ -1,3 +1,6 @@ +/*! + * Copyright 2024 Cognite AS + */ import { Color } from 'three'; export const DEFAULT_OVERLAY_COLOR = new Color('lightblue'); diff --git a/react-components/src/components/RevealContext/RevealContext.tsx b/react-components/src/components/RevealContext/RevealContext.tsx index 744842c25f9..d36be8d6b99 100644 --- a/react-components/src/components/RevealContext/RevealContext.tsx +++ b/react-components/src/components/RevealContext/RevealContext.tsx @@ -11,7 +11,7 @@ import { NodeCacheProvider } from '../CacheProvider/NodeCacheProvider'; import { AssetMappingCacheProvider } from '../CacheProvider/AssetMappingCacheProvider'; import { PointCloudAnnotationCacheProvider } from '../CacheProvider/PointCloudAnnotationCacheProvider'; import { Reveal3DResourcesCountContextProvider } from '../Reveal3DResources/Reveal3DResourcesCountContext'; -import { SDKProvider, useFdmSdk } from '../RevealCanvas/SDKProvider'; +import { SDKProvider } from '../RevealCanvas/SDKProvider'; import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; import { useRevealKeepAlive } from '../RevealKeepAlive/RevealKeepAliveContext'; import { Image360AnnotationCacheProvider } from '../CacheProvider/Image360AnnotationCacheProvider'; diff --git a/react-components/stories/utilities/RevealStoryContainer.tsx b/react-components/stories/utilities/RevealStoryContainer.tsx index a77d4ee7a4b..acd1870e9d5 100644 --- a/react-components/stories/utilities/RevealStoryContainer.tsx +++ b/react-components/stories/utilities/RevealStoryContainer.tsx @@ -18,7 +18,6 @@ import { type Image360AnnotationCache } from '../../src/components/CacheProvider import { type SceneIdentifiers } from '../../src/components/SceneContainer/sceneTypes'; import { RevealRenderTarget } from '../../src/architecture/base/renderTarget/RevealRenderTarget'; import { StoryBookConfig } from '../../src/architecture/concrete/config/StoryBookConfig'; -import { useFdmSdk } from '../../src/components/RevealCanvas/SDKProvider'; type RevealStoryContainerProps = Omit & { sdk?: CogniteClient; From 317fb4987d8687869a27885a086a346773feb00b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A5kon=20Flatval?= Date: Tue, 25 Jun 2024 10:59:46 +0200 Subject: [PATCH 10/19] chore: refactor/"simplify" RevealButtons --- .../components/Architecture/CommandButton.tsx | 9 +-- .../components/Architecture/RevealButtons.tsx | 63 ++++++++----------- 2 files changed, 26 insertions(+), 46 deletions(-) diff --git a/react-components/src/components/Architecture/CommandButton.tsx b/react-components/src/components/Architecture/CommandButton.tsx index 508a58fb64e..f15350f7a04 100644 --- a/react-components/src/components/Architecture/CommandButton.tsx +++ b/react-components/src/components/Architecture/CommandButton.tsx @@ -32,14 +32,7 @@ export const CommandButtons = ({ ); }; -export const CommandButtonFromCommand = ({ - commandConstructor, - isHorizontal = false -}: { - commandConstructor: () => BaseCommand; - isHorizontal?: boolean; -}): ReactElement => { - const command = useMemo(commandConstructor, [commandConstructor]); +export const createCommandButton = (command: BaseCommand, isHorizontal = false): ReactElement => { return ; }; diff --git a/react-components/src/components/Architecture/RevealButtons.tsx b/react-components/src/components/Architecture/RevealButtons.tsx index a4a5b82b920..41ab096c52f 100644 --- a/react-components/src/components/Architecture/RevealButtons.tsx +++ b/react-components/src/components/Architecture/RevealButtons.tsx @@ -2,55 +2,42 @@ * Copyright 2023 Cognite AS */ -import { type ReactElement } from 'react'; +import { useMemo, type ReactElement } from 'react'; import { NavigationTool } from '../../architecture/base/concreteCommands/NavigationTool'; -import { CommandButtonFromCommand } from './CommandButton'; +import { createCommandButton } from './CommandButton'; import { FitViewCommand } from '../../architecture/base/concreteCommands/FitViewCommand'; import { FlexibleControlsType } from '@cognite/reveal'; import { SetFlexibleControlsTypeCommand } from '../../architecture/base/concreteCommands/SetFlexibleControlsTypeCommand'; import { SetAxisVisibleCommand } from '../../architecture/concrete/axis/SetAxisVisibleCommand'; import { ClipTool } from '../../architecture/concrete/clipping/ClipTool'; import { MeasurementTool } from '../../architecture/concrete/measurements/MeasurementTool'; -import { useFdmSdk } from '../RevealCanvas/SDKProvider'; import { ObservationsTool } from '../../architecture/concrete/observationsDomainObject/ObservationsTool'; export class RevealButtons { - static FitView = (): ReactElement => ( - new FitViewCommand()} /> - ); - - static NavigationTool = (): ReactElement => ( - new NavigationTool()} /> - ); - - static SetAxisVisible = (): ReactElement => ( - new SetAxisVisibleCommand()} /> - ); - - static Measurement = (): ReactElement => ( - new MeasurementTool()} /> - ); - - static Clip = (): ReactElement => ( - new ClipTool()} /> - ); - - static SetFlexibleControlsTypeOrbit = (): ReactElement => ( - new SetFlexibleControlsTypeCommand(FlexibleControlsType.Orbit)} - /> - ); - - static SetFlexibleControlsTypeFirstPerson = (): ReactElement => ( - - new SetFlexibleControlsTypeCommand(FlexibleControlsType.FirstPerson) - } - /> - ); + static FitView = (): ReactElement => createCommandButton(useMemo(() => new FitViewCommand(), [])); + + static NavigationTool = (): ReactElement => + createCommandButton(useMemo(() => new NavigationTool(), [])); + + static SetAxisVisible = (): ReactElement => + createCommandButton(useMemo(() => new SetAxisVisibleCommand(), [])); + + static Measurement = (): ReactElement => + createCommandButton(useMemo(() => new MeasurementTool(), [])); + + static Clip = (): ReactElement => createCommandButton(useMemo(() => new ClipTool(), [])); + + static SetFlexibleControlsTypeOrbit = (): ReactElement => + createCommandButton( + useMemo(() => new SetFlexibleControlsTypeCommand(FlexibleControlsType.Orbit), []) + ); + + static SetFlexibleControlsTypeFirstPerson = (): ReactElement => + createCommandButton( + useMemo(() => new SetFlexibleControlsTypeCommand(FlexibleControlsType.FirstPerson), []) + ); static Observations = (): ReactElement => { - const fdmSdk = useFdmSdk(); - return new ObservationsTool(fdmSdk)} />; + return createCommandButton(useMemo(() => new ObservationsTool(), [])); }; } From bd88c14523e2d323d8677d23fb081c832929efaa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A5kon=20Flatval?= Date: Tue, 25 Jun 2024 11:00:07 +0200 Subject: [PATCH 11/19] chore: don't send undefined as argument to overlay constructor --- .../observationsDomainObject/ObservationsDomainObject.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/react-components/src/architecture/concrete/observationsDomainObject/ObservationsDomainObject.ts b/react-components/src/architecture/concrete/observationsDomainObject/ObservationsDomainObject.ts index 8218c2d2c59..873fd722c3d 100644 --- a/react-components/src/architecture/concrete/observationsDomainObject/ObservationsDomainObject.ts +++ b/react-components/src/architecture/concrete/observationsDomainObject/ObservationsDomainObject.ts @@ -13,7 +13,7 @@ import { DEFAULT_OVERLAY_COLOR } from './constants'; import { Changes } from '../../base/domainObjectsHelpers/Changes'; export class ObservationsDomainObject extends VisualDomainObject { - private readonly _collection = new Overlay3DCollection(undefined, { + private readonly _collection = new Overlay3DCollection([], { defaultOverlayColor: DEFAULT_OVERLAY_COLOR }); From 2318d229dd501432e741564f7aea8a37ff1b0f79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A5kon=20Flatval?= Date: Tue, 25 Jun 2024 11:08:43 +0200 Subject: [PATCH 12/19] chore: never reconstruct command object in command buttons --- .../components/Architecture/CommandButton.tsx | 6 ++++- .../components/Architecture/RevealButtons.tsx | 22 +++++++------------ 2 files changed, 13 insertions(+), 15 deletions(-) diff --git a/react-components/src/components/Architecture/CommandButton.tsx b/react-components/src/components/Architecture/CommandButton.tsx index f15350f7a04..ae97bac3bc7 100644 --- a/react-components/src/components/Architecture/CommandButton.tsx +++ b/react-components/src/components/Architecture/CommandButton.tsx @@ -32,7 +32,11 @@ export const CommandButtons = ({ ); }; -export const createCommandButton = (command: BaseCommand, isHorizontal = false): ReactElement => { +export const createCommandButton = ( + commandConstructor: () => BaseCommand, + isHorizontal = false +): ReactElement => { + const command = useMemo(commandConstructor, []); return ; }; diff --git a/react-components/src/components/Architecture/RevealButtons.tsx b/react-components/src/components/Architecture/RevealButtons.tsx index 41ab096c52f..c335e9b3812 100644 --- a/react-components/src/components/Architecture/RevealButtons.tsx +++ b/react-components/src/components/Architecture/RevealButtons.tsx @@ -14,30 +14,24 @@ import { MeasurementTool } from '../../architecture/concrete/measurements/Measur import { ObservationsTool } from '../../architecture/concrete/observationsDomainObject/ObservationsTool'; export class RevealButtons { - static FitView = (): ReactElement => createCommandButton(useMemo(() => new FitViewCommand(), [])); + static FitView = (): ReactElement => createCommandButton(() => new FitViewCommand()); - static NavigationTool = (): ReactElement => - createCommandButton(useMemo(() => new NavigationTool(), [])); + static NavigationTool = (): ReactElement => createCommandButton(() => new NavigationTool()); static SetAxisVisible = (): ReactElement => - createCommandButton(useMemo(() => new SetAxisVisibleCommand(), [])); + createCommandButton(() => new SetAxisVisibleCommand()); - static Measurement = (): ReactElement => - createCommandButton(useMemo(() => new MeasurementTool(), [])); + static Measurement = (): ReactElement => createCommandButton(() => new MeasurementTool()); - static Clip = (): ReactElement => createCommandButton(useMemo(() => new ClipTool(), [])); + static Clip = (): ReactElement => createCommandButton(() => new ClipTool()); static SetFlexibleControlsTypeOrbit = (): ReactElement => - createCommandButton( - useMemo(() => new SetFlexibleControlsTypeCommand(FlexibleControlsType.Orbit), []) - ); + createCommandButton(() => new SetFlexibleControlsTypeCommand(FlexibleControlsType.Orbit)); static SetFlexibleControlsTypeFirstPerson = (): ReactElement => - createCommandButton( - useMemo(() => new SetFlexibleControlsTypeCommand(FlexibleControlsType.FirstPerson), []) - ); + createCommandButton(() => new SetFlexibleControlsTypeCommand(FlexibleControlsType.FirstPerson)); static Observations = (): ReactElement => { - return createCommandButton(useMemo(() => new ObservationsTool(), [])); + return createCommandButton(() => new ObservationsTool()); }; } From 06811eed658518ece6db09d3592337dbd865eeda Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A5kon=20Flatval?= Date: Wed, 26 Jun 2024 09:39:44 +0200 Subject: [PATCH 13/19] chore: remove unnecessary domainObject functions --- .../architecture/concrete/exampleDomainObject/ExampleView.ts | 4 ---- .../src/architecture/concrete/primitives/box/BoxView.ts | 4 ---- .../src/architecture/concrete/primitives/line/LineView.ts | 4 ---- .../src/architecture/concrete/primitives/plane/PlaneView.ts | 4 ---- .../concrete/terrainDomainObject/TerrainThreeView.ts | 4 ---- 5 files changed, 20 deletions(-) diff --git a/react-components/src/architecture/concrete/exampleDomainObject/ExampleView.ts b/react-components/src/architecture/concrete/exampleDomainObject/ExampleView.ts index d12e77addc9..87c2a5cc9b8 100644 --- a/react-components/src/architecture/concrete/exampleDomainObject/ExampleView.ts +++ b/react-components/src/architecture/concrete/exampleDomainObject/ExampleView.ts @@ -21,10 +21,6 @@ export class ExampleView extends GroupThreeView { // INSTANCE PROPERTIES // ================================================== - public override get domainObject(): ExampleDomainObject { - return super.domainObject; - } - protected override get style(): ExampleRenderStyle { return super.style as ExampleRenderStyle; } diff --git a/react-components/src/architecture/concrete/primitives/box/BoxView.ts b/react-components/src/architecture/concrete/primitives/box/BoxView.ts index 565684a9ccf..7d452133a97 100644 --- a/react-components/src/architecture/concrete/primitives/box/BoxView.ts +++ b/react-components/src/architecture/concrete/primitives/box/BoxView.ts @@ -67,10 +67,6 @@ export class BoxView extends GroupThreeView { // INSTANCE PROPERTIES // ================================================== - public override get domainObject(): BoxDomainObject { - return super.domainObject; - } - protected override get style(): BoxRenderStyle { return super.style as BoxRenderStyle; } diff --git a/react-components/src/architecture/concrete/primitives/line/LineView.ts b/react-components/src/architecture/concrete/primitives/line/LineView.ts index 569b28a2559..4ba5677ab6e 100644 --- a/react-components/src/architecture/concrete/primitives/line/LineView.ts +++ b/react-components/src/architecture/concrete/primitives/line/LineView.ts @@ -46,10 +46,6 @@ export class LineView extends GroupThreeView { // INSTANCE PROPERTIES // ================================================== - public override get domainObject(): LineDomainObject { - return super.domainObject; - } - protected override get style(): LineRenderStyle { return super.style as LineRenderStyle; } diff --git a/react-components/src/architecture/concrete/primitives/plane/PlaneView.ts b/react-components/src/architecture/concrete/primitives/plane/PlaneView.ts index d51ded18a1b..6dd7906b863 100644 --- a/react-components/src/architecture/concrete/primitives/plane/PlaneView.ts +++ b/react-components/src/architecture/concrete/primitives/plane/PlaneView.ts @@ -44,10 +44,6 @@ export class PlaneView extends GroupThreeView { // INSTANCE PROPERTIES // ================================================== - public override get domainObject(): PlaneDomainObject { - return super.domainObject; - } - protected override get style(): PlaneRenderStyle { return super.style as PlaneRenderStyle; } diff --git a/react-components/src/architecture/concrete/terrainDomainObject/TerrainThreeView.ts b/react-components/src/architecture/concrete/terrainDomainObject/TerrainThreeView.ts index d54129e7da5..012855c696f 100644 --- a/react-components/src/architecture/concrete/terrainDomainObject/TerrainThreeView.ts +++ b/react-components/src/architecture/concrete/terrainDomainObject/TerrainThreeView.ts @@ -40,10 +40,6 @@ export class TerrainThreeView extends GroupThreeView { // INSTANCE PROPERTIES // ================================================== - public override get domainObject(): TerrainDomainObject { - return super.domainObject; - } - protected override get style(): TerrainRenderStyle { return super.style as TerrainRenderStyle; } From 6835aaabd0958e11c5b8abc00beed5250f8a8869 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A5kon=20Flatval?= Date: Wed, 26 Jun 2024 10:12:13 +0200 Subject: [PATCH 14/19] chore: handle selection and view updates outside tool --- .../ObservationsDomainObject.ts | 21 ++++++++--- .../ObservationsTool.ts | 37 ++++++------------- .../ObservationsView.ts | 17 +++++++++ 3 files changed, 44 insertions(+), 31 deletions(-) diff --git a/react-components/src/architecture/concrete/observationsDomainObject/ObservationsDomainObject.ts b/react-components/src/architecture/concrete/observationsDomainObject/ObservationsDomainObject.ts index 873fd722c3d..40153848ece 100644 --- a/react-components/src/architecture/concrete/observationsDomainObject/ObservationsDomainObject.ts +++ b/react-components/src/architecture/concrete/observationsDomainObject/ObservationsDomainObject.ts @@ -1,7 +1,7 @@ /*! * Copyright 2024 Cognite AS */ -import { CDF_TO_VIEWER_TRANSFORMATION, Overlay3DCollection } from '@cognite/reveal'; +import { CDF_TO_VIEWER_TRANSFORMATION, Overlay3D, Overlay3DCollection } from '@cognite/reveal'; import { OBSERVATION_SOURCE, type ObservationProperties, type Observation } from './models'; import { VisualDomainObject } from '../../base/domainObjects/VisualDomainObject'; import { type ThreeView } from '../../base/views/ThreeView'; @@ -13,6 +13,8 @@ import { DEFAULT_OVERLAY_COLOR } from './constants'; import { Changes } from '../../base/domainObjectsHelpers/Changes'; export class ObservationsDomainObject extends VisualDomainObject { + private _selectedOverlay: Overlay3D | undefined; + private readonly _collection = new Overlay3DCollection([], { defaultOverlayColor: DEFAULT_OVERLAY_COLOR }); @@ -29,6 +31,10 @@ export class ObservationsDomainObject extends VisualDomainObject { }); } + protected override createThreeView(): ThreeView | undefined { + return new ObservationsView(); + } + private initializeCollection(observations: Observation[]): void { const observationOverlays = observations.map((observation) => { const position = new Vector3( @@ -50,14 +56,19 @@ export class ObservationsDomainObject extends VisualDomainObject { return this._collection; } - protected override createThreeView(): ThreeView | undefined { - return new ObservationsView(); + public getSelectedOverlay(): Overlay3D | undefined { + return this._selectedOverlay; } -} -const observationsFilter: InstanceFilter = {}; + public setSelectedOverlay(overlay: Overlay3D | undefined) { + this._selectedOverlay = overlay; + this.notify(Changes.selected); + } +} async function fetchObservations(fdmSdk: FdmSDK): Promise { + const observationsFilter: InstanceFilter = {}; + const observationResult = await fdmSdk.filterAllInstances( observationsFilter, 'node', diff --git a/react-components/src/architecture/concrete/observationsDomainObject/ObservationsTool.ts b/react-components/src/architecture/concrete/observationsDomainObject/ObservationsTool.ts index 18c2d3d7001..e161fb57f6f 100644 --- a/react-components/src/architecture/concrete/observationsDomainObject/ObservationsTool.ts +++ b/react-components/src/architecture/concrete/observationsDomainObject/ObservationsTool.ts @@ -11,9 +11,6 @@ import { BaseEditTool } from '../../base/commands/BaseEditTool'; import { type VisualDomainObject } from '../../base/domainObjects/VisualDomainObject'; export class ObservationsTool extends BaseEditTool { - private _selectedOverlay: Overlay3D | undefined; - private _observationsDomainObject: ObservationsDomainObject | undefined; - public override get icon(): IconType { return 'Location'; } @@ -23,54 +20,42 @@ export class ObservationsTool extends BaseEditTool { } public override onActivate(): void { - if (this._observationsDomainObject === undefined) { - this._observationsDomainObject = new ObservationsDomainObject(this.renderTarget.fdmSdk); - this.renderTarget.rootDomainObject.addChild(this._observationsDomainObject); + let domainObject = this.getObservationsDomainObject(); + if (domainObject === undefined) { + domainObject = new ObservationsDomainObject(this.renderTarget.fdmSdk); + this.renderTarget.rootDomainObject.addChild(domainObject); } - this._observationsDomainObject.setVisibleInteractive(true, this.renderTarget); + domainObject.setVisibleInteractive(true, this.renderTarget); } public override onDeactivate(): void { - this._observationsDomainObject?.setVisibleInteractive(false, this.renderTarget); + this.getObservationsDomainObject()?.setVisibleInteractive(false, this.renderTarget); } public override async onClick(event: PointerEvent): Promise { const intersection = await this.getIntersection(event); - if (intersection === undefined) { - await super.onClick(event); - return; - } const domainObject = this.getIntersectedSelectableDomainObject(intersection); if (!(domainObject instanceof ObservationsDomainObject)) { + await super.onClick(event); return; } const normalizedCoords = this.getNormalizedPixelCoordinates(event); - const intersectedIcon = domainObject.overlayCollection.intersectOverlays( + const intersectedOverlay = domainObject.overlayCollection.intersectOverlays( normalizedCoords, this.renderTarget.camera ); - this.handleIntersectedOverlay(intersectedIcon); - - this.renderTarget.viewer.requestRedraw(); + domainObject.setSelectedOverlay(intersectedOverlay); } protected override canBeSelected(domainObject: VisualDomainObject): boolean { return domainObject instanceof ObservationsDomainObject; } - private handleIntersectedOverlay(overlay: Overlay3D | undefined): void { - this._selectedOverlay?.setColor(DEFAULT_OVERLAY_COLOR); - this._selectedOverlay = undefined; - - if (overlay === undefined) { - return; - } - overlay.setColor(SELECTED_OVERLAY_COLOR); - this.renderTarget.viewer.requestRedraw(); - this._selectedOverlay = overlay; + public getObservationsDomainObject(): ObservationsDomainObject | undefined { + return this.rootDomainObject.getDescendantByType(ObservationsDomainObject); } } diff --git a/react-components/src/architecture/concrete/observationsDomainObject/ObservationsView.ts b/react-components/src/architecture/concrete/observationsDomainObject/ObservationsView.ts index 3eaec67c248..33e1e8d3f42 100644 --- a/react-components/src/architecture/concrete/observationsDomainObject/ObservationsView.ts +++ b/react-components/src/architecture/concrete/observationsDomainObject/ObservationsView.ts @@ -6,6 +6,9 @@ import { type ObservationsDomainObject } from './ObservationsDomainObject'; import { GroupThreeView } from '../../base/views/GroupThreeView'; import { type CustomObjectIntersectInput, type CustomObjectIntersection } from '@cognite/reveal'; import { type DomainObjectIntersection } from '../../base/domainObjectsHelpers/DomainObjectIntersection'; +import { Changes } from '../../base/domainObjectsHelpers/Changes'; +import { DEFAULT_OVERLAY_COLOR, SELECTED_OVERLAY_COLOR } from './constants'; +import { DomainObjectChange } from '../../base/domainObjectsHelpers/DomainObjectChange'; export class ObservationsView extends GroupThreeView { protected override calculateBoundingBox(): Box3 { @@ -18,6 +21,20 @@ export class ObservationsView extends GroupThreeView { this.addChild(this.domainObject.overlayCollection); } + public override update(change: DomainObjectChange): void { + super.update(change); + if (change.isChanged(Changes.selected)) { + this.domainObject.overlayCollection + .getOverlays() + .forEach((overlay) => overlay.setColor(DEFAULT_OVERLAY_COLOR)); + + const overlay = this.domainObject.getSelectedOverlay(); + overlay?.setColor(SELECTED_OVERLAY_COLOR); + } + + this.renderTarget.viewer.requestRedraw(); + } + public override intersectIfCloser( intersectInput: CustomObjectIntersectInput, closestDistance: number | undefined From b7005741ea83b762328fe144fdbdc55809837a0b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A5kon=20Flatval?= Date: Wed, 26 Jun 2024 10:12:37 +0200 Subject: [PATCH 15/19] chore: update reveal version --- react-components/package.json | 4 ++-- react-components/yarn.lock | 12 ++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/react-components/package.json b/react-components/package.json index 29b0b98a2fe..761f6b9a857 100644 --- a/react-components/package.json +++ b/react-components/package.json @@ -30,7 +30,7 @@ }, "peerDependencies": { "@cognite/cogs.js": ">=9.84.3", - "@cognite/reveal": "4.15.0", + "@cognite/reveal": "4.15.1", "react": ">=18", "react-dom": ">=18", "styled-components": ">=5" @@ -44,7 +44,7 @@ "@cognite/cdf-i18n-utils": "^0.7.5", "@cognite/cdf-utilities": "^3.6.0", "@cognite/cogs.js": "^9.84.3", - "@cognite/reveal": "^4.15.0", + "@cognite/reveal": "^4.15.1", "@cognite/sdk": "^9.13.0", "@playwright/test": "^1.43.1", "@storybook/addon-essentials": "^8.0.9", diff --git a/react-components/yarn.lock b/react-components/yarn.lock index 1331bd07c71..962047edda1 100644 --- a/react-components/yarn.lock +++ b/react-components/yarn.lock @@ -1747,7 +1747,7 @@ __metadata: "@cognite/cdf-i18n-utils": "npm:^0.7.5" "@cognite/cdf-utilities": "npm:^3.6.0" "@cognite/cogs.js": "npm:^9.84.3" - "@cognite/reveal": "npm:^4.15.0" + "@cognite/reveal": "npm:^4.15.1" "@cognite/sdk": "npm:^9.13.0" "@playwright/test": "npm:^1.43.1" "@storybook/addon-essentials": "npm:^8.0.9" @@ -1802,16 +1802,16 @@ __metadata: vitest: "npm:^1.5.3" peerDependencies: "@cognite/cogs.js": ">=9.84.3" - "@cognite/reveal": 4.15.0 + "@cognite/reveal": 4.15.1 react: ">=18" react-dom: ">=18" styled-components: ">=5" languageName: unknown linkType: soft -"@cognite/reveal@npm:^4.15.0": - version: 4.15.0 - resolution: "@cognite/reveal@npm:4.15.0" +"@cognite/reveal@npm:^4.15.1": + version: 4.15.1 + resolution: "@cognite/reveal@npm:4.15.1" dependencies: "@rajesh896/broprint.js": "npm:^2.1.1" "@tweenjs/tween.js": "npm:^23.1.1" @@ -1831,7 +1831,7 @@ __metadata: peerDependencies: "@cognite/sdk": ^7.16.0 || ^8.0.0 three: 0.165.0 - checksum: 10/5d8111cf3cc5a2424a643fd0d743764a90b56ffb7602fccc3dc07aace1f9857eb514abe765a6fc2cd6ba8fdbe069dea22a1ba46a00526b6800bf8f947f64f3b0 + checksum: 10/0dc5ee79866cfc25043d04c687ade643674dd42f4587a2950e6cea080a2331fbe8d878673c74ffbf910018959a25f32c6a2f65518ebf25457982fadc1c89921e languageName: node linkType: hard From 32d64dc4fff9bcb34b77fbeb29884d427a2bb5ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A5kon=20Flatval?= Date: Wed, 26 Jun 2024 10:32:27 +0200 Subject: [PATCH 16/19] chore: move function --- .../observationsDomainObject/ObservationsDomainObject.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/react-components/src/architecture/concrete/observationsDomainObject/ObservationsDomainObject.ts b/react-components/src/architecture/concrete/observationsDomainObject/ObservationsDomainObject.ts index 40153848ece..2bfb0ea98f0 100644 --- a/react-components/src/architecture/concrete/observationsDomainObject/ObservationsDomainObject.ts +++ b/react-components/src/architecture/concrete/observationsDomainObject/ObservationsDomainObject.ts @@ -19,10 +19,6 @@ export class ObservationsDomainObject extends VisualDomainObject { defaultOverlayColor: DEFAULT_OVERLAY_COLOR }); - public override get typeName(): TranslateKey { - return { fallback: ObservationsDomainObject.name }; - } - constructor(fdmSdk: FdmSDK) { super(); void fetchObservations(fdmSdk).then((observations) => { @@ -31,6 +27,10 @@ export class ObservationsDomainObject extends VisualDomainObject { }); } + public override get typeName(): TranslateKey { + return { fallback: ObservationsDomainObject.name }; + } + protected override createThreeView(): ThreeView | undefined { return new ObservationsView(); } From 493ffb000e04beead11cd5396550d7516aa57a26 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A5kon=20Flatval?= Date: Wed, 26 Jun 2024 10:41:41 +0200 Subject: [PATCH 17/19] feat(react-components): Make sure stories always are initialized with config --- .../concrete/config/StoryBookConfig.ts | 2 ++ react-components/stories/Toolbar.stories.tsx | 1 - .../stories/utilities/RevealStoryContainer.tsx | 15 +++++++-------- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/react-components/src/architecture/concrete/config/StoryBookConfig.ts b/react-components/src/architecture/concrete/config/StoryBookConfig.ts index ae62b078558..1cfc959da63 100644 --- a/react-components/src/architecture/concrete/config/StoryBookConfig.ts +++ b/react-components/src/architecture/concrete/config/StoryBookConfig.ts @@ -20,6 +20,7 @@ import { ToggleMetricUnitsCommand } from '../../base/concreteCommands/ToggleMetr import { MeasurementTool } from '../measurements/MeasurementTool'; import { ClipTool } from '../clipping/ClipTool'; import { KeyboardSpeedCommand } from '../../base/concreteCommands/KeyboardSpeedCommand'; +import { ObservationsTool } from '../observationsDomainObject/ObservationsTool'; export class StoryBookConfig extends BaseRevealConfig { // ================================================== @@ -43,6 +44,7 @@ export class StoryBookConfig extends BaseRevealConfig { new ExampleTool(), new MeasurementTool(), new ClipTool(), + new ObservationsTool(), undefined, new SetTerrainVisibleCommand(), new UpdateTerrainCommand() diff --git a/react-components/stories/Toolbar.stories.tsx b/react-components/stories/Toolbar.stories.tsx index 8fb4d023942..c401be2a64d 100644 --- a/react-components/stories/Toolbar.stories.tsx +++ b/react-components/stories/Toolbar.stories.tsx @@ -110,7 +110,6 @@ export const Main: Story = { - ) diff --git a/react-components/stories/utilities/RevealStoryContainer.tsx b/react-components/stories/utilities/RevealStoryContainer.tsx index acd1870e9d5..b773914b767 100644 --- a/react-components/stories/utilities/RevealStoryContainer.tsx +++ b/react-components/stories/utilities/RevealStoryContainer.tsx @@ -40,21 +40,20 @@ export const RevealStoryContext = ({ const isLocal = sdkInstance.project === ''; const renderTarget = useMemo(() => { - if (viewer !== undefined) { - return new RevealRenderTarget(viewer, sdkInstance); - } else if (isLocal) { - const newViewer = new Cognite3DViewer({ + if (viewer === undefined) { + viewer = new Cognite3DViewer({ ...rest.viewerOptions, sdk: sdkInstance, // @ts-expect-error use local models - _localModels: true, + _localModels: isLocal, hasEventListeners: false, useFlexibleCameraManager: true }); - const renderTarget = new RevealRenderTarget(newViewer, sdkInstance); - renderTarget.setConfig(new StoryBookConfig()); - return renderTarget; } + + const renderTarget = new RevealRenderTarget(viewer, sdkInstance); + renderTarget.setConfig(new StoryBookConfig()); + return renderTarget; }, [viewer]); const renderTargetRef = useRef(renderTarget); From 0fcba5713cd3c660873117cea28acb91c34093c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A5kon=20Flatval?= Date: Wed, 26 Jun 2024 10:49:25 +0200 Subject: [PATCH 18/19] chore: lint fix --- .../observationsDomainObject/ObservationsDomainObject.ts | 4 ++-- .../concrete/observationsDomainObject/ObservationsTool.ts | 3 --- .../concrete/observationsDomainObject/ObservationsView.ts | 8 ++++---- react-components/stories/Toolbar.stories.tsx | 3 +-- 4 files changed, 7 insertions(+), 11 deletions(-) diff --git a/react-components/src/architecture/concrete/observationsDomainObject/ObservationsDomainObject.ts b/react-components/src/architecture/concrete/observationsDomainObject/ObservationsDomainObject.ts index 2bfb0ea98f0..540fa4ff125 100644 --- a/react-components/src/architecture/concrete/observationsDomainObject/ObservationsDomainObject.ts +++ b/react-components/src/architecture/concrete/observationsDomainObject/ObservationsDomainObject.ts @@ -1,7 +1,7 @@ /*! * Copyright 2024 Cognite AS */ -import { CDF_TO_VIEWER_TRANSFORMATION, Overlay3D, Overlay3DCollection } from '@cognite/reveal'; +import { CDF_TO_VIEWER_TRANSFORMATION, type Overlay3D, Overlay3DCollection } from '@cognite/reveal'; import { OBSERVATION_SOURCE, type ObservationProperties, type Observation } from './models'; import { VisualDomainObject } from '../../base/domainObjects/VisualDomainObject'; import { type ThreeView } from '../../base/views/ThreeView'; @@ -60,7 +60,7 @@ export class ObservationsDomainObject extends VisualDomainObject { return this._selectedOverlay; } - public setSelectedOverlay(overlay: Overlay3D | undefined) { + public setSelectedOverlay(overlay: Overlay3D | undefined): void { this._selectedOverlay = overlay; this.notify(Changes.selected); } diff --git a/react-components/src/architecture/concrete/observationsDomainObject/ObservationsTool.ts b/react-components/src/architecture/concrete/observationsDomainObject/ObservationsTool.ts index e161fb57f6f..da9a7765cd2 100644 --- a/react-components/src/architecture/concrete/observationsDomainObject/ObservationsTool.ts +++ b/react-components/src/architecture/concrete/observationsDomainObject/ObservationsTool.ts @@ -3,10 +3,7 @@ */ import { type IconType } from '@cognite/cogs.js'; import { type TranslateKey } from '../../base/utilities/TranslateKey'; -import { type Observation } from './models'; import { ObservationsDomainObject } from './ObservationsDomainObject'; -import { type Overlay3D } from '@cognite/reveal'; -import { DEFAULT_OVERLAY_COLOR, SELECTED_OVERLAY_COLOR } from './constants'; import { BaseEditTool } from '../../base/commands/BaseEditTool'; import { type VisualDomainObject } from '../../base/domainObjects/VisualDomainObject'; diff --git a/react-components/src/architecture/concrete/observationsDomainObject/ObservationsView.ts b/react-components/src/architecture/concrete/observationsDomainObject/ObservationsView.ts index 33e1e8d3f42..29058197ced 100644 --- a/react-components/src/architecture/concrete/observationsDomainObject/ObservationsView.ts +++ b/react-components/src/architecture/concrete/observationsDomainObject/ObservationsView.ts @@ -8,7 +8,7 @@ import { type CustomObjectIntersectInput, type CustomObjectIntersection } from ' import { type DomainObjectIntersection } from '../../base/domainObjectsHelpers/DomainObjectIntersection'; import { Changes } from '../../base/domainObjectsHelpers/Changes'; import { DEFAULT_OVERLAY_COLOR, SELECTED_OVERLAY_COLOR } from './constants'; -import { DomainObjectChange } from '../../base/domainObjectsHelpers/DomainObjectChange'; +import { type DomainObjectChange } from '../../base/domainObjectsHelpers/DomainObjectChange'; export class ObservationsView extends GroupThreeView { protected override calculateBoundingBox(): Box3 { @@ -24,9 +24,9 @@ export class ObservationsView extends GroupThreeView { public override update(change: DomainObjectChange): void { super.update(change); if (change.isChanged(Changes.selected)) { - this.domainObject.overlayCollection - .getOverlays() - .forEach((overlay) => overlay.setColor(DEFAULT_OVERLAY_COLOR)); + this.domainObject.overlayCollection.getOverlays().forEach((overlay) => { + overlay.setColor(DEFAULT_OVERLAY_COLOR); + }); const overlay = this.domainObject.getSelectedOverlay(); overlay?.setColor(SELECTED_OVERLAY_COLOR); diff --git a/react-components/stories/Toolbar.stories.tsx b/react-components/stories/Toolbar.stories.tsx index c401be2a64d..cbf5dab9eca 100644 --- a/react-components/stories/Toolbar.stories.tsx +++ b/react-components/stories/Toolbar.stories.tsx @@ -10,8 +10,7 @@ import { withSuppressRevealEvents, withCameraStateUrlParam, useGetCameraStateFromUrlParam, - useCameraNavigation, - RevealButtons + useCameraNavigation } from '../src'; import { Color } from 'three'; import styled from 'styled-components'; From 3cc36d4d3d79fa1036d4ede2a5f75053eff49b73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A5kon=20Flatval?= Date: Wed, 26 Jun 2024 11:13:42 +0200 Subject: [PATCH 19/19] chore: move requestRedraw --- .../concrete/observationsDomainObject/ObservationsView.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/react-components/src/architecture/concrete/observationsDomainObject/ObservationsView.ts b/react-components/src/architecture/concrete/observationsDomainObject/ObservationsView.ts index 29058197ced..441d03a4f57 100644 --- a/react-components/src/architecture/concrete/observationsDomainObject/ObservationsView.ts +++ b/react-components/src/architecture/concrete/observationsDomainObject/ObservationsView.ts @@ -30,9 +30,9 @@ export class ObservationsView extends GroupThreeView { const overlay = this.domainObject.getSelectedOverlay(); overlay?.setColor(SELECTED_OVERLAY_COLOR); - } - this.renderTarget.viewer.requestRedraw(); + this.renderTarget.invalidate(); + } } public override intersectIfCloser(