Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

feat(react-components): functionality surrounding Points of interest and bump to 0.67.0 #4866

Merged
merged 16 commits into from
Nov 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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.66.1",
"version": "0.67.0",
"exports": {
".": {
"import": "./dist/index.js",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import { VisualDomainObject } from '../domainObjects/VisualDomainObject';
import { type AnyIntersection } from '@cognite/reveal';
import { DomainObjectPanelUpdater } from '../reactUpdaters/DomainObjectPanelUpdater';
import { type CommandsController } from '../renderTarget/CommandsController';
import { PrimitiveEditTool } from '../../concrete/primitives/tools/PrimitiveEditTool';

/**
* The `BaseEditTool` class is an abstract class that extends the `NavigationTool` class.
Expand Down Expand Up @@ -211,5 +210,5 @@ export abstract class BaseEditTool extends NavigationTool {
}

export function isActiveEditTool(commandController: CommandsController): boolean {
return commandController.activeTool instanceof PrimitiveEditTool;
return commandController.activeTool instanceof BaseEditTool;
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ export abstract class BaseInputCommand extends RenderTargetCommand {
this._content = content;

const invokeResult = this.invoke();
this._onFinish?.();
this._content = '';
return invokeResult;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,19 +19,28 @@ import { Set360IconsSectionCommand } from './image360Collection/Set360IconsSecti
import { Set360IconsVisibleCommand } from './image360Collection/Set360IconsVisibleCommand';
import { Set360IconsOpacityCommand } from './image360Collection/Set360IconsOpacityCommand';
import { Set360IconsOccludedVisibleCommand } from './image360Collection/Set360IconsOccludedVisibleCommand';
import { SetPointsOfInterestVisibleCommand } from '../../concrete/pointsOfInterest/SetPointsOfInterestVisibleCommand';
import { PointsOfInterestDividerCommand } from '../../concrete/pointsOfInterest/PointsOfInterestDividerCommand';
import { PointsOfInterestSectionCommand } from '../../concrete/pointsOfInterest/PointsOfInterestSectionCommand';
import { SetGhostModeCommand } from './cad/SetGhostModeCommand';

export class SettingsCommand extends BaseSettingsCommand {
// ==================================================
// CONSTRUCTOR
// ==================================================

public constructor(include360Images: boolean = true) {
public constructor(include360Images: boolean = true, includePois: boolean = false) {
super();

this.add(new SetQualityCommand());
this.add(new SetGhostModeCommand());

if (includePois) {
this.add(new PointsOfInterestDividerCommand());
this.add(new PointsOfInterestSectionCommand());
this.add(new SetPointsOfInterestVisibleCommand());
}

if (include360Images) {
// 360 Images
this.add(new Image360CollectionDividerCommand());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,10 @@ import { AnnotationsCreateTool } from '../annotations/commands/AnnotationsCreate
import { AnnotationsShowCommand } from '../annotations/commands/AnnotationsShowCommand';
import { AnnotationsShowOnTopCommand } from '../annotations/commands/AnnotationsShowOnTopCommand';
import { AnnotationsSelectTool } from '../annotations/commands/AnnotationsSelectTool';
import { type DmsUniqueIdentifier } from '../../../data-providers';
import { PointsOfInterestTool } from '../pointsOfInterest/PointsOfInterestTool';
import { Image360ActionCommand } from '../../base/concreteCommands/image360Collection/Image360ActionCommand';
import { Image360Action } from '@cognite/reveal';
import { type ExternalId } from '../../../data-providers/FdmSDK';
import { Image360AnnotationTool } from '../annotation360/Image360AnnotationTool';

export class StoryBookConfig extends BaseRevealConfig {
Expand Down Expand Up @@ -65,7 +65,10 @@ export class StoryBookConfig extends BaseRevealConfig {
undefined,
new MeasurementTool(),
new ClipTool(),
new PointsOfInterestTool<DmsUniqueIdentifier>(),
new PointsOfInterestTool<ExternalId>(),
undefined,
new MockSettingsCommand(),
new MockFilterCommand(),
undefined,
new MockSettingsCommand(),
new MockFilterCommand(),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/*!
* Copyright 2024 Cognite AS
*/
import { BaseInputCommand } from '../../base/commands/BaseInputCommand';
import { Changes } from '../../base/domainObjectsHelpers/Changes';
import { type TranslateDelegate } from '../../base/utilities/TranslateKey';
import { PointsOfInterestDomainObject } from './PointsOfInterestDomainObject';
import { type PointOfInterest } from './types';

export class CreatePoiCommentCommand extends BaseInputCommand {
private readonly _poi: PointOfInterest<unknown>;

constructor(poi: PointOfInterest<unknown>) {
super();

this._poi = poi;
}

public override get hasData(): true {
return true;
}

public override getPostButtonLabel(t: TranslateDelegate): string | undefined {
return t('SEND', 'Send');
}

public override getCancelButtonLabel(t: TranslateDelegate): string | undefined {
return t('CANCEL', 'Cancel');
}

public override getPlaceholder(t: TranslateDelegate): string | undefined {
return t('COMMENT_PLACEHOLDER', 'Write a comment');
}

public override invokeCore(): boolean {
if (this._content === undefined) {
return false;
}

const domainObject = this.rootDomainObject.getDescendantByType(PointsOfInterestDomainObject);
void domainObject?.postCommentForPoi(this._poi, this._content).then(() => {
this._onFinish?.();
domainObject?.notify(Changes.addedPart);
});
return true;
}
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/*!
* Copyright 2024 Cognite AS
*/
import { type Vector3 } from 'three';
import { BaseInputCommand } from '../../base/commands/BaseInputCommand';
import { PointsOfInterestDomainObject } from './PointsOfInterestDomainObject';
import { type TranslateDelegate } from '../../base/utilities/TranslateKey';
import { createPointsOfInterestPropertiesFromPointAndTitle } from './types';

export class CreatePointsOfInterestWithDescriptionCommand extends BaseInputCommand {
private readonly _point: Vector3;

constructor(position: Vector3) {
super();

this._point = position;
}

public override getPostButtonLabel(t: TranslateDelegate): string | undefined {
return t('CREATE', 'Create');
}

public override getCancelButtonLabel(t: TranslateDelegate): string | undefined {
return t('CANCEL', 'Cancel');
}

public override getPlaceholder(t: TranslateDelegate): string | undefined {
return t('POI_DESCRIPTION_PLACEHOLDER', 'Write a points of interest description');
}

public override get hasData(): true {
return true;
}

public override invokeCore(): boolean {
if (this._content === undefined) {
return false;
}

const domainObject = this.renderTarget.rootDomainObject.getDescendantByType(
PointsOfInterestDomainObject
);
haakonflatval-cognite marked this conversation as resolved.
Show resolved Hide resolved

if (domainObject === undefined) {
return false;
}

const poi = domainObject.addPendingPointsOfInterest(
createPointsOfInterestPropertiesFromPointAndTitle(this._point, this._content)
);

void domainObject.save().then(() => {
this.onFinish?.();
domainObject.setSelectedPointOfInterest(poi);
});

return true;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ import { type ButtonType } from '../../../components/Architecture/types';
import { PointsOfInterestCommand } from './PointsOfInterestCommand';
import { type IconName } from '../../base/utilities/IconName';

export class DeletePointsOfInterestCommand<PoIIdType> extends PointsOfInterestCommand<PoIIdType> {
export class DeleteSelectedPointsOfInterestCommand<
PoiIdType
> extends PointsOfInterestCommand<PoiIdType> {
public override get icon(): IconName {
return 'Delete';
}
Expand Down Expand Up @@ -37,7 +39,8 @@ export class DeletePointsOfInterestCommand<PoIIdType> extends PointsOfInterestCo
}

pois.removePointsOfInterest(selectedOverlay);
pois.setSelectedPointsOfInterest(undefined);
pois.setSelectedPointOfInterest(undefined);
void pois.save();

return true;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/*!
* Copyright 2024 Cognite AS
*/
import { type Vector3 } from 'three';
import { type IconName } from '../../base/utilities/IconName';
import { type TranslateDelegate, type TranslateKey } from '../../base/utilities/TranslateKey';
import { RenderTargetCommand } from '../../base/commands/RenderTargetCommand';
import { PointsOfInterestTool } from './PointsOfInterestTool';

export class InitiatePointsOfInterestCommand extends RenderTargetCommand {
private readonly _position: Vector3;

constructor(position: Vector3) {
super();
this._position = position;
}

public override get hasData(): boolean {
return true;
}

public override get icon(): IconName {
return 'Waypoint';
}

public override get tooltip(): TranslateKey {
return { key: 'CREATE_POI', fallback: 'Create point of interest' };
danpriori marked this conversation as resolved.
Show resolved Hide resolved
}

public override getLabel(t: TranslateDelegate): string {
return t('CREATE_POI', 'Create point of interest');
}

protected override invokeCore(): boolean {
const poiTool = this.renderTarget.commandsController.getToolByType(PointsOfInterestTool);

if (poiTool === undefined) {
return false;
}

this.renderTarget.commandsController.setActiveTool(poiTool);
poiTool.openCreateCommandDialog(this._position);

return true;
}
}
Original file line number Diff line number Diff line change
@@ -1,29 +1,61 @@
/*!
* Copyright 2024 Cognite AS
*/
import { type PointsOfInterestInstance, type PointsOfInterestProperties } from './models';
import { type CommentProperties, type PointsOfInterestInstance } from './models';
import { type PointsOfInterestProvider } from './PointsOfInterestProvider';

/**
* A cache that takes care of loading the pois, but also buffers changes to the overlays
* list when e.g. adding or removing pois
*/
export class PointsOfInterestCache<PoIId> {
private readonly _loadedPromise: Promise<Array<PointsOfInterestInstance<PoIId>>>;
private readonly _poiProvider: PointsOfInterestProvider<PoIId>;
export class PointsOfInterestCache<PoiId> {
private readonly _loadedPromise: Promise<Array<PointsOfInterestInstance<PoiId>>>;
private readonly _poiProvider: PointsOfInterestProvider<PoiId>;

constructor(poiProvider: PointsOfInterestProvider<PoIId>) {
private readonly _poiCommentCache = new Map<string, CommentProperties[]>();

constructor(poiProvider: PointsOfInterestProvider<PoiId>) {
this._poiProvider = poiProvider;
this._loadedPromise = poiProvider.fetchAllPointsOfInterest();
}

public async getPoiCommentsForPoi(id: PoiId): Promise<CommentProperties[]> {
const hashKey = createHashKey(id);

const cacheElement = this._poiCommentCache.get(hashKey);

if (cacheElement !== undefined) {
return cacheElement;
}

const comments = await this._poiProvider.getPointsOfInterestComments(id);
this._poiCommentCache.set(hashKey, comments);

return comments;
}

public async postCommentForPoi(id: PoiId, content: string): Promise<CommentProperties> {
const comment = await this._poiProvider.postPointsOfInterestComment(id, content);

const hashKey = createHashKey(id);
const cacheElement = this._poiCommentCache.get(hashKey);

if (cacheElement !== undefined) {
cacheElement.push(comment);
} else {
this._poiCommentCache.set(hashKey, [comment]);
}

return comment;
}

public async getFinishedOriginalLoadingPromise(): Promise<
Array<PointsOfInterestInstance<PoIId>>
Array<PointsOfInterestInstance<PoiId>>
> {
return await this._loadedPromise;
}

public async deletePointsOfInterest(poiIds: PoIId[]): Promise<void> {
public async deletePointsOfInterest(poiIds: PoiId[]): Promise<void> {
if (poiIds.length === 0) {
return;
}
Expand All @@ -32,12 +64,24 @@ export class PointsOfInterestCache<PoIId> {
}

public async savePointsOfInterest(
pois: PointsOfInterestProperties[]
): Promise<Array<PointsOfInterestInstance<PoIId>>> {
pois: Array<PointsOfInterestInstance<PoiId>>
): Promise<Array<PointsOfInterestInstance<PoiId>>> {
if (pois.length === 0) {
return [];
}

return await this._poiProvider.createPointsOfInterest(pois);
}

public getDataProvider(): PointsOfInterestProvider<PoiId> {
return this._poiProvider;
}
}

function createHashKey(id: any): string {
if (typeof id === 'string') {
return id;
}

return JSON.stringify(id);
}
Loading
Loading