Skip to content

Commit

Permalink
fix(composer): split overlay content into parts
Browse files Browse the repository at this point in the history
  • Loading branch information
sheilaXu authored and TheEvilDev committed Oct 12, 2023
1 parent 95a4be6 commit 328a33c
Show file tree
Hide file tree
Showing 4 changed files with 184 additions and 28 deletions.
2 changes: 2 additions & 0 deletions packages/scene-composer/src/common/entityModelConstants.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { KnownComponentType } from '../interfaces';

export const MAX_PROPERTY_STRING_LENGTH = 256;

// Scene Nodes
const SCENE_COMPONENT_TYPE_ID_PREFIX = 'com.amazon.iottwinmaker.3d';
export const NODE_COMPONENT_TYPE_ID = `${SCENE_COMPONENT_TYPE_ID_PREFIX}.node`;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import {
prepareWorkspace,
} from '../../../utils/entityModelUtils/sceneUtils';
import { getGlobalSettings } from '../../../common/GlobalSettings';
import { DisplayMessageCategory, IDisplayMessage } from '../../../store/internalInterfaces';

export const MatterportTagSync: React.FC = () => {
const logger = useLifecycleLogging('MatterportTagSync');
Expand All @@ -26,6 +27,8 @@ export const MatterportTagSync: React.FC = () => {
const sceneComposerId = useSceneComposerId();
const getComponentRefByType = useStore(sceneComposerId)((state) => state.getComponentRefByType);
const getSceneNodeByRef = useStore(sceneComposerId)((state) => state.getSceneNodeByRef);
const addMessages = useStore(sceneComposerId)((state) => state.addMessages);

const matterportModelId = useStore(sceneComposerId)((state) =>
state.getSceneProperty<string>(KnownSceneProperty.MatterportModelId),
);
Expand All @@ -44,6 +47,7 @@ export const MatterportTagSync: React.FC = () => {

const doSync = useCallback(async () => {
setSyncTagStatus('loading');
const errorMessages: IDisplayMessage[] = [];

try {
const layerName = MATTERPORT_TAG_LAYER_PREFIX + matterportModelId;
Expand Down Expand Up @@ -84,16 +88,23 @@ export const MatterportTagSync: React.FC = () => {
// Process Matterport tags v2
if (tags) {
for (const [key, value] of tags) {
if (oldTagMap[key]) {
await handleUpdateMatterportTag({
layerId,
sceneRootId: rootId,
ref: oldTagMap[key].nodeRef,
node: oldTagMap[key].node,
item: value,
try {
if (oldTagMap[key]) {
await handleUpdateMatterportTag({
layerId,
sceneRootId: rootId,
ref: oldTagMap[key].nodeRef,
node: oldTagMap[key].node,
item: value,
});
} else {
await handleAddMatterportTag({ layerId, sceneRootId: rootId, id: key, item: value });
}
} catch (e) {
errorMessages.push({
category: DisplayMessageCategory.Warning,
messageText: `Sync tag ${key} failed with error: ${(e as Error).message}`,
});
} else {
await handleAddMatterportTag({ layerId, sceneRootId: rootId, id: key, item: value });
}
delete oldTagMap[key];
}
Expand All @@ -109,17 +120,25 @@ export const MatterportTagSync: React.FC = () => {
continue;
}

if (oldTagMap[key]) {
await handleUpdateMatterportTag({
layerId,
sceneRootId: rootId,
ref: oldTagMap[key].nodeRef,
node: oldTagMap[key].node,
item: value,
try {
if (oldTagMap[key]) {
await handleUpdateMatterportTag({
layerId,
sceneRootId: rootId,
ref: oldTagMap[key].nodeRef,
node: oldTagMap[key].node,
item: value,
});
} else {
await handleAddMatterportTag({ layerId, sceneRootId: rootId, id: key, item: value });
}
} catch (e) {
errorMessages.push({
category: DisplayMessageCategory.Warning,
messageText: `Sync tag ${key} failed with error: ${(e as Error).message}`,
});
} else {
await handleAddMatterportTag({ layerId, sceneRootId: rootId, id: key, item: value });
}

delete oldTagMap[key];
}
}
Expand All @@ -130,10 +149,18 @@ export const MatterportTagSync: React.FC = () => {
} catch (e) {
logger?.error(String(e));
setSyncTagStatus('error');
return;
errorMessages.push({
category: DisplayMessageCategory.Warning,
messageText: `Sync tags failed with error: ${(e as Error).message}`,
});
}

setSyncTagStatus('success');
if (isEmpty(errorMessages)) {
setSyncTagStatus('success');
} else {
setSyncTagStatus('error');
addMessages(errorMessages);
}
}, [
getSceneNodeByRef,
mattertagObserver,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,72 @@ describe('createOverlayEntityComponent', () => {
});
});

it('should return expected overlay component with data rows having long content', () => {
const longContent = new Array(60).fill('0123456789').join('');
const result = createOverlayEntityComponent({
type: KnownComponentType.DataOverlay,
subType: Component.DataOverlaySubType.TextAnnotation,
dataRows: [
{
rowType: Component.DataOverlayRowType.Markdown,
content: longContent,
},
],
valueDataBindings: [],
});

expect(result.properties).toEqual({
subType: {
value: { stringValue: Component.DataOverlaySubType.TextAnnotation },
},
dataRows: {
value: {
listValue: [
{
mapValue: {
rowType: {
stringValue: Component.DataOverlayRowType.Markdown,
},
content: {
stringValue:
'0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345',
},
content_1: {
stringValue:
'6789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901',
},
content_2: {
stringValue:
'2345678901234567890123456789012345678901234567890123456789012345678901234567890123456789',
},
},
},
],
},
},
});
});

it('should return expected overlay component with data rows having long content and split to no more than 10 parts', () => {
const longContent = new Array(1000).fill('0123456789').join('');
const result = createOverlayEntityComponent({
type: KnownComponentType.DataOverlay,
subType: Component.DataOverlaySubType.TextAnnotation,
dataRows: [
{
rowType: Component.DataOverlayRowType.Markdown,
content: longContent,
},
],
valueDataBindings: [],
});
const contentKeys = Object.keys(result.properties!.dataRows.value!.listValue![0].mapValue!).filter((key) =>
key.startsWith('content'),
);

expect(contentKeys.length).toEqual(10);
});

it('should return expected tag component with rowBindings', () => {
const result = createOverlayEntityComponent({
type: KnownComponentType.DataOverlay,
Expand Down Expand Up @@ -187,6 +253,42 @@ describe('parseOverlayComp', () => {
});
});

it('should parse to expected overlay component with data rows having long content', () => {
const result = parseOverlayComp({
componentTypeId: componentTypeToId[KnownComponentType.DataOverlay],
properties: [
{
propertyName: 'subType',
propertyValue: Component.DataOverlaySubType.TextAnnotation,
},
{
propertyName: 'dataRows',
propertyValue: [
{
rowType: Component.DataOverlayRowType.Markdown,
content: '0123456789',
content_1: '0123456789',
content_2: '0123456789',
},
],
},
],
});

expect(result).toEqual({
ref: expect.anything(),
type: KnownComponentType.DataOverlay,
subType: Component.DataOverlaySubType.TextAnnotation,
dataRows: [
{
rowType: Component.DataOverlayRowType.Markdown,
content: '012345678901234567890123456789',
},
],
valueDataBindings: [],
});
});

it('should parse to expected tag component with rowBindings', () => {
const result = parseOverlayComp({
componentTypeId: componentTypeToId[KnownComponentType.DataOverlay],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { isEmpty } from 'lodash';
import { DocumentType } from '@aws-sdk/types';

import { IDataOverlayComponent, KnownComponentType } from '../../interfaces';
import { componentTypeToId } from '../../common/entityModelConstants';
import { MAX_PROPERTY_STRING_LENGTH, componentTypeToId } from '../../common/entityModelConstants';
import { Component } from '../../models/SceneModels';
import { IDataOverlayComponentInternal } from '../../store';
import { generateUUID } from '../mathUtils';
Expand Down Expand Up @@ -31,14 +31,31 @@ export const createOverlayEntityComponent = (overlay: IDataOverlayComponent): Co
[OverlayComponentProperty.DataRows]: {
value: {
listValue: overlay.dataRows.map((r) => {
const contents: Record<string, { stringValue: string }> = {};
const encodedContent = encodeURI(r.content);
// Split the content into multiple parts to avoid the max string length being exceeded
for (
let index = 0;
index < Math.min(10, Math.ceil(encodedContent.length / MAX_PROPERTY_STRING_LENGTH));
index++
) {
// the ket for first content part will not have index suffix so existing overlays can continue to work
const key =
index === 0 ? OverlayComponentProperty.Content : `${OverlayComponentProperty.Content}_${index}`;
contents[key] = {
stringValue: encodedContent.substring(
index * MAX_PROPERTY_STRING_LENGTH,
Math.min(encodedContent.length, (index + 1) * MAX_PROPERTY_STRING_LENGTH),
),
};
}

return {
mapValue: {
[OverlayComponentProperty.RowType]: {
stringValue: r.rowType,
},
[OverlayComponentProperty.Content]: {
stringValue: encodeURI(r.content),
},
...contents,
},
};
}),
Expand Down Expand Up @@ -85,10 +102,18 @@ export const parseOverlayComp = (comp: DocumentType): IDataOverlayComponentInter
}));
const rows: Component.DataOverlayMarkdownRow[] = comp['properties']
.find((p) => p['propertyName'] === OverlayComponentProperty.DataRows)
?.propertyValue?.map((r) => ({
content: decodeURI(r[OverlayComponentProperty.Content]),
rowType: r[OverlayComponentProperty.RowType],
}));
?.propertyValue?.map((r) => {
let index = 1;
let content = r[OverlayComponentProperty.Content];
while (r[`${OverlayComponentProperty.Content}_${index}`]) {
content += r[`${OverlayComponentProperty.Content}_${index}`];
index++;
}
return {
content: decodeURI(content),
rowType: r[OverlayComponentProperty.RowType],
};
});

const overlayComp: IDataOverlayComponentInternal = {
ref: generateUUID(),
Expand Down

0 comments on commit 328a33c

Please sign in to comment.