From dd3f796f30f5869e5db70bd693cc461d0065daf4 Mon Sep 17 00:00:00 2001 From: Nestor Zepeda Date: Mon, 29 Jul 2024 17:39:26 -0400 Subject: [PATCH 01/20] UI-9566 - Ensure kpis with titles corresponding to empty measures have the titles migrated. --- .../migrate_43_to_50.test.ts.snap | 57 ++++++++++++++++++- .../__test_resources__/legacyKpi.ts | 3 + .../__test_resources__/smallLegacyUIFolder.ts | 24 ++++++++ src/4.3_to_5.0/getMigratedKpiTitles.test.ts | 1 + src/4.3_to_5.0/getMigratedKpiTitles.ts | 47 ++++++++------- src/4.3_to_5.0/migrateKpi.test.ts | 1 + src/migrateContentServer.test.ts | 39 +++++++++++++ 7 files changed, 148 insertions(+), 24 deletions(-) diff --git a/src/4.3_to_5.0/__snapshots__/migrate_43_to_50.test.ts.snap b/src/4.3_to_5.0/__snapshots__/migrate_43_to_50.test.ts.snap index 8d0554a7..cca1b8e3 100644 --- a/src/4.3_to_5.0/__snapshots__/migrate_43_to_50.test.ts.snap +++ b/src/4.3_to_5.0/__snapshots__/migrate_43_to_50.test.ts.snap @@ -2497,7 +2497,24 @@ exports[`migrate_43_to_50 returns a valid ActiveUI5 /ui folder on a small input "widgets": { "children": { "content": { - "children": {}, + "children": { + "kpi": { + "entry": { + "canRead": true, + "canWrite": true, + "content": "{"query":{"mdx":"SELECT NON EMPTY Hierarchize(AddCalculatedMembers(Descendants({[Geography].[City].[ALL].[AllMember]}, 1, SELF_AND_BEFORE))) ON ROWS, NON EMPTY {[Measures].[contributors.COUNT]} ON COLUMNS FROM [EquityDerivativesCube]","updateMode":"once"},"filters":["[Geography].[City].[ALL].[AllMember].[New York]"],"queryContext":[],"mapping":{"rows":["[Geography].[City].[City]"],"columns":[],"measures":["[Measures].[contributors.COUNT]"]},"serverKey":"my-server","titles":{"":"Title with empty location","[Measures].[contributors.COUNT]":"Custom title for contributors.COUNT"}}", + "isDirectory": false, + "lastEditor": "admin", + "owners": [ + "admin", + ], + "readers": [ + "admin", + ], + "timestamp": 1607879735685, + }, + }, + }, "entry": { "isDirectory": true, "owners": [ @@ -2509,7 +2526,41 @@ exports[`migrate_43_to_50 returns a valid ActiveUI5 /ui folder on a small input }, }, "structure": { - "children": {}, + "children": { + "kpi": { + "children": { + "kpi_metadata": { + "entry": { + "canRead": true, + "canWrite": true, + "content": "{"name":"KPI","widgetKey":"kpi"}", + "isDirectory": true, + "lastEditor": "admin", + "owners": [ + "admin", + ], + "readers": [ + "admin", + ], + "timestamp": 1607879735685, + }, + }, + }, + "entry": { + "canRead": true, + "canWrite": true, + "isDirectory": true, + "lastEditor": "admin", + "owners": [ + "admin", + ], + "readers": [ + "admin", + ], + "timestamp": 1607879735685, + }, + }, + }, "entry": { "isDirectory": true, "owners": [ @@ -2568,7 +2619,7 @@ exports[`migrate_43_to_50 returns a valid ActiveUI5 /ui folder on a small input "failed": 0, "partial": 0, "removed": 0, - "success": 0, + "success": 1, }, } `; diff --git a/src/4.3_to_5.0/__test_resources__/legacyKpi.ts b/src/4.3_to_5.0/__test_resources__/legacyKpi.ts index e32e9a9b..01f27b3c 100644 --- a/src/4.3_to_5.0/__test_resources__/legacyKpi.ts +++ b/src/4.3_to_5.0/__test_resources__/legacyKpi.ts @@ -31,6 +31,9 @@ export const legacyKpi: LegacyWidgetState = { configuration: { featuredValues: { locations: { + "": { + title: "Empty measure title", + }, // "EUR, USD" is not a member of the sandbox, but it is used here to check that the script supports member names including ",". "[Currency].[Currency].[AllMember].[EUR, USD],[Measures].[contributors.COUNT]": { diff --git a/src/4.3_to_5.0/__test_resources__/smallLegacyUIFolder.ts b/src/4.3_to_5.0/__test_resources__/smallLegacyUIFolder.ts index aeb3ad70..c84ee3f3 100644 --- a/src/4.3_to_5.0/__test_resources__/smallLegacyUIFolder.ts +++ b/src/4.3_to_5.0/__test_resources__/smallLegacyUIFolder.ts @@ -47,6 +47,19 @@ export const smallLegacyUIFolder = { canWrite: true, }, }, + kpi: { + entry: { + content: + '{"description": "A KPI","name":"KPI","type":"container","value": {"style": {},"showTitleBar": true,"body": {"serverUrl": "","mdx": "SELECT NON EMPTY Hierarchize(AddCalculatedMembers(Descendants({[Geography].[City].[ALL].[AllMember]},1,SELF_AND_BEFORE))) ON ROWS,NON EMPTY {[Measures].[contributors.COUNT]} ON COLUMNS FROM (SELECT[Geography].[City].[ALL].[AllMember].[New York] ON COLUMNS FROM [EquityDerivativesCube])","contextValues": {},"updateMode": "once","ranges": {"row": {},"column": {}},"configuration": {"featuredValues": {"locations":{"":{"title": "Title with empty location"},"[Measures].[contributors.COUNT]": {"title": "Custom title for contributors.COUNT"}}}}},"containerKey":"featured-values"},"writable": true}', + isDirectory: false, + owners: ["admin"], + readers: ["admin"], + timestamp: 1607879735685, + lastEditor: "admin", + canRead: true, + canWrite: true, + }, + }, }, }, i18n: { @@ -106,6 +119,17 @@ export const smallLegacyUIFolder = { canWrite: true, }, }, + kpi: { + entry: { + isDirectory: true, + owners: ["admin"], + readers: ["admin"], + timestamp: 1607879735685, + lastEditor: "admin", + canRead: true, + canWrite: true, + }, + }, }, }, }, diff --git a/src/4.3_to_5.0/getMigratedKpiTitles.test.ts b/src/4.3_to_5.0/getMigratedKpiTitles.test.ts index f720a443..1e7b60ff 100644 --- a/src/4.3_to_5.0/getMigratedKpiTitles.test.ts +++ b/src/4.3_to_5.0/getMigratedKpiTitles.test.ts @@ -33,6 +33,7 @@ describe("getMigratedKpiTitles", () => { }); expect(migratedKpiTitles).toMatchInlineSnapshot(` { + "": "Empty measure title", "[Measures].[contributors.COUNT],[Currency].[Currency].[AllMember].[EUR, USD]": "Hello World", } `); diff --git a/src/4.3_to_5.0/getMigratedKpiTitles.ts b/src/4.3_to_5.0/getMigratedKpiTitles.ts index 11b21ebb..56e6e604 100644 --- a/src/4.3_to_5.0/getMigratedKpiTitles.ts +++ b/src/4.3_to_5.0/getMigratedKpiTitles.ts @@ -43,24 +43,27 @@ function _getLegacyKpiTitles( } = {}; const memberUniqueNames = tupleKey.split(/,(?![^\[]*\])/); for (const memberUniqueName of memberUniqueNames) { - const compoundIdentifier = - parse(memberUniqueName); - const specificCompoundIdentifier = getSpecificCompoundIdentifier( - compoundIdentifier, - { cube }, - ); - if (specificCompoundIdentifier.type === "measure") { - tuple[`[Measures].[Measures]`] = [ - specificCompoundIdentifier.measureName, - ]; - } else if (specificCompoundIdentifier.type === "member") { - const hierarchyUniqueName = quote( - specificCompoundIdentifier.dimensionName, - specificCompoundIdentifier.hierarchyName, + if (memberUniqueName) { + const compoundIdentifier = + parse(memberUniqueName); + const specificCompoundIdentifier = getSpecificCompoundIdentifier( + compoundIdentifier, + { cube }, ); - tuple[hierarchyUniqueName] = specificCompoundIdentifier.path; + if (specificCompoundIdentifier.type === "measure") { + tuple[`[Measures].[Measures]`] = [ + specificCompoundIdentifier.measureName, + ]; + } else if (specificCompoundIdentifier.type === "member") { + const hierarchyUniqueName = quote( + specificCompoundIdentifier.dimensionName, + specificCompoundIdentifier.hierarchyName, + ); + tuple[hierarchyUniqueName] = specificCompoundIdentifier.path; + } } } + legacyTitles.push({ title, tuple }); } @@ -125,12 +128,14 @@ export function getMigratedKpiTitles( }); if (measuresPositionInTuple > -1) { - const measureName = tuple[quote("Measures", "Measures")][0]; - memberUniqueNames.splice( - measuresPositionInTuple, - 0, - quote("Measures", measureName), - ); + const measureName = tuple[quote("Measures", "Measures")]?.[0]; + if (measureName) { + memberUniqueNames.splice( + measuresPositionInTuple, + 0, + quote("Measures", measureName), + ); + } } const tupleKey = memberUniqueNames.join(","); diff --git a/src/4.3_to_5.0/migrateKpi.test.ts b/src/4.3_to_5.0/migrateKpi.test.ts index 7519e845..916b05f9 100644 --- a/src/4.3_to_5.0/migrateKpi.test.ts +++ b/src/4.3_to_5.0/migrateKpi.test.ts @@ -40,6 +40,7 @@ describe("migrateKpi", () => { ], "serverKey": "my-server", "titles": { + "": "Empty measure title", "[Measures].[contributors.COUNT],[Currency].[Currency].[AllMember].[EUR, USD]": "Hello World", }, "widgetKey": "kpi", diff --git a/src/migrateContentServer.test.ts b/src/migrateContentServer.test.ts index c0667927..6081e356 100644 --- a/src/migrateContentServer.test.ts +++ b/src/migrateContentServer.test.ts @@ -232,4 +232,43 @@ describe("migrateContentServer", () => { undefined, ); }); + + it("migrates custom titles for KPIs containing a blank measure in the mdx", async () => { + const contentServer: ContentRecord = { + children: { ui: smallLegacyUIFolder, pivot: smallLegacyPivotFolder }, + entry: { + owners: [], + readers: [], + isDirectory: true, + canRead: true, + canWrite: false, + lastEditor: "Freddie Mercury", + timestamp: 0xbeef, + }, + }; + + await migrateContentServer({ + contentServer, + servers, + fromVersion: "4.3", + toVersion: "5.1", + keysOfWidgetPluginsToRemove: [], + doesReportIncludeStacks: false, + shouldUpdateFiltersMdx: true, + behaviorOnError: "keep-original", + }); + + const migratedKpiContent = JSON.parse( + contentServer.children?.ui.children?.widgets.children?.content.children?.[ + "kpi" + ].entry.content, + ); + + expect(migratedKpiContent?.titles).toMatchInlineSnapshot(` + { + "": "Title with empty location", + "[Measures].[contributors.COUNT]": "Custom title for contributors.COUNT", + } + `); + }); }); From 620462ac0ff8340b7057e2661f20c19f8c55692f Mon Sep 17 00:00:00 2001 From: Nestor Zepeda Date: Mon, 29 Jul 2024 23:18:40 -0400 Subject: [PATCH 02/20] Minor improvement --- src/4.3_to_5.0/getMigratedKpiTitles.ts | 35 +++++++++++++------------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/src/4.3_to_5.0/getMigratedKpiTitles.ts b/src/4.3_to_5.0/getMigratedKpiTitles.ts index 56e6e604..426836a4 100644 --- a/src/4.3_to_5.0/getMigratedKpiTitles.ts +++ b/src/4.3_to_5.0/getMigratedKpiTitles.ts @@ -43,24 +43,25 @@ function _getLegacyKpiTitles( } = {}; const memberUniqueNames = tupleKey.split(/,(?![^\[]*\])/); for (const memberUniqueName of memberUniqueNames) { - if (memberUniqueName) { - const compoundIdentifier = - parse(memberUniqueName); - const specificCompoundIdentifier = getSpecificCompoundIdentifier( - compoundIdentifier, - { cube }, + if (!memberUniqueName) { + continue; + } + const compoundIdentifier = + parse(memberUniqueName); + const specificCompoundIdentifier = getSpecificCompoundIdentifier( + compoundIdentifier, + { cube }, + ); + if (specificCompoundIdentifier.type === "measure") { + tuple[`[Measures].[Measures]`] = [ + specificCompoundIdentifier.measureName, + ]; + } else if (specificCompoundIdentifier.type === "member") { + const hierarchyUniqueName = quote( + specificCompoundIdentifier.dimensionName, + specificCompoundIdentifier.hierarchyName, ); - if (specificCompoundIdentifier.type === "measure") { - tuple[`[Measures].[Measures]`] = [ - specificCompoundIdentifier.measureName, - ]; - } else if (specificCompoundIdentifier.type === "member") { - const hierarchyUniqueName = quote( - specificCompoundIdentifier.dimensionName, - specificCompoundIdentifier.hierarchyName, - ); - tuple[hierarchyUniqueName] = specificCompoundIdentifier.path; - } + tuple[hierarchyUniqueName] = specificCompoundIdentifier.path; } } From 88bab6ba8d07814a91dd629a901e8061c4d9f13c Mon Sep 17 00:00:00 2001 From: Nestor Zepeda Date: Mon, 29 Jul 2024 23:42:43 -0400 Subject: [PATCH 03/20] Drop kpi titles that have an empty location. --- .../migrate_43_to_50.test.ts.snap | 2 +- src/4.3_to_5.0/getMigratedKpiTitles.test.ts | 1 - src/4.3_to_5.0/getMigratedKpiTitles.ts | 18 ++++++++++-------- src/4.3_to_5.0/migrateKpi.test.ts | 1 - src/migrateContentServer.test.ts | 3 +-- 5 files changed, 12 insertions(+), 13 deletions(-) diff --git a/src/4.3_to_5.0/__snapshots__/migrate_43_to_50.test.ts.snap b/src/4.3_to_5.0/__snapshots__/migrate_43_to_50.test.ts.snap index cca1b8e3..bd938192 100644 --- a/src/4.3_to_5.0/__snapshots__/migrate_43_to_50.test.ts.snap +++ b/src/4.3_to_5.0/__snapshots__/migrate_43_to_50.test.ts.snap @@ -2502,7 +2502,7 @@ exports[`migrate_43_to_50 returns a valid ActiveUI5 /ui folder on a small input "entry": { "canRead": true, "canWrite": true, - "content": "{"query":{"mdx":"SELECT NON EMPTY Hierarchize(AddCalculatedMembers(Descendants({[Geography].[City].[ALL].[AllMember]}, 1, SELF_AND_BEFORE))) ON ROWS, NON EMPTY {[Measures].[contributors.COUNT]} ON COLUMNS FROM [EquityDerivativesCube]","updateMode":"once"},"filters":["[Geography].[City].[ALL].[AllMember].[New York]"],"queryContext":[],"mapping":{"rows":["[Geography].[City].[City]"],"columns":[],"measures":["[Measures].[contributors.COUNT]"]},"serverKey":"my-server","titles":{"":"Title with empty location","[Measures].[contributors.COUNT]":"Custom title for contributors.COUNT"}}", + "content": "{"query":{"mdx":"SELECT NON EMPTY Hierarchize(AddCalculatedMembers(Descendants({[Geography].[City].[ALL].[AllMember]}, 1, SELF_AND_BEFORE))) ON ROWS, NON EMPTY {[Measures].[contributors.COUNT]} ON COLUMNS FROM [EquityDerivativesCube]","updateMode":"once"},"filters":["[Geography].[City].[ALL].[AllMember].[New York]"],"queryContext":[],"mapping":{"rows":["[Geography].[City].[City]"],"columns":[],"measures":["[Measures].[contributors.COUNT]"]},"serverKey":"my-server","titles":{"[Measures].[contributors.COUNT]":"Custom title for contributors.COUNT"}}", "isDirectory": false, "lastEditor": "admin", "owners": [ diff --git a/src/4.3_to_5.0/getMigratedKpiTitles.test.ts b/src/4.3_to_5.0/getMigratedKpiTitles.test.ts index 1e7b60ff..f720a443 100644 --- a/src/4.3_to_5.0/getMigratedKpiTitles.test.ts +++ b/src/4.3_to_5.0/getMigratedKpiTitles.test.ts @@ -33,7 +33,6 @@ describe("getMigratedKpiTitles", () => { }); expect(migratedKpiTitles).toMatchInlineSnapshot(` { - "": "Empty measure title", "[Measures].[contributors.COUNT],[Currency].[Currency].[AllMember].[EUR, USD]": "Hello World", } `); diff --git a/src/4.3_to_5.0/getMigratedKpiTitles.ts b/src/4.3_to_5.0/getMigratedKpiTitles.ts index 426836a4..e7d84b6d 100644 --- a/src/4.3_to_5.0/getMigratedKpiTitles.ts +++ b/src/4.3_to_5.0/getMigratedKpiTitles.ts @@ -12,6 +12,7 @@ import { getMeasuresPositionOnAxis, MdxSelect, } from "@activeviam/mdx-5.0"; +import _isEmpty from "lodash/isEmpty"; interface LegacyKpiTitle { title: string; @@ -65,7 +66,9 @@ function _getLegacyKpiTitles( } } - legacyTitles.push({ title, tuple }); + if (!_isEmpty(tuple)) { + legacyTitles.push({ title, tuple }); + } } return legacyTitles; @@ -130,13 +133,12 @@ export function getMigratedKpiTitles( if (measuresPositionInTuple > -1) { const measureName = tuple[quote("Measures", "Measures")]?.[0]; - if (measureName) { - memberUniqueNames.splice( - measuresPositionInTuple, - 0, - quote("Measures", measureName), - ); - } + + memberUniqueNames.splice( + measuresPositionInTuple, + 0, + quote("Measures", measureName), + ); } const tupleKey = memberUniqueNames.join(","); diff --git a/src/4.3_to_5.0/migrateKpi.test.ts b/src/4.3_to_5.0/migrateKpi.test.ts index 916b05f9..7519e845 100644 --- a/src/4.3_to_5.0/migrateKpi.test.ts +++ b/src/4.3_to_5.0/migrateKpi.test.ts @@ -40,7 +40,6 @@ describe("migrateKpi", () => { ], "serverKey": "my-server", "titles": { - "": "Empty measure title", "[Measures].[contributors.COUNT],[Currency].[Currency].[AllMember].[EUR, USD]": "Hello World", }, "widgetKey": "kpi", diff --git a/src/migrateContentServer.test.ts b/src/migrateContentServer.test.ts index 6081e356..97eddd51 100644 --- a/src/migrateContentServer.test.ts +++ b/src/migrateContentServer.test.ts @@ -233,7 +233,7 @@ describe("migrateContentServer", () => { ); }); - it("migrates custom titles for KPIs containing a blank measure in the mdx", async () => { + it("migrates the kpi custom titles when the original version contains a custom title with a tupleKey that is empty.", async () => { const contentServer: ContentRecord = { children: { ui: smallLegacyUIFolder, pivot: smallLegacyPivotFolder }, entry: { @@ -266,7 +266,6 @@ describe("migrateContentServer", () => { expect(migratedKpiContent?.titles).toMatchInlineSnapshot(` { - "": "Title with empty location", "[Measures].[contributors.COUNT]": "Custom title for contributors.COUNT", } `); From 5e66d807d3dd97a080673c579da984528a929826 Mon Sep 17 00:00:00 2001 From: Nestor Zepeda Date: Mon, 29 Jul 2024 23:45:55 -0400 Subject: [PATCH 04/20] Update src/4.3_to_5.0/getMigratedKpiTitles.ts --- src/4.3_to_5.0/getMigratedKpiTitles.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/4.3_to_5.0/getMigratedKpiTitles.ts b/src/4.3_to_5.0/getMigratedKpiTitles.ts index e7d84b6d..51defb1c 100644 --- a/src/4.3_to_5.0/getMigratedKpiTitles.ts +++ b/src/4.3_to_5.0/getMigratedKpiTitles.ts @@ -132,8 +132,7 @@ export function getMigratedKpiTitles( }); if (measuresPositionInTuple > -1) { - const measureName = tuple[quote("Measures", "Measures")]?.[0]; - + const measureName = tuple[quote("Measures", "Measures")][0]; memberUniqueNames.splice( measuresPositionInTuple, 0, From 206fc727bd004ea27465e70e2571916280fd6dcd Mon Sep 17 00:00:00 2001 From: Nestor Zepeda Date: Tue, 30 Jul 2024 00:00:30 -0400 Subject: [PATCH 05/20] Update test resource --- src/4.3_to_5.0/__test_resources__/smallLegacyUIFolder.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/4.3_to_5.0/__test_resources__/smallLegacyUIFolder.ts b/src/4.3_to_5.0/__test_resources__/smallLegacyUIFolder.ts index c84ee3f3..070eb16c 100644 --- a/src/4.3_to_5.0/__test_resources__/smallLegacyUIFolder.ts +++ b/src/4.3_to_5.0/__test_resources__/smallLegacyUIFolder.ts @@ -50,7 +50,7 @@ export const smallLegacyUIFolder = { kpi: { entry: { content: - '{"description": "A KPI","name":"KPI","type":"container","value": {"style": {},"showTitleBar": true,"body": {"serverUrl": "","mdx": "SELECT NON EMPTY Hierarchize(AddCalculatedMembers(Descendants({[Geography].[City].[ALL].[AllMember]},1,SELF_AND_BEFORE))) ON ROWS,NON EMPTY {[Measures].[contributors.COUNT]} ON COLUMNS FROM (SELECT[Geography].[City].[ALL].[AllMember].[New York] ON COLUMNS FROM [EquityDerivativesCube])","contextValues": {},"updateMode": "once","ranges": {"row": {},"column": {}},"configuration": {"featuredValues": {"locations":{"":{"title": "Title with empty location"},"[Measures].[contributors.COUNT]": {"title": "Custom title for contributors.COUNT"}}}}},"containerKey":"featured-values"},"writable": true}', + '{"description": "A KPI containing a custom title with an empty tupleKey","name":"KPI","type":"container","value": {"style": {},"showTitleBar": true,"body": {"serverUrl": "","mdx": "SELECT NON EMPTY Hierarchize(AddCalculatedMembers(Descendants({[Geography].[City].[ALL].[AllMember]},1,SELF_AND_BEFORE))) ON ROWS,NON EMPTY {[Measures].[contributors.COUNT]} ON COLUMNS FROM (SELECT[Geography].[City].[ALL].[AllMember].[New York] ON COLUMNS FROM [EquityDerivativesCube])","contextValues": {},"updateMode": "once","ranges": {"row": {},"column": {}},"configuration": {"featuredValues": {"locations":{"":{"title": "Title with empty location"},"[Measures].[contributors.COUNT]": {"title": "Custom title for contributors.COUNT"}}}}},"containerKey":"featured-values"},"writable": true}', isDirectory: false, owners: ["admin"], readers: ["admin"], From 3876da1400437527a8acd06a302badd0c3651f40 Mon Sep 17 00:00:00 2001 From: Nestor Zepeda Date: Wed, 31 Jul 2024 11:53:30 -0400 Subject: [PATCH 06/20] Apply suggestions from code review --- src/migrateContentServer.test.ts | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/migrateContentServer.test.ts b/src/migrateContentServer.test.ts index 97eddd51..be5b6d48 100644 --- a/src/migrateContentServer.test.ts +++ b/src/migrateContentServer.test.ts @@ -233,7 +233,7 @@ describe("migrateContentServer", () => { ); }); - it("migrates the kpi custom titles when the original version contains a custom title with a tupleKey that is empty.", async () => { + it("migrates the KPI custom titles while dropping custom titles with an empty `tupleKey` for their location", async () => { const contentServer: ContentRecord = { children: { ui: smallLegacyUIFolder, pivot: smallLegacyPivotFolder }, entry: { @@ -258,11 +258,13 @@ describe("migrateContentServer", () => { behaviorOnError: "keep-original", }); - const migratedKpiContent = JSON.parse( - contentServer.children?.ui.children?.widgets.children?.content.children?.[ + // The widget with id "kpi" contains a custom title referenced with an empty `tupleKey`. + // Because this title doesn't represent any tuple, it is dropped. + const kpiContentBeforeMigration = contentServer.children?.ui.children?.widgets.children?.content.children?.[ "kpi" - ].entry.content, - ); + ].entry.content; + + const migratedKpiContent = JSON.parse(kpiContentBeforeMigration); expect(migratedKpiContent?.titles).toMatchInlineSnapshot(` { From 85700d86bc1e85c1af717bda187bb1728f8853ec Mon Sep 17 00:00:00 2001 From: Nestor Zepeda Date: Wed, 31 Jul 2024 12:11:39 -0400 Subject: [PATCH 07/20] Update tests --- src/migrateContentServer.test.ts | 31 ++++++++++++++++++++++++++----- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/src/migrateContentServer.test.ts b/src/migrateContentServer.test.ts index be5b6d48..49066c6b 100644 --- a/src/migrateContentServer.test.ts +++ b/src/migrateContentServer.test.ts @@ -247,6 +247,8 @@ describe("migrateContentServer", () => { }, }; + const contentServerBeforeMigration = _cloneDeep(contentServer); + await migrateContentServer({ contentServer, servers, @@ -258,13 +260,32 @@ describe("migrateContentServer", () => { behaviorOnError: "keep-original", }); + const kpiContentBeforeMigration = JSON.parse( + contentServerBeforeMigration.children?.ui.children?.bookmarks.children + ?.content.children?.["kpi"].entry.content, + ); + // The widget with id "kpi" contains a custom title referenced with an empty `tupleKey`. - // Because this title doesn't represent any tuple, it is dropped. - const kpiContentBeforeMigration = contentServer.children?.ui.children?.widgets.children?.content.children?.[ + // Because this title doesn't represent any tuple, it is dropped during the migration. + expect( + kpiContentBeforeMigration.value.body.configuration["featuredValues"] + .locations, + ).toMatchInlineSnapshot(` + { + "": { + "title": "Title with empty location", + }, + "[Measures].[contributors.COUNT]": { + "title": "Custom title for contributors.COUNT", + }, + } + `); + + const migratedKpiContent = JSON.parse( + contentServer.children?.ui.children?.widgets.children?.content.children?.[ "kpi" - ].entry.content; - - const migratedKpiContent = JSON.parse(kpiContentBeforeMigration); + ].entry.content, + ); expect(migratedKpiContent?.titles).toMatchInlineSnapshot(` { From 96a710af3d9ee40525ceac962255fa47924876bd Mon Sep 17 00:00:00 2001 From: Nestor Zepeda Date: Wed, 31 Jul 2024 14:08:54 -0400 Subject: [PATCH 08/20] 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. --- .../migrate_43_to_50.test.ts.snap | 57 +---- .../__test_resources__/legacyKpi.ts | 3 - .../__test_resources__/smallLegacyUIFolder.ts | 24 -- .../smallLegacyUIFolderWithInvalidKpiTitle.ts | 241 ++++++++++++++++++ ...ts => accumulateMigratedKpiTitles.test.ts} | 11 +- ...tles.ts => accumulateMigratedKpiTitles.ts} | 110 ++++---- src/4.3_to_5.0/migrateKpi.ts | 11 +- src/migrateContentServer.test.ts | 6 +- 8 files changed, 324 insertions(+), 139 deletions(-) create mode 100644 src/4.3_to_5.0/__test_resources__/smallLegacyUIFolderWithInvalidKpiTitle.ts rename src/4.3_to_5.0/{getMigratedKpiTitles.test.ts => accumulateMigratedKpiTitles.test.ts} (76%) rename src/4.3_to_5.0/{getMigratedKpiTitles.ts => accumulateMigratedKpiTitles.ts} (53%) diff --git a/src/4.3_to_5.0/__snapshots__/migrate_43_to_50.test.ts.snap b/src/4.3_to_5.0/__snapshots__/migrate_43_to_50.test.ts.snap index bd938192..8d0554a7 100644 --- a/src/4.3_to_5.0/__snapshots__/migrate_43_to_50.test.ts.snap +++ b/src/4.3_to_5.0/__snapshots__/migrate_43_to_50.test.ts.snap @@ -2497,24 +2497,7 @@ exports[`migrate_43_to_50 returns a valid ActiveUI5 /ui folder on a small input "widgets": { "children": { "content": { - "children": { - "kpi": { - "entry": { - "canRead": true, - "canWrite": true, - "content": "{"query":{"mdx":"SELECT NON EMPTY Hierarchize(AddCalculatedMembers(Descendants({[Geography].[City].[ALL].[AllMember]}, 1, SELF_AND_BEFORE))) ON ROWS, NON EMPTY {[Measures].[contributors.COUNT]} ON COLUMNS FROM [EquityDerivativesCube]","updateMode":"once"},"filters":["[Geography].[City].[ALL].[AllMember].[New York]"],"queryContext":[],"mapping":{"rows":["[Geography].[City].[City]"],"columns":[],"measures":["[Measures].[contributors.COUNT]"]},"serverKey":"my-server","titles":{"[Measures].[contributors.COUNT]":"Custom title for contributors.COUNT"}}", - "isDirectory": false, - "lastEditor": "admin", - "owners": [ - "admin", - ], - "readers": [ - "admin", - ], - "timestamp": 1607879735685, - }, - }, - }, + "children": {}, "entry": { "isDirectory": true, "owners": [ @@ -2526,41 +2509,7 @@ exports[`migrate_43_to_50 returns a valid ActiveUI5 /ui folder on a small input }, }, "structure": { - "children": { - "kpi": { - "children": { - "kpi_metadata": { - "entry": { - "canRead": true, - "canWrite": true, - "content": "{"name":"KPI","widgetKey":"kpi"}", - "isDirectory": true, - "lastEditor": "admin", - "owners": [ - "admin", - ], - "readers": [ - "admin", - ], - "timestamp": 1607879735685, - }, - }, - }, - "entry": { - "canRead": true, - "canWrite": true, - "isDirectory": true, - "lastEditor": "admin", - "owners": [ - "admin", - ], - "readers": [ - "admin", - ], - "timestamp": 1607879735685, - }, - }, - }, + "children": {}, "entry": { "isDirectory": true, "owners": [ @@ -2619,7 +2568,7 @@ exports[`migrate_43_to_50 returns a valid ActiveUI5 /ui folder on a small input "failed": 0, "partial": 0, "removed": 0, - "success": 1, + "success": 0, }, } `; diff --git a/src/4.3_to_5.0/__test_resources__/legacyKpi.ts b/src/4.3_to_5.0/__test_resources__/legacyKpi.ts index 01f27b3c..e32e9a9b 100644 --- a/src/4.3_to_5.0/__test_resources__/legacyKpi.ts +++ b/src/4.3_to_5.0/__test_resources__/legacyKpi.ts @@ -31,9 +31,6 @@ export const legacyKpi: LegacyWidgetState = { configuration: { featuredValues: { locations: { - "": { - title: "Empty measure title", - }, // "EUR, USD" is not a member of the sandbox, but it is used here to check that the script supports member names including ",". "[Currency].[Currency].[AllMember].[EUR, USD],[Measures].[contributors.COUNT]": { diff --git a/src/4.3_to_5.0/__test_resources__/smallLegacyUIFolder.ts b/src/4.3_to_5.0/__test_resources__/smallLegacyUIFolder.ts index 070eb16c..aeb3ad70 100644 --- a/src/4.3_to_5.0/__test_resources__/smallLegacyUIFolder.ts +++ b/src/4.3_to_5.0/__test_resources__/smallLegacyUIFolder.ts @@ -47,19 +47,6 @@ export const smallLegacyUIFolder = { canWrite: true, }, }, - kpi: { - entry: { - content: - '{"description": "A KPI containing a custom title with an empty tupleKey","name":"KPI","type":"container","value": {"style": {},"showTitleBar": true,"body": {"serverUrl": "","mdx": "SELECT NON EMPTY Hierarchize(AddCalculatedMembers(Descendants({[Geography].[City].[ALL].[AllMember]},1,SELF_AND_BEFORE))) ON ROWS,NON EMPTY {[Measures].[contributors.COUNT]} ON COLUMNS FROM (SELECT[Geography].[City].[ALL].[AllMember].[New York] ON COLUMNS FROM [EquityDerivativesCube])","contextValues": {},"updateMode": "once","ranges": {"row": {},"column": {}},"configuration": {"featuredValues": {"locations":{"":{"title": "Title with empty location"},"[Measures].[contributors.COUNT]": {"title": "Custom title for contributors.COUNT"}}}}},"containerKey":"featured-values"},"writable": true}', - isDirectory: false, - owners: ["admin"], - readers: ["admin"], - timestamp: 1607879735685, - lastEditor: "admin", - canRead: true, - canWrite: true, - }, - }, }, }, i18n: { @@ -119,17 +106,6 @@ export const smallLegacyUIFolder = { canWrite: true, }, }, - kpi: { - entry: { - isDirectory: true, - owners: ["admin"], - readers: ["admin"], - timestamp: 1607879735685, - lastEditor: "admin", - canRead: true, - canWrite: true, - }, - }, }, }, }, diff --git a/src/4.3_to_5.0/__test_resources__/smallLegacyUIFolderWithInvalidKpiTitle.ts b/src/4.3_to_5.0/__test_resources__/smallLegacyUIFolderWithInvalidKpiTitle.ts new file mode 100644 index 00000000..5e322132 --- /dev/null +++ b/src/4.3_to_5.0/__test_resources__/smallLegacyUIFolderWithInvalidKpiTitle.ts @@ -0,0 +1,241 @@ +/** + * The shortened version of the content of the /ui folder on a Content Server, useful for unit tests. + * Contains a KPI widget containing a custom title with an empty `tupleKey` for its location. + */ +export const smallLegacyUIFolderWithInvalidKpiTitle = { + 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: { + kpi: { + entry: { + content: + '{"description": "A KPI containing a custom title with an empty tupleKey","name":"KPI","type":"container","value": {"style": {},"showTitleBar": true,"body": {"serverUrl": "","mdx": "SELECT NON EMPTY Hierarchize(AddCalculatedMembers(Descendants({[Geography].[City].[ALL].[AllMember]},1,SELF_AND_BEFORE))) ON ROWS,NON EMPTY {[Measures].[contributors.COUNT]} ON COLUMNS FROM (SELECT[Geography].[City].[ALL].[AllMember].[New York] ON COLUMNS FROM [EquityDerivativesCube])","contextValues": {},"updateMode": "once","ranges": {"row": {},"column": {}},"configuration": {"featuredValues": {"locations":{"":{"title": "Title with empty location"},"[Measures].[contributors.COUNT]": {"title": "Custom title for contributors.COUNT"}}}}},"containerKey":"featured-values"},"writable": true}', + isDirectory: false, + owners: ["admin"], + readers: ["admin"], + timestamp: 1607879735685, + lastEditor: "admin", + canRead: true, + canWrite: true, + }, + }, + }, + }, + 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: { + kpi: { + entry: { + isDirectory: true, + owners: ["admin"], + readers: ["admin"], + timestamp: 1607879735685, + lastEditor: "admin", + canRead: true, + canWrite: true, + }, + }, + }, + }, + }, + }, + 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, + }, + }, + }, +}; diff --git a/src/4.3_to_5.0/getMigratedKpiTitles.test.ts b/src/4.3_to_5.0/accumulateMigratedKpiTitles.test.ts similarity index 76% rename from src/4.3_to_5.0/getMigratedKpiTitles.test.ts rename to src/4.3_to_5.0/accumulateMigratedKpiTitles.test.ts index f720a443..ed2c87fc 100644 --- a/src/4.3_to_5.0/getMigratedKpiTitles.test.ts +++ b/src/4.3_to_5.0/accumulateMigratedKpiTitles.test.ts @@ -1,12 +1,13 @@ import { dataModelsForTests } from "@activeviam/data-model-5.0"; -import { getMigratedKpiTitles } from "./getMigratedKpiTitles"; +import { accumulateMigratedKpiTitles } from "./accumulateMigratedKpiTitles"; import { legacyKpi } from "./__test_resources__/legacyKpi"; import { _getQueryInLegacyWidgetState } from "./_getQueryInLegacyWidgetState"; import { MdxSelect, parse } from "@activeviam/mdx-5.0"; +import { KpiWidgetState } from "@activeviam/activeui-sdk-5.0"; const cube = dataModelsForTests.sandbox.catalogs[0].cubes[0]; -describe("getMigratedKpiTitles", () => { +describe("accumulateMigratedKpiTitles", () => { it("returns the migrated KPI titles corresponding to the legacy KPI state, ready to be used in Atoti UI 5.0", () => { const legacyQuery = _getQueryInLegacyWidgetState(legacyKpi); @@ -15,7 +16,9 @@ describe("getMigratedKpiTitles", () => { } const legacyMdx = parse(legacyQuery.mdx); - const migratedKpiTitles = getMigratedKpiTitles(legacyKpi, { + const migratedTitles: KpiWidgetState["titles"] = {}; + accumulateMigratedKpiTitles(legacyKpi, { + migratedTitles, cube, legacyMdx, mapping: { @@ -31,7 +34,7 @@ describe("getMigratedKpiTitles", () => { ], }, }); - expect(migratedKpiTitles).toMatchInlineSnapshot(` + expect(migratedTitles).toMatchInlineSnapshot(` { "[Measures].[contributors.COUNT],[Currency].[Currency].[AllMember].[EUR, USD]": "Hello World", } diff --git a/src/4.3_to_5.0/getMigratedKpiTitles.ts b/src/4.3_to_5.0/accumulateMigratedKpiTitles.ts similarity index 53% rename from src/4.3_to_5.0/getMigratedKpiTitles.ts rename to src/4.3_to_5.0/accumulateMigratedKpiTitles.ts index 51defb1c..2abb7abf 100644 --- a/src/4.3_to_5.0/getMigratedKpiTitles.ts +++ b/src/4.3_to_5.0/accumulateMigratedKpiTitles.ts @@ -12,7 +12,6 @@ import { getMeasuresPositionOnAxis, MdxSelect, } from "@activeviam/mdx-5.0"; -import _isEmpty from "lodash/isEmpty"; interface LegacyKpiTitle { title: string; @@ -44,55 +43,55 @@ function _getLegacyKpiTitles( } = {}; const memberUniqueNames = tupleKey.split(/,(?![^\[]*\])/); for (const memberUniqueName of memberUniqueNames) { - if (!memberUniqueName) { - continue; - } - const compoundIdentifier = - parse(memberUniqueName); - const specificCompoundIdentifier = getSpecificCompoundIdentifier( - compoundIdentifier, - { cube }, - ); - if (specificCompoundIdentifier.type === "measure") { - tuple[`[Measures].[Measures]`] = [ - specificCompoundIdentifier.measureName, - ]; - } else if (specificCompoundIdentifier.type === "member") { - const hierarchyUniqueName = quote( - specificCompoundIdentifier.dimensionName, - specificCompoundIdentifier.hierarchyName, + if (memberUniqueName) { + const compoundIdentifier = + parse(memberUniqueName); + const specificCompoundIdentifier = getSpecificCompoundIdentifier( + compoundIdentifier, + { cube }, ); - tuple[hierarchyUniqueName] = specificCompoundIdentifier.path; + if (specificCompoundIdentifier.type === "measure") { + tuple[`[Measures].[Measures]`] = [ + specificCompoundIdentifier.measureName, + ]; + } else if (specificCompoundIdentifier.type === "member") { + const hierarchyUniqueName = quote( + specificCompoundIdentifier.dimensionName, + specificCompoundIdentifier.hierarchyName, + ); + tuple[hierarchyUniqueName] = specificCompoundIdentifier.path; + } } } - if (!_isEmpty(tuple)) { - legacyTitles.push({ title, tuple }); - } + legacyTitles.push({ title, tuple }); } return legacyTitles; } /** - * Returns the migrated KPI widget titles corresponding to legacyKpiState. + * Accumulates the migrated KPI widget titles corresponding to legacyKpiState. + * Mutates `migratedTitles`. */ -export function getMigratedKpiTitles( +export function accumulateMigratedKpiTitles( // Legacy widget states are not typed. // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types legacyKpiState: any, { + migratedTitles = {}, legacyMdx, mapping, cube, }: { + migratedTitles: KpiWidgetState["titles"]; legacyMdx: MdxSelect; mapping: DataVisualizationWidgetMapping; cube: Cube; }, -): KpiWidgetState["titles"] { +): void { const legacyTitles = _getLegacyKpiTitles(legacyKpiState, { cube }); - const migratedTitles: KpiWidgetState["titles"] = {}; + const errors: Error[] = []; const numberOfColumnFields = mapping.columns?.length ?? 0; @@ -114,35 +113,44 @@ export function getMigratedKpiTitles( const ordinalFields = [...(mapping.columns ?? []), ...(mapping.rows ?? [])]; legacyTitles.forEach(({ title, tuple }) => { - const memberUniqueNames: string[] = []; - - ordinalFields.forEach((field) => { - if (field.type === "hierarchy") { - const hierarchyUniqueName = quote( - field.dimensionName, - field.hierarchyName, - ); - const namePath = tuple[hierarchyUniqueName]; - if (namePath) { - memberUniqueNames.push( - `${hierarchyUniqueName}.${quote(...namePath)}`, + try { + const memberUniqueNames: string[] = []; + + ordinalFields.forEach((field) => { + if (field.type === "hierarchy") { + const hierarchyUniqueName = quote( + field.dimensionName, + field.hierarchyName, ); + const namePath = tuple[hierarchyUniqueName]; + if (namePath) { + memberUniqueNames.push( + `${hierarchyUniqueName}.${quote(...namePath)}`, + ); + } } + }); + + if (measuresPositionInTuple > -1) { + const measureName = tuple[quote("Measures", "Measures")][0]; + memberUniqueNames.splice( + measuresPositionInTuple, + 0, + quote("Measures", measureName), + ); } - }); - - if (measuresPositionInTuple > -1) { - const measureName = tuple[quote("Measures", "Measures")][0]; - memberUniqueNames.splice( - measuresPositionInTuple, - 0, - quote("Measures", measureName), - ); - } - const tupleKey = memberUniqueNames.join(","); - migratedTitles[tupleKey] = title; + const tupleKey = memberUniqueNames.join(","); + migratedTitles[tupleKey] = title; + } catch (error) { + errors.push(error as Error); + } }); - return migratedTitles; + if (errors.length > 0) { + throw new Error( + `One or more errors occurred while migrating the titles for the kpi named ${legacyKpiState.name}: ` + + errors.map((e) => e.message).join(", "), + ); + } } diff --git a/src/4.3_to_5.0/migrateKpi.ts b/src/4.3_to_5.0/migrateKpi.ts index 96c799a9..592389de 100644 --- a/src/4.3_to_5.0/migrateKpi.ts +++ b/src/4.3_to_5.0/migrateKpi.ts @@ -29,7 +29,7 @@ import { _getQueryInLegacyWidgetState } from "./_getQueryInLegacyWidgetState"; import { _getTargetCubeFromServerUrl } from "./_getTargetCubeFromServerUrl"; import { _migrateQuery } from "./_migrateQuery"; import { produce } from "immer"; -import { getMigratedKpiTitles } from "./getMigratedKpiTitles"; +import { accumulateMigratedKpiTitles } from "./accumulateMigratedKpiTitles"; import { PartialMigrationError } from "../PartialMigrationError"; const moveExpressionToWithClause = ( @@ -210,13 +210,15 @@ export function migrateKpi( }), }; + const migratedTitles: KpiWidgetState["titles"] = {}; try { if (legacyMdx) { // Migrate manually entered KPI titles. - const migratedTitles = getMigratedKpiTitles(legacyKpiState, { + accumulateMigratedKpiTitles(legacyKpiState, { cube, mapping, legacyMdx, + migratedTitles, }); if (migratedTitles && Object.keys(migratedTitles).length > 0) { migratedWidgetState.titles = migratedTitles; @@ -224,6 +226,11 @@ export function migrateKpi( } } catch (error) { // Migrating the KPI titles is a best effort. + // If there is an error while migrating one of the titles, the successfully migrated titles are still persisted. + if (migratedTitles && Object.keys(migratedTitles).length > 0) { + migratedWidgetState.titles = migratedTitles; + } + // The migration script should not fail if this part errors. throw new PartialMigrationError( `Could not migrate the titles of the featured values widget named "${legacyKpiState.name}"`, diff --git a/src/migrateContentServer.test.ts b/src/migrateContentServer.test.ts index 49066c6b..702b2638 100644 --- a/src/migrateContentServer.test.ts +++ b/src/migrateContentServer.test.ts @@ -4,6 +4,7 @@ import { smallLegacyPivotFolder } from "./4.3_to_5.0/__test_resources__/smallLeg import { smallLegacyUIFolder } from "./4.3_to_5.0/__test_resources__/smallLegacyUIFolder"; import { migrateContentServer } from "./migrateContentServer"; import _cloneDeep from "lodash/cloneDeep"; +import { smallLegacyUIFolderWithInvalidKpiTitle } from "./4.3_to_5.0/__test_resources__/smallLegacyUIFolderWithInvalidKpiTitle"; jest.mock(`./4.3_to_5.0/generateId`, () => { let counter = 0; @@ -235,7 +236,10 @@ describe("migrateContentServer", () => { it("migrates the KPI custom titles while dropping custom titles with an empty `tupleKey` for their location", async () => { const contentServer: ContentRecord = { - children: { ui: smallLegacyUIFolder, pivot: smallLegacyPivotFolder }, + children: { + ui: smallLegacyUIFolderWithInvalidKpiTitle, + pivot: smallLegacyPivotFolder, + }, entry: { owners: [], readers: [], From 6f50c45bf7d23391f4b83469b918cd6e1f27d949 Mon Sep 17 00:00:00 2001 From: Nestor Zepeda Date: Wed, 31 Jul 2024 14:15:45 -0400 Subject: [PATCH 09/20] Update src/migrateContentServer.test.ts --- src/migrateContentServer.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/migrateContentServer.test.ts b/src/migrateContentServer.test.ts index 702b2638..d4fd5dd5 100644 --- a/src/migrateContentServer.test.ts +++ b/src/migrateContentServer.test.ts @@ -234,7 +234,7 @@ describe("migrateContentServer", () => { ); }); - it("migrates the KPI custom titles while dropping custom titles with an empty `tupleKey` for their location", async () => { + it("migrates the KPI custom titles while dropping custom titles that could not be successfully migrated", async () => { const contentServer: ContentRecord = { children: { ui: smallLegacyUIFolderWithInvalidKpiTitle, From 71fbb2dd1c39cdcedfb1e98a990714ded976e184 Mon Sep 17 00:00:00 2001 From: Nestor Zepeda Date: Wed, 31 Jul 2024 14:30:12 -0400 Subject: [PATCH 10/20] Fixups --- .../smallLegacyUIFolderWithInvalidKpiTitle.ts | 2 +- src/4.3_to_5.0/accumulateMigratedKpiTitles.test.ts | 2 +- src/migrateContentServer.test.ts | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/4.3_to_5.0/__test_resources__/smallLegacyUIFolderWithInvalidKpiTitle.ts b/src/4.3_to_5.0/__test_resources__/smallLegacyUIFolderWithInvalidKpiTitle.ts index 5e322132..c8a8b597 100644 --- a/src/4.3_to_5.0/__test_resources__/smallLegacyUIFolderWithInvalidKpiTitle.ts +++ b/src/4.3_to_5.0/__test_resources__/smallLegacyUIFolderWithInvalidKpiTitle.ts @@ -38,7 +38,7 @@ export const smallLegacyUIFolderWithInvalidKpiTitle = { kpi: { entry: { content: - '{"description": "A KPI containing a custom title with an empty tupleKey","name":"KPI","type":"container","value": {"style": {},"showTitleBar": true,"body": {"serverUrl": "","mdx": "SELECT NON EMPTY Hierarchize(AddCalculatedMembers(Descendants({[Geography].[City].[ALL].[AllMember]},1,SELF_AND_BEFORE))) ON ROWS,NON EMPTY {[Measures].[contributors.COUNT]} ON COLUMNS FROM (SELECT[Geography].[City].[ALL].[AllMember].[New York] ON COLUMNS FROM [EquityDerivativesCube])","contextValues": {},"updateMode": "once","ranges": {"row": {},"column": {}},"configuration": {"featuredValues": {"locations":{"":{"title": "Title with empty location"},"[Measures].[contributors.COUNT]": {"title": "Custom title for contributors.COUNT"}}}}},"containerKey":"featured-values"},"writable": true}', + '{"description": "A KPI containing a custom title with an empty tupleKey","name":"KPI","type":"container","value": {"style": {},"showTitleBar": true,"body": {"serverUrl": "","mdx": "SELECT NON EMPTY Hierarchize(AddCalculatedMembers(Descendants({[Geography].[City].[ALL].[AllMember]},1,SELF_AND_BEFORE))) ON ROWS,NON EMPTY {[Measures].[contributors.COUNT]} ON COLUMNS FROM (SELECT[Geography].[City].[ALL].[AllMember].[New York] ON COLUMNS FROM [EquityDerivativesCube])","contextValues": {},"updateMode": "once","ranges": {"row": {},"column": {}},"configuration": {"featuredValues": {"locations":{"":{"title": "Title with empty tupleKey"},"[Measures].[contributors.COUNT]": {"title": "Custom title for contributors.COUNT"}}}}},"containerKey":"featured-values"},"writable": true}', isDirectory: false, owners: ["admin"], readers: ["admin"], diff --git a/src/4.3_to_5.0/accumulateMigratedKpiTitles.test.ts b/src/4.3_to_5.0/accumulateMigratedKpiTitles.test.ts index ed2c87fc..fee405dc 100644 --- a/src/4.3_to_5.0/accumulateMigratedKpiTitles.test.ts +++ b/src/4.3_to_5.0/accumulateMigratedKpiTitles.test.ts @@ -8,7 +8,7 @@ import { KpiWidgetState } from "@activeviam/activeui-sdk-5.0"; const cube = dataModelsForTests.sandbox.catalogs[0].cubes[0]; describe("accumulateMigratedKpiTitles", () => { - it("returns the migrated KPI titles corresponding to the legacy KPI state, ready to be used in Atoti UI 5.0", () => { + it("accumulates the migrated KPI titles corresponding to the legacy KPI state, ready to be used in Atoti UI 5.0", () => { const legacyQuery = _getQueryInLegacyWidgetState(legacyKpi); if (!legacyQuery || !legacyQuery.mdx) { diff --git a/src/migrateContentServer.test.ts b/src/migrateContentServer.test.ts index 702b2638..4c39ee64 100644 --- a/src/migrateContentServer.test.ts +++ b/src/migrateContentServer.test.ts @@ -269,15 +269,13 @@ describe("migrateContentServer", () => { ?.content.children?.["kpi"].entry.content, ); - // The widget with id "kpi" contains a custom title referenced with an empty `tupleKey`. - // Because this title doesn't represent any tuple, it is dropped during the migration. expect( kpiContentBeforeMigration.value.body.configuration["featuredValues"] .locations, ).toMatchInlineSnapshot(` { "": { - "title": "Title with empty location", + "title": "Title with empty tupleKey", }, "[Measures].[contributors.COUNT]": { "title": "Custom title for contributors.COUNT", @@ -285,6 +283,8 @@ describe("migrateContentServer", () => { } `); + // The widget with id "kpi" contains a custom title referenced with an empty `tupleKey`. + // Because this is not a valid `tupleKey`, the title is dropped. const migratedKpiContent = JSON.parse( contentServer.children?.ui.children?.widgets.children?.content.children?.[ "kpi" From 53e49641ffe4c194b2d901b7436d222244acd208 Mon Sep 17 00:00:00 2001 From: Nestor Zepeda Date: Wed, 14 Aug 2024 10:41:34 -0400 Subject: [PATCH 11/20] Use an empty folder test resource and a generator function to create the ui folder to be used for tests --- .../__test_resources__/emptyLegacyUIFolder.ts | 214 ++++++++++++++++++ src/4.3_to_5.0/addLegacyBookmarkToUIFolder.ts | 61 +++++ src/migrateContentServer.test.ts | 24 +- 3 files changed, 297 insertions(+), 2 deletions(-) create mode 100644 src/4.3_to_5.0/__test_resources__/emptyLegacyUIFolder.ts create mode 100644 src/4.3_to_5.0/addLegacyBookmarkToUIFolder.ts diff --git a/src/4.3_to_5.0/__test_resources__/emptyLegacyUIFolder.ts b/src/4.3_to_5.0/__test_resources__/emptyLegacyUIFolder.ts new file mode 100644 index 00000000..5243ecd8 --- /dev/null +++ b/src/4.3_to_5.0/__test_resources__/emptyLegacyUIFolder.ts @@ -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, + }, + }, + }, +}; diff --git a/src/4.3_to_5.0/addLegacyBookmarkToUIFolder.ts b/src/4.3_to_5.0/addLegacyBookmarkToUIFolder.ts new file mode 100644 index 00000000..42d09096 --- /dev/null +++ b/src/4.3_to_5.0/addLegacyBookmarkToUIFolder.ts @@ -0,0 +1,61 @@ +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 { + 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) => { + acc[key] = { + entry: { + isDirectory: true, + owners: [], + 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, + }; + }); +} diff --git a/src/migrateContentServer.test.ts b/src/migrateContentServer.test.ts index 9a22649e..45f0921d 100644 --- a/src/migrateContentServer.test.ts +++ b/src/migrateContentServer.test.ts @@ -4,8 +4,9 @@ import { smallLegacyPivotFolder } from "./4.3_to_5.0/__test_resources__/smallLeg import { smallLegacyUIFolder } from "./4.3_to_5.0/__test_resources__/smallLegacyUIFolder"; import { migrateContentServer } from "./migrateContentServer"; import _cloneDeep from "lodash/cloneDeep"; -import { smallLegacyUIFolderWithInvalidKpiTitle } from "./4.3_to_5.0/__test_resources__/smallLegacyUIFolderWithInvalidKpiTitle"; import { smallLegacyUIFolderWithInvalidWidget } from "./4.3_to_5.0/__test_resources__/smallLegacyUIFolderWithInvalidWidget"; +import { addLegacyBookmarkToUIFolder } from "./4.3_to_5.0/addLegacyBookmarkToUIFolder"; +import { emptyLegacyUIFolder } from "./4.3_to_5.0/__test_resources__/emptyLegacyUIFolder"; jest.mock(`./4.3_to_5.0/generateId`, () => { let counter = 0; @@ -339,9 +340,28 @@ describe("migrateContentServer", () => { }); it("migrates the KPI custom titles while dropping custom titles that could not be successfully migrated", async () => { + const legacyUIFolderWithInvalidKpiTitle = addLegacyBookmarkToUIFolder( + emptyLegacyUIFolder, + { + kpi: { + entry: { + content: + '{"description": "A KPI containing a custom title with an empty tupleKey","name":"KPI","type":"container","value": {"style": {},"showTitleBar": true,"body": {"serverUrl": "","mdx": "SELECT NON EMPTY Hierarchize(AddCalculatedMembers(Descendants({[Geography].[City].[ALL].[AllMember]},1,SELF_AND_BEFORE))) ON ROWS,NON EMPTY {[Measures].[contributors.COUNT]} ON COLUMNS FROM (SELECT[Geography].[City].[ALL].[AllMember].[New York] ON COLUMNS FROM [EquityDerivativesCube])","contextValues": {},"updateMode": "once","ranges": {"row": {},"column": {}},"configuration": {"featuredValues": {"locations":{"":{"title": "Title with empty tupleKey"},"[Measures].[contributors.COUNT]": {"title": "Custom title for contributors.COUNT"}}}}},"containerKey":"featured-values"},"writable": true}', + isDirectory: false, + owners: ["admin"], + readers: ["admin"], + timestamp: 1607879735685, + lastEditor: "admin", + canRead: true, + canWrite: true, + }, + }, + }, + ); + const contentServer: ContentRecord = { children: { - ui: smallLegacyUIFolderWithInvalidKpiTitle, + ui: legacyUIFolderWithInvalidKpiTitle, pivot: smallLegacyPivotFolder, }, entry: { From 22b55477ea773d363f9a36520abc0dd8eb20ef98 Mon Sep 17 00:00:00 2001 From: Nestor Zepeda Date: Wed, 14 Aug 2024 10:50:25 -0400 Subject: [PATCH 12/20] Update previously added tests to utilize the new test resource function --- src/migrateContentServer.test.ts | 63 ++++++++++++++++++++++++++++++-- 1 file changed, 60 insertions(+), 3 deletions(-) diff --git a/src/migrateContentServer.test.ts b/src/migrateContentServer.test.ts index 45f0921d..146e0ca2 100644 --- a/src/migrateContentServer.test.ts +++ b/src/migrateContentServer.test.ts @@ -4,7 +4,6 @@ import { smallLegacyPivotFolder } from "./4.3_to_5.0/__test_resources__/smallLeg import { smallLegacyUIFolder } from "./4.3_to_5.0/__test_resources__/smallLegacyUIFolder"; import { migrateContentServer } from "./migrateContentServer"; import _cloneDeep from "lodash/cloneDeep"; -import { smallLegacyUIFolderWithInvalidWidget } from "./4.3_to_5.0/__test_resources__/smallLegacyUIFolderWithInvalidWidget"; import { addLegacyBookmarkToUIFolder } from "./4.3_to_5.0/addLegacyBookmarkToUIFolder"; import { emptyLegacyUIFolder } from "./4.3_to_5.0/__test_resources__/emptyLegacyUIFolder"; @@ -20,6 +19,54 @@ jest.mock(`./4.3_to_5.0/generateId`, () => { }; }); +/** + * Contains three legacy bookmark widgets. + * 1. Widget with an invalid container container key. + * 2. Widget with a filter on an invalid hierarchy. + * 3. A valid widget. + */ +const bookmarkContentWithInvalidWidgets = { + "158": { + 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, + }, + }, + "1231": { + 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, + }, + }, + "777": { + entry: { + content: + '{"description": "Valid widget","name": "Valid 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].[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, + }, + }, +}; + describe("migrateContentServer", () => { it("migrates calculated measures from the /pivot folder to the /ui folder when migrating from 4.3 to 5.0", async () => { const contentServer: ContentRecord = { @@ -237,9 +284,14 @@ describe("migrateContentServer", () => { }); it("keeps the original item untouched, as before the whole migration when the item cannot be migrated due to an error and the `behaviorOnError` flag is set to `keep-original`.", async () => { + const legacyUIFolderWithInvalidWidgets = addLegacyBookmarkToUIFolder( + emptyLegacyUIFolder, + bookmarkContentWithInvalidWidgets, + ); + const contentServer: ContentRecord = { children: { - ui: smallLegacyUIFolderWithInvalidWidget, + ui: legacyUIFolderWithInvalidWidgets, pivot: smallLegacyPivotFolder, }, entry: { @@ -287,9 +339,14 @@ describe("migrateContentServer", () => { }); it("keeps the 5.0 version of the widget, when migrating from 4.3 to 5.1 with `behaviorOnError` set to `keep-last-successful-version` and the 5.0 to 5.1 step fails", async () => { + const legacyUIFolderWithInvalidWidgets = addLegacyBookmarkToUIFolder( + emptyLegacyUIFolder, + bookmarkContentWithInvalidWidgets, + ); + const contentServer: ContentRecord = { children: { - ui: smallLegacyUIFolderWithInvalidWidget, + ui: legacyUIFolderWithInvalidWidgets, pivot: smallLegacyPivotFolder, }, entry: { From 31e17548017681c8c2ffdd9c0bd36ee3bfbd57a0 Mon Sep 17 00:00:00 2001 From: Nestor Zepeda Date: Wed, 14 Aug 2024 10:53:09 -0400 Subject: [PATCH 13/20] Remove the now unnecessary test resource files --- .../smallLegacyUIFolderWithInvalidKpiTitle.ts | 241 ------------------ .../smallLegacyUIFolderWithInvalidWidget.ts | 186 -------------- 2 files changed, 427 deletions(-) delete mode 100644 src/4.3_to_5.0/__test_resources__/smallLegacyUIFolderWithInvalidKpiTitle.ts delete mode 100644 src/4.3_to_5.0/__test_resources__/smallLegacyUIFolderWithInvalidWidget.ts diff --git a/src/4.3_to_5.0/__test_resources__/smallLegacyUIFolderWithInvalidKpiTitle.ts b/src/4.3_to_5.0/__test_resources__/smallLegacyUIFolderWithInvalidKpiTitle.ts deleted file mode 100644 index c8a8b597..00000000 --- a/src/4.3_to_5.0/__test_resources__/smallLegacyUIFolderWithInvalidKpiTitle.ts +++ /dev/null @@ -1,241 +0,0 @@ -/** - * The shortened version of the content of the /ui folder on a Content Server, useful for unit tests. - * Contains a KPI widget containing a custom title with an empty `tupleKey` for its location. - */ -export const smallLegacyUIFolderWithInvalidKpiTitle = { - 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: { - kpi: { - entry: { - content: - '{"description": "A KPI containing a custom title with an empty tupleKey","name":"KPI","type":"container","value": {"style": {},"showTitleBar": true,"body": {"serverUrl": "","mdx": "SELECT NON EMPTY Hierarchize(AddCalculatedMembers(Descendants({[Geography].[City].[ALL].[AllMember]},1,SELF_AND_BEFORE))) ON ROWS,NON EMPTY {[Measures].[contributors.COUNT]} ON COLUMNS FROM (SELECT[Geography].[City].[ALL].[AllMember].[New York] ON COLUMNS FROM [EquityDerivativesCube])","contextValues": {},"updateMode": "once","ranges": {"row": {},"column": {}},"configuration": {"featuredValues": {"locations":{"":{"title": "Title with empty tupleKey"},"[Measures].[contributors.COUNT]": {"title": "Custom title for contributors.COUNT"}}}}},"containerKey":"featured-values"},"writable": true}', - isDirectory: false, - owners: ["admin"], - readers: ["admin"], - timestamp: 1607879735685, - lastEditor: "admin", - canRead: true, - canWrite: true, - }, - }, - }, - }, - 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: { - kpi: { - entry: { - isDirectory: true, - owners: ["admin"], - readers: ["admin"], - timestamp: 1607879735685, - lastEditor: "admin", - canRead: true, - canWrite: true, - }, - }, - }, - }, - }, - }, - 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, - }, - }, - }, -}; diff --git a/src/4.3_to_5.0/__test_resources__/smallLegacyUIFolderWithInvalidWidget.ts b/src/4.3_to_5.0/__test_resources__/smallLegacyUIFolderWithInvalidWidget.ts deleted file mode 100644 index 33948e4a..00000000 --- a/src/4.3_to_5.0/__test_resources__/smallLegacyUIFolderWithInvalidWidget.ts +++ /dev/null @@ -1,186 +0,0 @@ -/** - * The shortened version of the content of the /ui folder on a Content Server, useful for unit tests. - * Contains a valid widget, a widget whose `containerKey` is not valid, and another widget with a filter on a hierarchy that does not exist in the test cube. - */ -export const smallLegacyUIFolderWithInvalidWidget = { - 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: { - "158": { - 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, - }, - }, - "1231": { - 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, - }, - }, - "777": { - entry: { - content: - '{"description": "Valid widget","name": "Valid 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].[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, - }, - }, - }, - }, - 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: { - "158": { - entry: { - isDirectory: true, - owners: ["admin"], - readers: ["admin"], - timestamp: 1607879735685, - lastEditor: "admin", - canRead: true, - canWrite: true, - }, - }, - "1231": { - entry: { - isDirectory: true, - owners: ["admin"], - readers: ["admin"], - timestamp: 1607879735685, - lastEditor: "admin", - canRead: true, - canWrite: true, - }, - }, - "777": { - entry: { - isDirectory: true, - owners: ["admin"], - readers: ["admin"], - timestamp: 1607879735685, - lastEditor: "admin", - canRead: true, - canWrite: true, - }, - }, - }, - }, - }, - }, - settings: { - entry: { - isDirectory: true, - owners: ["ROLE_CS_ROOT"], - readers: ["ROLE_USER"], - 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, - }, - }, - }, -}; From bdcdec45c93ccbbde272ded7dcae2c9922a6d98f Mon Sep 17 00:00:00 2001 From: Nestor Zepeda Date: Wed, 18 Sep 2024 15:54:12 -0400 Subject: [PATCH 14/20] Move the location of addLegacyBookmarkToUIFolder to the test resources folder --- .../{ => __test_resources__}/addLegacyBookmarkToUIFolder.ts | 0 src/migrateContentServer.test.ts | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename src/4.3_to_5.0/{ => __test_resources__}/addLegacyBookmarkToUIFolder.ts (100%) diff --git a/src/4.3_to_5.0/addLegacyBookmarkToUIFolder.ts b/src/4.3_to_5.0/__test_resources__/addLegacyBookmarkToUIFolder.ts similarity index 100% rename from src/4.3_to_5.0/addLegacyBookmarkToUIFolder.ts rename to src/4.3_to_5.0/__test_resources__/addLegacyBookmarkToUIFolder.ts diff --git a/src/migrateContentServer.test.ts b/src/migrateContentServer.test.ts index 146e0ca2..97dc570a 100644 --- a/src/migrateContentServer.test.ts +++ b/src/migrateContentServer.test.ts @@ -4,7 +4,7 @@ import { smallLegacyPivotFolder } from "./4.3_to_5.0/__test_resources__/smallLeg import { smallLegacyUIFolder } from "./4.3_to_5.0/__test_resources__/smallLegacyUIFolder"; import { migrateContentServer } from "./migrateContentServer"; import _cloneDeep from "lodash/cloneDeep"; -import { addLegacyBookmarkToUIFolder } from "./4.3_to_5.0/addLegacyBookmarkToUIFolder"; +import { addLegacyBookmarkToUIFolder } from "./4.3_to_5.0/__test_resources__/addLegacyBookmarkToUIFolder"; import { emptyLegacyUIFolder } from "./4.3_to_5.0/__test_resources__/emptyLegacyUIFolder"; jest.mock(`./4.3_to_5.0/generateId`, () => { From 1eb0b418bb8960cc7c87f11701dcf7faf3ce6b26 Mon Sep 17 00:00:00 2001 From: Nestor Zepeda Date: Wed, 18 Sep 2024 16:11:38 -0400 Subject: [PATCH 15/20] The empty legacy ui folder test resource is truly empty --- .../__test_resources__/emptyLegacyUIFolder.ts | 104 +----------------- 1 file changed, 1 insertion(+), 103 deletions(-) diff --git a/src/4.3_to_5.0/__test_resources__/emptyLegacyUIFolder.ts b/src/4.3_to_5.0/__test_resources__/emptyLegacyUIFolder.ts index 5243ecd8..4327e3d4 100644 --- a/src/4.3_to_5.0/__test_resources__/emptyLegacyUIFolder.ts +++ b/src/4.3_to_5.0/__test_resources__/emptyLegacyUIFolder.ts @@ -94,109 +94,7 @@ export const emptyLegacyUIFolder = { 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, - }, - }, - }, - }, - }, - }, - }, + children: {}, }, version: { entry: { From 22ecfc2539190f1d0e0a8effa90365f76b7bbb4e Mon Sep 17 00:00:00 2001 From: Nestor Zepeda Date: Wed, 18 Sep 2024 16:14:47 -0400 Subject: [PATCH 16/20] Split out the invalid legacy bookmarks and their folder into their own test resource files --- .../invalidLegacyWidgets.ts | 37 ++++++++++++ .../legacyPivotTableBookmark.ts | 16 +++++ .../legacyUIFolderWithInvalidWidgets.ts | 15 +++++ src/migrateContentServer.test.ts | 59 +------------------ 4 files changed, 69 insertions(+), 58 deletions(-) create mode 100644 src/4.3_to_5.0/__test_resources__/invalidLegacyWidgets.ts create mode 100644 src/4.3_to_5.0/__test_resources__/legacyPivotTableBookmark.ts create mode 100644 src/4.3_to_5.0/__test_resources__/legacyUIFolderWithInvalidWidgets.ts diff --git a/src/4.3_to_5.0/__test_resources__/invalidLegacyWidgets.ts b/src/4.3_to_5.0/__test_resources__/invalidLegacyWidgets.ts new file mode 100644 index 00000000..4bf8dc82 --- /dev/null +++ b/src/4.3_to_5.0/__test_resources__/invalidLegacyWidgets.ts @@ -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, +}; diff --git a/src/4.3_to_5.0/__test_resources__/legacyPivotTableBookmark.ts b/src/4.3_to_5.0/__test_resources__/legacyPivotTableBookmark.ts new file mode 100644 index 00000000..6c3f3a7f --- /dev/null +++ b/src/4.3_to_5.0/__test_resources__/legacyPivotTableBookmark.ts @@ -0,0 +1,16 @@ +/** + * The content entry for a legacy bookmark representing a pivot table. + */ +export const legacyPivotTableBookmark = { + entry: { + content: + '{"description": "Valid widget","name": "Valid 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].[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, + }, +}; diff --git a/src/4.3_to_5.0/__test_resources__/legacyUIFolderWithInvalidWidgets.ts b/src/4.3_to_5.0/__test_resources__/legacyUIFolderWithInvalidWidgets.ts new file mode 100644 index 00000000..17e4548c --- /dev/null +++ b/src/4.3_to_5.0/__test_resources__/legacyUIFolderWithInvalidWidgets.ts @@ -0,0 +1,15 @@ +import { addLegacyBookmarkToUIFolder } from "./addLegacyBookmarkToUIFolder"; +import { emptyLegacyUIFolder } from "./emptyLegacyUIFolder"; +import { invalidLegacyWidgets } from "./invalidLegacyWidgets"; +import { legacyPivotTableBookmark } from "./legacyPivotTableBookmark"; + +/** + * Contains three legacy bookmark widgets. + * 1. Widget with an invalid container container key. + * 2. Widget with a filter on an invalid hierarchy. + * 3. A valid widget. + */ +export const legacyUIFolderWithInvalidWidgets = addLegacyBookmarkToUIFolder( + emptyLegacyUIFolder, + { ...invalidLegacyWidgets, "777": legacyPivotTableBookmark }, +); diff --git a/src/migrateContentServer.test.ts b/src/migrateContentServer.test.ts index 97dc570a..fdc68aa7 100644 --- a/src/migrateContentServer.test.ts +++ b/src/migrateContentServer.test.ts @@ -6,6 +6,7 @@ import { migrateContentServer } from "./migrateContentServer"; import _cloneDeep from "lodash/cloneDeep"; import { addLegacyBookmarkToUIFolder } from "./4.3_to_5.0/__test_resources__/addLegacyBookmarkToUIFolder"; import { emptyLegacyUIFolder } from "./4.3_to_5.0/__test_resources__/emptyLegacyUIFolder"; +import { legacyUIFolderWithInvalidWidgets } from "./4.3_to_5.0/__test_resources__/legacyUIFolderWithInvalidWidgets"; jest.mock(`./4.3_to_5.0/generateId`, () => { let counter = 0; @@ -19,54 +20,6 @@ jest.mock(`./4.3_to_5.0/generateId`, () => { }; }); -/** - * Contains three legacy bookmark widgets. - * 1. Widget with an invalid container container key. - * 2. Widget with a filter on an invalid hierarchy. - * 3. A valid widget. - */ -const bookmarkContentWithInvalidWidgets = { - "158": { - 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, - }, - }, - "1231": { - 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, - }, - }, - "777": { - entry: { - content: - '{"description": "Valid widget","name": "Valid 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].[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, - }, - }, -}; - describe("migrateContentServer", () => { it("migrates calculated measures from the /pivot folder to the /ui folder when migrating from 4.3 to 5.0", async () => { const contentServer: ContentRecord = { @@ -284,11 +237,6 @@ describe("migrateContentServer", () => { }); it("keeps the original item untouched, as before the whole migration when the item cannot be migrated due to an error and the `behaviorOnError` flag is set to `keep-original`.", async () => { - const legacyUIFolderWithInvalidWidgets = addLegacyBookmarkToUIFolder( - emptyLegacyUIFolder, - bookmarkContentWithInvalidWidgets, - ); - const contentServer: ContentRecord = { children: { ui: legacyUIFolderWithInvalidWidgets, @@ -339,11 +287,6 @@ describe("migrateContentServer", () => { }); it("keeps the 5.0 version of the widget, when migrating from 4.3 to 5.1 with `behaviorOnError` set to `keep-last-successful-version` and the 5.0 to 5.1 step fails", async () => { - const legacyUIFolderWithInvalidWidgets = addLegacyBookmarkToUIFolder( - emptyLegacyUIFolder, - bookmarkContentWithInvalidWidgets, - ); - const contentServer: ContentRecord = { children: { ui: legacyUIFolderWithInvalidWidgets, From 1cde91fa1fb33c153f9741f6dd4c725f88d58058 Mon Sep 17 00:00:00 2001 From: Nestor Zepeda Date: Wed, 18 Sep 2024 16:34:47 -0400 Subject: [PATCH 17/20] Split out the legacy kpi bookmark and folder into their own resource files --- .../legacyKpiWithInvalidTitle.ts | 16 ++++++++++++++ .../legacyUIFolderWithInvalidKpi.ts | 13 +++++++++++ src/migrateContentServer.test.ts | 22 +------------------ 3 files changed, 30 insertions(+), 21 deletions(-) create mode 100644 src/4.3_to_5.0/__test_resources__/legacyKpiWithInvalidTitle.ts create mode 100644 src/4.3_to_5.0/__test_resources__/legacyUIFolderWithInvalidKpi.ts diff --git a/src/4.3_to_5.0/__test_resources__/legacyKpiWithInvalidTitle.ts b/src/4.3_to_5.0/__test_resources__/legacyKpiWithInvalidTitle.ts new file mode 100644 index 00000000..861a0bce --- /dev/null +++ b/src/4.3_to_5.0/__test_resources__/legacyKpiWithInvalidTitle.ts @@ -0,0 +1,16 @@ +/** + * The content entry for a legacy bookmark representing a KPI widget + */ +export const legacyKpiWithInvalidTitle = { + entry: { + content: + '{"description": "A KPI containing a custom title with an empty tupleKey","name":"KPI","type":"container","value": {"style": {},"showTitleBar": true,"body": {"serverUrl": "","mdx": "SELECT NON EMPTY Hierarchize(AddCalculatedMembers(Descendants({[Geography].[City].[ALL].[AllMember]},1,SELF_AND_BEFORE))) ON ROWS,NON EMPTY {[Measures].[contributors.COUNT]} ON COLUMNS FROM (SELECT[Geography].[City].[ALL].[AllMember].[New York] ON COLUMNS FROM [EquityDerivativesCube])","contextValues": {},"updateMode": "once","ranges": {"row": {},"column": {}},"configuration": {"featuredValues": {"locations":{"":{"title": "Title with empty tupleKey"},"[Measures].[contributors.COUNT]": {"title": "Custom title for contributors.COUNT"}}}}},"containerKey":"featured-values"},"writable": true}', + isDirectory: false, + owners: ["admin"], + readers: ["admin"], + timestamp: 1607879735685, + lastEditor: "admin", + canRead: true, + canWrite: true, + }, +}; diff --git a/src/4.3_to_5.0/__test_resources__/legacyUIFolderWithInvalidKpi.ts b/src/4.3_to_5.0/__test_resources__/legacyUIFolderWithInvalidKpi.ts new file mode 100644 index 00000000..5fd48ff7 --- /dev/null +++ b/src/4.3_to_5.0/__test_resources__/legacyUIFolderWithInvalidKpi.ts @@ -0,0 +1,13 @@ +import { addLegacyBookmarkToUIFolder } from "./addLegacyBookmarkToUIFolder"; +import { emptyLegacyUIFolder } from "./emptyLegacyUIFolder"; +import { legacyKpiWithInvalidTitle } from "./legacyKpiWithInvalidTitle"; + +/** + * Legacy UI folder containing a single kpi bookmark with an invalid kpi title + */ +export const legacyUIFolderWithInvalidKpiTitle = addLegacyBookmarkToUIFolder( + emptyLegacyUIFolder, + { + kpi: legacyKpiWithInvalidTitle, + }, +); diff --git a/src/migrateContentServer.test.ts b/src/migrateContentServer.test.ts index fdc68aa7..7ef13d2d 100644 --- a/src/migrateContentServer.test.ts +++ b/src/migrateContentServer.test.ts @@ -4,9 +4,8 @@ import { smallLegacyPivotFolder } from "./4.3_to_5.0/__test_resources__/smallLeg import { smallLegacyUIFolder } from "./4.3_to_5.0/__test_resources__/smallLegacyUIFolder"; import { migrateContentServer } from "./migrateContentServer"; import _cloneDeep from "lodash/cloneDeep"; -import { addLegacyBookmarkToUIFolder } from "./4.3_to_5.0/__test_resources__/addLegacyBookmarkToUIFolder"; -import { emptyLegacyUIFolder } from "./4.3_to_5.0/__test_resources__/emptyLegacyUIFolder"; import { legacyUIFolderWithInvalidWidgets } from "./4.3_to_5.0/__test_resources__/legacyUIFolderWithInvalidWidgets"; +import { legacyUIFolderWithInvalidKpiTitle } from "./4.3_to_5.0/__test_resources__/legacyUIFolderWithInvalidKpi"; jest.mock(`./4.3_to_5.0/generateId`, () => { let counter = 0; @@ -340,25 +339,6 @@ describe("migrateContentServer", () => { }); it("migrates the KPI custom titles while dropping custom titles that could not be successfully migrated", async () => { - const legacyUIFolderWithInvalidKpiTitle = addLegacyBookmarkToUIFolder( - emptyLegacyUIFolder, - { - kpi: { - entry: { - content: - '{"description": "A KPI containing a custom title with an empty tupleKey","name":"KPI","type":"container","value": {"style": {},"showTitleBar": true,"body": {"serverUrl": "","mdx": "SELECT NON EMPTY Hierarchize(AddCalculatedMembers(Descendants({[Geography].[City].[ALL].[AllMember]},1,SELF_AND_BEFORE))) ON ROWS,NON EMPTY {[Measures].[contributors.COUNT]} ON COLUMNS FROM (SELECT[Geography].[City].[ALL].[AllMember].[New York] ON COLUMNS FROM [EquityDerivativesCube])","contextValues": {},"updateMode": "once","ranges": {"row": {},"column": {}},"configuration": {"featuredValues": {"locations":{"":{"title": "Title with empty tupleKey"},"[Measures].[contributors.COUNT]": {"title": "Custom title for contributors.COUNT"}}}}},"containerKey":"featured-values"},"writable": true}', - isDirectory: false, - owners: ["admin"], - readers: ["admin"], - timestamp: 1607879735685, - lastEditor: "admin", - canRead: true, - canWrite: true, - }, - }, - }, - ); - const contentServer: ContentRecord = { children: { ui: legacyUIFolderWithInvalidKpiTitle, From 2280099ae216f1dfeec8536f43d2ec3daf381af4 Mon Sep 17 00:00:00 2001 From: Nestor Zepeda Date: Wed, 18 Sep 2024 17:14:06 -0400 Subject: [PATCH 18/20] Create the smallLegacy ui folder with the new add legacy bookmark to UI folder function --- .../migrate_43_to_50.test.ts.snap | 97 +------ .../legacyDashboardBookmark.ts | 16 ++ .../legacyInvalidDashboardBookmark.ts | 17 ++ .../legacyInvalidFilterBookmark.ts | 17 ++ .../__test_resources__/smallLegacyUIFolder.ts | 245 +----------------- ...smallLegacyUIFolderWithInvalidDashboard.ts | 142 +--------- .../smallLegacyUIFolderWithInvalidFilter.ts | 143 +--------- 7 files changed, 79 insertions(+), 598 deletions(-) create mode 100644 src/4.3_to_5.0/__test_resources__/legacyDashboardBookmark.ts create mode 100644 src/4.3_to_5.0/__test_resources__/legacyInvalidDashboardBookmark.ts create mode 100644 src/4.3_to_5.0/__test_resources__/legacyInvalidFilterBookmark.ts diff --git a/src/4.3_to_5.0/__snapshots__/migrate_43_to_50.test.ts.snap b/src/4.3_to_5.0/__snapshots__/migrate_43_to_50.test.ts.snap index 8d0554a7..43a7bc78 100644 --- a/src/4.3_to_5.0/__snapshots__/migrate_43_to_50.test.ts.snap +++ b/src/4.3_to_5.0/__snapshots__/migrate_43_to_50.test.ts.snap @@ -2247,12 +2247,8 @@ exports[`migrate_43_to_50 returns a valid ActiveUI5 /ui folder on a small input "content": "{"name":"hidden grand totals"}", "isDirectory": true, "lastEditor": "admin", - "owners": [ - "admin", - ], - "readers": [ - "admin", - ], + "owners": [], + "readers": [], "timestamp": 1607879735685, }, }, @@ -2262,12 +2258,8 @@ exports[`migrate_43_to_50 returns a valid ActiveUI5 /ui folder on a small input "canWrite": true, "isDirectory": true, "lastEditor": "admin", - "owners": [ - "admin", - ], - "readers": [ - "admin", - ], + "owners": [], + "readers": [], "timestamp": 1607879735685, }, }, @@ -2357,6 +2349,7 @@ exports[`migrate_43_to_50 returns a valid ActiveUI5 /ui folder on a small input "organization_settings": { "entry": { "content": "{}", + "isDirectory": false, "owners": [ "ROLE_CS_ROOT", ], @@ -2404,86 +2397,6 @@ exports[`migrate_43_to_50 returns a valid ActiveUI5 /ui folder on a small input }, }, "users": { - "children": { - "admin": { - "children": { - "activity": { - "entry": { - "content": "{"userFilters":["[Geography].[City].[ALL].[AllMember].[Berlin]"]}", - "owners": [ - "admin", - ], - "readers": [ - "admin", - ], - }, - }, - "settings": { - "entry": { - "content": "{"theme":"dark-activeviam","search.maxResults":10,"userFilters.areEnabled":true,"drillthrough.defaultSelectedColumns":{"EquityDerivativesCube":["delta","gamma","pnlVega","Desk","Currency","Date","HostName"],"EquityDerivativesCubeDist":["BumpedMtmDown","ProductQtyMultiplier","vega","rho","productId","pnlVega","pnlDelta","pnl","gamma","delta","TradeId","ProductBaseMtm"]}}", - "owners": [ - "admin", - ], - "readers": [ - "admin", - ], - }, - }, - }, - "entry": { - "canRead": true, - "canWrite": true, - "isDirectory": true, - "lastEditor": "admin", - "owners": [ - "admin", - ], - "readers": [ - "admin", - ], - "timestamp": 1607879735685, - }, - }, - "user1": { - "children": { - "activity": { - "entry": { - "content": "{}", - "owners": [ - "user1", - ], - "readers": [ - "user1", - ], - }, - }, - "settings": { - "entry": { - "content": "{}", - "owners": [ - "user1", - ], - "readers": [ - "user1", - ], - }, - }, - }, - "entry": { - "canRead": true, - "canWrite": true, - "isDirectory": true, - "lastEditor": "admin", - "owners": [ - "user1", - ], - "readers": [ - "user1", - ], - "timestamp": 1607879735685, - }, - }, - }, "entry": { "isDirectory": true, "owners": [ diff --git a/src/4.3_to_5.0/__test_resources__/legacyDashboardBookmark.ts b/src/4.3_to_5.0/__test_resources__/legacyDashboardBookmark.ts new file mode 100644 index 00000000..03d601d8 --- /dev/null +++ b/src/4.3_to_5.0/__test_resources__/legacyDashboardBookmark.ts @@ -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, + }, +}; diff --git a/src/4.3_to_5.0/__test_resources__/legacyInvalidDashboardBookmark.ts b/src/4.3_to_5.0/__test_resources__/legacyInvalidDashboardBookmark.ts new file mode 100644 index 00000000..315ec2b2 --- /dev/null +++ b/src/4.3_to_5.0/__test_resources__/legacyInvalidDashboardBookmark.ts @@ -0,0 +1,17 @@ +/** + * Legacy content entry representing a bookmark of an invalid dashboard. + * Useful for unit tests. + */ +export const legacyInvalidDashboardBookmark = { + 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 [foo] 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, + }, +}; diff --git a/src/4.3_to_5.0/__test_resources__/legacyInvalidFilterBookmark.ts b/src/4.3_to_5.0/__test_resources__/legacyInvalidFilterBookmark.ts new file mode 100644 index 00000000..086cc0db --- /dev/null +++ b/src/4.3_to_5.0/__test_resources__/legacyInvalidFilterBookmark.ts @@ -0,0 +1,17 @@ +/** + * Content entry representing a legacy filter containing an invalid property + * Useful for unit tests. + */ +export const legacyInvalidFilterBookmark = { + entry: { + content: + '{"name":"AUI4 filter","type":"mdx","invalidvalue":{"shouldReplace":true,"type":"filter","mdx":"{[Geography].[City].[ALL].[AllMember].[Berlin], [Geography].[City].[ALL].[AllMember].[London]}","cube":"EquityDerivativesCube"}}', + isDirectory: false, + owners: ["admin"], + readers: ["admin"], + timestamp: 1607879735685, + lastEditor: "admin", + canRead: true, + canWrite: true, + }, +}; diff --git a/src/4.3_to_5.0/__test_resources__/smallLegacyUIFolder.ts b/src/4.3_to_5.0/__test_resources__/smallLegacyUIFolder.ts index aeb3ad70..e00cc382 100644 --- a/src/4.3_to_5.0/__test_resources__/smallLegacyUIFolder.ts +++ b/src/4.3_to_5.0/__test_resources__/smallLegacyUIFolder.ts @@ -1,240 +1,11 @@ +import { addLegacyBookmarkToUIFolder } from "./addLegacyBookmarkToUIFolder"; +import { emptyLegacyUIFolder } from "./emptyLegacyUIFolder"; +import { legacyDashboardBookmark } from "./legacyDashboardBookmark"; + /** * The shortened version of the content of the /ui folder on a Content Server, useful for unit tests. */ -export const smallLegacyUIFolder = { - 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: { - "158": { - 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, - }, - }, - }, - }, - 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: { - "158": { - entry: { - isDirectory: true, - owners: ["admin"], - readers: ["admin"], - timestamp: 1607879735685, - lastEditor: "admin", - canRead: true, - canWrite: true, - }, - }, - }, - }, - }, - }, - 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, - }, - }, - }, -}; +export const smallLegacyUIFolder = addLegacyBookmarkToUIFolder( + emptyLegacyUIFolder, + { "158": legacyDashboardBookmark }, +); diff --git a/src/4.3_to_5.0/__test_resources__/smallLegacyUIFolderWithInvalidDashboard.ts b/src/4.3_to_5.0/__test_resources__/smallLegacyUIFolderWithInvalidDashboard.ts index 713fbb95..e06eacf4 100644 --- a/src/4.3_to_5.0/__test_resources__/smallLegacyUIFolderWithInvalidDashboard.ts +++ b/src/4.3_to_5.0/__test_resources__/smallLegacyUIFolderWithInvalidDashboard.ts @@ -1,138 +1,12 @@ +import { addLegacyBookmarkToUIFolder } from "./addLegacyBookmarkToUIFolder"; +import { emptyLegacyUIFolder } from "./emptyLegacyUIFolder"; +import { legacyInvalidDashboardBookmark } from "./legacyInvalidDashboardBookmark"; + /** * The shortened version of the content of the /ui folder on a Content Server, useful for unit tests. * Contains an invalid dashboard whose id is numerical. */ -export const smallLegacyUIFolderWithInvalidDashboard = { - 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: { - "158": { - 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 [foo] 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, - }, - }, - }, - }, - 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: { - "158": { - entry: { - isDirectory: true, - owners: ["admin"], - readers: ["admin"], - timestamp: 1607879735685, - lastEditor: "admin", - canRead: true, - canWrite: true, - }, - }, - }, - }, - }, - }, - settings: { - entry: { - isDirectory: true, - owners: ["ROLE_CS_ROOT"], - readers: ["ROLE_USER"], - 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, - }, - }, - }, -}; +export const smallLegacyUIFolderWithInvalidDashboard = + addLegacyBookmarkToUIFolder(emptyLegacyUIFolder, { + "158": legacyInvalidDashboardBookmark, + }); diff --git a/src/4.3_to_5.0/__test_resources__/smallLegacyUIFolderWithInvalidFilter.ts b/src/4.3_to_5.0/__test_resources__/smallLegacyUIFolderWithInvalidFilter.ts index 7fee55e3..87fff2c7 100644 --- a/src/4.3_to_5.0/__test_resources__/smallLegacyUIFolderWithInvalidFilter.ts +++ b/src/4.3_to_5.0/__test_resources__/smallLegacyUIFolderWithInvalidFilter.ts @@ -1,139 +1,12 @@ +import { addLegacyBookmarkToUIFolder } from "./addLegacyBookmarkToUIFolder"; +import { emptyLegacyUIFolder } from "./emptyLegacyUIFolder"; +import { legacyInvalidFilterBookmark } from "./legacyInvalidFilterBookmark"; + /** * The shortened version of the content of the /ui folder on a Content Server, useful for unit tests. * Contains an invalid filter. */ -export const smallLegacyUIFolderWithInvalidFilter = { - 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: { - "158": { - entry: { - content: - '{"name":"AUI4 filter","type":"mdx","invalidvalue":{"shouldReplace":true,"type":"filter","mdx":"{[Geography].[City].[ALL].[AllMember].[Berlin], [Geography].[City].[ALL].[AllMember].[London]}","cube":"EquityDerivativesCube"}}', - isDirectory: false, - owners: ["admin"], - readers: ["admin"], - timestamp: 1607879735685, - lastEditor: "admin", - canRead: true, - canWrite: true, - }, - }, - }, - }, - 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: { - "158": { - entry: { - isDirectory: true, - owners: ["admin"], - readers: ["admin"], - timestamp: 1607879735685, - lastEditor: "admin", - canRead: true, - canWrite: true, - }, - }, - }, - }, - }, - }, - settings: { - entry: { - isDirectory: true, - owners: ["ROLE_CS_ROOT"], - readers: ["ROLE_USER"], - timestamp: 1607879735685, - lastEditor: "admin", - canRead: true, - canWrite: true, - }, - children: {}, - }, - 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, - }, - }, - }, -}; +export const smallLegacyUIFolderWithInvalidFilter = addLegacyBookmarkToUIFolder( + emptyLegacyUIFolder, + { "158": legacyInvalidFilterBookmark }, +); From 26adf4b5a2762a838b4fef827575a275c4644909 Mon Sep 17 00:00:00 2001 From: Nestor Zepeda Date: Wed, 18 Sep 2024 17:37:52 -0400 Subject: [PATCH 19/20] Apply suggestions from code review --- .../__test_resources__/legacyInvalidDashboardBookmark.ts | 2 +- .../__test_resources__/legacyInvalidFilterBookmark.ts | 2 +- .../__test_resources__/legacyKpiWithInvalidTitle.ts | 4 +++- .../__test_resources__/legacyUIFolderWithInvalidKpi.ts | 3 ++- 4 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/4.3_to_5.0/__test_resources__/legacyInvalidDashboardBookmark.ts b/src/4.3_to_5.0/__test_resources__/legacyInvalidDashboardBookmark.ts index 315ec2b2..c7f1a92b 100644 --- a/src/4.3_to_5.0/__test_resources__/legacyInvalidDashboardBookmark.ts +++ b/src/4.3_to_5.0/__test_resources__/legacyInvalidDashboardBookmark.ts @@ -1,5 +1,5 @@ /** - * Legacy content entry representing a bookmark of an invalid dashboard. + * The content entry representing a bookmark of an invalid dashboard. * Useful for unit tests. */ export const legacyInvalidDashboardBookmark = { diff --git a/src/4.3_to_5.0/__test_resources__/legacyInvalidFilterBookmark.ts b/src/4.3_to_5.0/__test_resources__/legacyInvalidFilterBookmark.ts index 086cc0db..adbd6c75 100644 --- a/src/4.3_to_5.0/__test_resources__/legacyInvalidFilterBookmark.ts +++ b/src/4.3_to_5.0/__test_resources__/legacyInvalidFilterBookmark.ts @@ -1,5 +1,5 @@ /** - * Content entry representing a legacy filter containing an invalid property + * The content entry representing a legacy filter containing an invalid property. * Useful for unit tests. */ export const legacyInvalidFilterBookmark = { diff --git a/src/4.3_to_5.0/__test_resources__/legacyKpiWithInvalidTitle.ts b/src/4.3_to_5.0/__test_resources__/legacyKpiWithInvalidTitle.ts index 861a0bce..56a7eca6 100644 --- a/src/4.3_to_5.0/__test_resources__/legacyKpiWithInvalidTitle.ts +++ b/src/4.3_to_5.0/__test_resources__/legacyKpiWithInvalidTitle.ts @@ -1,5 +1,7 @@ /** - * The content entry for a legacy bookmark representing a KPI widget + * The content entry for a legacy bookmark representing a KPI widget. + * Useful for unit tests. + */ export const legacyKpiWithInvalidTitle = { entry: { diff --git a/src/4.3_to_5.0/__test_resources__/legacyUIFolderWithInvalidKpi.ts b/src/4.3_to_5.0/__test_resources__/legacyUIFolderWithInvalidKpi.ts index 5fd48ff7..ad5a89f7 100644 --- a/src/4.3_to_5.0/__test_resources__/legacyUIFolderWithInvalidKpi.ts +++ b/src/4.3_to_5.0/__test_resources__/legacyUIFolderWithInvalidKpi.ts @@ -3,7 +3,8 @@ import { emptyLegacyUIFolder } from "./emptyLegacyUIFolder"; import { legacyKpiWithInvalidTitle } from "./legacyKpiWithInvalidTitle"; /** - * Legacy UI folder containing a single kpi bookmark with an invalid kpi title + * A legacy UI folder containing a single KPI bookmark with an invalid KPI title. + * Useful for unit tests. */ export const legacyUIFolderWithInvalidKpiTitle = addLegacyBookmarkToUIFolder( emptyLegacyUIFolder, From dee3129fe7be972b7336ecf5e11e455778b22f52 Mon Sep 17 00:00:00 2001 From: Nestor Zepeda Date: Wed, 25 Sep 2024 11:23:48 -0400 Subject: [PATCH 20/20] Ensure the test snapshots have not lost data --- .../migrate_43_to_50.test.ts.snap | 97 +++++++++++++++- .../addLegacyBookmarkToUIFolder.ts | 5 +- .../__test_resources__/emptyLegacyUIFolder.ts | 104 +++++++++++++++++- 3 files changed, 198 insertions(+), 8 deletions(-) diff --git a/src/4.3_to_5.0/__snapshots__/migrate_43_to_50.test.ts.snap b/src/4.3_to_5.0/__snapshots__/migrate_43_to_50.test.ts.snap index 43a7bc78..8d0554a7 100644 --- a/src/4.3_to_5.0/__snapshots__/migrate_43_to_50.test.ts.snap +++ b/src/4.3_to_5.0/__snapshots__/migrate_43_to_50.test.ts.snap @@ -2247,8 +2247,12 @@ exports[`migrate_43_to_50 returns a valid ActiveUI5 /ui folder on a small input "content": "{"name":"hidden grand totals"}", "isDirectory": true, "lastEditor": "admin", - "owners": [], - "readers": [], + "owners": [ + "admin", + ], + "readers": [ + "admin", + ], "timestamp": 1607879735685, }, }, @@ -2258,8 +2262,12 @@ exports[`migrate_43_to_50 returns a valid ActiveUI5 /ui folder on a small input "canWrite": true, "isDirectory": true, "lastEditor": "admin", - "owners": [], - "readers": [], + "owners": [ + "admin", + ], + "readers": [ + "admin", + ], "timestamp": 1607879735685, }, }, @@ -2349,7 +2357,6 @@ exports[`migrate_43_to_50 returns a valid ActiveUI5 /ui folder on a small input "organization_settings": { "entry": { "content": "{}", - "isDirectory": false, "owners": [ "ROLE_CS_ROOT", ], @@ -2397,6 +2404,86 @@ exports[`migrate_43_to_50 returns a valid ActiveUI5 /ui folder on a small input }, }, "users": { + "children": { + "admin": { + "children": { + "activity": { + "entry": { + "content": "{"userFilters":["[Geography].[City].[ALL].[AllMember].[Berlin]"]}", + "owners": [ + "admin", + ], + "readers": [ + "admin", + ], + }, + }, + "settings": { + "entry": { + "content": "{"theme":"dark-activeviam","search.maxResults":10,"userFilters.areEnabled":true,"drillthrough.defaultSelectedColumns":{"EquityDerivativesCube":["delta","gamma","pnlVega","Desk","Currency","Date","HostName"],"EquityDerivativesCubeDist":["BumpedMtmDown","ProductQtyMultiplier","vega","rho","productId","pnlVega","pnlDelta","pnl","gamma","delta","TradeId","ProductBaseMtm"]}}", + "owners": [ + "admin", + ], + "readers": [ + "admin", + ], + }, + }, + }, + "entry": { + "canRead": true, + "canWrite": true, + "isDirectory": true, + "lastEditor": "admin", + "owners": [ + "admin", + ], + "readers": [ + "admin", + ], + "timestamp": 1607879735685, + }, + }, + "user1": { + "children": { + "activity": { + "entry": { + "content": "{}", + "owners": [ + "user1", + ], + "readers": [ + "user1", + ], + }, + }, + "settings": { + "entry": { + "content": "{}", + "owners": [ + "user1", + ], + "readers": [ + "user1", + ], + }, + }, + }, + "entry": { + "canRead": true, + "canWrite": true, + "isDirectory": true, + "lastEditor": "admin", + "owners": [ + "user1", + ], + "readers": [ + "user1", + ], + "timestamp": 1607879735685, + }, + }, + }, "entry": { "isDirectory": true, "owners": [ diff --git a/src/4.3_to_5.0/__test_resources__/addLegacyBookmarkToUIFolder.ts b/src/4.3_to_5.0/__test_resources__/addLegacyBookmarkToUIFolder.ts index 42d09096..464db15d 100644 --- a/src/4.3_to_5.0/__test_resources__/addLegacyBookmarkToUIFolder.ts +++ b/src/4.3_to_5.0/__test_resources__/addLegacyBookmarkToUIFolder.ts @@ -33,11 +33,12 @@ export function addLegacyBookmarkToUIFolder( const bookmarkStructureToAdd = keysOfBookmarksToAdd.reduce( (acc: { [key: string]: ContentRecord }, key: string) => { + const bookmarkEntry = legacyBookmarksToAdd[key].entry; acc[key] = { entry: { isDirectory: true, - owners: [], - readers: [], + owners: bookmarkEntry.owners, + readers: bookmarkEntry.readers, timestamp: 1607879735685, lastEditor: "admin", canRead: true, diff --git a/src/4.3_to_5.0/__test_resources__/emptyLegacyUIFolder.ts b/src/4.3_to_5.0/__test_resources__/emptyLegacyUIFolder.ts index 4327e3d4..5243ecd8 100644 --- a/src/4.3_to_5.0/__test_resources__/emptyLegacyUIFolder.ts +++ b/src/4.3_to_5.0/__test_resources__/emptyLegacyUIFolder.ts @@ -94,7 +94,109 @@ export const emptyLegacyUIFolder = { canRead: true, canWrite: true, }, - children: {}, + 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: {