Skip to content

Commit

Permalink
UI-9566 - Ensure a best effort migration of the KPI titles even when …
Browse files Browse the repository at this point in the history
…some titles could not be successfully migrated. (#129)

* UI-9566 - Ensure kpis with titles corresponding to empty measures have the titles migrated.

* Minor improvement

* Drop kpi titles that have an empty location.

* Update src/4.3_to_5.0/getMigratedKpiTitles.ts

* Update test resource

* Apply suggestions from code review

* Update tests

* UI-9566 - Ensure a best effort migration of the kpi titles. If there is an error while migrating one of the titles the succesfully migrated titles should still be persisted.

* Update src/migrateContentServer.test.ts

* Fixups

* Use an empty folder test resource and a generator function to create the ui folder to be used for tests

* Update previously added tests to utilize the new test resource function

* Remove the now unnecessary test resource files

* Move the location of addLegacyBookmarkToUIFolder to the test resources folder

* The empty legacy ui folder test resource is truly empty

* Split out the invalid legacy bookmarks and their folder into their own test resource files

* Split out the legacy kpi bookmark and folder into their own resource files

* Create the smallLegacy ui folder with the new add legacy bookmark to UI folder function

* Apply suggestions from code review

* Ensure the test snapshots have not lost data
  • Loading branch information
NZepeda authored Sep 25, 2024
1 parent 5e3020e commit 5c4f836
Show file tree
Hide file tree
Showing 18 changed files with 593 additions and 745 deletions.
62 changes: 62 additions & 0 deletions src/4.3_to_5.0/__test_resources__/addLegacyBookmarkToUIFolder.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import { ContentRecord } from "@activeviam/activeui-sdk-5.1";
import { produce } from "immer";

/**
* Returns a new `legacyUIFolder` with the given `legacyBookmarksToAdd` added.
* Useful for creating legacyUIFolders for tests.
* Does not mutate `legacyUIFolder`.
*/
export function addLegacyBookmarkToUIFolder(
legacyUIFolder: ContentRecord,
legacyBookmarksToAdd: { [id: string]: any },
): ContentRecord<any, "response"> {
const content = legacyUIFolder.children?.bookmarks.children?.content;
const structure = legacyUIFolder.children?.bookmarks.children?.structure;

if (!content || !structure) {
throw new Error(
"Expected `legacyUIFolder` to contain the `content` and `structure` properties. Please ensure these properties exist",
);
}

return produce(legacyUIFolder, (draftFolder) => {
const existingBookmarks =
draftFolder.children!.bookmarks.children!.content!.children || {};

// Add the bookmark content
draftFolder.children!.bookmarks.children!.content!.children = {
...existingBookmarks,
...legacyBookmarksToAdd,
};

const keysOfBookmarksToAdd = Object.keys(legacyBookmarksToAdd);

const bookmarkStructureToAdd = keysOfBookmarksToAdd.reduce(
(acc: { [key: string]: ContentRecord }, key: string) => {
const bookmarkEntry = legacyBookmarksToAdd[key].entry;
acc[key] = {
entry: {
isDirectory: true,
owners: bookmarkEntry.owners,
readers: bookmarkEntry.readers,
timestamp: 1607879735685,
lastEditor: "admin",
canRead: true,
canWrite: true,
},
};
return acc;
},
{},
);

const existingStructure =
draftFolder.children!.bookmarks.children!.structure!.children || {};

// Add the bookmark structure
draftFolder.children!.bookmarks.children!.structure!.children = {
...existingStructure,
...bookmarkStructureToAdd,
};
});
}
214 changes: 214 additions & 0 deletions src/4.3_to_5.0/__test_resources__/emptyLegacyUIFolder.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,214 @@
/**
* Contains an empty /ui folder of a Content Server, useful for injecting content to be used in unit tests.
*/
export const emptyLegacyUIFolder = {
entry: {
isDirectory: true,
owners: ["admin"],
readers: ["admin"],
timestamp: 1607879725132,
lastEditor: "admin",
canRead: true,
canWrite: true,
},
children: {
bookmarks: {
entry: {
isDirectory: true,
owners: ["ROLE_CS_ROOT"],
readers: ["ROLE_USER"],
timestamp: 1607879735685,
lastEditor: "admin",
canRead: true,
canWrite: true,
},
children: {
content: {
entry: {
isDirectory: true,
owners: ["ROLE_USER"],
readers: ["ROLE_USER"],
timestamp: 1607879735685,
lastEditor: "admin",
canRead: true,
canWrite: true,
},
children: {},
},
i18n: {
entry: {
isDirectory: true,
owners: ["ROLE_CS_ROOT"],
readers: ["ROLE_USER"],
timestamp: 1607879735685,
lastEditor: "admin",
canRead: true,
canWrite: true,
},
children: {
"en-US": {
entry: {
isDirectory: true,
owners: ["ROLE_CS_ROOT"],
readers: ["ROLE_USER"],
timestamp: 1607879735685,
lastEditor: "admin",
canRead: true,
canWrite: true,
},
},
"fr-FR": {
entry: {
isDirectory: true,
owners: ["ROLE_CS_ROOT"],
readers: ["ROLE_USER"],
timestamp: 1607879735685,
lastEditor: "admin",
canRead: true,
canWrite: true,
},
},
},
},
structure: {
entry: {
isDirectory: true,
owners: ["ROLE_USER"],
readers: ["ROLE_USER"],
timestamp: 1607879735685,
lastEditor: "admin",
canRead: true,
canWrite: true,
},
children: {},
},
},
},
settings: {
entry: {
isDirectory: true,
owners: ["ROLE_CS_ROOT"],
readers: ["ROLE_USER"],
timestamp: 1607879735685,
lastEditor: "admin",
canRead: true,
canWrite: true,
},
children: {
default: {
entry: {
isDirectory: true,
owners: ["ROLE_CS_ROOT"],
readers: ["ROLE_USER"],
timestamp: 1607879735685,
lastEditor: "admin",
canRead: true,
canWrite: true,
},
children: {
preferences: {
entry: {
content: '{\n "allow": [],\n "deny": [],\n "map": {}\n}',
isDirectory: false,
owners: ["ROLE_CS_ROOT"],
readers: ["ROLE_USER"],
timestamp: 1607879735685,
lastEditor: "admin",
canRead: true,
canWrite: true,
},
},
},
},
roles: {
entry: {
isDirectory: true,
owners: ["ROLE_CS_ROOT"],
readers: ["ROLE_USER"],
timestamp: 1607879735685,
lastEditor: "admin",
canRead: true,
canWrite: true,
},
},
users: {
entry: {
isDirectory: true,
owners: ["ROLE_USER"],
readers: ["ROLE_USER"],
timestamp: 1607879735685,
lastEditor: "admin",
canRead: true,
canWrite: true,
},
children: {
user1: {
entry: {
isDirectory: true,
owners: ["user1"],
readers: ["user1"],
timestamp: 1607879735685,
lastEditor: "admin",
canRead: true,
canWrite: true,
},
children: {
preferences: {
entry: {
content:
'{\n "map": {\n "defaultPermissions": {\n "owners": [\n "user2"\n ],\n "readers": [\n "user2"\n ]\n }\n }\n}',
isDirectory: false,
owners: ["user1"],
readers: ["user1"],
timestamp: 1607879735685,
lastEditor: "admin",
canRead: true,
canWrite: true,
},
},
},
},
admin: {
entry: {
isDirectory: true,
owners: ["admin"],
readers: ["admin"],
timestamp: 1607879735685,
lastEditor: "admin",
canRead: true,
canWrite: true,
},
children: {
preferences: {
entry: {
content:
'{\n "map": {\n "tree.search.maxResults": 10,\n "global.theme": "dark-activeviam",\n "userFilters.enabled": true,\n "showLegacyCharts": true,\n "showLegacyMaps": true,\n "widgets.Tabular.drillthrough.selectedColumns": {\n "https://activepivot-ranch.activeviam.com:5900": {\n "EquityDerivativesCube": [\n {\n "functionName": "MemberValue",\n "columnName": "delta"\n },\n {\n "functionName": "Caption",\n "columnName": "delta"\n },\n {\n "functionName": "MemberValue",\n "columnName": "gamma"\n },\n {\n "functionName": "Caption",\n "columnName": "gamma"\n },\n {\n "functionName": "MemberValue",\n "columnName": "pnlVega"\n },\n {\n "functionName": "Caption",\n "columnName": "pnlVega"\n },\n {\n "functionName": "MemberValue",\n "columnName": "Desk"\n },\n {\n "functionName": "Caption",\n "columnName": "Desk"\n },\n {\n "functionName": "MemberValue",\n "columnName": "Currency"\n },\n {\n "functionName": "Caption",\n "columnName": "Currency"\n },\n {\n "functionName": "MemberValue",\n "columnName": "Date"\n },\n {\n "functionName": "Caption",\n "columnName": "Date"\n },\n {\n "columnName": "HostName",\n "functionName": "MemberValue"\n },\n {\n "columnName": "HostName",\n "functionName": "Caption"\n }\n ],\n "EquityDerivativesCubeDist": [\n {\n "functionName": "MemberValue",\n "columnName": "BumpedMtmDown"\n },\n {\n "functionName": "Caption",\n "columnName": "BumpedMtmDown"\n },\n {\n "functionName": "MemberValue",\n "columnName": "ProductQtyMultiplier"\n },\n {\n "functionName": "Caption",\n "columnName": "ProductQtyMultiplier"\n },\n {\n "functionName": "MemberValue",\n "columnName": "ProductQtyMultiplier"\n },\n {\n "functionName": "Caption",\n "columnName": "ProductQtyMultiplier"\n },\n {\n "functionName": "MemberValue",\n "columnName": "vega"\n },\n {\n "functionName": "Caption",\n "columnName": "vega"\n },\n {\n "functionName": "MemberValue",\n "columnName": "rho"\n },\n {\n "functionName": "Caption",\n "columnName": "rho"\n },\n {\n "functionName": "MemberValue",\n "columnName": "productId"\n },\n {\n "functionName": "Caption",\n "columnName": "productId"\n },\n {\n "functionName": "MemberValue",\n "columnName": "pnlVega"\n },\n {\n "functionName": "Caption",\n "columnName": "pnlVega"\n },\n {\n "functionName": "MemberValue",\n "columnName": "pnlDelta"\n },\n {\n "functionName": "Caption",\n "columnName": "pnlDelta"\n },\n {\n "functionName": "MemberValue",\n "columnName": "pnl"\n },\n {\n "functionName": "Caption",\n "columnName": "pnl"\n },\n {\n "functionName": "MemberValue",\n "columnName": "gamma"\n },\n {\n "functionName": "Caption",\n "columnName": "gamma"\n },\n {\n "functionName": "MemberValue",\n "columnName": "delta"\n },\n {\n "functionName": "Caption",\n "columnName": "delta"\n },\n {\n "functionName": "MemberValue",\n "columnName": "TradeId"\n },\n {\n "functionName": "Caption",\n "columnName": "TradeId"\n },\n {\n "functionName": "MemberValue",\n "columnName": "ProductQtyMultiplier"\n },\n {\n "functionName": "Caption",\n "columnName": "ProductQtyMultiplier"\n },\n {\n "functionName": "MemberValue",\n "columnName": "ProductQtyMultiplier"\n },\n {\n "functionName": "Caption",\n "columnName": "ProductQtyMultiplier"\n },\n {\n "functionName": "MemberValue",\n "columnName": "ProductBaseMtm"\n },\n {\n "functionName": "Caption",\n "columnName": "ProductBaseMtm"\n },\n {\n "columnName": "ProductQtyMultiplier",\n "functionName": "MemberValue"\n },\n {\n "columnName": "ProductQtyMultiplier",\n "functionName": "Caption"\n }\n ]\n }\n },\n "defaultPermissions": {\n "owners": [\n "admin"\n ],\n "readers": [\n "admin"\n ]\n },\n "project.content-editor.configuration": {\n "autoSwitchToFieldsOnEmptyWidget": true,\n "advancedModeDropdownHidden": false,\n "hideFieldsControls": false,\n "mdx-common": {\n "regularModeTab": "filters",\n "advancedModeEnabled": false,\n "advancedModeTab": "mdx"\n }\n },\n "user.contextValues": {\n "EquityDerivativesCube": {},\n "EquityDerivativesCubeDist": {}\n },\n "user.filters": {\n "EquityDerivativesCube": ["[Geography].[City].[ALL].[AllMember].[Berlin]"],\n "EquityDerivativesCubeDist": []\n },\n "filtering.hierarchyToFilterType.[Geography].[City]": "explicit",\n "filtering.hierarchyToFilterType.[Currency].[Currency]": "explicit",\n "filtering.hierarchyToFilterType.[Trades].[Trades]": "topcount",\n "servers.alias": {\n "https://activepivot-ranch.activeviam.com:5900": "http://localhost:8080"\n }\n }\n}',
isDirectory: false,
owners: ["admin"],
readers: ["admin"],
timestamp: 1607879735685,
lastEditor: "admin",
canRead: true,
canWrite: true,
},
},
},
},
},
},
},
},
version: {
entry: {
content: '{"package":"4.3.8","contentServerApi":"0.1.0"}',
isDirectory: false,
owners: ["ROLE_CS_ROOT"],
readers: ["ROLE_USER"],
timestamp: 1607879735685,
lastEditor: "admin",
canRead: true,
canWrite: true,
},
},
},
};
37 changes: 37 additions & 0 deletions src/4.3_to_5.0/__test_resources__/invalidLegacyWidgets.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
const widgetWithInvalidContainerKey = {
entry: {
content:
'{"description":"Widget with invalid container key","name":"Invalid widget","type":"container","value":{"style":{},"showTitleBar":false,"containerKey":"invalid-container-key","body":{"serverUrl":"","mdx":"SELECT NON EMPTY [Measures].[contributors.COUNT] ON COLUMNS FROM [EquityDerivativesCube] WHERE [Geography].[City].[ALL].[AllMember].[New York] CELL PROPERTIES VALUE, FORMATTED_VALUE, BACK_COLOR, FORE_COLOR, FONT_FLAGS","contextValues":{},"updateMode":"once","ranges":{}}}}',
isDirectory: false,
owners: ["admin"],
readers: ["admin"],
timestamp: 1607879735685,
lastEditor: "admin",
canRead: true,
canWrite: true,
},
};

const widgetWithFilterOnInvalidHierarchy = {
entry: {
content:
'{"description":"Widget with filter on invalid hierarchy","name":"Invalid widget","type":"container","value":{"style":{},"showTitleBar":false,"containerKey":"pivot-table","body":{"serverUrl":"","mdx":"SELECT NON EMPTY [Measures].[contributors.COUNT] ON COLUMNS FROM [EquityDerivativesCube] WHERE [Geography].[InvalidHierarchy].[ALL].[AllMember].[Member] CELL PROPERTIES VALUE, FORMATTED_VALUE, BACK_COLOR, FORE_COLOR, FONT_FLAGS","contextValues":{},"updateMode":"once","ranges":{}}}}',
isDirectory: false,
owners: ["admin"],
readers: ["admin"],
timestamp: 1607879735685,
lastEditor: "admin",
canRead: true,
canWrite: true,
},
};

/**
* Contains two legacy bookmark widgets.
* 1. Widget with an invalid container container key.
* 2. Widget with a filter on an invalid hierarchy.
*/
export const invalidLegacyWidgets = {
"158": widgetWithInvalidContainerKey,
"1231": widgetWithFilterOnInvalidHierarchy,
};
16 changes: 16 additions & 0 deletions src/4.3_to_5.0/__test_resources__/legacyDashboardBookmark.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/**
* Content entry representing a legacy dashboard containing a single pivot table.
* Useful for unit tests.
*/
export const legacyDashboardBookmark = {
entry: {
content: `{"name":"hidden grand totals","type":"container","value":{"style":{},"showTitleBar":false,"body":{"pages":[{"content":[{"key":"1","bookmark":{"name":"Untitled Pivot Table","type":"container","value":{"style":{},"showTitleBar":true,"body":{"serverUrl":"","mdx":"SELECT NON EMPTY Crossjoin(Hierarchize(DrilldownLevel([Geography].[City].[ALL].[AllMember])), Hierarchize(DrilldownLevel([Currency].[Currency].[ALL].[AllMember]))) ON ROWS, NON EMPTY [Measures].[contributors.COUNT] ON COLUMNS FROM [EquityDerivativesCube] CELL PROPERTIES VALUE, FORMATTED_VALUE, BACK_COLOR, FORE_COLOR, FONT_FLAGS","contextValues":{"mdx.hiddengrandtotals":"1"},"updateMode":"once","ranges":{"row":{"chunkSize":2000,"thresholdPercentage":0.1},"column":{"chunkSize":50,"thresholdPercentage":0.2}},"configuration":{"tabular":{"pinnedHeaderSelector":"member","sortingMode":"non-breaking","addButtonFilter":"numeric","cellRenderers":["tree-layout"],"statisticsShown":true,"columnsGroups":[{"captionProducer":"firstColumn","cellFactory":"kpi-status","selector":"kpi-status"},{"captionProducer":"firstColumn","cellFactory":"lookup","selector":"lookup"},{"captionProducer":"expiry","cellFactory":"expiry","selector":"kpi-expiry"},{"captionProducer":"columnMerge","cellFactory":{"args":{},"key":"treeCells"},"selector":"member"}],"hideAddButton":true,"defaultOptions":{},"expansion":{"automaticExpansion":true}}}},"containerKey":"pivot-table"},"writable":true}},{"key":"2","bookmark":{"name":"Untitled Chart","type":"container","value":{"style":{},"showTitleBar":true,"body":{"configuration":{"type":"plotly-line-chart","mapping":{"xAxis":["[Currency].[Currency].[Currency]"],"values":["[Measures].[pnl.FOREX]"],"splitBy":["[Booking].[Desk].[LegalEntity]"],"horizontalSubplots":[],"verticalSubplots":[]},"switchedTo":"plotly-clustered-column-chart"},"query":{"serverUrl":"","mdx":"SELECT NON EMPTY Crossjoin(Hierarchize(DrilldownLevel([Currency].[Currency])), Hierarchize(DrilldownLevel([Booking].[Desk].[ALL].[AllMember]))) ON ROWS, NON EMPTY [Measures].[pnl.FOREX] ON COLUMNS FROM [EquityDerivativesCube]","contextValues":{},"updateMode":"once"}},"containerKey":"chart"},"writable":true}}],"layout":{"children":{"0":{"ck":"2"},"1":{"ck":"1"}},"direction":"row"},"name":"Page 1","filters":{"EquityDerivativesCube":[]}}]},"containerKey":"dashboard"}}`,
isDirectory: false,
owners: ["admin"],
readers: ["admin"],
timestamp: 1607879735685,
lastEditor: "admin",
canRead: true,
canWrite: true,
},
};
Loading

0 comments on commit 5c4f836

Please sign in to comment.