From 12498c564321b16bf08d3ae59e4a70b152c46f1e Mon Sep 17 00:00:00 2001 From: Eskil Gjerde Sviggum Date: Mon, 19 Aug 2024 09:57:05 +0200 Subject: [PATCH 1/3] [Feature] Improve RNANews demo (#13) * Add base pathname to baseURL * Add select environment, show loading, apply styling to RNANews demo * Adapt distribution changes to RNANews dmeo * Implement test for loading RNANews * Implement test for RNANews response validation --- demos/rna-news/demo.css | 42 +++ demos/rna-news/demo.html | 15 +- demos/rna-news/demo.js | 304 ++++++++++-------- demos/stock/demo.js | 2 +- src/RNANews/RNANewsJSON.ts | 6 +- src/Shared/MorningstarAPI.ts | 2 + .../RNANews/RNANewsConverter.test.ts | 61 ++++ 7 files changed, 294 insertions(+), 138 deletions(-) create mode 100644 demos/rna-news/demo.css create mode 100644 test/unit-tests/RNANews/RNANewsConverter.test.ts diff --git a/demos/rna-news/demo.css b/demos/rna-news/demo.css new file mode 100644 index 0000000..bc7209c --- /dev/null +++ b/demos/rna-news/demo.css @@ -0,0 +1,42 @@ +@import url("https://code.highcharts.com/dashboards/css/datagrid.css"); +@import url("https://code.highcharts.com/css/highcharts.css"); +@import url("https://code.highcharts.com/dashboards/css/dashboards.css"); + +body { + font-family: "Helvetica Neue", Helvetica, "Segoe UI", Arial, sans-serif; +} + +.row { + display: flex; + flex-wrap: wrap; +} + +.cell { + flex: 1; + min-width: 20px; +} + +.cell > .highcharts-dashboards-component { + position: relative; + margin: 10px; + background-clip: border-box; +} + +.highcharts-dashboards-component-title { + padding: 10px; + margin: 0; + background-color: var(--highcharts-neutral-color-5); + color: var(--highcharts-neutral-color-100); + border: solid 1px var(--highcharts-neutral-color-20); + border-bottom: none; +} + +#dashboard-col-1 .highcharts-dashboards-component-title { + background-color: #336; +} + +@media screen and (max-width: 1000px) { + .row { + flex-direction: column; + } +} diff --git a/demos/rna-news/demo.html b/demos/rna-news/demo.html index 1a57937..7ce1e65 100644 --- a/demos/rna-news/demo.html +++ b/demos/rna-news/demo.html @@ -2,13 +2,22 @@ - - + + + RNA News Demo - Morningstar Connectors Demos -
+

+ Add your Postman environment file from Morningstar to start the demo: + +

+ +
+
+
+
diff --git a/demos/rna-news/demo.js b/demos/rna-news/demo.js index e1bd70e..8344ed3 100644 --- a/demos/rna-news/demo.js +++ b/demos/rna-news/demo.js @@ -1,148 +1,190 @@ -Dashboards.DataConnector.registerType( - 'MorningstarRNANews', - Connectors.Morningstar.RNANewsConnector -); +const loadingLabel = document.getElementById('loading-label'); -const board = Dashboards.board('container', { - dataPool: { - connectors: [{ - id: 'rna', - type: 'MorningstarRNANews', - options: { - security: { - id: 'US0378331005' - }, - postman: { - environmentURL: '/tmp/Environment.json' +function displayRNANews (postmanJSON) { + const board = Dashboards.board('container', { + dataPool: { + connectors: [{ + id: 'rna', + type: 'MorningstarRNANews', + options: { + security: { + id: 'GB00BLGZ9862', + idType: 'MSID' + }, + postman: { + environmentJSON: postmanJSON + } } - } - }, - { - id: 'rna-type-amount', - type: 'JSON', - options: { - columnNames: ['Type', 'Amount'], - data: [ - [], - [] - ], - orientation: 'columns', - firstRowAsNames: false - } - } - ] - }, - components: [ - { - renderTo: 'dashboard-col-0', - connector: { - id: 'rna' }, - type: 'DataGrid', - title: 'News', - dataGridOptions: { - editable: false, - columns: { - Day: { - cellFormatter: function () { - return new Date(this.value) - .toISOString() - .substring(0, 10); - } - } + { + id: 'rna-type-amount', + type: 'JSON', + options: { + columnNames: ['Type', 'Amount'], + data: [ + [], + [] + ], + orientation: 'columns', + firstRowAsNames: false } } + ] }, - { - renderTo: 'dashboard-col-1', - connector: { - id: 'rna-type-amount', - columnAssignment: [{ - seriesId: 'number-per-type', - data: ['Type', 'Amount'] - }] - }, - type: 'Highcharts', - chartOptions: { - chart: { - animation: false, - type: 'column' - }, - title: { - text: 'Number of items per type' - }, - subtitle: { - text: 'Shows number of news items of each kind' - }, - series: [{ - id: 'number-per-type', - name: 'Number per type' - }], - tooltip: { - shared: true, - split: true, - stickOnContact: true - }, - lang: { - accessibility: { - chartContainerLabel: - 'Shows number of news items of each kind' - } + components: [ + { + renderTo: 'dashboard-col-0', + connector: { + id: 'rna' }, - xAxis: { - type: 'category', - accessibility: { - description: 'Kind of news annoucement' + type: 'DataGrid', + title: 'News', + dataGridOptions: { + editable: false, + columns: { + Day: { + cellFormatter: function () { + return new Date(this.value) + .toISOString() + .substring(0, 10); + } + } } + } + }, + { + renderTo: 'dashboard-col-1', + connector: { + id: 'rna-type-amount', + columnAssignment: [{ + seriesId: 'number-per-type', + data: ['Type', 'Amount'] + }] }, - yAxis: { + type: 'Highcharts', + chartOptions: { + chart: { + animation: false, + type: 'column' + }, title: { - text: 'Number of announcements' + text: 'Number of items per type' + }, + subtitle: { + text: 'Shows number of news items of each kind' + }, + series: [{ + id: 'number-per-type', + name: 'Number per type' + }], + tooltip: { + shared: true, + split: true, + stickOnContact: true + }, + lang: { + accessibility: { + chartContainerLabel: + 'Shows number of news items of each kind' + } + }, + xAxis: { + type: 'category', + accessibility: { + description: 'Kind of news annoucement' + } + }, + yAxis: { + title: { + text: 'Number of announcements' + } } } } - } - ] -}); - -board.dataPool - .getConnectorTable('rna') - .then(async table => { - const types = table.getColumn('Type'); - const uniqueTypes = Array.from(new Set(types)); - const numberPerType = uniqueTypes.map(type => - types.reduce((previous, current) => { - if (current === type) { - return previous + 1; + ] + }); + + board.dataPool + .getConnectorTable('rna') + .then(async table => { + const types = table.getColumn('Type'); + const uniqueTypes = Array.from(new Set(types)); + const numberPerType = uniqueTypes.map(type => + types.reduce((previous, current) => { + if (current === type) { + return previous + 1; + } + return previous; + }, 0) + ); + + board.dataPool.setConnectorOptions({ + id: 'rna-type-amount', + type: 'JSON', + options: { + columnNames: ['Type', 'Amount'], + orientation: 'columns', + firstRowAsNames: false, + data: [ + uniqueTypes, + numberPerType + ] } - return previous; - }, 0) - ); - - board.dataPool.setConnectorOptions({ - id: 'rna-type-amount', - type: 'JSON', - options: { - columnNames: ['Type', 'Amount'], - orientation: 'columns', - firstRowAsNames: false, - data: [ - uniqueTypes, - numberPerType - ] - } + }); + + // Refresh the component after updating the table + await board.getComponentByCellId('dashboard-col-1').initConnectors(); + await board.getComponentByCellId('dashboard-col-1').update({ + connector: { + id: 'rna-type-amount', + columnAssignment: [{ + seriesId: 'number-per-type', + data: ['Type', 'Amount'] + }] + } + }); + }) + .finally(() => { + loadingLabel.style.display = 'none'; }); +} - // Refresh the component after updating the table - await board.getComponentByCellId('dashboard-col-1').initConnectors(); - await board.getComponentByCellId('dashboard-col-1').update({ - connector: { - id: 'rna-type-amount', - columnAssignment: [{ - seriesId: 'number-per-type', - data: ['Type', 'Amount'] - }] +async function handleSelectEnvironment (evt) { + const target = evt.target; + const postmanJSON = await getPostmanJSON(target); + + if (!postmanJSON) { + loadingLabel.textContent = 'The provided file is not a Postman Environment Configuration.'; + loadingLabel.style.display = 'block'; + + return; + } + + target.parentNode.style.display = 'none'; + + loadingLabel.style.display = 'block'; + loadingLabel.textContent = 'Loading data…'; + + displayRNANews(postmanJSON); +} + +document.getElementById('postman-json') + .addEventListener('change', handleSelectEnvironment); + +async function getPostmanJSON (htmlInputFile) { + let file; + let fileJSON; + + for (file of htmlInputFile.files) { + try { + fileJSON = JSON.parse(await file.text()); + if (Connectors.Morningstar.isPostmanEnvironmentJSON(fileJSON)) { + break; } - }); - }) - .catch(window.alert); + } catch (error) { + // fail silently + } + } + + return fileJSON; +} diff --git a/demos/stock/demo.js b/demos/stock/demo.js index 3b142f9..7c9fad0 100644 --- a/demos/stock/demo.js +++ b/demos/stock/demo.js @@ -2,7 +2,7 @@ document.getElementById('postman-json').addEventListener( 'change', async function (evt) { const target = evt.target; - const postmanJSON = await getPostmanJSON(evt.target); + const postmanJSON = await getPostmanJSON(target); if (!postmanJSON) { return; diff --git a/src/RNANews/RNANewsJSON.ts b/src/RNANews/RNANewsJSON.ts index 8d56ba9..0424d2a 100644 --- a/src/RNANews/RNANewsJSON.ts +++ b/src/RNANews/RNANewsJSON.ts @@ -77,8 +77,8 @@ export namespace RNANewsJSON { return ( !!json && Array.isArray(json) && - json.length === 0 || - isResponseItem((json as Array)[0]) + (json.length === 0 || + isResponseItem((json as Array)[0])) ); } @@ -91,7 +91,7 @@ export namespace RNANewsJSON { typeof json === 'object' && typeof (json as ResponseItem).day === 'string' && typeof (json as ResponseItem).items === 'object' && - isRNANewsResponseItem(typeof (json as ResponseItem).items[0]) + isRNANewsResponseItem((json as ResponseItem).items[0]) ); } diff --git a/src/Shared/MorningstarAPI.ts b/src/Shared/MorningstarAPI.ts index 52c65d1..96af715 100644 --- a/src/Shared/MorningstarAPI.ts +++ b/src/Shared/MorningstarAPI.ts @@ -57,6 +57,8 @@ export class MorningstarAPI { window.location.href ); + this.baseURL.pathname = '/ecint/v1/'; + if (this.baseURL.protocol !== 'https:') { throw new Error('Insecure API protocol'); } diff --git a/test/unit-tests/RNANews/RNANewsConverter.test.ts b/test/unit-tests/RNANews/RNANewsConverter.test.ts new file mode 100644 index 0000000..8f5b410 --- /dev/null +++ b/test/unit-tests/RNANews/RNANewsConverter.test.ts @@ -0,0 +1,61 @@ +import * as Assert from 'node:assert/strict'; +import * as MC from '../../../code/connectors-morningstar.src'; +import RNANewsJSON from '../../../src/RNANews/RNANewsJSON'; + +export async function rnaNewsLoad ( + api: MC.Shared.MorningstarAPIOptions +) { + const connector = new MC.RNANewsConnector({ + api, + security: { + id: 'GB00BLGZ9862', + idType: 'ISIN' + }, + startDate: '2023-05-13', + endDate: '2023-05-23' + }); + + Assert.ok( + connector instanceof MC.RNANewsConnector, + 'Connector should be instance of RNANewsConnector class.' + ); + + Assert.ok( + connector.converter instanceof + MC.RNANewsConverter, + 'Converter should be instance of RNANewsConverter.' + ); + + await connector.load(); + + Assert.deepStrictEqual( + connector.table.getColumnNames(), + ['Day', 'Title', 'Source', 'Type'], + 'Connector table should exist of expected columns.' + ); + + Assert.strictEqual( + connector.table.getRowCount(), + 10, + 'Connector table should have one expected dividend row.' + ); + +} + +export function rnaNewsValidation () { + + const day = '1723766400000'; + const item = ['LSE20240816070005_5311334', 'Transaction in Own Shares', 'RNS', 'POS']; + + const mockResponse = [ + { + day: day, + items: [item] + } + ]; + + Assert.ok( + RNANewsJSON.isResponse(mockResponse), + 'Mock response should be considered a valid response' + ); +} From 24a1cab1b0214ca86a8ec91dd616e09391fa583a Mon Sep 17 00:00:00 2001 From: bre1470 <40056287+bre1470@users.noreply.github.com> Date: Mon, 19 Aug 2024 12:13:35 +0200 Subject: [PATCH 2/3] Updated README.md after renaming. --- README.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 82e125f..5fecf02 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,7 @@ Morningstar Connectors ====================== -Collection of [Highcharts Dashboards] connectors for -[Morningstar Direct Web Services]. +Collection of [Highcharts connectors] for [Morningstar Direct Web Services]. @@ -11,15 +10,16 @@ Usage The connectors are available as -* ES6 modules by importing `@highcharts/morningstar-connectors` in your project. +* ES6 modules by importing `@highcharts/connectors-morningstar` in your project. -* UMD bundle by adding the `@highcharts/morningstar-connectors/dist/all.js` - script to your web app or web page. +* UMD bundle by adding the + `@highcharts/connectors-morningstar/connectors-morningstar.js` script to your + web app or web page. -[Highcharts Dashboards]: https://highcharts.com/dashboards/ +[Highcharts connectors]: https://highcharts.com/connectors/ [Morningstar Direct Web Services]: https://developer.morningstar.com/direct-web-services/ From ae05bcd7232efe096d9395203109d0a9574ba55f Mon Sep 17 00:00:00 2001 From: Sophie Bremer <40056287+bre1470@users.noreply.github.com> Date: Mon, 19 Aug 2024 13:34:50 +0200 Subject: [PATCH 3/3] Fix renaming of leftovers (#19) * Updated LICENSE.md. * Updated README.md. * Removed old index.html. * Renamed demo folders. * Renamed docs draft. --- LICENSE.md | 2 +- README.md | 7 +++++-- .../{rna-news => dashboards-rna-news}/demo.css | 0 .../demo.html | 3 ++- .../{rna-news => dashboards-rna-news}/demo.js | 0 demos/index.html | 7 ++++--- demos/{stock => stock-timeseries}/demo.html | 3 ++- demos/{stock => stock-timeseries}/demo.js | 0 .../morningstar.md} | 8 ++++---- index.html | 18 ------------------ 10 files changed, 18 insertions(+), 30 deletions(-) rename demos/{rna-news => dashboards-rna-news}/demo.css (100%) rename demos/{rna-news => dashboards-rna-news}/demo.html (87%) rename demos/{rna-news => dashboards-rna-news}/demo.js (100%) rename demos/{stock => stock-timeseries}/demo.html (81%) rename demos/{stock => stock-timeseries}/demo.js (100%) rename docs/{morningstar/morningstar-connectors.md => connectors/morningstar.md} (77%) delete mode 100644 index.html diff --git a/LICENSE.md b/LICENSE.md index fb5afb7..19a76e4 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -1,4 +1,4 @@ -This is the source code repository of the Highcharts Dashboards connectors for Morningstar Direct Web Services. +This is the source code repository of the Highcharts Connectors for Morningstar Direct Web Services. Read more on licensing alternatives here: - https://shop.highcharts.com/ diff --git a/README.md b/README.md index 5fecf02..7d72792 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ Morningstar Connectors ====================== -Collection of [Highcharts connectors] for [Morningstar Direct Web Services]. +Collection of [Highcharts Connectors] for [Morningstar Direct Web Services]. @@ -16,10 +16,13 @@ The connectors are available as `@highcharts/connectors-morningstar/connectors-morningstar.js` script to your web app or web page. +**Note:** The UMD bundle is not available via +`https://code.highcharts.com/connectors/connectors-morningstar.js` yet. + -[Highcharts connectors]: https://highcharts.com/connectors/ +[Highcharts Connectors]: https://highcharts.com/connectors/ [Morningstar Direct Web Services]: https://developer.morningstar.com/direct-web-services/ diff --git a/demos/rna-news/demo.css b/demos/dashboards-rna-news/demo.css similarity index 100% rename from demos/rna-news/demo.css rename to demos/dashboards-rna-news/demo.css diff --git a/demos/rna-news/demo.html b/demos/dashboards-rna-news/demo.html similarity index 87% rename from demos/rna-news/demo.html rename to demos/dashboards-rna-news/demo.html index 7ce1e65..65e2cee 100644 --- a/demos/rna-news/demo.html +++ b/demos/dashboards-rna-news/demo.html @@ -6,9 +6,10 @@ - RNA News Demo - Morningstar Connectors Demos + Highcharts Dashboards + Morningstar RNA News +

Highcharts Dashboards + Morningstar RNA News

Add your Postman environment file from Morningstar to start the demo: diff --git a/demos/rna-news/demo.js b/demos/dashboards-rna-news/demo.js similarity index 100% rename from demos/rna-news/demo.js rename to demos/dashboards-rna-news/demo.js diff --git a/demos/index.html b/demos/index.html index adf70c7..dea0220 100644 --- a/demos/index.html +++ b/demos/index.html @@ -5,9 +5,10 @@ Morningstar Connectors Demos +

Morningstar Connectors Demos

- \ No newline at end of file + diff --git a/demos/stock/demo.html b/demos/stock-timeseries/demo.html similarity index 81% rename from demos/stock/demo.html rename to demos/stock-timeseries/demo.html index 8fd59d8..8ee303c 100644 --- a/demos/stock/demo.html +++ b/demos/stock-timeseries/demo.html @@ -4,9 +4,10 @@ - Highcharts Stock Demo - Morningstar Connectors Demos + Highcharts Stock + Morningstar TimeSeries +

Highcharts Stock + Morningstar TimeSeries

Add your Postman environment file from Morningstar to start the demo: diff --git a/demos/stock/demo.js b/demos/stock-timeseries/demo.js similarity index 100% rename from demos/stock/demo.js rename to demos/stock-timeseries/demo.js diff --git a/docs/morningstar/morningstar-connectors.md b/docs/connectors/morningstar.md similarity index 77% rename from docs/morningstar/morningstar-connectors.md rename to docs/connectors/morningstar.md index de8fa81..ca5c431 100644 --- a/docs/morningstar/morningstar-connectors.md +++ b/docs/connectors/morningstar.md @@ -1,8 +1,8 @@ # Morningstar Connectors -With the Highcharts Morningstar Connectors you can access the Morningstar Direct -Web Services. These services provide finance-related information to different -kinds of financial assets. +With the Highcharts Connectors for the Morningstar Direct Web Services you can +access finance-related information to different kinds of financial assets. This +requires a Highcharts license and a Morningstar subscription. @@ -40,7 +40,7 @@ assing the resulting table to your series options. ### Highcharts Dashboards Quick Start -For Highcharts Dashboards you just need to load teh `morningstar-connectors` +For Highcharts Dashboards you just need to load the `morningstar-connectors` bundle, which will register all connectors to the Dashboards registry. All Morningstar connectors are then available in the data pool as other connector types. diff --git a/index.html b/index.html deleted file mode 100644 index 20dfc94..0000000 --- a/index.html +++ /dev/null @@ -1,18 +0,0 @@ - - - - - Morningstar Connectors Demos - Highcharts Dashboards - - -

-

Morningstar Connectors Demos

- -
- -