Skip to content

Commit

Permalink
feat(react-components): color clicked poi instance and bump to 0.73.0 (
Browse files Browse the repository at this point in the history
…#4915)

* refactor(react-components): move caching into domain object

* chore: preliminary lint fix

* chore: lint fix some more

* chore: remove unwanted changes

* chore: make direct reference from render targe to caches

* feat(react-components): color clicked instance from POI tool

* fix: issue where cad data would sometimes get uncached

* feat: add event listener to InstanceStylingController

* chore: export InstanceStylingGroup type

* chore: return undefined at end of function

* feat: set style on assigned instance in PoITool

* chore: rename variable

* chore: lint fix

* chore: remove unnecessary async

* chore: correct method name

* chore: bump package version

* chore: add option to turn off exit button
  • Loading branch information
haakonflatval-cognite authored Dec 2, 2024
1 parent 5d59392 commit e345cbf
Show file tree
Hide file tree
Showing 13 changed files with 379 additions and 93 deletions.
2 changes: 1 addition & 1 deletion react-components/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@cognite/reveal-react-components",
"version": "0.73.0",
"version": "0.73.1",
"exports": {
".": {
"import": "./dist/index.js",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ export class CdfCaches {
private readonly _pointCloudAnnotationCache: PointCloudAnnotationCache;
private readonly _image360AnnotationCache: Image360AnnotationCache;

private readonly _cogniteClient: CogniteClient;

constructor(
cdfClient: CogniteClient,
fdm3dDataProvider: Fdm3dDataProvider,
Expand All @@ -27,6 +29,8 @@ export class CdfCaches {
this._fdmNodeCache = new FdmNodeCache(cdfClient, fdmClient, fdm3dDataProvider);
this._pointCloudAnnotationCache = new PointCloudAnnotationCache(cdfClient);
this._image360AnnotationCache = new Image360AnnotationCache(cdfClient, viewer);

this._cogniteClient = cdfClient;
}

public get assetMappingAndNode3dCache(): AssetMappingAndNode3DCache {
Expand All @@ -44,4 +48,8 @@ export class CdfCaches {
public get image360Cache(): Image360AnnotationCache {
return this._image360AnnotationCache;
}

public get cogniteClient(): CogniteClient {
return this._cogniteClient;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*!
* Copyright 2024 Cognite AS
*/

import { remove } from 'lodash';
import { type InstanceStylingGroup } from '../../../components/Reveal3DResources/types';

export class InstanceStylingController {
private readonly _eventHandlers: Array<() => void> = [];

private readonly _stylingMap = new Map<symbol, InstanceStylingGroup>();

setStylingGroup(symbol: symbol, group: InstanceStylingGroup | undefined): void {
if (group === undefined) {
this._stylingMap.delete(symbol);
this.fireChangeEvent();
return;
}

this._stylingMap.set(symbol, group);
this.fireChangeEvent();
}

getStylingGroups(): Iterable<InstanceStylingGroup> {
return this._stylingMap.values();
}

addEventListener(eventHandler: () => void): void {
this._eventHandlers.push(eventHandler);
}

removeEventListener(eventHandler: () => void): boolean {
return remove(this._eventHandlers, eventHandler).length > 0;
}

private fireChangeEvent(): void {
this._eventHandlers.forEach((f) => {
f();
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ import { Changes } from '../domainObjectsHelpers/Changes';
import { type CogniteClient } from '@cognite/sdk';
import { type BaseTool } from '../commands/BaseTool';
import { ContextMenuController } from './ContextMenuController';
import { InstanceStylingController } from './InstanceStylingController';
import { type Class } from '../domainObjectsHelpers/Class';
import { type CdfCaches } from './CdfCaches';

Expand All @@ -53,6 +54,8 @@ export class RevealRenderTarget {
private readonly _rootDomainObject: RootDomainObject;
private readonly _contextmenuController: ContextMenuController;
private readonly _cdfCaches: CdfCaches;
private readonly _instanceStylingController: InstanceStylingController;

private _ambientLight: AmbientLight | undefined;
private _directionalLight: DirectionalLight | undefined;
private _clippedBoundingBox: Box3 | undefined;
Expand All @@ -79,6 +82,7 @@ export class RevealRenderTarget {
this._commandsController.addEventListeners();
this._contextmenuController = new ContextMenuController();
this._cdfCaches = cdfCaches;
this._instanceStylingController = new InstanceStylingController();
this._rootDomainObject = new RootDomainObject(this, sdk);

this.initializeLights();
Expand Down Expand Up @@ -131,6 +135,10 @@ export class RevealRenderTarget {
return this._cdfCaches;
}

public get instanceStylingController(): InstanceStylingController {
return this._instanceStylingController;
}

public get cursor(): string {
return this.domElement.style.cursor;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,18 @@ import { AnchoredDialogUpdater } from '../../base/reactUpdaters/AnchoredDialogUp
import { CreatePointsOfInterestWithDescriptionCommand } from './CreatePointsOfInterestWithDescriptionCommand';
import { type RevealRenderTarget } from '../../base/renderTarget/RevealRenderTarget';
import { BaseEditTool } from '../../base/commands/BaseEditTool';
import { getInstancesFromClick } from '../../../utilities/getInstancesFromClick';
import { type InstanceReference } from '../../../data-providers';
import { DefaultNodeAppearance } from '@cognite/reveal';
import { isAssetInstance } from '../../../data-providers/types';

const ASSIGNED_INSTANCE_STYLING_SYMBOL = Symbol('poi3d-assigned-instance-styling');

export class PointsOfInterestTool<PoiIdType> extends BaseEditTool {
private _isCreating: boolean = false;

private _assignedInstance: InstanceReference | undefined;

private _anchoredDialogContent: AnchoredDialogContent | undefined;

public override get icon(): IconName {
Expand Down Expand Up @@ -50,11 +58,12 @@ export class PointsOfInterestTool<PoiIdType> extends BaseEditTool {
const domainObject = this.getPointsOfInterestDomainObject();
domainObject.setSelectedPointOfInterest(undefined);
this.setIsCreating(false);
this.setAssignedInstance(undefined);
}

public override async onClick(event: PointerEvent): Promise<void> {
if (this._isCreating) {
await this.initiateCreatPointOfInterest(event);
await this.initiateCreatePointOfInterest(event);
this.setIsCreating(false);
return;
}
Expand Down Expand Up @@ -105,6 +114,32 @@ export class PointsOfInterestTool<PoiIdType> extends BaseEditTool {
}
}

private setAssignedInstance(instance: InstanceReference | undefined): void {
this._assignedInstance = instance;

if (instance === undefined) {
this.renderTarget.instanceStylingController.setStylingGroup(
ASSIGNED_INSTANCE_STYLING_SYMBOL,
undefined
);
return;
}

const modelStyle = DefaultNodeAppearance.Highlighted;

if (isAssetInstance(instance)) {
this.renderTarget.instanceStylingController.setStylingGroup(
ASSIGNED_INSTANCE_STYLING_SYMBOL,
{ assetIds: [instance.assetId], style: { cad: modelStyle, pointcloud: modelStyle } }
);
} else {
this.renderTarget.instanceStylingController.setStylingGroup(
ASSIGNED_INSTANCE_STYLING_SYMBOL,
{ fdmAssetExternalIds: [instance], style: { cad: modelStyle, pointcloud: modelStyle } }
);
}
}

private setAnchoredDialogContent(dialogContent: AnchoredDialogContent | undefined): void {
this._anchoredDialogContent = dialogContent;
AnchoredDialogUpdater.update();
Expand Down Expand Up @@ -167,12 +202,19 @@ export class PointsOfInterestTool<PoiIdType> extends BaseEditTool {
intersection.domainObject.setSelectedPointOfInterest(intersection.userData);
}

private async initiateCreatPointOfInterest(event: PointerEvent): Promise<void> {
private async initiateCreatePointOfInterest(event: PointerEvent): Promise<void> {
const intersection = await this.getIntersection(event);
if (intersection === undefined || isPointsOfInterestIntersection(intersection)) {
this.closeCreateCommandDialog();
return;
}

this.openCreateCommandDialog(intersection.point);

const instances = await getInstancesFromClick(this.renderTarget, event);

if (instances !== undefined && instances.length !== 0) {
this.setAssignedInstance(instances[0]);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -235,20 +235,18 @@ export class AssetMappingAndNode3DCache {
})
.autoPagingToArray({ limit: Infinity });

assetMapping3D.forEach(async (item) => {
const keyAssetId: ModelAssetIdKey = modelRevisionNodesAssetToKey(
modelId,
revisionId,
item.assetId
);
const keyNodeId: ModelTreeIndexKey = modelRevisionNodesAssetToKey(
modelId,
revisionId,
item.nodeId
);
await this.assetIdsToAssetMappingCache.setAssetMappingsCacheItem(keyAssetId, item);
await this.nodeIdsToAssetMappingCache.setAssetMappingsCacheItem(keyNodeId, item);
});
await Promise.all(
assetMapping3D.map(async (item) => {
const keyAssetId: ModelAssetIdKey = modelRevisionNodesAssetToKey(
modelId,
revisionId,
item.assetId
);
const keyNodeId = modelRevisionNodesAssetToKey(modelId, revisionId, item.nodeId);
await this.assetIdsToAssetMappingCache.setAssetMappingsCacheItem(keyAssetId, item);
await this.nodeIdsToAssetMappingCache.setAssetMappingsCacheItem(keyNodeId, item);
})
);

currentChunk.forEach(async (id) => {
const key = modelRevisionNodesAssetToKey(modelId, revisionId, id);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,13 @@ import { useImage360Collections } from '../../hooks/useImage360Collections';

type Image360DetailsProps = {
appLanguage?: string;
enableExitButton?: boolean;
};

export function Image360Details({ appLanguage }: Image360DetailsProps): ReactElement {
export function Image360Details({
appLanguage,
enableExitButton = true
}: Image360DetailsProps): ReactElement {
const viewer = useReveal();
const [enteredEntity, setEnteredEntity] = useState<Image360 | undefined>();
const [is360HistoricalPanelExpanded, setIs360HistoricalPanelExpanded] = useState<boolean>(false);
Expand Down Expand Up @@ -57,9 +61,15 @@ export function Image360Details({ appLanguage }: Image360DetailsProps): ReactEle
fallbackLanguage={appLanguage}
/>
</Image360HistoricalPanel>
<ExitButtonContainer>
<StyledExitButton icon=<CloseLargeIcon /> type="tertiary" onClick={exitImage360Image} />
</ExitButtonContainer>
{enableExitButton && (
<ExitButtonContainer>
<StyledExitButton
icon=<CloseLargeIcon />
type="tertiary"
onClick={exitImage360Image}
/>
</ExitButtonContainer>
)}
</>
)}
</>
Expand Down
1 change: 1 addition & 0 deletions react-components/src/components/Reveal3DResources/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export type {
AssetStylingGroup,
DefaultResourceStyling,
Image360AssetStylingGroup,
InstanceStylingGroup,
CommonImage360Settings,
TaggedAddCadResourceOptions,
TaggedAddPointCloudResourceOptions,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/*!
* Copyright 2024 Cognite AS
*/

import { type UseQueryResult, useQuery } from '@tanstack/react-query';
import { type PointCloudAnnotationMappedAssetData } from '../types';
import { EMPTY_ARRAY } from '../../utilities/constants';
import { type AnyIntersection } from '@cognite/reveal';
import { queryKeys } from '../../utilities/queryKeys';
import { usePointCloudAnnotationCache } from '../../components/CacheProvider/CacheProvider';
import { fetchAnnotationsForModel } from './fetchAnnotationsForModel';

export const usePointCloudAnnotationMappingForAssetId = (
intersection: AnyIntersection | undefined
): UseQueryResult<PointCloudAnnotationMappedAssetData[]> => {
const pointCloudAnnotationCache = usePointCloudAnnotationCache();

const isPointCloudIntersection = intersection?.type === 'pointcloud';
const [modelId, revisionId, assetId] = isPointCloudIntersection
? [
intersection.model.modelId,
intersection.model.revisionId,
intersection.assetRef?.externalId ?? intersection.assetRef?.id
]
: [undefined, undefined, undefined];

return useQuery({
queryKey: [
queryKeys.pointCloudAnnotationForAssetId(
`${modelId}/${revisionId}`,
assetId?.toString() ?? ''
)
],
queryFn: async () => {
if (modelId === undefined || revisionId === undefined || assetId === undefined) {
return EMPTY_ARRAY;
}
const result = await fetchAnnotationsForModel(
modelId,
revisionId,
[assetId],
pointCloudAnnotationCache
);
return result ?? EMPTY_ARRAY;
},
staleTime: Infinity,
enabled: isPointCloudIntersection && assetId !== undefined
});
};
Loading

0 comments on commit e345cbf

Please sign in to comment.