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

Open
wants to merge 16 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,26 @@ 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';

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

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

this.add(new SetQualityCommand());

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';

export class StoryBookConfig extends BaseRevealConfig {
// ==================================================
Expand Down Expand Up @@ -63,7 +63,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,45 @@
/*!
* 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');
}
danpriori marked this conversation as resolved.
Show resolved Hide resolved

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

const domainObject = this.rootDomainObject.getDescendantByType(PointsOfInterestDomainObject);
void domainObject?.postCommentForPoi(this._poi, this._content);
domainObject?.notify(Changes.addedPart);
return true;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/*!
* 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();
domainObject.setSelectedPointOfInterest(poi);

return true;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ export class DeletePointsOfInterestCommand<PoIIdType> extends PointsOfInterestCo
}

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

return true;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
/*!
* 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';
import { CreatePointsOfInterestWithDescriptionCommand } from './CreatePointsOfInterestWithDescriptionCommand';

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

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

public override get isEnabled(): boolean {
return this._position !== undefined;
}

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');
}

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

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

const poiTool = this.renderTarget.commandsController.getToolByType(PointsOfInterestTool);

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

const previousTool = this.renderTarget.commandsController.activeTool;
this.renderTarget.commandsController.setActiveTool(poiTool);
const createPointCommand = new CreatePointsOfInterestWithDescriptionCommand(this._position);

const onFinishCallback = (): void => {
poiTool.setAnchoredDialogContent(undefined);
};

const onCancelCallback = (): void => {
this.renderTarget.commandsController.setActiveTool(previousTool);
onFinishCallback();
};

createPointCommand.onFinish = onFinishCallback;
createPointCommand.onCancel = onCancelCallback;

poiTool.setAnchoredDialogContent({
contentCommands: [createPointCommand],
position: this._position,
onCloseCallback: onCancelCallback
});

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

/**
Expand All @@ -12,11 +16,43 @@ export class PointsOfInterestCache<PoIId> {
private readonly _loadedPromise: Promise<Array<PointsOfInterestInstance<PoIId>>>;
private readonly _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[]> {
haakonflatval-cognite marked this conversation as resolved.
Show resolved Hide resolved
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>>
> {
Expand All @@ -41,3 +77,11 @@ export class PointsOfInterestCache<PoIId> {
return await this._poiProvider.createPointsOfInterest(pois);
}
}

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

return JSON.stringify(id);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/*!
* Copyright 2024 Cognite AS
*/

import { DividerCommand } from '../../base/commands/DividerCommand';
import { PointsOfInterestTool } from './PointsOfInterestTool';

export class PointsOfInterestDividerCommand extends DividerCommand {
public override get isVisible(): boolean {
return this.renderTarget.commandsController.getToolByType(PointsOfInterestTool) !== undefined;
}
}
Loading