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

UI-9566 - Ensure a best effort migration of the KPI titles even when some titles could not be successfully migrated. #129

Merged
merged 23 commits into from
Sep 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
dd3f796
UI-9566 - Ensure kpis with titles corresponding to empty measures hav…
NZepeda Jul 29, 2024
620462a
Minor improvement
NZepeda Jul 30, 2024
88bab6b
Drop kpi titles that have an empty location.
NZepeda Jul 30, 2024
5e66d80
Update src/4.3_to_5.0/getMigratedKpiTitles.ts
NZepeda Jul 30, 2024
206fc72
Update test resource
NZepeda Jul 30, 2024
fd9896d
Merge branch 'task/nze/UI-9566-support-migrating-empty-titles' of git…
NZepeda Jul 30, 2024
3876da1
Apply suggestions from code review
NZepeda Jul 31, 2024
85700d8
Update tests
NZepeda Jul 31, 2024
96a710a
UI-9566 - Ensure a best effort migration of the kpi titles. If there …
NZepeda Jul 31, 2024
6f50c45
Update src/migrateContentServer.test.ts
NZepeda Jul 31, 2024
71fbb2d
Fixups
NZepeda Jul 31, 2024
1d5c86c
Merge branch 'task/nze/UI-9566-support-migrating-empty-titles' of git…
NZepeda Jul 31, 2024
643e807
Merge main
NZepeda Aug 1, 2024
53e4964
Use an empty folder test resource and a generator function to create …
NZepeda Aug 14, 2024
22b5547
Update previously added tests to utilize the new test resource function
NZepeda Aug 14, 2024
31e1754
Remove the now unnecessary test resource files
NZepeda Aug 14, 2024
bdcdec4
Move the location of addLegacyBookmarkToUIFolder to the test resource…
NZepeda Sep 18, 2024
1eb0b41
The empty legacy ui folder test resource is truly empty
NZepeda Sep 18, 2024
22ecfc2
Split out the invalid legacy bookmarks and their folder into their ow…
NZepeda Sep 18, 2024
1cde91f
Split out the legacy kpi bookmark and folder into their own resource …
NZepeda Sep 18, 2024
2280099
Create the smallLegacy ui folder with the new add legacy bookmark to …
NZepeda Sep 18, 2024
26adf4b
Apply suggestions from code review
NZepeda Sep 18, 2024
dee3129
Ensure the test snapshots have not lost data
NZepeda Sep 25, 2024
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
@@ -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}',
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would prefer to not have this in emptyLegacyUIFolder and to have it actually be empty.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Nouzbe Removing this would mean losing the settings in the snapshot for the migrate_43_to_50 test since now we're generating smallLegacyUIFolder with this file and injecting the bookmark content via the addLegacyBookmarkToUIFolder. I'll keep this as is.

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
Loading