From eea27dbcea0d69e81707e2b607250b46d8c6c740 Mon Sep 17 00:00:00 2001 From: Cara <99646608+cfisher-scottlogic@users.noreply.github.com> Date: Tue, 14 Nov 2023 12:33:06 +0000 Subject: [PATCH] Sync mains (pull) (#107) * #900 disable failing test * Update check on viewport and context menu (#913) * remove reprecated Portal, fixes in COntextMenu * use woff2 font, fix portal * make sure ContextMenu always has theme attributes * type fixes * Tidy package and type issues (#914) * fix package references, type issues * add typescript config for correct auto import resolution * Layout Management (#916) * fix vuu-filters types * drawer and dialog fix * drag drop flexbox editable * Update vuu-ui/packages/vuu-filters/src/filter-utils.ts Whitespace between guard clauses Co-authored-by: Luke Vincent * layout header * restore double quotes * layout-provider * layout-reducer * layout-view * palette * palette * placeholder * layout-view decomment * registry * rollback multi filter dropdown * stack * tabs * config wrapper * tools * utils * layout top level * revert flexbox layout change * restore lost semicolon * missing space * change action to a type union * Update README.md * Sync with Finos main * VUU-41 style fixes * VUU-41 rename css variable to --vuu * Manage layout persistence via interface (#55) * VUU-27 interface to return promises * VUU-47 add methods for loading and saving tempLayout * VUU-47 use loadLayoutById in LayoutList * VUU-47 remove unused files * VUU-47 update other examples to use new hook * Calculated column (#882) * calculated column in settings, instrument search * additional mock data sources * instrument tiles * calculated column editing * measured-container * Row used columnMap rathe than column key * full keyboard nav for table * fix drag drop in column group headerr * use MeasuredContainer for Table List * table cell editing updates datasource * table editing * fix type issues * fix old background renderer * remove outdated import in showcase story * exclude PatternValidator from semgrep * add vuu tooltip component (#885) * VUU-47 improve naming * VUU-47 use placeholder in defaultLayout * VUU-47 update docs with new naming * remove duplicate CSS * VUU-47 fix layoutList styling * VUU-47 add loaded layouts to layout view * VUU-47 rename currentLayout to applicationLayout * VUU-47 make defaultLayout closeable and update features * VUU-27 interface to return promises * VUU-54: Validate IDs in LocalLayoutPersistenceManager * VUU-54: Mock get/saveLocalEntity * VUU-54: Refactor promises * VUU-54: Remove unnecessary asyncs * VUU-54: Use string union to distinguish layouts/metadata * VUU-54: Rename variables * VUU-54: Convert layout types to interfaces * VUU-54: Extract loadAndFilter method * VUU-54: Replace filter with find * VUU-54: Rename validateId variables * VUU-54: Change vars to lets * VUU-54: Update imports for consistency * VUU-54: Add comment to explain filter(Boolean) * VUU-54: Refactor tests * VUU-54: Extract expectError * VUU-54: Remove loadAndFilter method * VUU-54: Remove removeEntry method * VUU-52: Add E2E tests to CI * VUU-52: Use commit hash for cypress-io * VUU-52: Add comment to explain full SHA * VUU-47 rename imports * VUU-59 set up notification context * VUU-47 fix cypress test * Update vuu-ui/packages/vuu-layout/src/layout-persistence/LayoutPersistenceManager.ts Co-authored-by: Cara <99646608+cfisher-scottlogic@users.noreply.github.com> * VUU-47 remove unused import * VUU-59 notifications with animation * VUU-59 revert changes to imports * VUU-59 change toast timeout * VUU-59 change notificationType to enum * VUU-59 improvements to example and add comments --------- Co-authored-by: harryhartley Co-authored-by: Luke Vincent Co-authored-by: Joe Dunleavy <107405201+Joe-Dunleavy@users.noreply.github.com> Co-authored-by: Joe Dunleavy Co-authored-by: cfisher-scottlogic Co-authored-by: Cara <99646608+cfisher-scottlogic@users.noreply.github.com> Co-authored-by: Peter Ling Co-authored-by: pling-scottlogic <79100986+pling-scottlogic@users.noreply.github.com> Co-authored-by: heswell * add Layout Management Provider to sample apps (#917) * add Layout Management Provider to sample apps * fix test dependencies * Drag drop provider (#918) * add DragDrop example, resume drag in DragProvider * full flow for remote drag * fix type issues * fix post rebase conflicts, type issues * ignore type issue in drag drop code for now, so packages build * Filterbar styling (#919) * improve the keyboards navigation in Toolbar * fix form control styling, uennecessaryb layout rerenders, table resize bug * make sure all table config setting changes are saved, style tweaks * calculated columns * fix dropdown width * fix width of combo in SaveLayout Panel * remove console.log * fix bug in OverflowContainer when orientation vertical * remove global error listener, leave this to cypress * move test schemas out of showcase (#920) * Update dependency electron to v22 [SECURITY] (#894) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * bump vite, vitest versions to latest (#921) * Instrument picker (#923) * make instrument-picker more generic * refactor Table navigation, preparing for row highlighting * fix broken import paths * add empty inlined worker as vitext mocj fails otherwise * reinstate ignore for inlined-wotker so stub file doesn't get overwritten (#924) * disable basket functionality in showcase while we wait for full server (#925) * disable basket functionality in showcase while we wait for server implementation * remove console log * fix styling of main tabs during drag (#929) * wiring together calculated column pieces (#931) * wiring together calculated column pieces * remove logging * re-enable all tests * fix FilterTable resize bug (#932) * move table height fix to measured container (#933) * type fixes (#934) * final styling for calculated column input (#935) * connect filterbar to persistence (#936) * connect filterbar to persistence * skip test for missing TreeWalker finctionality until its there * final adjustments to table column header styling (#937) * move date generators to test data package (#938) * Bump postcss from 8.4.27 to 8.4.31 in /vuu-ui (#926) Bumps [postcss](https://github.com/postcss/postcss) from 8.4.27 to 8.4.31. - [Release notes](https://github.com/postcss/postcss/releases) - [Changelog](https://github.com/postcss/postcss/blob/main/CHANGELOG.md) - [Commits](https://github.com/postcss/postcss/compare/8.4.27...8.4.31) --- updated-dependencies: - dependency-name: postcss dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * #850 added for functionality to the rpc service, not ready for the big time yet, but not far off. * #850 added ability to reference tables in separate modules. * #850 refactored simul module to take prices out to prices module * #850 refactored tableDefContainer to make it an implicit, otherwise it is re-used in the tests causing issues. * #850 found a bug with basket constituents, not resolved as of this commit. * #850 found a bug with basket constituents, not resolved as of this commit. * Update basket tables UI (#940) * update all basket tables, integrate basket server changes * filter basket tables when loading * connect cell editing * remove console log * fix newFeature story * remove console log * fix for dropdown width error * remove console.log * basket workflow (#941) * Login panel (#942) * login panel * WIP * tidy up type issues etc * import fixes * remove deprecated example * #944 Added fix for threading related issue in ViewPortContainer.scala when change was called. * #944 Reduced logging * Switch UI to new Theme (#943) * remove sample app * rename basket trading app to sample-app * fix broken inmports * fix bugs persistning table settings * 862 create a basketdesign table that represents the specific instance of a basket that we are modifying it will be based on a basket entry but can be customized to what the user needs (#948) * #862 Fixed test versions to abstract out clock. * #862 Added Viewport scoped rpc service to test. * #862 Added ability to edit baskets join service. * Fix minor UI issues (#949) * fix UI dataTable issue - bugs after resize A column resize operation populates the ColumnState state value. From this point on columnState shadows modelColumns so subsequent changes to modelColumns are not rendered. * enable custom editors for cell renderers Column Settings Panel allows a custom renderer to be selected. Some renderers will have settings of their own. This enables editors form those settings to be made available. * fix type issue * update baskets used in showcase examples to match server tables (#950) * add initial support for columns backed by lookup tables (#951) * move basket data generation into simulated vuu module to pave way for rpc support * add updater for prices, insert for array data source * create Table for test data in modules * fix scrolling issue in table when focusing edit fields * add initial support for table columns backed by lookup tables * wire table cell editing to server calls (#953) * Schema load sequence (#955) * cache table meta requests with promise to avoid multiple server requests * ensure table meta is loaded before client is notified of subcribe table meta for all tables was being requested from server every time any hook asked for the table data. This was happening twice at startup. Now we cache the metadata. If we didn't have table meta at point where CREATE_VP_SUCCESS was handled, we notified client anyway. This caused tables to be rendered with no type information, so alignment was wrong on numerics. * fix all data tests * Issue 850 added the first example module test for rpc services (#954) * #850 Refactored example code so that simulation is in its own module * #850 Refactored example code into its own module * #850 updated documentation * #850 organized imports * #850 added first consumer test outline * #850 added ability to create viewport in test easily * #850 added ability to create viewport in test easily * #850 added first example working test calling viewport Rpc call. * #850 renamed test case. * #850 Added example flow for baskets * #850 Added additional example for editRowAction * #850 Added additional methods for editable example. * #850 Added additional methods for editable example. * #850 Added more functionality to the demo basket app. * #850 Added thorough test of basket functionality. * #850 Fixed test assert which accidentally changed contract in test. * #850 Fixed test assert which accidentally changed contract in test. * #850 Fixed test assert which accidentally changed contract in test. * #850 fixed the bad pom definition. * #850 deleted duplicate and not required config and updated semgrep. * Release 0.9.20 beta (#956) * [maven-release-plugin] prepare release vuu-parent-0.9.20-beta * [maven-release-plugin] prepare for next development iteration --------- Co-authored-by: GitHub Actions * #957 added all projects to release build. (#960) * #957 added all projects to release build. * #957 added all projects to release build. * #957 added all projects to release build. * Release 0.9.33 beta (#961) * [maven-release-plugin] prepare release vuu-parent-0.9.33-beta * [maven-release-plugin] prepare for next development iteration --------- Co-authored-by: GitHub Actions * #957 fixed issue with javadoc. (#963) * Release 0.9.35 beta (#964) * [maven-release-plugin] prepare release vuu-parent-0.9.35-beta * [maven-release-plugin] prepare for next development iteration --------- Co-authored-by: GitHub Actions * enable context menu on basket constituents (#965) * fix behaviour in baskets module in data-test * fix pinned column rendering gap * enable context menu in basket constituent table in basket feature * remove console log * Fix conflict resolutions --------- Signed-off-by: dependabot[bot] Co-authored-by: keikeicheung Co-authored-by: heswell Co-authored-by: Vasco <98337074+vferraro-scottlogic@users.noreply.github.com> Co-authored-by: harryhartley Co-authored-by: Luke Vincent Co-authored-by: Joe Dunleavy <107405201+Joe-Dunleavy@users.noreply.github.com> Co-authored-by: Joe Dunleavy Co-authored-by: Peter Ling Co-authored-by: pling-scottlogic <79100986+pling-scottlogic@users.noreply.github.com> Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: chris Co-authored-by: chrisjstevo Co-authored-by: GitHub Actions --- .github/workflows/legal-report.yml | 4 +- .semgrepignore | 3 + benchmark/pom.xml | 4 +- docs/getting_started/developing.md | 2 +- example/basket/pom.xml | 271 +++++ .../basket/src/main/java/Dummy4JavaDoc.java | 2 + .../src/main/resources/static/ftse100.csv | 100 ++ .../basket/src/main/resources/static/hsi.csv | 81 ++ .../src/main/resources/static/nasdaq100.csv | 102 ++ .../src/main/resources/static/sp500.csv | 504 ++++++++ .../core/module/basket/BasketConstants.scala | 0 .../vuu/core/module/basket/BasketModule.scala | 43 +- .../module/basket/csv/CsvStaticLoader.scala | 10 +- .../module/basket/provider/AlgoProvider.scala | 11 +- .../provider/BasketConstituentProvider.scala | 2 +- .../basket/provider/BasketProvider.scala | 0 .../provider/BasketTradingProvider.scala | 51 + .../module/basket/provider/NullProvider.scala | 0 .../provider/PriceStrategyProvider.scala | 2 +- .../module/basket/service/BasketService.scala | 45 +- .../BasketTradingConstituentJoinService.scala | 13 + .../BasketTradingConstituentService.scala | 12 + .../basket/service/BasketTradingService.scala | 63 + .../core/module/basket/BasketCreateTest.scala | 75 ++ .../basket/BasketMutateOffMarketTest.scala | 143 +++ .../module/basket/BasketTestCaseHelper.scala | 27 + .../vuu/core/module/basket/TestService.scala | 25 + .../BasketConstituentProviderTest.scala | 102 ++ .../vuu/provider/BasketProviderTest.scala | 55 + example/editable/pom.xml | 246 ++++ .../editable/src/main/java/Dummy4JavaDoc.java | 2 + .../core/module/editable/EditableModule.scala | 6 +- .../editable/FixSequenceRpcService.scala | 2 +- .../module/editable/ProcessProvider.scala | 2 +- .../module/editable/ProcessRpcService.scala | 6 +- .../core/module/editable/EditableTest.scala | 78 ++ .../module/editable/EditableTestModule.scala | 89 ++ .../core/module/editable/NullProvider.scala | 17 + example/main/pom.xml | 329 ++++++ example/main/src/main/java/Dummy4JavaDoc.java | 2 + .../main/src/main/resources/FilterSpec.txt | 35 + .../main/src/main/resources/application.conf | 3 + .../main}/src/main/resources/certs/cert.pem | 0 .../main}/src/main/resources/certs/key.pem | 0 example/main/src/main/resources/down.gif | Bin 0 -> 76 bytes .../src/main/resources/icon-arrow-right.png | Bin 0 -> 1062 bytes .../src/main/resources/logback-netty.xml | 0 .../src/main/resources/logback-socket.xml | 0 .../src/main/resources/logback-trace.xml | 0 .../main}/src/main/resources/logback.xml | 0 example/main/src/main/resources/right.png | Bin 0 -> 279 bytes .../src/main/resources/sort-arrow-down.gif | Bin 0 -> 76 bytes .../main/src/main/resources/sort-arrow-up.gif | Bin 0 -> 76 bytes .../src/main/resources/static/ftse100.csv | 100 ++ .../main/src/main/resources/static/hsi.csv | 81 ++ .../src/main/resources/static/nasdaq100.csv | 102 ++ .../main/src/main/resources/static/sp500.csv | 504 ++++++++ .../main/scala/org/finos/vuu/SimulMain.scala | 20 +- example/order/pom.xml | 297 +++++ .../order/src/main/java/Dummy4JavaDoc.java | 2 + .../core/module/simul/SimulationModule.scala | 39 +- .../simul/provider/ChildOrdersProvider.scala | 4 +- .../simul/provider/OrdersSimulProvider.scala | 4 +- .../provider/ParentChildOrdersModel.scala | 0 .../simul/provider/ParentOrdersProvider.scala | 4 +- .../provider/PermissionedOrdersProvider.scala | 0 .../simul/service/ParentOrdersService.scala | 2 +- .../SimulatedBigInstrumentsProvider.scala | 4 +- .../SimulatedInstrumentProvider.scala | 2 +- .../simulation/SimulatedPricesProvider.scala | 4 +- example/permission/pom.xml | 294 +++++ .../src/main/java/Dummy4JavaDoc.java | 2 + .../vuu/core/module/authn/AuthNModule.scala | 4 +- .../core/module/authn/AuthNRestService.scala | 4 +- .../core/module/authn/VuuAuthHandler.scala | 2 + .../module/auths/OrderPermissionChecker.scala | 4 +- .../core/module/auths/PermissionModule.scala | 0 .../vuu/core/module/auths/PermissionSet.scala | 1 - .../auths/provider/PermissionsProvider.scala | 0 .../auths/service/PermissionsRpcService.scala | 8 +- .../core/module/authn/AuthNServerTest.scala | 16 +- .../auths/PermissionFilteredViewport.scala | 158 +++ .../core/module/auths/PermissionsTest.scala | 3 +- .../auths/TestFriendlyPermissionChecker.scala | 3 +- example/pom.xml | 61 + example/price/pom.xml | 294 +++++ .../price/src/main/java/Dummy4JavaDoc.java | 2 + .../vuu/core/module/price/PriceModule.scala | 35 +- .../simulation/SimulatedPricesProvider.scala | 354 ++++++ .../SimulatedPricesProviderTest.scala | 8 +- .../TestFriendlyJoinTableProvider.scala | 21 + pom.xml | 3 +- toolbox/pom.xml | 2 +- .../src/hooks/useVuuMenuActions.ts | 51 +- .../src/TickingArrayDataSource.ts | 8 +- .../vuu-data-test/src/basket/basket-module.ts | 30 +- .../src/basket/basket-schemas.ts | 3 + .../src/basket/data-generators/index.ts | 5 +- .../src/simul/OrderUpdateGenerator.ts | 15 +- .../array-data-source/array-data-source.ts | 44 +- .../src/array-data-source/array-data-utils.ts | 69 ++ .../vuu-data/src/connection-manager.ts | 79 +- vuu-ui/packages/vuu-data/src/data-source.ts | 7 - .../packages/vuu-data/src/inlined-worker.js | 212 ++-- .../packages/vuu-data/src/json-data-source.ts | 93 +- vuu-ui/packages/vuu-datagrid-types/index.d.ts | 6 +- .../LocalLayoutPersistenceManager.ts | 4 - .../src/menu/context-menu-provider.tsx | 9 +- .../src/layout-management/LayoutList.tsx | 6 +- .../layout-management/useLayoutManager.tsx | 12 +- .../src/cell-edit-validators/CaseValidator.ts | 2 +- .../cell-edit-validators/PatternValidator.ts | 2 +- .../vuu-table/src/table-next/TableNext.tsx | 9 +- .../src/table-next/header-cell/HeaderCell.css | 4 +- .../vuu-table/src/table-next/useTableNext.ts | 16 +- .../vuu-table/src/table/useTableModel.ts | 1 - .../packages/vuu-theme/fonts/NunitoSans.css | 2 +- .../cycle-state-button/CycleStateButton.tsx | 9 +- .../src/editable/editable-utils.ts | 8 +- .../src/editable/useEditableText.ts | 100 +- .../src/expando-input/ExpandoInput.tsx | 4 +- .../src/vuu-input/VuuInput.tsx | 7 +- .../vuu-utils/src/component-registry.ts | 3 +- vuu-ui/pom.xml | 2 +- .../src/VuuBasketTradingFeature.tsx | 3 +- .../src/basket-table-edit/BasketTableEdit.tsx | 96 +- .../src/basket-table-live/BasketTableLive.tsx | 128 +-- .../basketConstituentLiveColumns.ts | 93 ++ .../src/basket-toolbar/BasketToolbar.tsx | 17 +- .../cell-renderers/spread-cell/SpreadCell.tsx | 5 +- .../src/new-basket-panel/NewBasketPanel.css | 2 +- .../src/new-basket-panel/useNewBasketPanel.ts | 1 + ...ketTabMenu.ts => useBasketContextMenus.ts} | 2 +- .../src/useBasketTrading.tsx | 29 +- .../src/examples/Table/TableNext.examples.tsx | 3 +- .../examples/Table/TableVuuData.examples.tsx | 102 +- .../VuuFeatures/BasketToolbar.examples.tsx | 59 +- .../utils/useAutoLoginToVuuServer.tsx | 3 +- vuu-ui/tsconfig.json | 89 +- vuu/pom.xml | 4 +- vuu/src/main/resources/application.conf | 3 - .../main/resources/issue/size.noset.vuu.log | 232 ---- vuu/src/main/resources/issue/size.set.vuu.log | 1010 ----------------- .../runconfigurations/SimulMain.run.xml | 2 +- vuu/src/main/resources/static/ftse100.csv | 200 ++-- vuu/src/main/resources/static/hsi.csv | 162 +-- vuu/src/main/resources/static/nasdaq100.csv | 2 +- vuu/src/main/resources/static/sp500.csv | 1002 ++++++++-------- .../finos/vuu/core/AbstractVuuServer.scala | 18 + .../finos/vuu/core/CoreServerApiHandler.scala | 4 +- .../scala/org/finos/vuu/core/VuuServer.scala | 9 +- .../finos/vuu/core/module/ModuleFactory.scala | 24 +- .../org/finos/vuu/core/module/VsModule.scala | 10 +- .../vuu/net/ClientConnectionCreator.scala | 6 +- .../scala/org/finos/vuu/net/Messages.scala | 7 +- .../net/json/CoreJsonSerializationMixin.scala | 2 + .../vuu/provider/VuuJoinTableProvider.scala | 9 +- .../vuu/viewport/ViewPortContainer.scala | 4 +- .../vuu/core/module/core/CoreModuleTest.scala | 95 -- .../vuu/core/sort/FilterAndSortFixture.scala | 2 +- .../vuu/core/table/TableTestHelper.scala | 20 +- .../BasketConstituentProviderTest.scala | 102 -- .../vuu/provider/BasketProviderTest.scala | 55 - .../TestFriendlyJoinTableProvider.scala | 3 +- .../org/finos/vuu/test/TestVuuServer.scala | 106 ++ .../finos/vuu/test/VuuServerTestCase.scala | 35 + .../org/finos/vuu/test/impl/TestChannel.scala | 136 +++ .../vuu/test/impl/TestVuuServerImpl.scala | 200 ++++ .../finos/vuu/test/rpc/RpcDynamicProxy.scala | 207 ++++ .../finos/vuu/util/table/TableAsserts.scala | 14 + .../viewport/CreateViewPortScenarioTest.scala | 174 --- .../finos/vuu/viewport/ViewPortSetup.scala | 61 - .../auths/PermissionFilteredViewport.scala | 96 -- .../editable/EditableViewPortTest.scala | 8 +- .../AbstractSessionTestCase.scala | 8 +- .../SessionTableViewportTest.scala | 8 +- 176 files changed, 7065 insertions(+), 3446 deletions(-) create mode 100644 example/basket/pom.xml create mode 100644 example/basket/src/main/java/Dummy4JavaDoc.java create mode 100644 example/basket/src/main/resources/static/ftse100.csv create mode 100644 example/basket/src/main/resources/static/hsi.csv create mode 100644 example/basket/src/main/resources/static/nasdaq100.csv create mode 100644 example/basket/src/main/resources/static/sp500.csv rename {vuu => example/basket}/src/main/scala/org/finos/vuu/core/module/basket/BasketConstants.scala (100%) rename {vuu => example/basket}/src/main/scala/org/finos/vuu/core/module/basket/BasketModule.scala (83%) rename {vuu => example/basket}/src/main/scala/org/finos/vuu/core/module/basket/csv/CsvStaticLoader.scala (92%) rename {vuu => example/basket}/src/main/scala/org/finos/vuu/core/module/basket/provider/AlgoProvider.scala (86%) rename {vuu => example/basket}/src/main/scala/org/finos/vuu/core/module/basket/provider/BasketConstituentProvider.scala (97%) rename {vuu => example/basket}/src/main/scala/org/finos/vuu/core/module/basket/provider/BasketProvider.scala (100%) create mode 100644 example/basket/src/main/scala/org/finos/vuu/core/module/basket/provider/BasketTradingProvider.scala rename {vuu => example/basket}/src/main/scala/org/finos/vuu/core/module/basket/provider/NullProvider.scala (100%) rename {vuu => example/basket}/src/main/scala/org/finos/vuu/core/module/basket/provider/PriceStrategyProvider.scala (95%) rename {vuu => example/basket}/src/main/scala/org/finos/vuu/core/module/basket/service/BasketService.scala (66%) rename {vuu => example/basket}/src/main/scala/org/finos/vuu/core/module/basket/service/BasketTradingConstituentJoinService.scala (87%) rename {vuu => example/basket}/src/main/scala/org/finos/vuu/core/module/basket/service/BasketTradingConstituentService.scala (86%) create mode 100644 example/basket/src/main/scala/org/finos/vuu/core/module/basket/service/BasketTradingService.scala create mode 100644 example/basket/src/test/scala/org/finos/vuu/core/module/basket/BasketCreateTest.scala create mode 100644 example/basket/src/test/scala/org/finos/vuu/core/module/basket/BasketMutateOffMarketTest.scala create mode 100644 example/basket/src/test/scala/org/finos/vuu/core/module/basket/BasketTestCaseHelper.scala create mode 100644 example/basket/src/test/scala/org/finos/vuu/core/module/basket/TestService.scala create mode 100644 example/basket/src/test/scala/org/finos/vuu/provider/BasketConstituentProviderTest.scala create mode 100644 example/basket/src/test/scala/org/finos/vuu/provider/BasketProviderTest.scala create mode 100644 example/editable/pom.xml create mode 100644 example/editable/src/main/java/Dummy4JavaDoc.java rename {vuu => example/editable}/src/main/scala/org/finos/vuu/core/module/editable/EditableModule.scala (93%) rename {vuu => example/editable}/src/main/scala/org/finos/vuu/core/module/editable/FixSequenceRpcService.scala (89%) rename {vuu => example/editable}/src/main/scala/org/finos/vuu/core/module/editable/ProcessProvider.scala (93%) rename {vuu => example/editable}/src/main/scala/org/finos/vuu/core/module/editable/ProcessRpcService.scala (70%) create mode 100644 example/editable/src/test/scala/org/finos/vuu/core/module/editable/EditableTest.scala create mode 100644 example/editable/src/test/scala/org/finos/vuu/core/module/editable/EditableTestModule.scala create mode 100644 example/editable/src/test/scala/org/finos/vuu/core/module/editable/NullProvider.scala create mode 100644 example/main/pom.xml create mode 100644 example/main/src/main/java/Dummy4JavaDoc.java create mode 100644 example/main/src/main/resources/FilterSpec.txt create mode 100644 example/main/src/main/resources/application.conf rename {vuu => example/main}/src/main/resources/certs/cert.pem (100%) rename {vuu => example/main}/src/main/resources/certs/key.pem (100%) create mode 100644 example/main/src/main/resources/down.gif create mode 100644 example/main/src/main/resources/icon-arrow-right.png rename {vuu => example/main}/src/main/resources/logback-netty.xml (100%) rename {vuu => example/main}/src/main/resources/logback-socket.xml (100%) rename {vuu => example/main}/src/main/resources/logback-trace.xml (100%) rename {vuu => example/main}/src/main/resources/logback.xml (100%) create mode 100644 example/main/src/main/resources/right.png create mode 100644 example/main/src/main/resources/sort-arrow-down.gif create mode 100644 example/main/src/main/resources/sort-arrow-up.gif create mode 100644 example/main/src/main/resources/static/ftse100.csv create mode 100644 example/main/src/main/resources/static/hsi.csv create mode 100644 example/main/src/main/resources/static/nasdaq100.csv create mode 100644 example/main/src/main/resources/static/sp500.csv rename {vuu => example/main}/src/main/scala/org/finos/vuu/SimulMain.scala (94%) create mode 100644 example/order/pom.xml create mode 100644 example/order/src/main/java/Dummy4JavaDoc.java rename {vuu => example/order}/src/main/scala/org/finos/vuu/core/module/simul/SimulationModule.scala (91%) rename {vuu => example/order}/src/main/scala/org/finos/vuu/core/module/simul/provider/ChildOrdersProvider.scala (100%) rename {vuu => example/order}/src/main/scala/org/finos/vuu/core/module/simul/provider/OrdersSimulProvider.scala (100%) rename {vuu => example/order}/src/main/scala/org/finos/vuu/core/module/simul/provider/ParentChildOrdersModel.scala (100%) rename {vuu => example/order}/src/main/scala/org/finos/vuu/core/module/simul/provider/ParentOrdersProvider.scala (100%) rename {vuu => example/order}/src/main/scala/org/finos/vuu/core/module/simul/provider/PermissionedOrdersProvider.scala (100%) rename {vuu => example/order}/src/main/scala/org/finos/vuu/core/module/simul/service/ParentOrdersService.scala (95%) rename {vuu => example/order}/src/main/scala/org/finos/vuu/provider/simulation/SimulatedBigInstrumentsProvider.scala (100%) rename {vuu => example/order}/src/main/scala/org/finos/vuu/provider/simulation/SimulatedInstrumentProvider.scala (100%) rename {vuu => example/order}/src/main/scala/org/finos/vuu/provider/simulation/SimulatedPricesProvider.scala (100%) create mode 100644 example/permission/pom.xml create mode 100644 example/permission/src/main/java/Dummy4JavaDoc.java rename {vuu => example/permission}/src/main/scala/org/finos/vuu/core/module/authn/AuthNModule.scala (100%) rename {vuu => example/permission}/src/main/scala/org/finos/vuu/core/module/authn/AuthNRestService.scala (100%) rename {vuu => example/permission}/src/main/scala/org/finos/vuu/core/module/authn/VuuAuthHandler.scala (92%) rename {vuu => example/permission}/src/main/scala/org/finos/vuu/core/module/auths/OrderPermissionChecker.scala (90%) rename {vuu => example/permission}/src/main/scala/org/finos/vuu/core/module/auths/PermissionModule.scala (100%) rename {vuu => example/permission}/src/main/scala/org/finos/vuu/core/module/auths/PermissionSet.scala (99%) rename {vuu => example/permission}/src/main/scala/org/finos/vuu/core/module/auths/provider/PermissionsProvider.scala (100%) rename {vuu => example/permission}/src/main/scala/org/finos/vuu/core/module/auths/service/PermissionsRpcService.scala (93%) rename {vuu => example/permission}/src/test/scala/org/finos/vuu/core/module/authn/AuthNServerTest.scala (98%) create mode 100644 example/permission/src/test/scala/org/finos/vuu/core/module/auths/PermissionFilteredViewport.scala rename {vuu => example/permission}/src/test/scala/org/finos/vuu/core/module/auths/PermissionsTest.scala (99%) rename {vuu/src/test/scala/org/finos/vuu/viewport => example/permission/src/test/scala/org/finos/vuu/core/module}/auths/TestFriendlyPermissionChecker.scala (91%) create mode 100644 example/pom.xml create mode 100644 example/price/pom.xml create mode 100644 example/price/src/main/java/Dummy4JavaDoc.java rename {vuu => example/price}/src/main/scala/org/finos/vuu/core/module/price/PriceModule.scala (50%) create mode 100644 example/price/src/main/scala/org/finos/vuu/provider/simulation/SimulatedPricesProvider.scala rename {vuu => example/price}/src/test/scala/org/finos/vuu/provider/simulation/SimulatedPricesProviderTest.scala (95%) create mode 100644 example/price/src/test/scala/org/finos/vuu/provider/simulation/TestFriendlyJoinTableProvider.scala create mode 100644 vuu-ui/packages/vuu-data/src/array-data-source/array-data-utils.ts create mode 100644 vuu-ui/sample-apps/feature-basket-trading/src/basket-table-live/basketConstituentLiveColumns.ts rename vuu-ui/sample-apps/feature-basket-trading/src/{useBasketTabMenu.ts => useBasketContextMenus.ts} (97%) delete mode 100644 vuu/src/main/resources/application.conf delete mode 100644 vuu/src/main/resources/issue/size.noset.vuu.log delete mode 100644 vuu/src/main/resources/issue/size.set.vuu.log create mode 100644 vuu/src/main/scala/org/finos/vuu/core/AbstractVuuServer.scala delete mode 100644 vuu/src/test/scala/org/finos/vuu/core/module/core/CoreModuleTest.scala delete mode 100644 vuu/src/test/scala/org/finos/vuu/provider/BasketConstituentProviderTest.scala delete mode 100644 vuu/src/test/scala/org/finos/vuu/provider/BasketProviderTest.scala rename vuu/src/test/scala/org/finos/vuu/{provider => test}/TestFriendlyJoinTableProvider.scala (90%) create mode 100644 vuu/src/test/scala/org/finos/vuu/test/TestVuuServer.scala create mode 100644 vuu/src/test/scala/org/finos/vuu/test/VuuServerTestCase.scala create mode 100644 vuu/src/test/scala/org/finos/vuu/test/impl/TestChannel.scala create mode 100644 vuu/src/test/scala/org/finos/vuu/test/impl/TestVuuServerImpl.scala create mode 100644 vuu/src/test/scala/org/finos/vuu/test/rpc/RpcDynamicProxy.scala delete mode 100644 vuu/src/test/scala/org/finos/vuu/viewport/CreateViewPortScenarioTest.scala delete mode 100644 vuu/src/test/scala/org/finos/vuu/viewport/auths/PermissionFilteredViewport.scala diff --git a/.github/workflows/legal-report.yml b/.github/workflows/legal-report.yml index 0bf4b5861..dfc94eb06 100644 --- a/.github/workflows/legal-report.yml +++ b/.github/workflows/legal-report.yml @@ -17,7 +17,7 @@ jobs: java-version: 1.16 cache: maven - name: Build with Maven - run: mvn clean install -Dmaven.test.skip=true + run: mvn clean install - name: License report run: mvn org.apache.maven.plugins:maven-site-plugin:3.12.1:site org.apache.maven.plugins:maven-project-info-reports-plugin:3.4.1:licenses -P legal-report @@ -37,7 +37,7 @@ jobs: - name: Install XQ run: pip install xq - name: Build with Maven - run: mvn clean install -Dmaven.test.skip=true + run: mvn clean install - name: License XML report run: mvn org.codehaus.mojo:license-maven-plugin:2.0.0:download-licenses - name: Validate XML report diff --git a/.semgrepignore b/.semgrepignore index 5b374e053..ded413c74 100644 --- a/.semgrepignore +++ b/.semgrepignore @@ -1,6 +1,9 @@ .github/workflows/release-mvn-central.yml vuu/src/main/resources/certs/key.pem +example/main/src/main/resources/certs/key.pem +example/main/src/main/resources/certs/cert.pem vuu/src/main/resources/www/ws-example.html +example/order/src/main/scala/org/finos/vuu/provider/simulation/SimulatedBigInstrumentsProvider.scala vuu/src/main/scala/org/finos/vuu/provider/simulation/SimulatedBigInstrumentsProvider.scala vuu-ui/packages/vuu-data/src/array-data-source/group-utils.ts vuu-ui/packages/vuu-datagrid-extras/src/column-expression-input/column-language-parser/walkExpressionTree.ts diff --git a/benchmark/pom.xml b/benchmark/pom.xml index 733c759d6..4bf6b0be9 100644 --- a/benchmark/pom.xml +++ b/benchmark/pom.xml @@ -4,7 +4,7 @@ org.finos.vuu vuu-parent - 0.5.09-SNAPSHOT + 0.9.36-SNAPSHOT @@ -22,7 +22,7 @@ org.finos.vuu vuu - 0.5.09-SNAPSHOT + 0.9.36-SNAPSHOT diff --git a/docs/getting_started/developing.md b/docs/getting_started/developing.md index b1e1e6d28..8189bb1b0 100644 --- a/docs/getting_started/developing.md +++ b/docs/getting_started/developing.md @@ -43,7 +43,7 @@ cd vuu #run the maven compile step mvn compile #cd into vuu, child in repo -cd vuu +cd example/main #The server should now be started on your machine with Simulation module mvn exec:exec ``` diff --git a/example/basket/pom.xml b/example/basket/pom.xml new file mode 100644 index 000000000..5da3ef8bd --- /dev/null +++ b/example/basket/pom.xml @@ -0,0 +1,271 @@ + + + 4.0.0 + + + org.finos.vuu + example + 0.9.36-SNAPSHOT + + + basket + + + + org.finos.vuu + vuu + 0.9.36-SNAPSHOT + + + + org.finos.vuu + vuu + 0.9.36-SNAPSHOT + tests + test-jar + test + + + + org.finos.vuu + price + 0.9.36-SNAPSHOT + + + + org.finos.vuu + order + 0.9.36-SNAPSHOT + + + + org.scala-lang + scala-library + ${scala.version} + + + + org.scala-lang + scala-reflect + ${scala.version} + + + + junit + junit + 4.13.2 + test + + + + org.scalatest + scalatest_2.13 + ${scalatest.version} + test + + + org.scala-lang + scala-library + + + org.scala-lang + scala-reflect + + + + + + + + + + + sign-it + + + sign + true + + + + + + org.apache.maven.plugins + maven-gpg-plugin + 3.0.1 + + + sign-artifacts + verify + + sign + + + + --pinentry-mode + loopback + + + + + + + + + + + legal-report + + + + org.scala-tools + maven-scala-plugin + ${maven.scala.plugin} + + + **/*.scala + + + + + + + + + + src/main/java + src/test/java + + + + + org.apache.maven.plugins + maven-source-plugin + + + + compile + + jar + + + + + + + org.apache.maven.plugins + maven-release-plugin + + + + + org.apache.maven.plugins + maven-javadoc-plugin + + + attach-javadocs + + jar + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.0 + + ${maven.compiler.source} + ${maven.compiler.target} + + + + org.ow2.asm + asm + 6.2 + + + + + + + org.scala-tools + maven-scala-plugin + ${maven.scala.plugin} + + + + compile + testCompile + + + + + src/main/scala + src/test/scala + + -Xms64m + -Xmx1024m + + + + + + org.apache.maven.plugins + maven-jar-plugin + 3.1.2 + + + + test-jar + + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.7 + + + + + + + org.scalatest + scalatest-maven-plugin + 2.0.2 + + ${project.build.directory}/surefire-reports + . + test-reports.txt + + + + test + + test + + + + + + + + + + + org.scala-tools + maven-scala-plugin + ${maven.scala.plugin} + + ${scala.version} + + + + + + \ No newline at end of file diff --git a/example/basket/src/main/java/Dummy4JavaDoc.java b/example/basket/src/main/java/Dummy4JavaDoc.java new file mode 100644 index 000000000..00b8d1897 --- /dev/null +++ b/example/basket/src/main/java/Dummy4JavaDoc.java @@ -0,0 +1,2 @@ +public class Dummy4JavaDoc { +} diff --git a/example/basket/src/main/resources/static/ftse100.csv b/example/basket/src/main/resources/static/ftse100.csv new file mode 100644 index 000000000..aa0315f95 --- /dev/null +++ b/example/basket/src/main/resources/static/ftse100.csv @@ -0,0 +1,100 @@ +Symbol,Name,Last Trade,Change,Volume, Weighting +AAL.L,Anglo American PLC,436.35�13:13,�5.35�(1.24%),5799089,0.0278736825813547 +ABF.L,Associated British Foods PLC,"3,435.60�13:12",�7.40�(0.21%),86808,0.000417248060431947 +ADM.L,Admiral Group PLC,"1,627.00�13:13",,86808,0.000417248060431947 +ADN.L,Aberdeen Asset Management PLC,334.00�13:13,�2.50�(0.75%),806880,0.00387831899135251 +AHT.L,Ashtead Group PLC,"1,027.00�13:13",�6.00�(0.59%),331255,0.00159219779580666 +ANTO.L,Antofagasta PLC,484.10�13:13,�11.70�(2.48%),1753976,0.00843059492263598 +ARM.L,ARM Holdings PLC,"1,058.00�13:13",�3.00�(0.28%),475927,0.00228757277736148 +AV.L,Aviva PLC,493.97�13:13,�2.23�(0.45%),2226835,0.0107034211668507 +AZN.L,AstraZeneca PLC,"4,399.50�13:13",�2.50�(0.06%),815133,0.00391798755004232 +BA.L,BAE Systems PLC,478.10�13:13,�4.30�(0.91%),2039934,0.00980506986578636 +BAB.L,Babcock International Group PLC,988.00�13:13,�9.50�(0.97%),209614,0.00100752275066102 +BARC.L,Barclays PLC,226.30�13:13,�1.15�(0.51%),6575664,0.0316063387021032 +BATS.L,British American Tobacco PLC,"3,803.50�13:13",�8.50�(0.22%),465110,0.0022355801929258 +BDEV.L,Barratt Developments PLC,576.00�13:13,�0.50�(0.09%),1044365,0.00501980543997108 +BG.L,BG Group PLC,"1,013.50�13:13",�5.50�(0.55%),1507332,0.00724508516988073 +BKG.L,Berkeley Group Holdings (The) PLC,"3,126.00�13:13",�15.00�(0.48%),95071,0.000456964684744788 +BLND.L,British Land Co PLC,828.06�13:12,�10.44�(1.25%),1802548,0.00866405926683583 +BLT.L,BHP Billiton PLC,881.40�13:13,�4.30�(0.49%),4947287,0.0237794431982097 +BNZL.L,Bunzl PLC,"1,875.40�13:05",�4.60�(0.24%),104541,0.000502482829757812 +BP.L,BP PLC,381.50�13:13,�2.95�(0.78%),10493561,0.0504379547308349 +BRBY.L,Burberry Group PLC,"1,269.00�13:13",�7.00�(0.55%),295647,0.00142104572530785 +BT-A.L,BT Group PLC,489.20�13:13,�3.70�(0.75%),3914982,0.0188176048996174 +CCL.L,Carnival PLC,"3,426.00�13:12",�22.00�(0.64%),86257,0.000414599644602783 +CNA.L,Centrica PLC,212.80�13:13,�0.60�(0.28%),2144540,0.0103078651220939 +CPG.L,Compass Group PLC,"1,054.00�13:08",�5.00�(0.48%),1001167,0.00481217156158961 +CPI.L,Capita PLC,"1,235.00�13:11",�1.00�(0.08%),244591,0.0011756418803464 +CRH.L,CRH PLC,"1,783.20�13:12",�17.80�(0.99%),897325,0.00431304851888186 +DC.L,DIXONS CARPHONE,462.10�13:11,,756906,0.00363811584680332 +DGE.L,Diageo PLC,"1,881.50�13:13",�6.50�(0.34%),756906,0.00363811584680332 +DLG.L,Direct Line Insurance Group PLC,403.80�13:13,�0.40�(0.10%),1095340,0.00526481995338596 +EXPN.L,Experian PLC,"1,191.00�13:12",�2.00�(0.17%),467283,0.00224602485281105 +EZJ.L,easyJet PLC,"1,682.00�13:12",�28.00�(1.64%),1191230,0.00572572121265722 +FRES.L,Fresnillo PLC,678.50�13:12,�6.50�(0.97%),381871,0.00183548675335462 +GFS.L,G4S PLC,232.30�13:03,�2.00�(0.85%),1096551,0.00527064070033535 +GKN.L,GKN PLC,294.80�13:12,�2.50�(0.86%),792247,0.00380798456516713 +GLEN.L,Glencore PLC,90.48�13:13,�1.65�(1.86%),41631528,0.200104533116974 +GSK.L,GlaxoSmithKline PLC,"1,345.00�13:13",�0.50�(0.04%),1767356,0.00849490672625522 +HIK.L,Hikma Pharmaceuticals PLC,"2,010.00�13:04",�57.00�(2.92%),261511,0.00125696891451962 +HL.L,Hargreaves Lansdown PLC,"1,488.03�13:12",�9.97�(0.67%),372261,0.00178929568961912 +HMSO.L,Hammerson PLC,597.50�13:11,�3.50�(0.58%),478301,0.0022989835562697 +HSBA.L,HSBC Holdings PLC,519.70�13:13,�0.50�(0.10%),7415629,0.0356436828072631 +IAG.L,International Consolidated Airlines Group SA,575.40�13:12,�16.10�(2.72%),4311514,0.0207235606629018 +IHG.L,InterContinental Hotels Group PLC,"2,481.00�13:12",�19.00�(0.76%),219918,0.00105704956863507 +III.L,3i Group PLC,487.30�13:11,�4.50�(0.92%),189987,0.000913184352332553 +IMT.L,Imperial Tobacco Group PLC,"3,571.00�13:13",�29.00�(0.81%),926816,0.00445479884777089 +INTU.L,intu properties plc,319.90�13:09,�4.60�(1.42%),514821,0.0024745192115892 +ISAT.L,Inmarsat PLC,"1,054.44�13:13",�3.44�(0.33%),988089,0.00474931133978598 +ITRK.L,Intertek Group PLC,"2,643.00�13:14",�3.00�(0.11%),45868,0.000220467399731505 +ITV.L,ITV PLC,267.30�13:14,�2.60�(0.96%),3453208,0.0165980593985356 +JMAT.L,Johnson Matthey PLC,"2,445.00�13:14",�29.00�(1.20%),276397,0.00132851940096775 +KGF.L,Kingfisher PLC,346.20�13:14,�4.30�(1.23%),1021408,0.00490946118917235 +LAND.L,Land Securities Group PLC,"1,239.00�13:13",�7.00�(0.56%),384973,0.00185039670961971 +LGEN.L,Legal & General Group PLC,266.00�13:14,�1.60�(0.60%),1998399,0.00960542930051541 +LLOY.L,Lloyds Banking Group PLC,73.86�13:14,�0.02�(0.03%),18907878,0.0908818936317375 +LSE.L,London Stock Exchange Group PLC,"2,544.00�13:11",�6.00�(0.24%),129657,0.000623204448569543 +MGGT.L,Meggitt PLC,386.00�13:15,�3.20�(0.84%),611044,0.00293702105610748 +MKS.L,Marks & Spencer Group PLC,514.75�13:12,�3.25�(0.63%),920128,0.00442265255908587 +MNDI.L,Mondi PLC,"1,463.00�13:14",�7.00�(0.48%),383546,0.00184353774521278 +MRW.L,Morrison (Wm) Supermarkets PLC,155.20�13:14,,920128,0.00442265255908587 +NG.L,National Grid PLC,926.40�13:14,�1.10�(0.12%),1659592,0.00797693234619361 +NXT.L,Next PLC,"7,765.00�13:11",�95.00�(1.21%),114062,0.000548246109448308 +OML.L,Old Mutual PLC,198.50�13:14,�0.40�(0.20%),2040849,0.00980946787029396 +PRU.L,Prudential PLC,"1,499.50�13:15",�14.00�(0.93%),580870,0.00279198784516525 +PSON.L,Pearson PLC,794.00�13:09,�5.00�(0.63%),1177953,0.00566190448495522 +RB.L,Reckitt Benckiser Group PLC,"6,293.00�13:14",�34.00�(0.54%),281172,0.0013514707359664 +RBS.L,Royal Bank of Scotland Group PLC,313.40�13:14,�2.40�(0.77%),2100058,0.0100940596177149 +RDSA.L,Royal Dutch Shell PLC,"1,636.00�13:14",�18.00�(1.11%),2467461,0.0118600050276642 +RDSB.L,Royal Dutch Shell PLC,"1,652.00�13:15",�14.50�(0.89%),1457434,0.0070052473240666 +REL.L,Reed Elsevier PLC,"1,170.00�13:14",0.00�(0.00%),908802,0.00436821343443777 +RIO.L,Rio Tinto PLC,"2,235.00�13:15",�21.00�(0.95%),2190722,0.0105298417823887 +RMG.L,Royal Mail PLC,453.50�13:14,�1.20�(0.26%),995316,0.00478404836555252 +RR.L,Rolls-Royce Group PLC,546.63�13:14,�8.38�(1.51%),2792915,0.0134243199555489 +RRS.L,Randgold Resources Ltd,"3,929.00�13:14",0.00�(0.00%),135524,0.000651404549603483 +RSA.L,RSA Insurance Group PLC,437.10�13:14,�0.10�(0.02%),395477,0.00190088484005443 +SAB.L,SABMiller PLC,"4,011.00�13:15",�1.00�(0.02%),892451,0.00428962133421518 +SBRY.L,Sainsbury (J) PLC,255.80�13:14,�7.40�(2.98%),2395670,0.0115149371133421 +SDR.L,Schroders PLC,"2,930.00�13:09",�12.00�(0.41%),44674,0.000214728364341268 +SGE.L,Sage Group (The) PLC,545.50�13:13,�0.50�(0.09%),539717,0.00259418338669419 +SHP.L,Shire PLC,"4,685.00�13:14",�22.00�(0.47%),221318,0.0010637787558598 +SKY.L,SKY,"1,095.00�13:12",�4.00�(0.37%),925016,0.0044461470356248 +SL.L,Standard Life PLC,399.90�13:14,�3.20�(0.79%),861636,0.00414150711683647 +SMIN.L,Smiths Group PLC,992.50�13:14,�27.50�(2.70%),640309,0.00307768510191594 +SN.L,Smith & Nephew PLC,"1,110.00�13:14",�9.00�(0.82%),480018,0.00230723642374461 +SPD.L,Sports Direct International PLC,694.50�13:11,�1.50�(0.22%),157981,0.000759345519250522 +SSE.L,SSE PLC,"1,463.00�13:13",�2.00�(0.14%),562454,0.00270347019378617 +STAN.L,Standard Chartered PLC,583.00�13:14,�0.60�(0.10%),2018697,0.00970299290214945 +STJ.L,St James's Place PLC,964.00�13:14,�11.00�(1.13%),418480,0.00201145019271912 +SVT.L,Severn Trent PLC,"2,199.00�13:12",�1.00�(0.05%),95342,0.000458267263129005 +TPK.L,Travis Perkins PLC,"1,945.00�13:13",�4.00�(0.21%),92916,0.000446606542981001 +TSCO.L,Tesco PLC,171.54�13:14,�2.54�(1.50%),9831136,0.0472539676970174 +TUI.L,TUI AG,"1,115.00�13:10",�5.00�(0.45%),458970,0.00220606790038304 +TW.L,Taylor Wimpey PLC,183.90�13:15,�1.10�(0.59%),3180729,0.0152883721086725 +ULVR.L,Unilever PLC,"2,791.00�13:14",�29.00�(1.03%),824827,0.0039645823650113 +UU.L,United Utilities Group PLC,959.00�13:10,�2.50�(0.26%),436911,0.00210003994253274 +VOD.L,Vodafone Group PLC,224.25�13:15,�1.30�(0.58%),17572036,0.0844610858312637 +WOS.L,Wolseley PLC,"3,657.00�13:14",�4.00�(0.11%),179536,0.000862950969699912 +WPP.L,WPP PLC,"1,502.00�13:15",�12.00�(0.79%),857887,0.0041234873147611 +WTB.L,Whitbread PLC,"4,484.00�13:16",�60.00�(1.32%),141036,0.000677898321019722 +,,,,208048900, diff --git a/example/basket/src/main/resources/static/hsi.csv b/example/basket/src/main/resources/static/hsi.csv new file mode 100644 index 000000000..fcd24d46c --- /dev/null +++ b/example/basket/src/main/resources/static/hsi.csv @@ -0,0 +1,81 @@ +Name,Symbol,Last,Change,Change %,Volume,Turn.,P/E,P/B,Yield,Market Cap,Weighting +CKH HOLDINGS,00001.HK,41.9,1.15,+2.822%,5.15M,215.13M,4.38,0.31,6.98%,160.48B,0.0278736825813547 +CLP HOLDINGS,00002.HK,57.95,-0.1,-0.172%,3.32M,193.19M,156.62,1.39,5.35%,146.41B,0.000417248060431947 +HK & CHINA GAS,00003.HK,5.46,0.13,+2.439%,16.16M,88.00M,19.43,1.66,6.41%,101.88B,0.000417248060431947 +HSBC HOLDINGS,00005.HK,61.7,1.1,+1.815%,22.19M,1.37B,10.54,0.86,4.05%,1,0.00387831899135251 +POWER ASSETS,00006.HK,37.9,-0.25,-0.655%,4.23M,160.75M,14.3,0.93,7.44%,80.77B,0.00159219779580666 +HANG SENG BANK,00011.HK,97.45,2.95,+3.122%,2.54M,247.44M,19.69,1.01,4.21%,186.31B,0.00843059492263598 +HENDERSON LAND,00012.HK,20.65,0.85,+4.293%,5.07M,103.70M,10.81,0.31,8.72%,99.97B,0.00228757277736148 +SHK PPT,00016.HK,83.8,3.25,+4.035%,8.25M,685.41M,10.16,0.4,5.91%,242.83B,0.0107034211668507 +NEW WORLD DEV,00017.HK,15.24,0.8,+5.540%,12.95M,196.19M,30.48,0.18,13.52%,38.35B,0.00391798755004232 +GALAXY ENT,00027.HK,47.15,1.9,+4.199%,11.97M,560.21M,No Profit,3.22,0.00%,206.21B,0.00980506986578636 +MTR CORPORATION,00066.HK,31,0.8,+2.649%,4.68M,144.86M,19.5,1.07,4.23%,192.64B,0.00100752275066102 +HANG LUNG PPT,00101.HK,10.72,0.56,+5.512%,7.68M,81.99M,12.61,0.36,7.28%,48.23B,0.0316063387021032 +GEELY AUTO,00175.HK,9.24,0.17,+1.874%,18.77M,173.30M,16.06,1.15,2.27%,92.99B,0.0022355801929258 +ALI HEALTH,00241.HK,4.88,0.47,+10.658%,53.62M,257.82M,108.09,3.81,0.00%,66.04B,0.00501980543997108 +CITIC,00267.HK,7.2,0.2,+2.857%,11.54M,82.96M,2.78,0.28,9.04%,209.45B,0.00724508516988073 +WH GROUP,00288.HK,4.11,0.08,+1.985%,18.94M,77.65M,4.93,0.7,7.30%,52.73B,0.000456964684744788 +CHINA RES BEER,00291.HK,42.95,1.2,+2.874%,4.83M,207.98M,28.41,4.57,1.41%,139.34B,0.00866405926683583 +OOIL,00316.HK,104.5,-0.4,-0.381%,296.54K,30.98M,0.89,0.66,78.90%,69.01B,0.0237794431982097 +TINGYI,00322.HK,10.94,0.18,+1.673%,2.91M,31.81M,20.75,4.09,9.39%,61.64B,0.000502482829757812 +SINOPEC CORP,00386.HK,4.28,-0.01,-0.233%,92.43M,396.61M,6.94,0.58,9.36%,105.92B,0.0504379547308349 +HKEX,00388.HK,292.6,9,+3.173%,4.61M,1.34B,36.76,7.46,2.44%,370.97B,0.00142104572530785 +TECHTRONIC IND,00669.HK,76,1.35,+1.808%,5.47M,414.78M,16.54,3.43,2.43%,139.45B,0.0188176048996174 +CHINA OVERSEAS,00688.HK,16.24,0.52,+3.308%,13.15M,212.60M,6.76,0.44,4.93%,177.74B,0.000414599644602783 +TENCENT,00700.HK,306.2,8.8,+2.959%,11.25M,3.43B,13.74,3.6,0.78%,2,0.0103078651220939 +CHINA UNICOM,00762.HK,5.68,-0.05,-0.873%,9.23M,52.77M,9.16,0.45,5.44%,173.80B,0.00481217156158961 +LINK REIT,00823.HK,38.4,1.45,+3.924%,12.04M,460.96M,5.42,0.52,7.03%,98.38B,0.0011756418803464 +CHINA RES POWER,00836.HK,14.94,0.32,+2.189%,9.91M,147.81M,10.23,0.87,3.92%,71.87B,0.00431304851888186 +PETROCHINA,00857.HK,5.9,0,0.000%,64.23M,380.44M,6.38,0.7,8.08%,124.48B,0.00363811584680332 +XINYI GLASS,00868.HK,10.14,0.17,+1.705%,3.75M,38.02M,8.01,1.3,6.11%,42.22B,0.00363811584680332 +ZHONGSHENG HLDG,00881.HK,22.05,1.45,+7.039%,6.76M,147.71M,7.08,1.07,4.94%,52.72B,0.00526481995338596 +CNOOC,00883.HK,13.78,-0.02,-0.145%,26.37M,365.08M,4.03,0.97,19.09%,655.47B,0.00224602485281105 +CCB,00939.HK,4.42,0.06,+1.376%,233.61M,1.03B,3.06,0.35,9.93%,1,0.00572572121265722 +CHINA MOBILE,00941.HK,65.7,0.25,+0.382%,7.82M,516.10M,9.91,0.96,6.71%,1,0.00183548675335462 +LONGFOR GROUP,00960.HK,14.08,0.9,+6.829%,10.88M,150.68M,3.06,0.55,9.05%,92.81B,0.00527064070033535 +XINYI SOLAR,00968.HK,5.86,0.28,+5.018%,15.99M,92.88M,13.64,1.75,3.41%,52.17B,0.00380798456516713 +SMIC,00981.HK,20.05,0.25,+1.263%,13.10M,264.32M,11.17,1.06,0.00%,159.31B,0.200104533116974 +LENOVO GROUP,00992.HK,8.07,0.25,+3.197%,33.60M,270.50M,7.61,2.23,4.71%,97.87B,0.00849490672625522 +CKI HOLDINGS,01038.HK,37.05,-0.2,-0.537%,1.44M,53.73M,12.03,0.78,6.83%,93.35B,0.00125696891451962 +HENGAN INT'L,01044.HK,24.95,0.2,+0.808%,2.62M,64.97M,13.35,1.32,6.33%,28.99B,0.00178929568961912 +CHINA SHENHUA,01088.HK,25.4,0.35,+1.397%,7.98M,203.11M,6.14,1.13,11.33%,85.79B,0.0022989835562697 +CSPC PHARMA,01093.HK,5.74,0.05,+0.879%,29.29M,167.41M,9.96,2.01,3.66%,68.32B,0.0356436828072631 +SINOPHARM,01099.HK,22.7,0.2,+0.889%,2.07M,46.80M,7.37,0.92,4.08%,30.46B,0.0207235606629018 +CHINA RES LAND,01109.HK,31.2,1,+3.311%,9.88M,305.88M,7.02,0.81,5.07%,222.49B,0.00105704956863507 +CK ASSET,01113.HK,41.25,1.25,+3.125%,8.57M,352.44M,6.9,0.39,5.53%,146.47B,0.000913184352332553 +SINO BIOPHARM,01177.HK,2.83,0.02,+0.712%,26.30M,74.09M,18.37,1.59,4.24%,53.21B,0.00445479884777089 +CHINA RES MIXC,01209.HK,31.6,1.6,+5.333%,3.07M,96.42M,28.97,4.48,2.87%,72.13B,0.0024745192115892 +BYD COMPANY,01211.HK,242,7,+2.979%,3.90M,938.50M,37.57,5.63,0.53%,265.72B,0.00474931133978598 +AIA,01299.HK,63.85,0.95,+1.510%,38.75M,2.48B,408.88,2.53,2.41%,735.40B,0.000220467399731505 +CHINAHONGQIAO,01378.HK,7.67,0.28,+3.789%,13.05M,99.58M,7.27,0.76,6.65%,72.68B,0.0165980593985356 +ICBC,01398.HK,3.77,0.07,+1.892%,233.48M,881.67M,3.45,0.36,9.08%,327.21B,0.00132851940096775 +XIAOMI-W,01810.HK,12.34,0.62,+5.290%,78.53M,960.98M,109.39,1.9,0.00%,308.83B,0.00490946118917235 +BUD APAC,01876.HK,15.46,0.16,+1.046%,16.17M,250.45M,28.65,2.44,1.91%,204.74B,0.00185039670961971 +SANDS CHINA LTD,01928.HK,24,0.95,+4.121%,19.98M,475.93M,No Profit,N/A,0.00%,194.24B,0.00960542930051541 +CHOW TAI FOOK,01929.HK,11.8,0.28,+2.431%,4.88M,57.68M,21.93,3.64,10.34%,118.00B,0.0908818936317375 +WHARF REIC,01997.HK,30.25,1.4,+4.853%,4.23M,127.31M,No Profit,0.48,4.33%,91.85B,0.000623204448569543 +ANTA SPORTS,02020.HK,88.15,4.4,+5.254%,4.82M,422.51M,27.71,6.16,1.52%,249.70B,0.00293702105610748 +WUXI BIO,02269.HK,45.65,1.55,+3.515%,17.91M,811.49M,38.18,4.88,0.00%,194.01B,0.00442265255908587 +SHENZHOU INTL,02313.HK,75,4.6,+6.534%,5.52M,410.68M,21.87,3.25,2.55%,112.74B,0.00184353774521278 +PING AN,02318.HK,44.85,0.85,+1.932%,23.05M,1.03B,8.28,0.85,6.09%,334.02B,0.00442265255908587 +MENGNIU DAIRY,02319.HK,26.25,1.5,+6.061%,8.58M,223.15M,17.34,2.3,1.73%,103.42B,0.00797693234619361 +LI NING,02331.HK,32.95,1.5,+4.769%,22.54M,738.37M,18.8,3.16,1.58%,86.86B,0.000548246109448308 +SUNNY OPTICAL,02382.HK,54.7,1.05,+1.957%,5.62M,308.60M,22.01,2.44,0.91%,60.00B,0.00980946787029396 +BOC HONG KONG,02388.HK,21.45,0.3,+1.418%,6.53M,140.32M,8.38,0.75,6.33%,226.79B,0.00279198784516525 +CHINA LIFE,02628.HK,12.2,0.24,+2.007%,13.53M,165.07M,9.49,0.7,4.53%,90.78B,0.00566190448495522 +ENN ENERGY,02688.HK,65,1.15,+1.801%,3.06M,198.69M,11.08,1.67,4.48%,73.53B,0.0013514707359664 +ZIJIN MINING,02899.HK,11.98,0.16,+1.354%,16.20M,194.50M,13.97,3.14,1.88%,68.73B,0.0100940596177149 +MEITUAN-W,03690.HK,114.6,3.8,+3.430%,19.17M,2.19B,No Profit,4.89,0.00%,715.43B,0.0118600050276642 +HANSOH PHARMA,03692.HK,10.66,0.16,+1.524%,17.56M,187.72M,21.48,2.47,0.94%,63.25B,0.0070052473240666 +CM BANK,03968.HK,32.7,0.1,+0.307%,11.13M,363.99M,5.51,0.86,6.00%,150.12B,0.00436821343443777 +BANK OF CHINA,03988.HK,2.74,0.05,+1.859%,275.47M,754.54M,3.33,0.33,9.55%,229.13B,0.0105298417823887 +CG SERVICES,06098.HK,8.08,0.25,+3.193%,16.08M,128.87M,12.42,0.65,5.20%,27.01B,0.00478404836555252 +JD HEALTH,06618.HK,40.6,2.95,+7.835%,7.75M,312.36M,299.91,2.56,0.00%,129.12B,0.0134243199555489 +HAIER SMARTHOME,06690.HK,24.65,1.15,+4.894%,7.24M,178.37M,13.83,2.21,2.59%,70.46B,0.000651404549603483 +HAIDILAO,06862.HK,21,0.6,+2.941%,6.86M,143.79M,74.46,13.94,0.55%,117.05B,0.00190088484005443 +JD-SW,09618.HK,115.1,4,+3.600%,7.43M,852.28M,30.73,1.5,6.38%,360.24B,0.00428962133421518 +NONGFU SPRING,09633.HK,45,1.5,+3.448%,3.69M,165.62M,52.49,18.63,1.71%,226.56B,0.0115149371133421 +BIDU-SW,09888.HK,133.4,4.6,+3.571%,5.82M,772.73M,47.3,1.5,0.00%,377.37B,0.000214728364341268 +TRIP.COM-S,09961.HK,279.2,7,+2.572%,1.25M,349.59M,114.05,1.4,0.00%,176.65B,0.00259418338669419 +BABA-SW,09988.HK,85.6,2.6,+3.133%,34.61M,2.96B,21.65,1.62,0.00%,1,0.0010637787558598 +NTES-S,09999.HK,159.5,8.3,+5.489%,5.02M,797.10M,22.7,4.63,1.36%,546.99B,0.0044461470356248 diff --git a/example/basket/src/main/resources/static/nasdaq100.csv b/example/basket/src/main/resources/static/nasdaq100.csv new file mode 100644 index 000000000..6447cbb7a --- /dev/null +++ b/example/basket/src/main/resources/static/nasdaq100.csv @@ -0,0 +1,102 @@ +#,Name,Symbol,Weighting,Last Trade,Chg,% Chg +1,Apple Inc,AAPL,11.007,174.94,0.15,(0.09%) +2,Microsoft Corp,MSFT,9.61,316.98,-0.03,(-0.01%) +3,Amazon.com Inc,AMZN,5.401,129.31,0.19,(0.14%) +4,NVIDIA Corp,NVDA,4.101,415.74,-0.36,(-0.09%) +5,Meta Platforms Inc,META,3.729,299.42,0.34,(0.11%) +6,Tesla Inc,TSLA,3.285,244.13,-0.75,(-0.31%) +7,Alphabet Inc,GOOGL,3.133,130.49,0.24,(0.18%) +8,Alphabet Inc,GOOG,3.085,131.49,0.24,(0.18%) +9,Broadcom Inc,AVGO,2.896,833.04,3.96,(0.48%) +10,Costco Wholesale Corp,COST,2.137,557.85,-0.74,(-0.13%) +11,PepsiCo Inc,PEP,2.096,174.84,-0.43,(-0.25%) +12,Adobe Inc,ADBE,2.033,511.42,-1.48,(-0.29%) +13,Cisco Systems Inc,CSCO,1.887,53.68,0.11,(0.20%) +14,Comcast Corp,CMCSA,1.633,45.30,-0.01,(-0.01%) +15,Netflix Inc,NFLX,1.478,379.89,0.08,(0.02%) +16,T-Mobile US Inc,TMUS,1.43,140.18,0.83,(0.60%) +17,Advanced Micro Devices Inc,AMD,1.348,96.09,-0.11,(-0.12%) +18,Texas Instruments Inc,TXN,1.264,161.00,0.69,(0.43%) +19,Intel Corp,INTC,1.26,34.19,0.01,(0.01%) +20,Amgen Inc,AMGN,1.251,271.18,3.48,(1.30%) +21,Intuit Inc,INTU,1.226,509.00,0.43,(0.08%) +22,Honeywell International Inc,HON,1.103,188.67,-1.12,(-0.59%) +23,QUALCOMM Inc,QCOM,1.046,107.53,-0.16,(-0.14%) +24,Applied Materials Inc,AMAT,0.982,136.32,0.15,(0.11%) +25,Booking Holdings Inc,BKNG,0.941,3,019.20,-43.30,(-1.42%) +26,Starbucks Corp,SBUX,0.926,93.80,0.12,(0.12%) +27,Intuitive Surgical Inc,ISRG,0.867,288.50,0.30,(0.10%) +28,Automatic Data Processing Inc,ADP,0.854,239.45,0.10,(0.04%) +29,Mondelez International Inc,MDLZ,0.835,71.25,0.82,(1.16%) +30,Gilead Sciences Inc,GILD,0.814,75.47,0.46,(0.61%) +31,Vertex Pharmaceuticals Inc,VRTX,0.794,353.67,4.14,(1.18%) +32,Regeneron Pharmaceuticals Inc,REGN,0.763,828.09,3.25,(0.39%) +33,Analog Devices Inc,ADI,0.752,176.82,1.34,(0.76%) +34,Lam Research Corp,LRCX,0.702,620.00,0.89,(0.14%) +35,Micron Technology Inc,MU,0.646,68.90,0.02,(0.03%) +36,Palo Alto Networks Inc,PANW,0.604,228.70,0.19,(0.08%) +37,Synopsys Inc,SNPS,0.587,447.12,0.27,(0.06%) +38,Charter Communications Inc,CHTR,0.581,441.88,-3.33,(-0.75%) +39,MercadoLibre Inc,MELI,0.562,1,275.50,-1.47,(-0.11%) +40,PayPal Holdings Inc,PYPL,0.559,57.90,0.02,(0.03%) +41,CSX Corp,CSX,0.54,31.23,0.03,(0.09%) +42,Cadence Design Systems Inc,CDNS,0.539,230.83,0.17,(0.07%) +43,KLA Corp,KLAC,0.53,456.11,4.29,(0.95%) +44,PDD Holdings Inc ADR,PDD,0.521,95.93,-0.01,(-0.01%) +45,Marriott International Inc/MD,MAR,0.505,193.90,-0.46,(-0.23%) +46,Monster Beverage Corp,MNST,0.498,54.48,-0.04,(-0.08%) +47,Airbnb Inc,ABNB,0.491,132.09,-0.11,(-0.08%) +48,O'Reilly Automotive Inc,ORLY,0.485,936.67,0.65,(0.07%) +49,Cintas Corp,CTAS,0.446,505.27,0.52,(0.10%) +50,ASML Holding NV,ASML,0.438,585.00,-2.10,(-0.36%) +51,NXP Semiconductors NV,NXPI,0.434,196.76,-0.04,(-0.02%) +52,Workday Inc,WDAY,0.414,235.55,4.73,(2.05%) +53,Lululemon Athletica Inc,LULU,0.405,386.36,-1.69,(-0.44%) +54,Keurig Dr Pepper Inc,KDP,0.404,33.25,0.13,(0.39%) +55,Fortinet Inc,FTNT,0.401,58.29,0.05,(0.09%) +56,Marvell Technology Inc,MRVL,0.388,52.38,0.08,(0.14%) +57,PACCAR Inc,PCAR,0.38,84.97,0.04,(0.04%) +58,Old Dominion Freight Line Inc,ODFL,0.38,401.01,0.35,(0.09%) +59,Autodesk Inc,ADSK,0.379,204.07,0.03,(0.01%) +60,Kraft Heinz Co/The,KHC,0.368,34.27,0.11,(0.31%) +61,Microchip Technology Inc,MCHP,0.36,77.00,-0.08,(-0.10%) +62,Copart Inc,CPRT,0.358,43.26,0.10,(0.22%) +63,American Electric Power Co Inc,AEP,0.357,79.23,0.06,(0.08%) +64,Paychex Inc,PAYX,0.355,113.01,0.06,(0.06%) +65,Exelon Corp,EXC,0.35,40.28,0.07,(0.16%) +66,ON Semiconductor Corp,ON,0.341,93.87,0.06,(0.06%) +67,AstraZeneca PLC ADR,AZN,0.339,67.35,-0.49,(-0.72%) +68,Seagen Inc,SGEN,0.336,212.18,-1.52,(-0.71%) +69,Ross Stores Inc,ROST,0.335,111.71,0.05,(0.04%) +70,Moderna Inc,MRNA,0.331,100.32,0.33,(0.33%) +71,Biogen Inc,BIIB,0.326,257.93,0.25,(0.10%) +72,Crowdstrike Holdings Inc,CRWD,0.319,162.85,0.28,(0.17%) +73,IDEXX Laboratories Inc,IDXX,0.316,439.41,3.72,(0.85%) +74,Baker Hughes Co,BKR,0.307,35.44,0.04,(0.10%) +75,Constellation Energy Corp,CEG,0.307,110.41,0.05,(0.04%) +76,Cognizant Technology Solutions Corp,CTSH,0.303,70.19,0.58,(0.83%) +77,Verisk Analytics Inc,VRSK,0.303,242.05,0.10,(0.04%) +78,Dexcom Inc,DXCM,0.3,88.30,0.80,(0.92%) +79,Trade Desk Inc/The,TTD,0.293,76.38,0.03,(0.03%) +80,Xcel Energy Inc,XEL,0.284,59.76,0.03,(0.04%) +81,Electronic Arts Inc,EA,0.279,118.38,-0.63,(-0.53%) +82,CoStar Group Inc,CSGP,0.277,78.18,0.12,(0.15%) +83,GLOBALFOUNDRIES Inc,GFS,0.273,57.21,0.38,(0.67%) +84,Fastenal Co,FAST,0.268,54.32,0.11,(0.20%) +85,Atlassian Corp,TEAM,0.253,196.01,0.55,(0.28%) +86,GE HealthCare Technologies Inc,GEHC,0.252,63.78,-0.56,(-0.86%) +87,Warner Bros Discovery Inc,WBD,0.244,11.09,-0.02,(-0.14%) +88,Diamondback Energy Inc,FANG,0.235,150.70,0.13,(0.09%) +89,Datadog Inc,DDOG,0.23,88.81,0.05,(0.06%) +90,ANSYS Inc,ANSS,0.227,300.60,-2.31,(-0.76%) +91,eBay Inc,EBAY,0.203,43.22,0.09,(0.20%) +92,Dollar Tree Inc,DLTR,0.201,104.77,0.27,(0.25%) +93,Align Technology Inc,ALGN,0.2,297.25,-1.31,(-0.44%) +94,Zscaler Inc,ZS,0.188,151.80,0.09,(0.06%) +95,Illumina Inc,ILMN,0.183,132.31,-0.13,(-0.10%) +96,Walgreens Boots Alliance Inc,WBA,0.161,21.18,0.06,(0.28%) +97,Zoom Video Communications Inc,ZM,0.151,68.57,-0.29,(-0.41%) +98,Enphase Energy Inc,ENPH,0.148,120.41,0.49,(0.41%) +99,Sirius XM Holdings Inc,SIRI,0.137,4.05,0.02,(0.50%) +100,JD.com Inc ADR,JD,0.117,30.43,0.02,(0.05%) +101,Lucid Group Inc,LCID,0.102,5.14,0.03,(0.49%) \ No newline at end of file diff --git a/example/basket/src/main/resources/static/sp500.csv b/example/basket/src/main/resources/static/sp500.csv new file mode 100644 index 000000000..19701b2cc --- /dev/null +++ b/example/basket/src/main/resources/static/sp500.csv @@ -0,0 +1,504 @@ +#,Name,Symbol,Weighting,Price,Change,Change %, +1,Apple Inc,AAPL,6.992488,171.9,1.47,(0.86%), +2,Microsoft Corp,MSFT,6.487978,314.55,1.76,(0.56%), +3,Amazon.com Inc,AMZN,3.193379,126.25,0.27,(0.22%), +4,Nvidia Corp,NVDA,2.928461,433.11,8.43,(1.99%), +5,Alphabet Inc Cl A,GOOGL,2.162218,132.93,2.39,(1.83%), +6,Tesla Inc,TSLA,1.854311,246.56,6.06,(2.52%), +7,Alphabet Inc Cl C,GOOG,1.85251,133.81,2.35,(1.78%), +8,Meta Platforms Inc Class A,META,1.847731,305.93,8.19,(2.75%), +9,Berkshire Hathaway Inc Cl B,BRK.B,1.82184,358.67,0.89,(0.25%), +10,Exxon Mobil Corp,XOM,1.343563,118.97,-1.23,(-1.03%), +11,Unitedhealth Group Inc,UNH,1.302884,510.04,6.31,(1.25%), +12,Eli Lilly & Co,LLY,1.224046,546.65,-3.11,(-0.57%), +13,Jpmorgan Chase & Co,JPM,1.182918,148.23,2.45,(1.68%), +14,Johnson & Johnson W/d,JNJ,1.056344,156.83,-0.28,(-0.18%), +15,Visa Inc Class a Shares,V,1.029636,231.97,2.47,(1.08%), +16,Procter & Gamble Co,PG,0.969793,145.75,-1.59,(-1.08%), +17,Broadcom Inc,AVGO,0.941177,835.33,18.52,(2.27%), +18,Mastercard Inc A,MA,0.918779,400.65,5.17,(1.31%), +19,Chevron Corp,CVX,0.847353,170.55,-0.49,(-0.28%), +20,Home Depot Inc,HD,0.847289,304.35,2.53,(0.84%), +22,Abbvie Inc,ABBV,0.754672,152.14,-0.99,(-0.65%), +23,Merck & Co. Inc.,MRK,0.736434,104.2,0.26,(0.25%), +24,Costco Wholesale Corp,COST,0.697258,569.05,5.52,(0.98%), +25,Pepsico Inc,PEP,0.651768,168.92,-0.65,(-0.38%), +26,Walmart Inc,WMT,0.644449,161.87,0.15,(0.09%), +27,Adobe Inc,ADBE,0.639652,507.17,4.57,(0.91%), +28,Coca Cola Co,KO,0.60801,55.82,-0.13,(-0.23%), +29,Cisco Systems Inc,CSCO,0.605326,53.97,0.77,(1.44%), +30,Accenture Plc Cl A,ACN,0.55372,298.5,-15.9,(-5.05%), +31,Salesforce Inc,CRM,0.551342,204.46,1.73,(0.85%), +32,Thermo Fisher Scientific Inc,TMO,0.536951,503.47,5.18,(1.04%), +33,Mcdonald S Corp,MCD,0.536457,265.83,2.19,(0.83%), +34,Bank of America Corp,BAC,0.526405,27.51,0.24,(0.86%), +35,Comcast Corp Class A,CMCSA,0.512537,45.17,0.57,(1.27%), +36,Linde Plc,LIN,0.506835,375.48,3.47,(0.93%), +37,Pfizer Inc,PFE,0.506043,32.09,-0.02,(-0.05%), +38,Netflix Inc,NFLX,0.467192,377.77,0.18,(0.05%), +39,Abbott Laboratories,ABT,0.462893,97.52,1.99,(2.08%), +40,Oracle Corp,ORCL,0.459877,106.29,1.67,(1.60%), +41,Danaher Corp,DHR,0.454026,248.24,0.8,(0.32%), +42,Advanced Micro Devices,AMD,0.442473,103.74,5.67,(5.78%), +43,Wells Fargo & Co,WFC,0.417428,41.04,0.18,(0.43%), +44,Conocophillips,COP,0.411569,123.32,0.23,(0.18%), +45,Walt Disney Co,DIS,0.408438,80.35,0.45,(0.56%), +46,Intel Corp,INTC,0.404462,35.5,0.89,(2.56%), +47,Amgen Inc,AMGN,0.401904,270.91,1.93,(0.72%), +48,Texas Instruments Inc,TXN,0.400931,160.98,2.84,(1.80%), +49,Intuit Inc,INTU,0.397406,515.11,6.87,(1.35%), +50,Philip Morris International,PM,0.39143,92.66,2.34,(2.59%), +51,Caterpillar Inc,CAT,0.388444,276.34,3.63,(1.33%), +52,Verizon Communications Inc,VZ,0.380327,32.56,0.16,(0.48%), +53,Intl Business Machines Corp,IBM,0.364246,140.89,-2.28,(-1.59%), +54,Honeywell International Inc,HON,0.348317,188.68,0.8,(0.43%), +55,Union Pacific Corp,UNP,0.344419,203.88,1.48,(0.73%), +56,Qualcomm Inc,QCOM,0.340195,111.55,2.36,(2.16%), +57,Nextera Energy Inc,NEE,0.338809,57.64,-2.32,(-3.88%), +58,Lowe S Cos Inc,LOW,0.338613,209.52,2.56,(1.24%), +59,Bristol Myers Squibb Co,BMY,0.337683,58.3,0.41,(0.70%), +60,General Electric Co,GE,0.336989,112.43,1.54,(1.39%), +61,S&p Global Inc,SPGI,0.32985,369.21,6.15,(1.69%), +62,Applied Materials Inc,AMAT,0.316678,139.15,4.09,(3.03%), +63,Servicenow Inc,NOW,0.3112,552.84,6.46,(1.18%), +64,Boeing Co,BA,0.309673,193.12,-2.34,(-1.20%), +65,United Parcel Service Cl B,UPS,0.307795,154.29,1.88,(1.23%), +66,Booking Holdings Inc,BKNG,0.307126,3,86.26,3.6,(0.12%) +67,Nike Inc Cl B,NKE,0.305871,89.63,0.21,(0.24%), +68,At&t Inc,T,0.296603,14.94,0.07,(0.44%), +69,Goldman Sachs Group Inc,GS,0.296356,325.72,3.77,(1.17%), +70,Rtx Corp,RTX,0.296189,72.54,-0.34,(-0.46%), +71,Elevance Health Inc,ELV,0.292632,448.99,4.23,(0.95%), +72,Deere & Co,DE,0.291602,388.36,4,(1.04%), +73,Starbucks Corp,SBUX,0.291579,91.21,0.04,(0.04%), +74,Morgan Stanley,MS,0.29087,82.34,0.69,(0.84%), +75,Medtronic Plc,MDT,0.290688,78.77,0.55,(0.71%), +76,Prologis Inc,PLD,0.286912,112.3,1.05,(0.94%), +77,Intuitive Surgical Inc,ISRG,0.285764,296.31,4.88,(1.67%), +78,Tjx Companies Inc,TJX,0.282733,89.27,1.16,(1.32%), +79,Automatic Data Processing,ADP,0.279113,243.79,1.16,(0.48%), +80,Marsh & Mclennan Cos,MMC,0.266169,193.53,0.55,(0.29%), +81,Mondelez International Inc A,MDLZ,0.26425,69.44,-0.56,(-0.79%), +82,Gilead Sciences Inc,GILD,0.26285,75.96,0.41,(0.54%), +83,Lockheed Martin Corp,LMT,0.255775,410.4,1.68,(0.41%), +84,Blackrock Inc,BLK,0.252096,645.37,1.98,(0.31%), +85,Vertex Pharmaceuticals Inc,VRTX,0.251521,353.91,4.26,(1.22%), +86,Stryker Corp,SYK,0.250789,273.07,6.53,(2.45%), +87,Cvs Health Corp,CVS,0.250255,70.11,0.33,(0.47%), +88,Regeneron Pharmaceuticals,REGN,0.2481,835.67,3.11,(0.37%), +89,American Express Co,AXP,0.243515,150.42,0.52,(0.34%), +90,Chubb Ltd,CB,0.242706,212.92,1.29,(0.61%), +91,Analog Devices Inc,ADI,0.241943,177.01,4.2,(2.43%), +92,Schlumberger Ltd,SLB,0.241232,61.02,0.22,(0.36%), +93,Eaton Corp Plc,ETN,0.238556,216.42,2.06,(0.96%), +94,The Cigna Group,CI,0.238517,291.43,2.82,(0.98%), +95,Progressive Corp,PGR,0.229854,140.76,0.14,(0.10%), +96,Lam Research Corp,LRCX,0.228483,627.46,13.54,(2.20%), +97,Schwab (Charles) Corp,SCHW,0.225784,54.57,0.19,(0.35%), +98,Zoetis Inc,ZTS,0.224522,174.68,0,(-0.00%), +99,Citigroup Inc,C,0.217552,41.24,0.78,(1.92%), +100,Boston Scientific Corp,BSX,0.213003,53.3,1.2,(2.31%), +101,Blackstone Inc,BX,0.211158,108.88,2.33,(2.19%), +102,Eog Resources Inc,EOG,0.21104,130.56,0.75,(0.57%), +103,Becton Dickinson and Co,BDX,0.209627,262.6,3.8,(1.47%), +104,Micron Technology Inc,MU,0.208276,66.25,-1.96,(-2.87%), +105,American Tower Corp,AMT,0.207727,160.73,1.04,(0.65%), +106,Altria Group Inc,MO,0.207666,42.11,0.2,(0.47%), +107,T Mobile Us Inc,TMUS,0.20192,140.3,0.6,(0.43%), +108,Cme Group Inc,CME,0.201368,200.22,-0.14,(-0.07%), +109,Southern Co,SO,0.20116,65.04,-1.1,(-1.67%), +110,Palo Alto Networks Inc,PANW,0.198047,236.42,4.52,(1.95%), +111,Duke Energy Corp,DUK,0.193827,88.87,-1.23,(-1.36%), +112,Fiserv Inc,FI,0.192662,113.67,0.48,(0.42%), +113,Synopsys Inc,SNPS,0.189768,458.88,12.17,(2.72%), +114,Activision Blizzard Inc,ATVI,0.18717,93.71,-0.22,(-0.23%), +115,Aon Plc Class A,AON,0.186896,330.04,0.12,(0.04%), +116,Equinix Inc,EQIX,0.184757,715.84,8.74,(1.24%), +117,Illinois Tool Works,ITW,0.177501,233.17,0.77,(0.33%), +118,Air Products & Chemicals Inc,APD,0.17678,289.15,3.89,(1.36%), +119,Paypal Holdings Inc,PYPL,0.175802,58.3,0.96,(1.67%), +120,Cadence Design Sys Inc,CDNS,0.175052,235.09,4.44,(1.93%), +121,Northrop Grumman Corp,NOC,0.173654,441.3,4.06,(0.93%), +122,Intercontinental Exchange In,ICE,0.172998,109.93,1.66,(1.53%), +123,Humana Inc,HUM,0.170476,495.73,2.16,(0.44%), +124,Marathon Petroleum Corp,MPC,0.170186,155.28,2.85,(1.87%), +125,Kla Corp,KLAC,0.170079,459.61,14.05,(3.15%), +126,Fedex Corp,FDX,0.169747,266.99,4.28,(1.63%), +127,Csx Corp,CSX,0.169632,30.62,0.34,(1.14%), +128,Mckesson Corp,MCK,0.167376,445.58,1.2,(0.27%), +129,Sherwin Williams Co,SHW,0.165389,254.95,4.33,(1.73%), +130,Colgate Palmolive Co,CL,0.164,71.11,0.06,(0.08%), +131,Airbnb Inc Class A,ABNB,0.159553,137.66,3.63,(2.70%), +132,Waste Management Inc,WM,0.15893,154.17,-0.25,(-0.16%), +133,Emerson Electric Co,EMR,0.154857,97.31,0.45,(0.47%), +134,O Reilly Automotive Inc,ORLY,0.154194,918.15,3.98,(0.44%), +135,Pioneer Natural Resources Co,PXD,0.1524,234.43,0.34,(0.14%), +136,Phillips 66,PSX,0.150197,122.81,2.01,(1.66%), +137,Freeport Mcmoran Inc,FCX,0.146185,37.34,0.79,(2.17%), +138,3m Co W/d,MMM,0.144312,93.48,0.02,(0.02%), +139,Roper Technologies Inc,ROP,0.144165,486.61,-0.02,(-0.00%), +140,Valero Energy Corp,VLO,0.141937,147.59,3.64,(2.53%), +141,Nxp Semiconductors Nv,NXPI,0.141583,202.19,5.49,(2.79%), +142,Target Corp,TGT,0.141106,109.31,-0.44,(-0.40%), +143,Parker Hannifin Corp,PH,0.140358,396.29,5.18,(1.32%), +144,Us Bancorp,USB,0.139291,32.59,0.07,(0.20%), +145,General Dynamics Corp,GD,0.139193,223.44,2.44,(1.10%), +146,Chipotle Mexican Grill Inc,CMG,0.139055,1,828.59,22.51,(1.25%) +147,Hca Healthcare Inc,HCA,0.138966,251.59,4.33,(1.75%), +148,Arthur J Gallagher & Co,AJG,0.138231,231.77,1.44,(0.62%), +149,Moody S Corp,MCO,0.138162,319.07,4.56,(1.45%), +150,Amphenol Corp Cl A,APH,0.136941,84.4,2.04,(2.47%), +151,Ford Motor Co,F,0.1362,12.58,0.19,(1.49%), +152,Marriott International Cl A,MAR,0.135619,199.53,5.65,(2.92%), +153,Pnc Financial Services Group,PNC,0.135457,123.09,1.28,(1.05%), +154,Transdigm Group Inc,TDG,0.131273,860.46,8.64,(1.01%), +155,Carrier Global Corp,CARR,0.129065,56.83,1.75,(3.17%), +156,Autozone Inc,AZO,0.128857,2,556.17,15.27,(0.60%) +157,Trane Technologies Plc,TT,0.12759,207.07,7.01,(3.50%), +158,Motorola Solutions Inc,MSI,0.127284,275.18,2.2,(0.81%), +159,Arista Networks Inc,ANET,0.12715,184.23,2.63,(1.45%), +160,Norfolk Southern Corp,NSC,0.124378,197.3,1.08,(0.55%), +161,General Motors Co,GM,0.124282,33.25,0.9,(2.77%), +162,Paccar Inc,PCAR,0.123613,86.12,1.31,(1.54%), +163,Charter Communications Inc A,CHTR,0.123199,442.28,8.86,(2.04%), +164,Hess Corp,HES,0.121942,157.3,-0.74,(-0.47%), +165,Sempra,SRE,0.121909,68.15,-1.26,(-1.81%), +166,Occidental Petroleum Corp,OXY,0.121531,66.03,0.43,(0.66%), +167,American International Group,AIG,0.121272,61.73,0.72,(1.18%), +168,Autodesk Inc,ADSK,0.120711,208.03,5.75,(2.84%), +169,Edwards Lifesciences Corp,EW,0.119074,69.68,-0.43,(-0.62%), +170,Ecolab Inc,ECL,0.118911,169.5,1.63,(0.97%), +171,Public Storage,PSA,0.117206,266.58,1.6,(0.60%), +172,Microchip Technology Inc,MCHP,0.116275,78.91,2.41,(3.15%), +173,Aflac Inc,AFL,0.11627,77.65,0.62,(0.81%), +174,Cintas Corp,CTAS,0.116227,486.83,5.75,(1.19%), +175,Welltower Inc,WELL,0.116157,81.07,0.87,(1.08%), +176,Williams Cos Inc,WMB,0.115685,34.65,0.55,(1.61%), +177,Kimberly Clark Corp,KMB,0.114902,121.11,-0.55,(-0.45%), +178,Archer Daniels Midland Co,ADM,0.114307,76.74,0.38,(0.50%), +179,Msci Inc,MSCI,0.113047,518.97,7.03,(1.37%), +180,Constellation Brands Inc A,STZ,0.112869,251.62,1.03,(0.41%), +181,On Semiconductor,ON,0.111009,95.12,3.07,(3.33%), +182,Metlife Inc,MET,0.110772,63.06,0.26,(0.41%), +183,Monster Beverage Corp,MNST,0.110311,53.31,0.19,(0.35%), +184,Hilton Worldwide Holdings In,HLT,0.109054,153.24,3.88,(2.60%), +185,American Electric Power,AEP,0.108899,74.71,-1.15,(-1.51%), +186,Crown Castle Inc,CCI,0.108512,91.35,1.65,(1.83%), +187,Exelon Corp,EXC,0.107894,38.11,-0.69,(-1.78%), +188,Nucor Corp,NUE,0.107787,158.31,2.6,(1.67%), +189,Travelers Cos Inc,TRV,0.107342,167.42,-0.51,(-0.30%), +190,Dominion Energy Inc,D,0.106001,44.61,-0.86,(-1.88%), +191,Te Connectivity Ltd,TEL,0.105581,123.84,3.4,(2.82%), +192,Halliburton Co,HAL,0.105449,42.18,0.15,(0.37%), +193,Centene Corp,CNC,0.105443,69.87,0.13,(0.18%), +194,Fortinet Inc,FTNT,0.105315,59.07,0.93,(1.59%), +195,Oneok Inc,OKE,0.104854,64.86,0.35,(0.53%), +196,General Mills Inc,GIS,0.104655,63.79,-0.26,(-0.40%), +197,Copart Inc,CPRT,0.104453,43.66,0.61,(1.41%), +198,Paychex Inc,PAYX,0.104412,117.4,0.89,(0.76%), +199,Biogen Inc,BIIB,0.103916,258.95,1.43,(0.55%), +200,Truist Financial Corp,TFC,0.103679,28.15,0.18,(0.63%), +201,Ross Stores Inc,ROST,0.10361,111.18,2.26,(2.07%), +202,Johnson Controls Internation,JCI,0.103601,53.69,-0.85,(-1.55%), +203,Iqvia Holdings Inc,IQV,0.103397,200.11,-2.1,(-1.04%), +204,Capital One Financial Corp,COF,0.101688,96.63,1.14,(1.20%), +205,Baker Hughes Co,BKR,0.101425,36.62,0.37,(1.02%), +206,Idexx Laboratories Inc,IDXX,0.101263,439.37,2.51,(0.57%), +207,Corteva Inc,CTVA,0.100577,50.77,0.02,(0.05%), +208,Dow Inc,DOW,0.100258,50.87,-0.13,(-0.26%), +209,Old Dominion Freight Line,ODFL,0.100037,406.82,6.93,(1.73%), +210,Constellation Energy,CEG,0.099445,109.94,-0.81,(-0.73%), +211,Dexcom Inc,DXCM,0.099384,95.68,3.59,(3.90%), +212,Simon Property Group Inc,SPG,0.098977,108.45,0.26,(0.24%), +213,Digital Realty Trust Inc,DLR,0.098757,117.6,0.76,(0.65%), +214,Realty Income Corp,O,0.098278,49.83,0.17,(0.33%), +215,Kenvue Inc W/i,KVUE,0.097359,20.2,-0.02,(-0.12%), +216,Verisk Analytics Inc,VRSK,0.097203,241.97,2.34,(0.98%), +217,Cognizant Tech Solutions A,CTSH,0.096172,68.15,-0.05,(-0.07%), +218,P G & E Corp,PCG,0.095995,16.36,-0.09,(-0.52%), +219,Prudential Financial Inc,PRU,0.095804,94.93,0.41,(0.43%), +220,Ametek Inc,AME,0.09567,150.03,1.17,(0.79%), +221,Yum Brands Inc,YUM,0.095443,123.55,1.57,(1.29%), +222,Dupont De Nemours Inc,DD,0.094185,74.58,1.11,(1.51%), +223,Ameriprise Financial Inc,AMP,0.093691,332.11,5.16,(1.58%), +224,L3harris Technologies Inc,LHX,0.092512,173.16,-2.04,(-1.16%), +225,Fidelity National Info Serv,FIS,0.09207,56.06,0.52,(0.94%), +226,Sysco Corp,SYY,0.091968,65.99,0.78,(1.20%), +227,Moderna Inc,MRNA,0.091789,100.61,1.17,(1.18%), +228,Bank of New York Mellon Corp,BK,0.091699,42.76,0.59,(1.39%), +229,Agilent Technologies Inc,A,0.091382,111.91,1.41,(1.28%), +230,Otis Worldwide Corp,OTIS,0.091228,80.55,1.2,(1.51%), +231,Rockwell Automation Inc,ROK,0.091103,288.26,3.46,(1.21%), +232,Dr Horton Inc,DHI,0.090974,108.96,1.95,(1.82%), +233,Cummins Inc,CMI,0.090916,232.98,3.03,(1.32%), +234,Estee Lauder Companies Cl A,EL,0.090788,139.94,-0.1,(-0.07%), +235,Kinder Morgan Inc,KMI,0.090175,16.71,0.05,(0.27%), +236,Keurig Dr Pepper Inc,KDP,0.088358,31.51,-0.16,(-0.51%), +237,Fastenal Co,FAST,0.087952,55.72,0.66,(1.21%), +238,Xcel Energy Inc,XEL,0.087474,56.5,-0.71,(-1.25%), +239,Devon Energy Corp,DVN,0.087359,48.84,0,(0.01%), +240,Ww Grainger Inc,GWW,0.086956,704.07,3.96,(0.57%), +241,Costar Group Inc,CSGP,0.086756,77.1,0.75,(0.99%), +242,Cencora Inc,COR,0.086188,183.99,-1.17,(-0.63%), +243,United Rentals Inc,URI,0.085093,454.44,8.22,(1.84%), +244,Hershey Co,HSY,0.084755,201.01,-1.55,(-0.76%), +245,Arch Capital Group Ltd,ACGL,0.083799,81.62,0.54,(0.67%), +246,Ppg Industries Inc,PPG,0.083787,130.49,2.46,(1.92%), +247,Global Payments Inc,GPN,0.083671,116.72,1.47,(1.28%), +248,Consolidated Edison Inc,ED,0.083432,85.06,-1.57,(-1.81%), +249,Newmont Corp,NEM,0.082799,36.78,-0.5,(-1.34%), +250,Republic Services Inc,RSG,0.082765,145.01,0.28,(0.19%), +251,Allstate Corp,ALL,0.08254,112.77,-0.25,(-0.22%), +252,Electronic Arts Inc,EA,0.081213,119.76,1.79,(1.51%), +253,Vici Properties Inc,VICI,0.081127,29.28,0.4,(1.37%), +254,Kroger Co,KR,0.080998,44.96,0.48,(1.07%), +255,Public Service Enterprise Gp,PEG,0.080723,56.88,-1.02,(-1.75%), +256,Lennar Corp A,LEN,0.078759,113.41,1.71,(1.53%), +257,Diamondback Energy Inc,FANG,0.078498,158.01,0.78,(0.50%), +258,West Pharmaceutical Services,WST,0.077362,377.15,1.97,(0.52%), +259,Quanta Services Inc,PWR,0.077074,190.82,0.7,(0.37%), +260,Gartner Inc,IT,0.076911,347.78,-1.41,(-0.40%), +261,Aptiv Plc,APTV,0.0757,99.21,3.35,(3.50%), +262,Vulcan Materials Co,VMC,0.075604,207.6,4,(1.97%), +263,Kraft Heinz Co,KHC,0.075468,33.72,-0.31,(-0.90%), +264,Ge Healthcare Technology,GEHC,0.074734,69.81,1.53,(2.24%), +265,Cdw Corp/de,CDW,0.074375,202.53,3.84,(1.93%), +266,Fortive Corp,FTV,0.072323,74.75,1.16,(1.58%), +267,Ingersoll Rand Inc,IR,0.071683,64.52,1.25,(1.97%), +268,Ansys Inc,ANSS,0.071343,299.19,4.85,(1.65%), +269,Extra Space Storage Inc,EXR,0.071269,120.75,0.24,(0.20%), +270,Wec Energy Group Inc,WEC,0.071007,79.67,-0.91,(-1.12%), +271,Martin Marietta Materials,MLM,0.070759,418,8.05,(1.96%), +272,Edison International,EIX,0.068887,63.92,-1.38,(-2.11%), +273,American Water Works Co Inc,AWK,0.068233,123.27,-3.07,(-2.43%), +274,Warner Bros Discovery Inc,WBD,0.068207,10.89,-0.15,(-1.31%), +275,Lyondellbasell Indu Cl A,LYB,0.067294,94.86,-0.11,(-0.11%), +276,Mettler Toledo International,MTD,0.067028,1,112.26,14.48,(1.32%) +277,Avalonbay Communities Inc,AVB,0.066762,171.85,-0.6,(-0.35%), +278,Delta Air Lines Inc,DAL,0.065781,37.32,0.66,(1.79%), +279,T Rowe Price Group Inc,TROW,0.064996,104.73,1.19,(1.15%), +280,Keysight Technologies In,KEYS,0.064934,133.51,3.11,(2.38%), +281,Zimmer Biomet Holdings Inc,ZBH,0.064476,112.14,1.38,(1.24%), +282,Dollar General Corp,DG,0.064042,105.04,0.7,(0.67%), +283,Corning Inc,GLW,0.064037,30.35,0.29,(0.98%), +284,Ebay Inc,EBAY,0.063728,43.45,0.56,(1.31%), +285,Cbre Group Inc A,CBRE,0.063578,73.84,0.35,(0.48%), +286,Weyerhaeuser Co,WY,0.063312,30.4,-0.64,(-2.05%), +287,Church & Dwight Co Inc,CHD,0.062765,91.68,-0.29,(-0.31%), +288,Cardinal Health Inc,CAH,0.062583,88.18,0.14,(0.16%), +289,Hp Inc,HPQ,0.062013,25.73,0.09,(0.36%), +290,Equifax Inc,EFX,0.061821,185.4,4.68,(2.59%), +291,Tractor Supply Company,TSCO,0.061683,205.07,2.06,(1.02%), +292,Willis Towers Watson Plc,WTW,0.06168,211.96,0.35,(0.17%), +293,Hewlett Packard Enterprise,HPE,0.061499,17.7,0.63,(3.66%), +294,Fair Isaac Corp,FICO,0.061481,890.19,4.58,(0.52%), +295,Dollar Tree Inc,DLTR,0.061287,106.46,1.11,(1.05%), +296,Hartford Financial Svcs Grp,HIG,0.061236,72.24,0.53,(0.73%), +297,Resmed Inc,RMD,0.060853,149.81,1.16,(0.78%), +298,Take Two Interactive Softwre,TTWO,0.060753,139.63,1.85,(1.34%), +299,Royal Caribbean Cruises Ltd,RCL,0.060515,94.38,2.42,(2.64%), +300,Xylem Inc,XYL,0.060192,91.4,1.09,(1.20%), +301,Align Technology Inc,ALGN,0.060095,309.06,7.38,(2.45%), +302,Steris Plc,STE,0.060013,221.57,3.67,(1.69%), +303,Broadridge Financial Solutio,BR,0.059572,181.18,-0.04,(-0.02%), +304,Discover Financial Services,DFS,0.059507,86.35,1.09,(1.28%), +305,State Street Corp,STT,0.059411,67.81,1.03,(1.54%), +306,Sba Communications Corp,SBAC,0.059216,198.11,2.05,(1.05%), +307,Monolithic Power Systems Inc,MPWR,0.058699,457.69,16.51,(3.74%), +308,Illumina Inc,ILMN,0.058584,133.02,-0.28,(-0.21%), +309,Dte Energy Company,DTE,0.058057,98.82,-1.72,(-1.71%), +310,M & T Bank Corp,MTB,0.057846,126.63,2.09,(1.68%), +311,Coterra Energy Inc,CTRA,0.057589,27.48,0.34,(1.23%), +312,Eversource Energy,ES,0.057281,57.54,-1.23,(-2.09%), +313,Genuine Parts Co,GPC,0.055796,142.94,0.63,(0.45%), +314,Equity Residential,EQR,0.055712,58.67,0.23,(0.40%), +315,Entergy Corp,ETR,0.055241,92.23,-1.02,(-1.10%), +316,Dover Corp,DOV,0.055103,141.68,1.09,(0.77%), +317,Ameren Corporation,AEE,0.054981,74.6,-1.51,(-1.98%), +318,Ulta Beauty Inc,ULTA,0.054585,398.17,5.73,(1.46%), +319,Teledyne Technologies Inc,TDY,0.054228,414.36,0.92,(0.22%), +320,Nvr Inc,NVR,0.054188,6,27.42,86.42,(1.45%) +321,Targa Resources Corp,TRGP,0.05408,87.52,0.93,(1.08%), +322,Molina Healthcare Inc,MOH,0.053618,333.09,2.03,(0.61%), +323,Wabtec Corp,WAB,0.053425,108.18,1.35,(1.26%), +324,Fleetcor Technologies Inc,FLT,0.053345,260.14,1.28,(0.49%), +325,Albemarle Corp,ALB,0.053229,172.99,10.36,(6.37%), +326,Baxter International Inc,BAX,0.05272,37.54,0.21,(0.57%), +327,Raymond James Financial Inc,RJF,0.052247,101.39,1.84,(1.85%), +328,Mccormick & Co Non Vtg Shrs,MKC,0.051871,74.55,0.46,(0.63%), +329,Invitation Homes Inc,INVH,0.051153,31.73,0.03,(0.11%), +330,Firstenergy Corp,FE,0.050777,34.56,-0.69,(-1.94%), +331,Laboratory Crp of Amer Hldgs,LH,0.05072,204.23,-0.62,(-0.30%), +332,Howmet Aerospace Inc,HWM,0.050386,46.99,0.91,(1.97%), +333,Verisign Inc,VRSN,0.050215,202.93,2.46,(1.23%), +334,Ppl Corp,PPL,0.04902,23.56,-0.39,(-1.61%), +335,Iron Mountain Inc,IRM,0.047985,59.55,0.56,(0.94%), +336,Jacobs Solutions Inc,J,0.047882,136.45,0.27,(0.20%), +337,Intl Flavors & Fragrances,IFF,0.047868,67.84,0.64,(0.95%), +338,Centerpoint Energy Inc,CNP,0.047827,26.68,-0.48,(-1.75%), +339,Darden Restaurants Inc,DRI,0.047736,143.44,2.01,(1.42%), +340,Hologic Inc,HOLX,0.047358,69.99,0.75,(1.08%), +341,First Solar Inc,FSLR,0.047324,161.9,3.29,(2.07%), +342,Expeditors Intl Wash Inc,EXPD,0.046936,114.74,1.08,(0.95%), +343,Brown & Brown Inc,BRO,0.046675,71.15,0.19,(0.26%), +344,Factset Research Systems Inc,FDS,0.046601,443.66,8.47,(1.95%), +345,Fifth Third Bancorp,FITB,0.046598,25.05,0.19,(0.74%), +346,Ventas Inc,VTR,0.046351,42.18,0.77,(1.85%), +347,Marathon Oil Corp,MRO,0.046321,27.51,0.12,(0.45%), +348,Steel Dynamics Inc,STLD,0.046096,106.96,0.52,(0.48%), +349,Bunge Ltd,BG,0.046038,110.67,1.1,(1.00%), +350,Ptc Inc,PTC,0.045951,140.25,1.78,(1.28%), +351,Everest Group Ltd,EG,0.04587,381.3,-0.42,(-0.11%), +352,Cincinnati Financial Corp,CINF,0.045852,104.4,-0.3,(-0.29%), +353,Enphase Energy Inc,ENPH,0.045679,121.39,1.28,(1.07%), +354,Nasdaq Inc,NDAQ,0.04562,49.07,0.74,(1.52%), +355,Akamai Technologies Inc,AKAM,0.045578,107.75,0.79,(0.74%), +356,Cboe Global Markets Inc,CBOE,0.045525,155.28,0.51,(0.33%), +357,Cf Industries Holdings Inc,CF,0.04496,84.93,1.48,(1.78%), +358,Waters Corp,WAT,0.044936,274.46,2.12,(0.78%), +359,Pultegroup Inc,PHM,0.044848,74.85,1.65,(2.25%), +360,Tyler Technologies Inc,TYL,0.044831,387.74,2.43,(0.63%), +361,Principal Financial Group,PFG,0.044705,72.74,0.74,(1.02%), +362,Clorox Company,CLX,0.04465,128.98,-0.17,(-0.13%), +363,Southwest Airlines Co,LUV,0.044478,27.3,0.49,(1.81%), +364,Regions Financial Corp,RF,0.044397,17.16,0.22,(1.27%), +365,Garmin Ltd,GRMN,0.044336,104.65,1.42,(1.38%), +366,Atmos Energy Corp,ATO,0.044128,106.32,-0.14,(-0.13%), +367,Netapp Inc,NTAP,0.044116,76.49,1.54,(2.05%), +368,Textron Inc,TXT,0.043659,79.27,0.33,(0.41%), +369,Cooper Cos Inc,COO,0.04361,318.15,2.23,(0.71%), +370,Kellogg Co,K,0.043517,58.9,-0.22,(-0.38%), +371,Idex Corp,IEX,0.043484,210.72,3.28,(1.58%), +372,Cms Energy Corp,CMS,0.043476,52.78,-0.57,(-1.07%), +373,Skyworks Solutions Inc,SWKS,0.042974,98.55,2.25,(2.33%), +374,Alexandria Real Estate Equit,ARE,0.042466,99.48,0.59,(0.60%), +375,Hunt (Jb) Transprt Svcs Inc,JBHT,0.042319,186.54,0.95,(0.51%), +376,Las Vegas Sands Corp,LVS,0.042222,45.63,-0.53,(-1.15%), +377,Ball Corp,BALL,0.042202,48.27,0.04,(0.08%), +378,Walgreens Boots Alliance Inc,WBA,0.04215,20.97,-0.06,(-0.26%), +379,Teradyne Inc,TER,0.041494,100.04,3.56,(3.68%), +380,Mid America Apartment Comm,MAA,0.041385,128.55,0.48,(0.37%), +381,Epam Systems Inc,EPAM,0.041006,257.76,0.96,(0.37%), +382,Avery Dennison Corp,AVY,0.040961,183.42,1.39,(0.76%), +383,Omnicom Group,OMC,0.040483,74.6,1.21,(1.65%), +384,Huntington Bancshares Inc,HBAN,0.040444,10.25,0.13,(1.24%), +385,Eqt Corp,EQT,0.040251,40,0.39,(0.99%), +386,Tyson Foods Inc Cl A,TSN,0.040042,49.74,-0.37,(-0.74%), +387,Western Digital Corp,WDC,0.039814,45.5,0.94,(2.11%), +388,Northern Trust Corp,NTRS,0.039557,69.29,0.84,(1.23%), +389,Carnival Corp,CCL,0.039206,14.52,0.54,(3.88%), +390,Expedia Group Inc,EXPE,0.038585,102.75,2.5,(2.49%), +391,United Airlines Holdings Inc,UAL,0.038383,42.84,0.81,(1.94%), +392,Quest Diagnostics Inc,DGX,0.038331,123.71,0.31,(0.25%), +393,Axon Enterprise Inc,AXON,0.03828,195.69,1.04,(0.53%), +394,Packaging Corp of America,PKG,0.038236,152.79,0.9,(0.59%), +395,Revvity Inc,RVTY,0.0378,110.55,1.5,(1.38%), +396,Snap on Inc,SNA,0.037774,257.97,4,(1.58%), +397,Pool Corp,POOL,0.037475,353.56,9.86,(2.87%), +398,Essex Property Trust Inc,ESS,0.03733,210.81,0.07,(0.03%), +399,Domino S Pizza Inc,DPZ,0.037258,382.39,2.18,(0.57%), +400,Amcor Plc,AMCR,0.037101,9.09,0.06,(0.61%), +401,Best Buy Co Inc,BBY,0.037071,68.66,0.29,(0.43%), +402,Apa Corp,APA,0.03662,42.49,0.11,(0.27%), +403,Lamb Weston Holdings Inc,LW,0.036553,91.47,0.09,(0.10%), +404,Wr Berkley Corp,WRB,0.036551,65.21,0.86,(1.33%), +405,Conagra Brands Inc,CAG,0.036484,27.44,-0.1,(-0.35%), +406,Lkq Corp,LKQ,0.036449,49.51,0.72,(1.47%), +407,Jm Smucker Co,SJM,0.035767,124.48,-0.96,(-0.77%), +408,Stanley Black & Decker Inc,SWK,0.035567,83.87,0.97,(1.17%), +409,Synchrony Financial,SYF,0.035241,30.73,0.55,(1.84%), +410,Carmax Inc,KMX,0.035202,71.64,-8.05,(-10.10%), +411,Leidos Holdings Inc,LDOS,0.034943,92.2,0.21,(0.23%), +412,Seagate Technology Holdings,STX,0.034918,65.71,1.42,(2.20%), +413,Paycom Software Inc,PAYC,0.034914,259.42,2.34,(0.91%), +414,Celanese Corp,CE,0.034212,127.11,3.81,(3.09%), +415,Trimble Inc,TRMB,0.034136,52.22,3.01,(6.12%), +416,Alliant Energy Corp,LNT,0.03411,48.06,-0.49,(-1.02%), +417,Citizens Financial Group,CFG,0.033972,26.28,0.52,(2.00%), +418,International Paper Co,IP,0.033961,35.1,0.15,(0.41%), +419,Masco Corp,MAS,0.033414,54.58,1.37,(2.58%), +420,Nordson Corp,NDSN,0.033057,223.81,3.73,(1.69%), +421,Loews Corp,L,0.032942,64.16,0.36,(0.56%), +422,Evergy Inc,EVRG,0.032792,50.48,-0.58,(-1.13%), +423,Mosaic Co,MOS,0.03266,35.63,0.43,(1.22%), +424,Molson Coors Beverage Co B,TAP,0.032624,62.29,-0.12,(-0.19%), +425,Zebra Technologies Corp Cl A,ZBRA,0.03257,236.95,11.04,(4.89%), +426,Viatris Inc,VTRS,0.032115,9.8,0.21,(2.14%), +427,Live Nation Entertainment In,LYV,0.032035,83.73,2.71,(3.34%), +428,Host Hotels & Resorts Inc,HST,0.03173,16.38,0.34,(2.11%), +429,Insulet Corp,PODD,0.031493,166.19,4.49,(2.77%), +430,Match Group Inc,MTCH,0.031269,40.07,0.09,(0.23%), +431,Interpublic Group of Cos Inc,IPG,0.031184,29.12,0.39,(1.35%), +432,Hormel Foods Corp,HRL,0.030887,38.15,-0.19,(-0.48%), +433,Incyte Corp,INCY,0.03067,58.93,-0.18,(-0.30%), +434,Udr Inc,UDR,0.030252,35.67,0.28,(0.79%), +435,Jack Henry & Associates Inc,JKHY,0.030211,150.61,2.17,(1.46%), +436,Kimco Realty Corp,KIM,0.029862,17.73,0.24,(1.34%), +437,Aes Corp,AES,0.029775,15.29,-0.65,(-4.05%), +438,Bio Techne Corp,TECH,0.029742,67.67,0.1,(0.15%), +439,Pentair Plc,PNR,0.029592,65.59,0.87,(1.34%), +440,Rollins Inc,ROL,0.029276,37.64,0.2,(0.52%), +441,Mgm Resorts International,MGM,0.028601,36.76,0.27,(0.74%), +442,Ceridian Hcm Holding Inc,CDAY,0.028589,67.38,0.35,(0.52%), +443,Brown Forman Corp Class B,BF.B,0.028542,56.78,0.14,(0.25%), +444,Nisource Inc,NI,0.028365,24.84,-0.35,(-1.37%), +445,Gen Digital Inc,GEN,0.028124,17.83,-0.07,(-0.37%), +446,C.H. Robinson Worldwide Inc,CHRW,0.028048,86.31,0.02,(0.02%), +447,Camden Property Trust,CPT,0.027984,94.56,-0.32,(-0.34%), +448,Charles River Laboratories,CRL,0.027736,195.69,0.75,(0.38%), +449,Healthpeak Properties Inc,PEAK,0.027617,18.15,0.1,(0.58%), +450,Caesars Entertainment Inc,CZR,0.027217,47.52,1.54,(3.36%), +451,Regency Centers Corp,REG,0.027131,59.98,0.85,(1.43%), +452,Keycorp,KEY,0.0269,10.52,0.22,(2.09%), +453,Henry Schein Inc,HSIC,0.026715,73.88,0.62,(0.84%), +454,Globe Life Inc,GL,0.026574,110.04,0.61,(0.56%), +455,Borgwarner Inc,BWA,0.026416,40.72,0.92,(2.31%), +456,F5 Inc,FFIV,0.026087,160.33,2.74,(1.74%), +457,Qorvo Inc,QRVO,0.025849,96.39,1.83,(1.93%), +458,Teleflex Inc,TFX,0.025796,199.42,2.91,(1.48%), +459,Allegion Plc,ALLE,0.025545,104.97,1.68,(1.63%), +460,Westrock Co,WRK,0.025292,35.98,0.23,(0.64%), +461,Eastman Chemical Co,EMN,0.025003,76.99,2.35,(3.15%), +462,Wynn Resorts Ltd,WYNN,0.024938,92.21,0,(-0.00%), +463,Nrg Energy Inc,NRG,0.024681,38.55,-0.03,(-0.08%), +464,Juniper Networks Inc,JNPR,0.024655,27.92,0.42,(1.52%), +465,Pinnacle West Capital,PNW,0.02321,73.45,-0.71,(-0.95%), +466,Hasbro Inc,HAS,0.02308,65.23,0.24,(0.37%), +467,Catalent Inc,CTLT,0.023069,45.85,0.07,(0.15%), +468,American Airlines Group Inc,AAL,0.02296,13,0.39,(3.05%), +469,Fmc Corp,FMC,0.022942,66.03,0.02,(0.03%), +470,Campbell Soup Co,CPB,0.022776,41.15,-0.31,(-0.76%), +471,Smith (a.O.) Corp,AOS,0.022769,66.99,1.54,(2.35%), +472,Boston Properties Inc,BXP,0.02269,59.66,0.79,(1.34%), +473,Huntington Ingalls Industrie,HII,0.022502,204.41,1.22,(0.60%), +474,Fox Corp Class A,FOXA,0.021902,31.47,0.55,(1.76%), +475,Robert Half Inc,RHI,0.021872,73.78,0.64,(0.87%), +476,Assurant Inc,AIZ,0.021618,145.63,-0.13,(-0.09%), +477,Universal Health Services B,UHS,0.021551,127,2.8,(2.25%), +478,Etsy Inc,ETSY,0.021257,63.53,1.64,(2.65%), +479,Marketaxess Holdings Inc,MKTX,0.021132,205.89,4.11,(2.04%), +480,News Corp Class A,NWSA,0.0209,20,0.35,(1.76%), +481,Bio Rad Laboratories A,BIO,0.020548,356.1,3.63,(1.03%), +482,Bath & Body Works Inc,BBWI,0.020412,33.19,1.04,(3.23%), +483,Dentsply Sirona Inc,XRAY,0.020079,33.94,-0.17,(-0.51%), +484,Solaredge Technologies Inc,SEDG,0.020026,132.35,4.34,(3.39%), +485,Whirlpool Corp,WHR,0.019812,131.66,1.03,(0.79%), +486,Franklin Resources Inc,BEN,0.019128,24.55,0.28,(1.14%), +487,Generac Holdings Inc,GNRC,0.018958,110.73,1.84,(1.69%), +488,Norwegian Cruise Line Holdin,NCLH,0.018812,16.96,0.67,(4.08%), +489,Federal Realty Invs Trust,FRT,0.018475,91.45,1.05,(1.16%), +490,Tapestry Inc,TPR,0.01809,28.18,0.23,(0.84%), +491,Invesco Ltd,IVZ,0.017835,14.31,0.22,(1.53%), +492,Paramount Global Class B,PARA,0.017208,12.89,0.11,(0.89%), +493,Vf Corp,VFC,0.015631,16.59,-0.32,(-1.89%), +494,Comerica Inc,CMA,0.014638,41.07,1.12,(2.81%), +495,Davita Inc,DVA,0.014395,95.75,0.01,(0.01%), +496,Zions Bancorp Na,ZION,0.013918,33.96,0.79,(2.39%), +497,Ralph Lauren Corp,RL,0.013127,115.52,0.26,(0.22%), +498,Sealed Air Corp,SEE,0.012794,32.2,0.46,(1.46%), +499,Alaska Air Group Inc,ALK,0.012574,37.04,0.63,(1.73%), +500,Mohawk Industries Inc,MHK,0.011998,85.15,1.23,(1.46%), +501,Organon & Co,OGN,0.011665,16.93,0.34,(2.02%), +502,Dxc Technology Co,DXC,0.011658,20.64,0.29,(1.40%), +503,Fox Corp Class B,FOX,0.010545,29.16,0.53,(1.85%), +504,News Corp Class B,NWS,0.006575,20.75,0.36,(1.74%), diff --git a/vuu/src/main/scala/org/finos/vuu/core/module/basket/BasketConstants.scala b/example/basket/src/main/scala/org/finos/vuu/core/module/basket/BasketConstants.scala similarity index 100% rename from vuu/src/main/scala/org/finos/vuu/core/module/basket/BasketConstants.scala rename to example/basket/src/main/scala/org/finos/vuu/core/module/basket/BasketConstants.scala diff --git a/vuu/src/main/scala/org/finos/vuu/core/module/basket/BasketModule.scala b/example/basket/src/main/scala/org/finos/vuu/core/module/basket/BasketModule.scala similarity index 83% rename from vuu/src/main/scala/org/finos/vuu/core/module/basket/BasketModule.scala rename to example/basket/src/main/scala/org/finos/vuu/core/module/basket/BasketModule.scala index 20ea87f02..02065bd65 100644 --- a/vuu/src/main/scala/org/finos/vuu/core/module/basket/BasketModule.scala +++ b/example/basket/src/main/scala/org/finos/vuu/core/module/basket/BasketModule.scala @@ -2,31 +2,26 @@ package org.finos.vuu.core.module.basket import org.finos.toolbox.lifecycle.LifecycleContainer import org.finos.toolbox.time.Clock -import org.finos.vuu.api.{JoinSpec, JoinTableDef, JoinTo, LeftOuterJoin, Link, TableDef, ViewPortDef, VisualLinks} -import org.finos.vuu.core.module.basket.provider.{AlgoProvider, BasketConstituentProvider, BasketProvider, NullProvider, PriceStrategyProvider} -import org.finos.vuu.core.module.basket.service.{BasketService, BasketTradingConstituentJoinService, BasketTradingConstituentService} +import org.finos.vuu.api._ +import org.finos.vuu.core.module.basket.provider._ +import org.finos.vuu.core.module.basket.service.{BasketService, BasketTradingConstituentJoinService, BasketTradingConstituentService, BasketTradingService} import org.finos.vuu.core.module.price.PriceModule -import org.finos.vuu.core.module.simul.SimulationModule import org.finos.vuu.core.module.{DefaultModule, ModuleFactory, TableDefContainer, ViewServerModule} import org.finos.vuu.core.table.Columns object BasketModule extends DefaultModule { - private final val NAME = "BASKET" + final val NAME = "BASKET" final val BasketTable = "basket" final val BasketTradingTable = "basketTrading" final val BasketConstituentTable = "basketConstituent" - final val BasketTradingConstituent = "basketTradingConstituent" + final val BasketTradingConstituentTable = "basketTradingConstituent" final val BasketTradingConstituentJoin = "basketTradingConstituentJoin" def apply()(implicit clock: Clock, lifecycle: LifecycleContainer, tableDefContainer: TableDefContainer): ViewServerModule = { - import org.finos.vuu.core.module.basket.BasketModule.{BasketColumnNames => B} - import org.finos.vuu.core.module.basket.BasketModule.{BasketConstituentColumnNames => BC} - import org.finos.vuu.core.module.basket.BasketModule.{BasketTradingColumnNames => BT} - import org.finos.vuu.core.module.basket.BasketModule.{BasketTradingConstituentColumnNames => BTC} - import org.finos.vuu.core.module.basket.BasketModule.{PriceStrategy => PS} + import org.finos.vuu.core.module.basket.BasketModule.{BasketColumnNames => B, BasketConstituentColumnNames => BC, BasketTradingColumnNames => BT, BasketTradingConstituentColumnNames => BTC, PriceStrategy => PS} ModuleFactory.withNamespace(NAME) .addTable( @@ -49,7 +44,7 @@ object BasketModule extends DefaultModule { name = BasketConstituentTable, keyField = BC.RicBasketId, columns = Columns.fromNames(BC.RicBasketId.string(), BC.Ric.string(), BC.BasketId.string(), BC.Weighting.double(), BC.LastTrade.string(), BC.Change.string(), - BC.Volume.string(), BC.Side.string()), // we can join to instruments and other tables to get the rest of the data..... + BC.Volume.string(), BC.Side.string(), BC.Description.string()), // we can join to instruments and other tables to get the rest of the data..... VisualLinks(), joinFields = BC.RicBasketId, BC.Ric ), @@ -59,15 +54,19 @@ object BasketModule extends DefaultModule { TableDef( name = BasketTradingTable, keyField = BT.InstanceId, - columns = Columns.fromNames(BT.InstanceId.string(), BT.BasketId.string(), BT.BasketName.string(), BT.Status.string(), BT.Units.int(), BT.FilledPct.double(), BT.FxRateToUsd.double(), BT.TotalNotional.double(), BT.TotalNotionalUsd.double()), // we can join to instruments and other tables to get the rest of the data..... + columns = Columns.fromNames(BT.InstanceId.string(), BT.BasketId.string(), BT.BasketName.string(), BT.Status.string(), BT.Units.int(), BT.FilledPct.double(), BT.FxRateToUsd.double(), BT.TotalNotional.double(), BT.TotalNotionalUsd.double(), BT.Side.string()), // we can join to instruments and other tables to get the rest of the data..... VisualLinks(), joinFields = BT.BasketId ), - (table, vs) => new NullProvider(table), + (table, vs) => new BasketTradingProvider(table, vs.tableContainer), + (table, _, _, tableContainer) => ViewPortDef( + columns = table.getTableDef.columns, + service = new BasketTradingService(table, tableContainer) + ) ) .addTable( TableDef( - name = BasketTradingConstituent, + name = BasketTradingConstituentTable, keyField = BTC.InstanceIdRic, columns = Columns.fromNames(BTC.Quantity.long(), BTC.Side.string(), BTC.InstanceIdRic.string(), BTC.InstanceId.string(), BTC.Ric.string(), @@ -116,8 +115,8 @@ object BasketModule extends DefaultModule { .addJoinTable(tableDefs => JoinTableDef( name = BasketTradingConstituentJoin, - baseTable = tableDefs.get(NAME, BasketTradingConstituent), - joinColumns = Columns.allFrom(tableDefs.get(NAME, BasketTradingConstituent)) ++ Columns.allFromExcept(tableDefs.get(PriceModule.NAME, "prices"), "ric"), + baseTable = tableDefs.get(NAME, BasketTradingConstituentTable), + joinColumns = Columns.allFrom(tableDefs.get(NAME, BasketTradingConstituentTable)) ++ Columns.allFromExcept(tableDefs.get(PriceModule.NAME, "prices"), "ric"), joins = JoinTo( table = tableDefs.get(PriceModule.NAME, "prices"), @@ -170,9 +169,9 @@ object BasketModule extends DefaultModule { final val Units = "units" final val TotalNotionalUsd = "totalNotionalUsd" final val TotalNotional = "totalNotional" - //BasketTrading Screen final val Status = "status" final val FilledPct = "filledPct" + final val Side = "side" } object BasketTradingConstituentColumnNames { @@ -183,9 +182,6 @@ object BasketModule extends DefaultModule { final val Ric = "ric" final val Description = "description" final val Quantity = "quantity" - final val Last = "last" - final val Bid = "bid" - final val Offer = "offer" final val LimitPrice = "limitPrice" final val PriceStrategyId = "priceStrategyId" final val NotionalUsd = "notionalUsd" @@ -197,4 +193,9 @@ object BasketModule extends DefaultModule { final val Weighting = "weighting" final val PriceSpread = "priceSpread" } + + object Sides{ + final val Buy = "Buy" + final val Sell = "Sell" + } } diff --git a/vuu/src/main/scala/org/finos/vuu/core/module/basket/csv/CsvStaticLoader.scala b/example/basket/src/main/scala/org/finos/vuu/core/module/basket/csv/CsvStaticLoader.scala similarity index 92% rename from vuu/src/main/scala/org/finos/vuu/core/module/basket/csv/CsvStaticLoader.scala rename to example/basket/src/main/scala/org/finos/vuu/core/module/basket/csv/CsvStaticLoader.scala index ac111cf88..13023bffa 100644 --- a/vuu/src/main/scala/org/finos/vuu/core/module/basket/csv/CsvStaticLoader.scala +++ b/example/basket/src/main/scala/org/finos/vuu/core/module/basket/csv/CsvStaticLoader.scala @@ -1,14 +1,18 @@ package org.finos.vuu.core.module.basket.csv +import com.typesafe.scalalogging.StrictLogging + import scala.io.Source -object CsvStaticLoader { +object CsvStaticLoader extends StrictLogging { def loadConstituent(basketId: String): Array[Map[String, Any]] = { + val staticDirPath = getClass.getResource("/static").getPath val dir = new java.io.File(staticDirPath) val csvFiles = dir.listFiles.filter(_.isFile) .filter(_.getName.endsWith(basketId.replace(".","").toLowerCase + ".csv")) val csvFile = csvFiles(0) + logger.info("Loading basket static:" + basketId + "(" + csvFile + ")") val bufferedSource = Source.fromFile(csvFile) val csv = for (line <- bufferedSource.getLines) yield line.split(",").map(_.trim) val array = csv.toArray @@ -19,7 +23,7 @@ object CsvStaticLoader { val nameInd = header.indexOf("Name") val lastTradeInd = header.indexOf("Last Trade") val volumeInd = header.indexOf("Volume") - val weightInd = header.indexOf("Weight") + val weightInd = header.indexOf("Weighting") val changeInd = header.indexOf("Change") val list = array.tail.map(e => { val weighting = if(getValueFromIndex(weightInd, e) == null) 0.0D else getValueFromIndex(weightInd, e).toDouble @@ -27,7 +31,7 @@ object CsvStaticLoader { "Symbol" -> getValueFromIndex(symbolInd, e), "Last Trade" -> getValueFromIndex(lastTradeInd, e), "Name" -> getValueFromIndex(nameInd, e), - "Weight" -> weighting, + "Weighting" -> weighting, "Volume" -> getValueFromIndex(volumeInd, e), "Change" -> getValueFromIndex(changeInd, e) ) diff --git a/vuu/src/main/scala/org/finos/vuu/core/module/basket/provider/AlgoProvider.scala b/example/basket/src/main/scala/org/finos/vuu/core/module/basket/provider/AlgoProvider.scala similarity index 86% rename from vuu/src/main/scala/org/finos/vuu/core/module/basket/provider/AlgoProvider.scala rename to example/basket/src/main/scala/org/finos/vuu/core/module/basket/provider/AlgoProvider.scala index 21efb1815..5ae352bc5 100644 --- a/vuu/src/main/scala/org/finos/vuu/core/module/basket/provider/AlgoProvider.scala +++ b/example/basket/src/main/scala/org/finos/vuu/core/module/basket/provider/AlgoProvider.scala @@ -10,11 +10,12 @@ class AlgoProvider(val table: DataTable)(implicit lifecycle: LifecycleContainer, lifecycle(this) private final val Algos = List( - (0, "Sniper"), - (1, "Dark Liquidity"), - (2, "VWAP"), - (3, "POV"), - (4, "Dynamic CLose"), + (-1, "None"), + (1, "Sniper"), + (2, "Dark Liquidity"), + (3, "VWAP"), + (4, "POV"), + (5, "Dynamic CLose"), ) override def doStart(): Unit = { diff --git a/vuu/src/main/scala/org/finos/vuu/core/module/basket/provider/BasketConstituentProvider.scala b/example/basket/src/main/scala/org/finos/vuu/core/module/basket/provider/BasketConstituentProvider.scala similarity index 97% rename from vuu/src/main/scala/org/finos/vuu/core/module/basket/provider/BasketConstituentProvider.scala rename to example/basket/src/main/scala/org/finos/vuu/core/module/basket/provider/BasketConstituentProvider.scala index 182cfe867..4b1ec3d06 100644 --- a/vuu/src/main/scala/org/finos/vuu/core/module/basket/provider/BasketConstituentProvider.scala +++ b/example/basket/src/main/scala/org/finos/vuu/core/module/basket/provider/BasketConstituentProvider.scala @@ -31,7 +31,7 @@ class BasketConstituentProvider(val table: DataTable)(implicit lifecycle: Lifecy val lastTrade = row("Last Trade") val change = row("Change") val volume = row("Volume") - val weighting = row("Weight") + val weighting = row("Weighting") val side = BasketConstants.Side.Buy val ricBasketId = symbol + "." + basketId table.processUpdate(ricBasketId, RowWithData(symbol, Map( diff --git a/vuu/src/main/scala/org/finos/vuu/core/module/basket/provider/BasketProvider.scala b/example/basket/src/main/scala/org/finos/vuu/core/module/basket/provider/BasketProvider.scala similarity index 100% rename from vuu/src/main/scala/org/finos/vuu/core/module/basket/provider/BasketProvider.scala rename to example/basket/src/main/scala/org/finos/vuu/core/module/basket/provider/BasketProvider.scala diff --git a/example/basket/src/main/scala/org/finos/vuu/core/module/basket/provider/BasketTradingProvider.scala b/example/basket/src/main/scala/org/finos/vuu/core/module/basket/provider/BasketTradingProvider.scala new file mode 100644 index 000000000..7e67b3b48 --- /dev/null +++ b/example/basket/src/main/scala/org/finos/vuu/core/module/basket/provider/BasketTradingProvider.scala @@ -0,0 +1,51 @@ +package org.finos.vuu.core.module.basket.provider + +import org.finos.toolbox.lifecycle.LifecycleContainer +import org.finos.toolbox.thread.LifeCycleRunner +import org.finos.toolbox.time.Clock +import org.finos.vuu.core.module.basket.BasketModule.BasketTradingColumnNames.{TotalNotional, TotalNotionalUsd} +import org.finos.vuu.core.module.basket.BasketModule.BasketTradingConstituentColumnNames.{InstanceId, Quantity} +import org.finos.vuu.core.module.basket.BasketModule.BasketTradingConstituentJoin +import org.finos.vuu.core.table.{DataTable, RowWithData, TableContainer} +import org.finos.vuu.provider.DefaultProvider + +class BasketTradingProvider(val table: DataTable, val tableContainer: TableContainer)(implicit lifecycle: LifecycleContainer, clock: Clock) extends DefaultProvider{ + private val runner = new LifeCycleRunner("BasketTradingProvider", runOnce, minCycleTime = 2_000) + + lifecycle(this).dependsOn(runner) + + def runOnce(): Unit = { + + val constituent = tableContainer.getTable(BasketTradingConstituentJoin) + + table.primaryKeys.foreach( key => { + + val sumOfNotional = constituent.primaryKeys.filter( conKey =>{ + val row = constituent.pullRow(conKey) + row.get(InstanceId).asInstanceOf[String] == key + }).map(conKey => { + + val quantity = constituent.pullRow(conKey).get(Quantity).asInstanceOf[Long] + val bid =constituent.pullRow(conKey).get("bid").asInstanceOf[Double] + val ask =constituent.pullRow(conKey).get("ask").asInstanceOf[Double] + val last =constituent.pullRow(conKey).get("last").asInstanceOf[Double] + + if(last > 0){ + quantity * last + }else if(bid > 0){ + quantity * bid + } else if (ask > 0) { + quantity * ask + }else{ + 0 + } + + } ).sum + + table.processUpdate(key, RowWithData(key, Map(InstanceId -> key, TotalNotionalUsd -> sumOfNotional.asInstanceOf[Long], TotalNotional -> sumOfNotional.asInstanceOf[Long])), clock.now()) + }) + + } + + override val lifecycleId: String = "BasketTradingProvider#" + hashCode() +} diff --git a/vuu/src/main/scala/org/finos/vuu/core/module/basket/provider/NullProvider.scala b/example/basket/src/main/scala/org/finos/vuu/core/module/basket/provider/NullProvider.scala similarity index 100% rename from vuu/src/main/scala/org/finos/vuu/core/module/basket/provider/NullProvider.scala rename to example/basket/src/main/scala/org/finos/vuu/core/module/basket/provider/NullProvider.scala diff --git a/vuu/src/main/scala/org/finos/vuu/core/module/basket/provider/PriceStrategyProvider.scala b/example/basket/src/main/scala/org/finos/vuu/core/module/basket/provider/PriceStrategyProvider.scala similarity index 95% rename from vuu/src/main/scala/org/finos/vuu/core/module/basket/provider/PriceStrategyProvider.scala rename to example/basket/src/main/scala/org/finos/vuu/core/module/basket/provider/PriceStrategyProvider.scala index 90f2ece34..0939b2f23 100644 --- a/vuu/src/main/scala/org/finos/vuu/core/module/basket/provider/PriceStrategyProvider.scala +++ b/example/basket/src/main/scala/org/finos/vuu/core/module/basket/provider/PriceStrategyProvider.scala @@ -9,7 +9,7 @@ class PriceStrategyProvider(val table: DataTable)(implicit lifecycle: LifecycleC lifecycle(this) - private final val Strategies = List( + final val Strategies = List( (0, "Peg To Near Touch"), (1, "Far Touch"), (2, "Limit"), diff --git a/vuu/src/main/scala/org/finos/vuu/core/module/basket/service/BasketService.scala b/example/basket/src/main/scala/org/finos/vuu/core/module/basket/service/BasketService.scala similarity index 66% rename from vuu/src/main/scala/org/finos/vuu/core/module/basket/service/BasketService.scala rename to example/basket/src/main/scala/org/finos/vuu/core/module/basket/service/BasketService.scala index 722ee686d..9be3540bb 100644 --- a/vuu/src/main/scala/org/finos/vuu/core/module/basket/service/BasketService.scala +++ b/example/basket/src/main/scala/org/finos/vuu/core/module/basket/service/BasketService.scala @@ -3,12 +3,12 @@ package org.finos.vuu.core.module.basket.service import com.typesafe.scalalogging.StrictLogging import org.finos.toolbox.time.Clock import org.finos.vuu.core.module.basket.BasketModule -import org.finos.vuu.core.module.basket.BasketModule.BasketConstituentTable +import org.finos.vuu.core.module.basket.BasketModule.{BasketConstituentTable, PriceStrategy, Sides} import org.finos.vuu.core.module.basket.service.BasketService.counter import org.finos.vuu.core.table.{DataTable, RowData, RowWithData, TableContainer} +import org.finos.vuu.net.rpc.{EditRpcHandler, RpcHandler} import org.finos.vuu.net.{ClientSessionId, RequestContext} -import org.finos.vuu.net.rpc.RpcHandler -import org.finos.vuu.viewport.{NoAction, SelectionViewPortMenuItem, ViewPortAction, ViewPortMenu, ViewPortSelection} +import org.finos.vuu.viewport._ import java.util.concurrent.atomic.AtomicInteger @@ -16,13 +16,15 @@ object BasketService{ val counter = new AtomicInteger(0) } -class BasketService(val table: DataTable, val tableContainer: TableContainer)(implicit clock: Clock) extends RpcHandler with StrictLogging { +trait BasketServiceIF{ + def createBasket(basketKey: String, name: String)(ctx: RequestContext): ViewPortAction +} + +class BasketService(val table: DataTable, val tableContainer: TableContainer)(implicit clock: Clock) extends RpcHandler with BasketServiceIF with StrictLogging { //private val counter = new AtomicInteger(0) - import org.finos.vuu.core.module.basket.BasketModule.{BasketTradingColumnNames => BT} - import org.finos.vuu.core.module.basket.BasketModule.{BasketConstituentColumnNames => BC} - import org.finos.vuu.core.module.basket.BasketModule.{BasketTradingConstituentColumnNames => BTC} + import org.finos.vuu.core.module.basket.BasketModule.{BasketConstituentColumnNames => BC, BasketTradingColumnNames => BT, BasketTradingConstituentColumnNames => BTC} private def getAndPadCounter(session: ClientSessionId): String = { val counterValue = counter.incrementAndGet() @@ -35,21 +37,27 @@ class BasketService(val table: DataTable, val tableContainer: TableContainer)(im keys.map( key => table.pullRow(key) ).filter(_.get(BC.BasketId).toString == key) } - private def mkTradingConstituentRow(side: String, basketKey: String, instanceKey: String, constituentKey: String, quantity: Long, basketConsRow: RowData): RowWithData = { - RowWithData(constituentKey, Map(BTC.BasketId -> basketKey, BTC.Ric -> basketConsRow.get(BC.Ric), BTC.InstanceId -> instanceKey, + private def mkTradingConstituentRow(side: String, basketKey: String, instanceKey: String, + constituentKey: String, quantity: Long, weighting: Double, basketConsRow: RowData): RowWithData = { + RowWithData(constituentKey, Map(BTC.BasketId -> basketKey, + BTC.Ric -> basketConsRow.get(BC.Ric), + BTC.InstanceId -> instanceKey, BTC.Quantity -> quantity, BTC.InstanceIdRic -> constituentKey, BTC.Description -> basketConsRow.get(BC.Description), - BTC.Side -> side + BTC.Side -> side, + BTC.Weighting -> weighting, + BTC.PriceStrategyId -> 2, + BTC.Algo -> -1, )) } private def mkTradingBasketRow(instanceKey: String, basketKey: String): RowWithData = { - RowWithData(instanceKey, Map(BT.InstanceId -> instanceKey, BT.Status -> "OFF-MARKET", BT.BasketId -> basketKey)) + RowWithData(instanceKey, Map(BT.InstanceId -> instanceKey, BT.Status -> "OFF-MARKET", BT.BasketId -> basketKey, BT.BasketName -> instanceKey, BT.Side -> Sides.Buy, BT.Units -> 1)) } def createBasketFromRpc(basketKey: String, name: String)(ctx: RequestContext): ViewPortAction = { - createBasket(basketKey, name) + createBasket(basketKey, name)(ctx) } def createBasket(selection: ViewPortSelection, session: ClientSessionId): ViewPortAction = { @@ -58,10 +66,14 @@ class BasketService(val table: DataTable, val tableContainer: TableContainer)(im val instanceKey = getAndPadCounter(session) - createBasket(basketKey, instanceKey) + createBasketInternal(basketKey, instanceKey, session) } - private def createBasket(basketKey: String, name: String): ViewPortAction = { + def createBasket(basketKey: String, name: String)(ctx: RequestContext): ViewPortAction = { + createBasketInternal(basketKey, name, ctx.session) + } + + private def createBasketInternal(basketKey: String, name: String, sessionId: ClientSessionId): ViewPortAction = { val constituents = getConstituentsForBasketKey(basketKey) @@ -72,14 +84,14 @@ class BasketService(val table: DataTable, val tableContainer: TableContainer)(im logger.error("Cannot find the Basket Trading table.") } - tableContainer.getTable(BasketModule.BasketTradingConstituent) match { + tableContainer.getTable(BasketModule.BasketTradingConstituentTable) match { case table: DataTable => constituents.foreach( rowData => { val constituentKey = name + "." + rowData.get(BTC.Ric) val weighting = rowData.get(BTC.Weighting).asInstanceOf[Double] val quantity = (weighting * 100).asInstanceOf[Long] val side = rowData.get(BTC.Side).toString - table.processUpdate(constituentKey, mkTradingConstituentRow(side, basketKey, name, constituentKey, quantity, rowData), clock.now()) + table.processUpdate(constituentKey, mkTradingConstituentRow(side, basketKey, name, constituentKey, quantity, weighting, rowData), clock.now()) }) case null => logger.error("Cannot find the Basket Trading Constituent.") @@ -91,4 +103,5 @@ class BasketService(val table: DataTable, val tableContainer: TableContainer)(im override def menuItems(): ViewPortMenu = ViewPortMenu( new SelectionViewPortMenuItem("Create New", "", (sel, sess) => this.createBasket(sel, sess), "CREATE_NEW_BASKET"), ) + } diff --git a/vuu/src/main/scala/org/finos/vuu/core/module/basket/service/BasketTradingConstituentJoinService.scala b/example/basket/src/main/scala/org/finos/vuu/core/module/basket/service/BasketTradingConstituentJoinService.scala similarity index 87% rename from vuu/src/main/scala/org/finos/vuu/core/module/basket/service/BasketTradingConstituentJoinService.scala rename to example/basket/src/main/scala/org/finos/vuu/core/module/basket/service/BasketTradingConstituentJoinService.scala index 5681d8ba7..6a6685641 100644 --- a/vuu/src/main/scala/org/finos/vuu/core/module/basket/service/BasketTradingConstituentJoinService.scala +++ b/example/basket/src/main/scala/org/finos/vuu/core/module/basket/service/BasketTradingConstituentJoinService.scala @@ -76,4 +76,17 @@ class BasketTradingConstituentJoinService(val table: DataTable, val tableContain override def onFormClose(): ViewPortFormCloseAction = ViewPortFormCloseAction("", this.onFormClose) + def setSell(selection: ViewPortSelection, session: ClientSessionId): ViewPortAction = { + ViewPortEditSuccess() + } + + def setBuy(selection: ViewPortSelection, session: ClientSessionId): ViewPortAction = { + ViewPortEditSuccess() + } + + override def menuItems(): ViewPortMenu = ViewPortMenu("Direction", + new SelectionViewPortMenuItem("Set Sell", "", this.setSell, "SET_SELECTION_SELL"), + new SelectionViewPortMenuItem("Set Buy", "", this.setBuy, "SET_SELECTION_Buy") + ) + } diff --git a/vuu/src/main/scala/org/finos/vuu/core/module/basket/service/BasketTradingConstituentService.scala b/example/basket/src/main/scala/org/finos/vuu/core/module/basket/service/BasketTradingConstituentService.scala similarity index 86% rename from vuu/src/main/scala/org/finos/vuu/core/module/basket/service/BasketTradingConstituentService.scala rename to example/basket/src/main/scala/org/finos/vuu/core/module/basket/service/BasketTradingConstituentService.scala index faa21347a..2975b4299 100644 --- a/vuu/src/main/scala/org/finos/vuu/core/module/basket/service/BasketTradingConstituentService.scala +++ b/example/basket/src/main/scala/org/finos/vuu/core/module/basket/service/BasketTradingConstituentService.scala @@ -69,4 +69,16 @@ class BasketTradingConstituentService(val table: DataTable, val tableContainer: override def onFormClose(): ViewPortFormCloseAction = ViewPortFormCloseAction("", this.onFormClose) + def setSell(selection: ViewPortSelection, session: ClientSessionId): ViewPortAction = { + ViewPortEditSuccess() + } + + def setBuy(selection: ViewPortSelection, session: ClientSessionId): ViewPortAction = { + ViewPortEditSuccess() + } + + override def menuItems(): ViewPortMenu = ViewPortMenu("Direction", + new SelectionViewPortMenuItem("Set Sell", "", this.setSell, "SET_SELECTION_SELL"), + new SelectionViewPortMenuItem("Set Buy", "", this.setBuy, "SET_SELECTION_Buy") + ) } diff --git a/example/basket/src/main/scala/org/finos/vuu/core/module/basket/service/BasketTradingService.scala b/example/basket/src/main/scala/org/finos/vuu/core/module/basket/service/BasketTradingService.scala new file mode 100644 index 000000000..5767db434 --- /dev/null +++ b/example/basket/src/main/scala/org/finos/vuu/core/module/basket/service/BasketTradingService.scala @@ -0,0 +1,63 @@ +package org.finos.vuu.core.module.basket.service + +import com.typesafe.scalalogging.StrictLogging +import org.finos.toolbox.time.Clock +import org.finos.vuu.core.module.basket.BasketModule.{BasketTradingConstituentTable, Sides} +import org.finos.vuu.core.table.{DataTable, RowWithData, TableContainer} +import org.finos.vuu.net.ClientSessionId +import org.finos.vuu.net.rpc.{EditRpcHandler, RpcHandler} +import org.finos.vuu.viewport.{ViewPort, ViewPortAddRowAction, ViewPortDeleteCellAction, ViewPortDeleteRowAction, ViewPortEditAction, ViewPortEditCellAction, ViewPortEditRowAction, ViewPortEditSuccess, ViewPortFormCloseAction, ViewPortFormSubmitAction} + +trait BasketTradingServiceIF extends EditRpcHandler{ + +} + +class BasketTradingService(val table: DataTable, val tableContainer: TableContainer)(implicit clock: Clock) extends RpcHandler with BasketTradingServiceIF with StrictLogging { + + import org.finos.vuu.core.module.basket.BasketModule.{BasketConstituentColumnNames => BC, BasketTradingColumnNames => BT, BasketTradingConstituentColumnNames => BTC} + + private def onEditCell(key: String, columnName: String, data: Any, vp: ViewPort, session: ClientSessionId): ViewPortEditAction = { + logger.info("Changing cell value for key:" + key + "(" + columnName + ":" + data + ")") + table.processUpdate(key, RowWithData(key, Map(BT.InstanceId -> key, columnName -> data)), clock.now()) + + columnName match { + case BT.Units => + val constituentTable = tableContainer.getTable(BasketTradingConstituentTable) + val constituents = constituentTable.primaryKeys.map(key => constituentTable.pullRow(key)).filter(_.get(BTC.InstanceId) == key) + constituents.foreach( row => { + val unitsAsInt = data.asInstanceOf[Int] + val weighting = row.get(BTC.Weighting) + val quantity = (weighting.asInstanceOf[Double] * unitsAsInt).toLong + constituentTable.processUpdate(row.key(), RowWithData(row.key(), Map(BTC.InstanceIdRic -> row.key(), BTC.Quantity -> quantity)), clock.now()) + }) + case BT.Side => + val constituentTable = tableContainer.getTable(BasketTradingConstituentTable) + val constituents = constituentTable.primaryKeys.map(key => constituentTable.pullRow(key)).filter(_.get(BTC.InstanceId) == key) + val side = data.asInstanceOf[String] + constituents.foreach(row => { + val newSide = row.get(BTC.Side) match { + case Sides.Buy => Sides.Sell + case _ => Sides.Buy + } + constituentTable.processUpdate(row.key(), RowWithData(row.key(), Map(BTC.InstanceIdRic -> row.key(), BTC.Side -> newSide)), clock.now()) + }) + + case _ => + } + + ViewPortEditSuccess() + } + override def deleteRowAction(): ViewPortDeleteRowAction = ??? + + override def deleteCellAction(): ViewPortDeleteCellAction = ??? + + override def addRowAction(): ViewPortAddRowAction = ??? + + override def editCellAction(): ViewPortEditCellAction = ViewPortEditCellAction("", onEditCell) + override def editRowAction(): ViewPortEditRowAction = ??? + + override def onFormSubmit(): ViewPortFormSubmitAction = ??? + + override def onFormClose(): ViewPortFormCloseAction = ??? + +} diff --git a/example/basket/src/test/scala/org/finos/vuu/core/module/basket/BasketCreateTest.scala b/example/basket/src/test/scala/org/finos/vuu/core/module/basket/BasketCreateTest.scala new file mode 100644 index 000000000..43bde891c --- /dev/null +++ b/example/basket/src/test/scala/org/finos/vuu/core/module/basket/BasketCreateTest.scala @@ -0,0 +1,75 @@ +package org.finos.vuu.core.module.basket + +import org.finos.toolbox.jmx.{MetricsProvider, MetricsProviderImpl} +import org.finos.toolbox.lifecycle.LifecycleContainer +import org.finos.toolbox.time.{Clock, TestFriendlyClock} +import org.finos.vuu.api.ViewPortDef +import org.finos.vuu.core.module.TableDefContainer +import org.finos.vuu.core.module.basket.service.{BasketServiceIF, BasketTradingServiceIF} +import org.finos.vuu.core.module.price.PriceModule +import org.finos.vuu.core.table.TableTestHelper.combineQs +import org.finos.vuu.test.VuuServerTestCase +import org.finos.vuu.util.table.TableAsserts.assertVpEq +import org.scalatest.prop.Tables.Table + +class BasketCreateTest extends VuuServerTestCase { + + Feature("Basket Service Test Case") { + + Scenario("Check the creation of the baskets and constituents") { + + implicit val clock: Clock = new TestFriendlyClock(10001L) + implicit val lifecycle: LifecycleContainer = new LifecycleContainer() + implicit val tableDefContainer: TableDefContainer = new TableDefContainer(Map()) + implicit val metricsProvider: MetricsProvider = new MetricsProviderImpl + + import BasketModule.{BasketTradingColumnNames => BT, _} + + withVuuServer(PriceModule(), BasketModule()) { + vuuServer => + + vuuServer.login("testUser", "testToken") + + vuuServer.overrideViewPortDef("prices", (table, _, _, _) => ViewPortDef(table.getTableDef.columns, null)) + + val pricesProvider = vuuServer.getProvider(PriceModule.NAME, "prices") + + pricesProvider.tick("VOD.L", Map("ric" -> "VOD.L", "phase" -> "C")) + + val viewport = vuuServer.createViewPort(PriceModule.NAME, "prices") + + vuuServer.runOnce() + + assertVpEq(combineQsForVp(viewport)) { + Table( + ("ric", "bid", "ask", "bidSize", "askSize", "last", "open", "close", "phase", "scenario"), + ("VOD.L", null, null, null, null, null, null, null, "C", null) + ) + } + + val viewportBasket = vuuServer.createViewPort(BasketModule.NAME, BasketTable) + + val basketService = vuuServer.getViewPortRpcServiceProxy[BasketServiceIF](viewportBasket) + + val action = basketService.createBasket(".FTSE", "chris-001")(vuuServer.requestContext) + + val viewportBasketTrading = vuuServer.createViewPort(BasketModule.NAME, BasketTradingTable) + + val basketTradingService = vuuServer.getViewPortRpcServiceProxy[BasketTradingServiceIF](viewportBasketTrading) + + //CJS: I don't like this forced cast, need to look at that a bit + basketTradingService.editCellAction().func("chris-001", BT.Units, 100.asInstanceOf[Object], viewportBasketTrading, vuuServer.session) + + vuuServer.runOnce() + + assertVpEq(combineQsForVp(viewportBasketTrading)) { + Table( + ("basketId", "instanceId", "basketName", "units", "status", "filledPct", "totalNotionalUsd", "totalNotional", "fxRateToUsd", "side"), + (".FTSE", "chris-001", "chris-001", 100, "OFF-MARKET", null, null, null, null, "Buy") + ) + } + } + } + } + +} diff --git a/example/basket/src/test/scala/org/finos/vuu/core/module/basket/BasketMutateOffMarketTest.scala b/example/basket/src/test/scala/org/finos/vuu/core/module/basket/BasketMutateOffMarketTest.scala new file mode 100644 index 000000000..93d8e73cc --- /dev/null +++ b/example/basket/src/test/scala/org/finos/vuu/core/module/basket/BasketMutateOffMarketTest.scala @@ -0,0 +1,143 @@ +package org.finos.vuu.core.module.basket + +import org.finos.toolbox.jmx.{MetricsProvider, MetricsProviderImpl} +import org.finos.toolbox.lifecycle.LifecycleContainer +import org.finos.toolbox.time.{Clock, TestFriendlyClock} +import org.finos.vuu.api.ViewPortDef +import org.finos.vuu.core.module.TableDefContainer +import org.finos.vuu.core.module.basket.service.{BasketServiceIF, BasketTradingServiceIF} +import org.finos.vuu.core.module.price.PriceModule +import org.finos.vuu.test.VuuServerTestCase +import org.finos.vuu.util.table.TableAsserts.assertVpEq +import org.scalatest.prop.Tables.Table + +class BasketMutateOffMarketTest extends VuuServerTestCase { + + import BasketTestCaseHelper._ + + Feature("Basket Service Test Case") { + + Scenario("Check the creation of the baskets and constituents") { + + implicit val clock: Clock = new TestFriendlyClock(10001L) + implicit val lifecycle: LifecycleContainer = new LifecycleContainer() + implicit val tableDefContainer: TableDefContainer = new TableDefContainer(Map()) + implicit val metricsProvider: MetricsProvider = new MetricsProviderImpl + + import BasketModule._ + + withVuuServer(PriceModule(), BasketModule()) { + vuuServer => + + vuuServer.login("testUser", "testToken") + + vuuServer.overrideViewPortDef("prices", (table, _, _, _) => ViewPortDef(table.getTableDef.columns, null)) + + val pricesProvider = vuuServer.getProvider(PriceModule.NAME, "prices") + val basketProvider = vuuServer.getProvider(BasketModule.NAME, BasketTable) + val constituentProvider = vuuServer.getProvider(BasketModule.NAME, BasketConstituentTable) + + tickPrices(pricesProvider) + tickBasketDef(basketProvider) + tickConstituentsDef(constituentProvider) + + val vpBasket = vuuServer.createViewPort(BasketModule.NAME, BasketTable) + + vuuServer.runOnce() + + When("we have 2 basket definitions") + assertVpEq(combineQsForVp(vpBasket)) { + Table( + ("id", "name", "notionalValue", "notionalValueUsd"), + (".FTSE", ".FTSE 100", 1000001, 1500001), + (".NASDAQ", ".NASDAQ", 3000001, 3500001) + ) + } + + val vpConstituent = vuuServer.createViewPort(BasketModule.NAME, BasketConstituentTable) + + vuuServer.runOnce() + + And(".FTSE is composed of 3 constituents") + assertVpEq(combineQsForVp(vpConstituent)) { + Table( + ("ricBasketId", "ric", "basketId", "weighting", "lastTrade", "change", "volume", "description", "side"), + ("BP.L.FTSE", "BP.L", ".FTSE", 0.1, null, null, null, "Beyond Petroleum", "Buy"), + ("BT.L.FTSE", "BT.L", ".FTSE", 0.1, null, null, null, "British Telecom", "Sell"), + ("VOD.L.FTSE", "VOD.L", ".FTSE", 0.1, null, null, null, "Vodafone", "Buy") + ) + } + + Then("Get the Basket RPC Service and call create basket") + val basketService = vuuServer.getViewPortRpcServiceProxy[BasketServiceIF](vpBasket) + basketService.createBasket(".FTSE", "chris-001")(vuuServer.requestContext) + + val vpBasketTrading = vuuServer.createViewPort(BasketModule.NAME, BasketTradingTable) + + vuuServer.runOnce() + + And("Check the basket trading record has been created") + //BT.InstanceId.string(), BT.BasketId.string(), BT.BasketName.string(), BT.Status.string(), BT.Units.int(), BT.FilledPct.double(), BT.FxRateToUsd.double(), BT.TotalNotional.double(), BT.TotalNotionalUsd.double(), BT.Side.string() + assertVpEq(combineQsForVp(vpBasketTrading)) { + Table( + ("instanceId", "basketId", "basketName", "status", "units", "filledPct", "fxRateToUsd", "totalNotional", "totalNotionalUsd", "side"), + ("chris-001", ".FTSE", "chris-001", "OFF-MARKET", 1, null, null, null, null, "Buy") + ) + } + + val vpBasketTradingCons = vuuServer.createViewPort(BasketModule.NAME, BasketTradingConstituentTable) + + vuuServer.runOnce() + + assertVpEq(combineQsForVp(vpBasketTradingCons)) { + Table( + ("quantity", "side", "instanceId", "instanceIdRic", "basketId", "ric", "description", "notionalUsd", "notionalLocal", "venue", "algo", "algoParams", "pctFilled", "weighting", "priceSpread", "limitPrice", "priceStrategyId"), + (10L, "Buy", "chris-001", "chris-001.BP.L", ".FTSE", "BP.L", "Beyond Petroleum", null, null, null, -1, null, null, 0.1, null, null, 2), + (10L, "Sell", "chris-001", "chris-001.BT.L", ".FTSE", "BT.L", "British Telecom", null, null, null, -1, null, null, 0.1, null, null, 2), + (10L, "Buy", "chris-001", "chris-001.VOD.L", ".FTSE", "VOD.L", "Vodafone", null, null, null, -1, null, null, 0.1, null, null, 2) + ) + } + + val basketTradingService = vuuServer.getViewPortRpcServiceProxy[BasketTradingServiceIF](vpBasketTrading) + + When("we edit the side of the parent basket") + basketTradingService.editCellAction().func("chris-001", "side", "Sell", vpBasketTrading, vuuServer.session) + + Then("get all the updates that have occurred for all view ports from the outbound queue") + val updates = combineQs(vpBasketTrading) + + And("assert the basket trading table has flipped side....") + assertVpEq(filterByVp(vpBasketTrading, updates)) { + Table( + ("instanceId", "basketId", "basketName", "status", "units", "filledPct", "fxRateToUsd", "totalNotional", "totalNotionalUsd", "side"), + ("chris-001", ".FTSE", "chris-001", "OFF-MARKET", 1, null, null, null, null, "Sell") + ) + } + + //vuuServer.runOnce() + And("assert the basket trading constituent table has flipped sides also") + assertVpEq(filterByVp(vpBasketTradingCons,updates)) { + Table( + ("quantity", "side", "instanceId", "instanceIdRic", "basketId", "ric", "description", "notionalUsd", "notionalLocal", "venue", "algo", "algoParams", "pctFilled", "weighting", "priceSpread", "limitPrice", "priceStrategyId"), + (10L, "Sell", "chris-001", "chris-001.BP.L", ".FTSE", "BP.L", "Beyond Petroleum", null, null, null, -1, null, null, 0.1, null, null, 2), + (10L, "Buy", "chris-001", "chris-001.BT.L", ".FTSE", "BT.L", "British Telecom", null, null, null, -1, null, null, 0.1, null, null, 2), + (10L, "Sell", "chris-001", "chris-001.VOD.L", ".FTSE", "VOD.L", "Vodafone", null, null, null, -1, null, null, 0.1, null, null, 2) + ) + } + + When("we edit the units of the parent basket") + basketTradingService.editCellAction().func("chris-001", "units", 1000L.asInstanceOf[Object], vpBasketTrading, vuuServer.session) + + And("assert the basket trading constituent table has increased the units") + assertVpEq(filterByVp(vpBasketTradingCons, combineQs(vpBasketTrading))) { + Table( + ("quantity", "side", "instanceId", "instanceIdRic", "basketId", "ric", "description", "notionalUsd", "notionalLocal", "venue", "algo", "algoParams", "pctFilled", "weighting", "priceSpread", "limitPrice", "priceStrategyId"), + (100L, "Sell", "chris-001", "chris-001.BP.L", ".FTSE", "BP.L", "Beyond Petroleum", null, null, null, -1, null, null, 0.1, null, null, 2), + (100L, "Buy", "chris-001", "chris-001.BT.L", ".FTSE", "BT.L", "British Telecom", null, null, null, -1, null, null, 0.1, null, null, 2), + (100L, "Sell", "chris-001", "chris-001.VOD.L", ".FTSE", "VOD.L", "Vodafone", null, null, null, -1, null, null, 0.1, null, null, 2) + ) + } + } + } + } +} \ No newline at end of file diff --git a/example/basket/src/test/scala/org/finos/vuu/core/module/basket/BasketTestCaseHelper.scala b/example/basket/src/test/scala/org/finos/vuu/core/module/basket/BasketTestCaseHelper.scala new file mode 100644 index 000000000..540cb1d2d --- /dev/null +++ b/example/basket/src/test/scala/org/finos/vuu/core/module/basket/BasketTestCaseHelper.scala @@ -0,0 +1,27 @@ +package org.finos.vuu.core.module.basket + +import org.finos.vuu.core.module.basket.BasketModule.{BasketColumnNames => B, BasketConstituentColumnNames => BC} +import org.finos.vuu.provider.MockProvider + +object BasketTestCaseHelper { + def tickPrices(provider: MockProvider): Unit = { + provider.tick("VOD.L", Map("ric" -> "VOD.L", "phase" -> "C", "bid" -> 100, "ask" -> 101, "last" -> 101.5)) + provider.tick("BT.L", Map("ric" -> "BT.L", "phase" -> "C", "bid" -> 200, "ask" -> 201, "last" -> 201.5)) + provider.tick("BP.L", Map("ric" -> "BP.L", "phase" -> "C", "bid" -> 300, "ask" -> 301, "last" -> 301.5)) + provider.tick("AAPL", Map("ric" -> "AAPL", "phase" -> "C", "bid" -> 1000, "ask" -> 1001, "last" -> 1001.5)) + provider.tick("MSFT", Map("ric" -> "MSFT", "phase" -> "C", "bid" -> 1100, "ask" -> 1001, "last" -> 1001.5)) + } + def tickBasketDef(provider: MockProvider): Unit = { + provider.tick(".FTSE", Map(B.Id -> ".FTSE", B.Name -> ".FTSE 100", B.NotionalValue -> 1000001, B.NotionalValueUsd -> 1500001)) + provider.tick(".NASDAQ", Map(B.Id -> ".NASDAQ", B.Name -> ".NASDAQ", B.NotionalValue -> 3000001, B.NotionalValueUsd -> 3500001)) + } + + def tickConstituentsDef(provider: MockProvider): Unit = { + //symbol + "." + basketId + //Columns.fromNames(BC.RicBasketId.string(), BC.Ric.string(), BC.BasketId.string(), BC.Weighting.double(), BC.LastTrade.string(), BC.Change.string(), + // BC.Volume.string(), BC.Side.string()) + provider.tick("VOD.L.FTSE", Map(BC.RicBasketId -> "VOD.L.FTSE", BC.Ric -> "VOD.L", BC.BasketId -> ".FTSE", BC.Weighting -> 0.1, BC.Side -> "Buy", BC.Description -> "Vodafone")) + provider.tick("BT.L.FTSE", Map(BC.RicBasketId -> "BT.L.FTSE", BC.Ric -> "BT.L", BC.BasketId -> ".FTSE", BC.Weighting -> 0.1, BC.Side -> "Sell", BC.Description -> "British Telecom")) + provider.tick("BP.L.FTSE", Map(BC.RicBasketId -> "BP.L.FTSE", BC.Ric -> "BP.L", BC.BasketId -> ".FTSE", BC.Weighting -> 0.1, BC.Side -> "Buy", BC.Description -> "Beyond Petroleum")) + } +} diff --git a/example/basket/src/test/scala/org/finos/vuu/core/module/basket/TestService.scala b/example/basket/src/test/scala/org/finos/vuu/core/module/basket/TestService.scala new file mode 100644 index 000000000..a2f66c49e --- /dev/null +++ b/example/basket/src/test/scala/org/finos/vuu/core/module/basket/TestService.scala @@ -0,0 +1,25 @@ +package org.finos.vuu.core.module.basket + +import org.finos.vuu.net.rpc.{EditRpcHandler, RpcHandler} +import org.finos.vuu.viewport.{ViewPortAction, ViewPortAddRowAction, ViewPortDeleteCellAction, ViewPortDeleteRowAction, ViewPortEditCellAction, ViewPortEditRowAction, ViewPortEditSuccess, ViewPortFormCloseAction, ViewPortFormSubmitAction} + +class TestService extends RpcHandler with EditRpcHandler { + def sendBasketToMarket(): ViewPortAction = { + println("test") + ViewPortEditSuccess() + } + + override def deleteRowAction(): ViewPortDeleteRowAction = ??? + + override def deleteCellAction(): ViewPortDeleteCellAction = ??? + + override def addRowAction(): ViewPortAddRowAction = ??? + + override def editCellAction(): ViewPortEditCellAction = ??? + + override def editRowAction(): ViewPortEditRowAction = ??? + + override def onFormSubmit(): ViewPortFormSubmitAction = ??? + + override def onFormClose(): ViewPortFormCloseAction = ??? +} diff --git a/example/basket/src/test/scala/org/finos/vuu/provider/BasketConstituentProviderTest.scala b/example/basket/src/test/scala/org/finos/vuu/provider/BasketConstituentProviderTest.scala new file mode 100644 index 000000000..f8a959b93 --- /dev/null +++ b/example/basket/src/test/scala/org/finos/vuu/provider/BasketConstituentProviderTest.scala @@ -0,0 +1,102 @@ +//package org.finos.vuu.provider +// +//import org.finos.toolbox.jmx.{MetricsProvider, MetricsProviderImpl} +//import org.finos.toolbox.lifecycle.LifecycleContainer +//import org.finos.toolbox.time.TestFriendlyClock +//import org.finos.vuu.api.{TableDef, VisualLinks} +//import org.finos.vuu.core.module.FieldDefString +//import org.finos.vuu.core.module.basket.BasketModule.{BasketConstituentColumnNames => BC} +//import org.finos.vuu.core.module.basket.provider.BasketConstituentProvider +//import org.finos.vuu.core.table.{Column, Columns, SimpleDataTable, ViewPortColumnCreator} +//import org.scalatest.BeforeAndAfter +//import org.scalatest.featurespec.AnyFeatureSpec +//import org.scalatest.matchers.should.Matchers +// +//class BasketConstituentProviderTest extends AnyFeatureSpec with Matchers with BeforeAndAfter { +// final val TEST_TIME = 1450770869442L +// val joinProvider = new TestFriendlyJoinTableProvider +// implicit val timeProvider: TestFriendlyClock = new TestFriendlyClock(TEST_TIME) +// implicit val metrics: MetricsProvider = new MetricsProviderImpl +// implicit val lifecycleContainer: LifecycleContainer = new LifecycleContainer +// +// val tableDef = TableDef( +// name = "basketConstituent", +// keyField = BC.RicBasketId, +// columns = Columns.fromNames(new FieldDefString(BC.RicBasketId).string(), +// new FieldDefString(BC.Ric).string(), +// new FieldDefString(BC.BasketId).string(), +// new FieldDefString(BC.Weighting).double(), +// new FieldDefString(BC.LastTrade).string(), +// new FieldDefString(BC.Change).string(), +// new FieldDefString(BC.Volume).string()), // we can join to instruments and other tables to get the rest of the data..... +// VisualLinks(), +// joinFields = BC.RicBasketId +// ) +// val table = new SimpleDataTable(tableDef, joinProvider) +// val provider = new BasketConstituentProvider(table) +// val columns: Array[Column] = provider.table.getTableDef.columns +// val headers: Array[String] = columns.map(_.name) +// +// before { +// provider.runOnce +// } +// +// ignore("Able to load basket constituents from .FTSE100 and show on basket constituent table") { +// +// Scenario("display ric") { +// assert(getDataForBasket(".FTSE100")(0)(headers.indexOf(BC.Ric)) == "AAL.L") +// } +// +// Scenario("display basket id") { +// assert(getDataForBasket(".FTSE100")(0)(headers.indexOf(BC.BasketId)) == ".FTSE100") +// } +// +// Scenario("display change") { +// assert(getDataForBasket(".FTSE100")(0)(headers.indexOf(BC.Change)) == "�5.35�(1.24%)") +// } +// +// // TODO emily - volume with , is not parsed correctly +//// Scenario("display volume") { +//// assert(getDataForBasket(".FTSE100")(0)(headers.indexOf(BC.Volume)) == "5,799,089") +//// } +// +// Scenario("display weighting") { +// assert(getDataForBasket(".FTSE100")(0)(headers.indexOf(BC.Weighting)) == null) +// } +// } +// +// ignore("Able to load basket constituents from .NASDAQ100 and show on basket constituent table") { +// +//// Scenario("display ric") { +//// val array = getDataForBasket(".NASDAQ100") +//// assert(array(0)(headers.indexOf(BC.Ric)) == "AAPL") +//// } +// +// Scenario("display basket id") { +// assert(getDataForBasket(".NASDAQ100")(0)(headers.indexOf(BC.BasketId)) == ".NASDAQ100") +// } +// +// Scenario("display change") { +// assert(getDataForBasket(".NASDAQ100")(0)(headers.indexOf(BC.Change)) == null) +// } +// +// Scenario("display volume") { +// assert(getDataForBasket(".NASDAQ100")(0)(headers.indexOf(BC.Volume)) == null) +// } +// +//// Scenario("display weighting") { +//// assert(getDataForBasket(".NASDAQ100")(0)(headers.indexOf(BC.Weighting)) == "11.007") +//// } +// } +// +// +// private def getData = { +// val keys = provider.table.primaryKeys +// val data = keys.toArray.map(key => provider.table.pullRowAsArray(key, ViewPortColumnCreator.create(provider.table, columns.map(_.name).toList))) +// data +// } +// private def getDataForBasket(basketId:String) = { +// val data = getData +// data.filter(e => e(headers.indexOf(BC.BasketId))==basketId) +// } +//} diff --git a/example/basket/src/test/scala/org/finos/vuu/provider/BasketProviderTest.scala b/example/basket/src/test/scala/org/finos/vuu/provider/BasketProviderTest.scala new file mode 100644 index 000000000..04602a52d --- /dev/null +++ b/example/basket/src/test/scala/org/finos/vuu/provider/BasketProviderTest.scala @@ -0,0 +1,55 @@ +//package org.finos.vuu.provider +// +//import org.finos.toolbox.jmx.{MetricsProvider, MetricsProviderImpl} +//import org.finos.toolbox.lifecycle.LifecycleContainer +//import org.finos.toolbox.time.TestFriendlyClock +//import org.finos.vuu.api.{TableDef, VisualLinks} +//import org.finos.vuu.core.module.FieldDefString +//import org.finos.vuu.core.module.basket.BasketModule.{BasketColumnNames => B} +//import org.finos.vuu.core.module.basket.provider.BasketProvider +//import org.finos.vuu.core.table.{Column, Columns, SimpleDataTable, ViewPortColumnCreator} +//import org.scalatest.BeforeAndAfter +//import org.scalatest.featurespec.AnyFeatureSpec +//import org.scalatest.matchers.should.Matchers +// +//class BasketProviderTest extends AnyFeatureSpec with Matchers with BeforeAndAfter { +// final val TEST_TIME = 1450770869442L +// val joinProvider = new TestFriendlyJoinTableProvider +// implicit val timeProvider: TestFriendlyClock = new TestFriendlyClock(TEST_TIME) +// implicit val metrics: MetricsProvider = new MetricsProviderImpl +// implicit val lifecycleContainer: LifecycleContainer = new LifecycleContainer +// +// val tableDef = TableDef( +// name = "basket", +// keyField = B.Id, +// columns = Columns.fromNames( +// new FieldDefString(B.Id).string(), +// new FieldDefString(B.Name).string(), +// new FieldDefString(B.NotionalValue).double(), +// new FieldDefString(B.NotionalValueUsd).double()), +// VisualLinks(), +// joinFields = B.Id +// ) +// val table = new SimpleDataTable(tableDef, joinProvider) +// val provider = new BasketProvider(table) +// val columns: Array[Column] = provider.table.getTableDef.columns +// val headers: Array[String] = columns.map(_.name) +// +// before { +// provider.runOnce() +// } +// +// Feature("Able to load baskets") { +// +// Scenario("get list of baskets") { +// val ids = getData.map(e => e(headers.indexOf(B.Id))) +//// assert(ids.sameElements(Array(".NASDAQ100", ".FTSE100", ".SP500", ".HSI"))) +// } +// } +// +// private def getData = { +// val keys = provider.table.primaryKeys +// val data = keys.toArray.map(key => provider.table.pullRowAsArray(key, ViewPortColumnCreator.create(provider.table, columns.map(_.name).toList))) +// data +// } +//} diff --git a/example/editable/pom.xml b/example/editable/pom.xml new file mode 100644 index 000000000..ce599c302 --- /dev/null +++ b/example/editable/pom.xml @@ -0,0 +1,246 @@ + + + 4.0.0 + + + org.finos.vuu + example + 0.9.36-SNAPSHOT + + + + editable + + + + org.finos.vuu + vuu + 0.9.36-SNAPSHOT + + + + org.finos.vuu + vuu + 0.9.36-SNAPSHOT + tests + test-jar + test + + + + org.scala-lang + scala-library + ${scala.version} + + + + org.scala-lang + scala-reflect + ${scala.version} + + + + junit + junit + 4.13.2 + test + + + + org.scalatest + scalatest_2.13 + ${scalatest.version} + test + + + org.scala-lang + scala-library + + + org.scala-lang + scala-reflect + + + + + + + + + + + legal-report + + + + org.scala-tools + maven-scala-plugin + ${maven.scala.plugin} + + + **/*.scala + + + + + + + + + + src/main/java + src/test/java + + + + + org.apache.maven.plugins + maven-source-plugin + + + + compile + + jar + + + + + + + org.apache.maven.plugins + maven-release-plugin + + + + + org.apache.maven.plugins + maven-javadoc-plugin + + + attach-javadocs + + jar + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.0 + + ${maven.compiler.source} + ${maven.compiler.target} + + + + org.ow2.asm + asm + 6.2 + + + + + + + org.scala-tools + maven-scala-plugin + ${maven.scala.plugin} + + + + compile + testCompile + + + + + src/main/scala + src/test/scala + + -Xms64m + -Xmx1024m + + + + + + org.codehaus.mojo + build-helper-maven-plugin + 3.2.0 + + + generate-sources + + add-source + + + + target/generated-sources/antlr4 + + + + + + + + + org.apache.maven.plugins + maven-jar-plugin + 3.1.2 + + + + test-jar + + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.7 + + + + + + + org.scalatest + scalatest-maven-plugin + 2.0.2 + + ${project.build.directory}/surefire-reports + . + test-reports.txt + + + + test + + test + + + + + + + + + + + org.scala-tools + maven-scala-plugin + ${maven.scala.plugin} + + ${scala.version} + + + + + + \ No newline at end of file diff --git a/example/editable/src/main/java/Dummy4JavaDoc.java b/example/editable/src/main/java/Dummy4JavaDoc.java new file mode 100644 index 000000000..00b8d1897 --- /dev/null +++ b/example/editable/src/main/java/Dummy4JavaDoc.java @@ -0,0 +1,2 @@ +public class Dummy4JavaDoc { +} diff --git a/vuu/src/main/scala/org/finos/vuu/core/module/editable/EditableModule.scala b/example/editable/src/main/scala/org/finos/vuu/core/module/editable/EditableModule.scala similarity index 93% rename from vuu/src/main/scala/org/finos/vuu/core/module/editable/EditableModule.scala rename to example/editable/src/main/scala/org/finos/vuu/core/module/editable/EditableModule.scala index e7efa02b7..0ce63035b 100644 --- a/vuu/src/main/scala/org/finos/vuu/core/module/editable/EditableModule.scala +++ b/example/editable/src/main/scala/org/finos/vuu/core/module/editable/EditableModule.scala @@ -1,12 +1,10 @@ package org.finos.vuu.core.module.editable +import org.finos.toolbox.lifecycle.LifecycleContainer +import org.finos.toolbox.time.Clock import org.finos.vuu.api.{SessionTableDef, TableDef, ViewPortDef, VisualLinks} import org.finos.vuu.core.module.{DefaultModule, ModuleFactory, TableDefContainer, ViewServerModule} import org.finos.vuu.core.table.Columns -import org.finos.vuu.provider.RpcProvider -import org.finos.toolbox.lifecycle.LifecycleContainer -import org.finos.toolbox.time.Clock -import org.finos.vuu.core.module.vui.VuiStateStoreProvider object EditableModule extends DefaultModule { diff --git a/vuu/src/main/scala/org/finos/vuu/core/module/editable/FixSequenceRpcService.scala b/example/editable/src/main/scala/org/finos/vuu/core/module/editable/FixSequenceRpcService.scala similarity index 89% rename from vuu/src/main/scala/org/finos/vuu/core/module/editable/FixSequenceRpcService.scala rename to example/editable/src/main/scala/org/finos/vuu/core/module/editable/FixSequenceRpcService.scala index 22b4a1e42..381b747fa 100644 --- a/vuu/src/main/scala/org/finos/vuu/core/module/editable/FixSequenceRpcService.scala +++ b/example/editable/src/main/scala/org/finos/vuu/core/module/editable/FixSequenceRpcService.scala @@ -4,7 +4,7 @@ import org.finos.toolbox.time.Clock import org.finos.vuu.core.table.RowWithData import org.finos.vuu.net.ClientSessionId import org.finos.vuu.net.rpc.{EditRpcHandler, RpcHandler} -import org.finos.vuu.viewport.{CloseDialogViewPortAction, ViewPort, ViewPortAction, ViewPortAddRowAction, ViewPortDeleteCellAction, ViewPortDeleteRowAction, ViewPortEditAction, ViewPortEditCellAction, ViewPortEditFailure, ViewPortEditRowAction, ViewPortEditSuccess, ViewPortFormCloseAction, ViewPortFormSubmitAction} +import org.finos.vuu.viewport._ class FixSequenceRpcService(implicit clock: Clock) extends RpcHandler with EditRpcHandler{ diff --git a/vuu/src/main/scala/org/finos/vuu/core/module/editable/ProcessProvider.scala b/example/editable/src/main/scala/org/finos/vuu/core/module/editable/ProcessProvider.scala similarity index 93% rename from vuu/src/main/scala/org/finos/vuu/core/module/editable/ProcessProvider.scala rename to example/editable/src/main/scala/org/finos/vuu/core/module/editable/ProcessProvider.scala index 720d504de..629fb0a11 100644 --- a/vuu/src/main/scala/org/finos/vuu/core/module/editable/ProcessProvider.scala +++ b/example/editable/src/main/scala/org/finos/vuu/core/module/editable/ProcessProvider.scala @@ -1,7 +1,7 @@ package org.finos.vuu.core.module.editable import org.finos.toolbox.lifecycle.LifecycleContainer -import org.finos.toolbox.thread.{LifeCycleRunner, RunOnceLifeCycleRunner} +import org.finos.toolbox.thread.RunOnceLifeCycleRunner import org.finos.toolbox.time.Clock import org.finos.vuu.core.table.{DataTable, RowWithData} import org.finos.vuu.provider.Provider diff --git a/vuu/src/main/scala/org/finos/vuu/core/module/editable/ProcessRpcService.scala b/example/editable/src/main/scala/org/finos/vuu/core/module/editable/ProcessRpcService.scala similarity index 70% rename from vuu/src/main/scala/org/finos/vuu/core/module/editable/ProcessRpcService.scala rename to example/editable/src/main/scala/org/finos/vuu/core/module/editable/ProcessRpcService.scala index d44dcfb68..97701e3da 100644 --- a/vuu/src/main/scala/org/finos/vuu/core/module/editable/ProcessRpcService.scala +++ b/example/editable/src/main/scala/org/finos/vuu/core/module/editable/ProcessRpcService.scala @@ -1,10 +1,10 @@ package org.finos.vuu.core.module.editable import org.finos.toolbox.time.Clock -import org.finos.vuu.core.table.{DataTable, RowWithData, TableContainer} +import org.finos.vuu.core.table.{RowWithData, TableContainer} import org.finos.vuu.net.ClientSessionId -import org.finos.vuu.net.rpc.{EditRpcHandler, RpcHandler} -import org.finos.vuu.viewport.{OpenDialogViewPortAction, RenderComponent, SelectionViewPortMenuItem, ViewPortAction, ViewPortAddRowAction, ViewPortDeleteCellAction, ViewPortDeleteRowAction, ViewPortEditCellAction, ViewPortEditRowAction, ViewPortFormCloseAction, ViewPortFormSubmitAction, ViewPortMenu, ViewPortSelection, ViewPortTable} +import org.finos.vuu.net.rpc.RpcHandler +import org.finos.vuu.viewport._ class ProcessRpcService(val tableContainer: TableContainer)(implicit clock: Clock) extends RpcHandler{ diff --git a/example/editable/src/test/scala/org/finos/vuu/core/module/editable/EditableTest.scala b/example/editable/src/test/scala/org/finos/vuu/core/module/editable/EditableTest.scala new file mode 100644 index 000000000..2ae309bf3 --- /dev/null +++ b/example/editable/src/test/scala/org/finos/vuu/core/module/editable/EditableTest.scala @@ -0,0 +1,78 @@ +package org.finos.vuu.core.module.editable + +import org.finos.toolbox.jmx.{MetricsProvider, MetricsProviderImpl} +import org.finos.toolbox.lifecycle.LifecycleContainer +import org.finos.toolbox.time.{Clock, TestFriendlyClock} +import org.finos.vuu.core.module.TableDefContainer +import org.finos.vuu.core.table.TableTestHelper.combineQs +import org.finos.vuu.test.VuuServerTestCase +import org.finos.vuu.util.table.TableAsserts.assertVpEq +import org.scalatest.prop.Tables.Table + +class EditableTest extends VuuServerTestCase { + + Feature("Editable Test Case") { + + Scenario("Check the editable functionality") { + + implicit val clock: Clock = new TestFriendlyClock(10001L) + implicit val lifecycle: LifecycleContainer = new LifecycleContainer() + implicit val tableDefContainer: TableDefContainer = new TableDefContainer(Map()) + implicit val metricsProvider: MetricsProvider = new MetricsProviderImpl + + withVuuServer(EditableTestModule()) { + vuuServer => + + vuuServer.login("testUser", "testToken") + + val viewport = vuuServer.createViewPort(EditableTestModule.NAME, "editTestTable") + + val service = vuuServer.getViewPortRpcServiceProxy[TestEditableServiceIF](viewport) + + service.addRowAction().func("key1", Map("rowId" -> "key1", "A" -> "TEST", "B" -> 1001D, "C" -> 500, "D" -> true), viewport, vuuServer.session) + + vuuServer.runOnce() + + assertVpEq(combineQsForVp(viewport)) { + Table( + ("rowId", "A", "B", "C", "D"), + ("key1", "TEST", 1001.0, 500, true) + ) + } + + service.editCellAction().func("key1", "B", 200D.asInstanceOf[Object], viewport, vuuServer.session) + + vuuServer.runOnce() + + assertVpEq(combineQsForVp(viewport)) { + Table( + ("rowId", "A", "B", "C", "D"), + ("key1", "TEST", 200.0, 500, true) + ) + } + + service.addRowAction().func("key1", Map("rowId" -> "key2", "A" -> "TEST2", "B" -> 1001D, "C" -> 500, "D" -> true), viewport, vuuServer.session) + + vuuServer.runOnce() + + assertVpEq(combineQsForVp(viewport)) { + Table( + ("rowId", "A", "B", "C", "D"), + ("key2", "TEST2", 1001.0, 500, true) + ) + } + + service.deleteRowAction().func("key1", viewport, vuuServer.session) + + vuuServer.runOnce() + + assertVpEq(combineQsForVp(viewport)) { + Table( + ("rowId", "A", "B", "C", "D") + ) + } + + } + } + } +} diff --git a/example/editable/src/test/scala/org/finos/vuu/core/module/editable/EditableTestModule.scala b/example/editable/src/test/scala/org/finos/vuu/core/module/editable/EditableTestModule.scala new file mode 100644 index 000000000..3b591cab9 --- /dev/null +++ b/example/editable/src/test/scala/org/finos/vuu/core/module/editable/EditableTestModule.scala @@ -0,0 +1,89 @@ +package org.finos.vuu.core.module.editable + +import com.typesafe.scalalogging.StrictLogging +import org.finos.toolbox.lifecycle.LifecycleContainer +import org.finos.toolbox.time.Clock +import org.finos.vuu.api.{TableDef, ViewPortDef, VisualLinks} +import org.finos.vuu.core.module.{ModuleFactory, TableDefContainer, ViewServerModule} +import org.finos.vuu.core.module.ModuleFactory.stringToString +import org.finos.vuu.core.table.{Columns, DataTable, RowWithData, TableContainer} +import org.finos.vuu.net.ClientSessionId +import org.finos.vuu.net.rpc.{EditRpcHandler, RpcHandler} +import org.finos.vuu.viewport.{ViewPort, ViewPortAddRowAction, ViewPortDeleteCellAction, ViewPortDeleteRowAction, ViewPortEditAction, ViewPortEditCellAction, ViewPortEditRowAction, ViewPortEditSuccess, ViewPortFormCloseAction, ViewPortFormSubmitAction} + +trait TestEditableServiceIF extends EditRpcHandler { + +} + +class TestEditableService(val table: DataTable, val tableContainer: TableContainer)(implicit clock: Clock) extends RpcHandler with TestEditableServiceIF with StrictLogging { + + def addRow(key: String, data: Map[String, Any], vp: ViewPort, session: ClientSessionId): ViewPortEditAction = { + table.processUpdate(key, RowWithData(key, data), clock.now()) + ViewPortEditSuccess() + } + + def editRow(key: String, data: Map[String, Any], vp: ViewPort, session: ClientSessionId): ViewPortEditAction = { + table.processUpdate(key, RowWithData(key, data), clock.now()) + ViewPortEditSuccess() + } + + def editCell(key: String, column: String, data: Any, vp: ViewPort, session: ClientSessionId): ViewPortEditAction = { + table.processUpdate(key, RowWithData(key, Map("rowId" -> key, column -> data)), clock.now()) + ViewPortEditSuccess() + } + + def deleteRow(key: String, vp: ViewPort, session: ClientSessionId): ViewPortEditAction = { + table.processDelete(key) + ViewPortEditSuccess() + } + + def deleteCell(key: String, column: String, vp: ViewPort, session: ClientSessionId): ViewPortEditAction = { + table.processUpdate(key, RowWithData(key, Map("rowId" -> key, column -> null)), clock.now()) + ViewPortEditSuccess() + } + + def formSubmit(vp: ViewPort, session: ClientSessionId): ViewPortEditAction = { + //table.processUpdate(key, RowWithData(key, Map("rowId" -> key, column -> null)), clock.now()) + ViewPortEditSuccess() + } + + def formClose(vp: ViewPort, session: ClientSessionId): ViewPortEditAction = { + //table.processUpdate(key, RowWithData(key, Map("rowId" -> key, column -> null)), clock.now()) + ViewPortEditSuccess() + } + + override def deleteRowAction(): ViewPortDeleteRowAction = ViewPortDeleteRowAction("", deleteRow) + override def deleteCellAction(): ViewPortDeleteCellAction = ViewPortDeleteCellAction("", deleteCell) + override def addRowAction(): ViewPortAddRowAction = ViewPortAddRowAction("", addRow) + override def editCellAction(): ViewPortEditCellAction = ViewPortEditCellAction("", editCell) + override def editRowAction(): ViewPortEditRowAction = ViewPortEditRowAction("", editRow) + override def onFormSubmit(): ViewPortFormSubmitAction = ViewPortFormSubmitAction("", formSubmit) + override def onFormClose(): ViewPortFormCloseAction = ViewPortFormCloseAction("", formClose) +} + +object EditableTestModule { + + final val NAME = "EDITTEST" + + def apply()(implicit clock: Clock, lifecycle: LifecycleContainer, tableDefContainer: TableDefContainer): ViewServerModule = { + + ModuleFactory.withNamespace(NAME) + .addTable( + //this table should contain one row for each of .FTSE, .DJI, .HSI, .etc... + TableDef( + name = "editTestTable", + keyField = "rowId", + columns = Columns.fromNames("rowId".string(), "A".string(), "B".double(), "C".int(), "D".boolean()), + VisualLinks(), + joinFields = "rowId" + ), + (table, _) => new NullProvider(), + (table, _, _, tableContainer) => ViewPortDef( + columns = table.getTableDef.columns, + service = new TestEditableService(table, tableContainer) + ) + ).asModule() + + } + +} diff --git a/example/editable/src/test/scala/org/finos/vuu/core/module/editable/NullProvider.scala b/example/editable/src/test/scala/org/finos/vuu/core/module/editable/NullProvider.scala new file mode 100644 index 000000000..ead6afcb4 --- /dev/null +++ b/example/editable/src/test/scala/org/finos/vuu/core/module/editable/NullProvider.scala @@ -0,0 +1,17 @@ +package org.finos.vuu.core.module.editable + +import org.finos.vuu.provider.Provider + +class NullProvider extends Provider { + override def subscribe(key: String): Unit = {} + + override def doStart(): Unit = {} + + override def doStop(): Unit = {} + + override def doInitialize(): Unit = {} + + override def doDestroy(): Unit = {} + + override val lifecycleId: String = "NullProvider" +} diff --git a/example/main/pom.xml b/example/main/pom.xml new file mode 100644 index 000000000..a52e54006 --- /dev/null +++ b/example/main/pom.xml @@ -0,0 +1,329 @@ + + + 4.0.0 + + + org.finos.vuu + example + 0.9.36-SNAPSHOT + + + + main + + + + + org.finos.vuu + vuu + 0.9.36-SNAPSHOT + + + + org.finos.vuu + basket + 0.9.36-SNAPSHOT + + + + org.finos.vuu + price + 0.9.36-SNAPSHOT + + + + org.finos.vuu + order + 0.9.36-SNAPSHOT + + + + org.finos.vuu + editable + 0.9.36-SNAPSHOT + + + + org.finos.vuu + permission + 0.9.36-SNAPSHOT + + + + org.scala-lang + scala-library + ${scala.version} + + + + org.scala-lang + scala-reflect + ${scala.version} + + + + junit + junit + 4.13.2 + test + + + + org.scalatest + scalatest_2.13 + ${scalatest.version} + test + + + org.scala-lang + scala-library + + + org.scala-lang + scala-reflect + + + + + + + + + + + sign-it + + + sign + true + + + + + + org.apache.maven.plugins + maven-gpg-plugin + 3.0.1 + + + sign-artifacts + verify + + sign + + + + --pinentry-mode + loopback + + + + + + + + + + + legal-report + + + + org.scala-tools + maven-scala-plugin + ${maven.scala.plugin} + + + **/*.scala + + + + + + + + + + src/main/java + src/test/java + + + + + org.apache.maven.plugins + maven-source-plugin + + + + compile + + jar + + + + + + + org.apache.maven.plugins + maven-release-plugin + + + + + org.apache.maven.plugins + maven-javadoc-plugin + + + attach-javadocs + + jar + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.0 + + ${maven.compiler.source} + ${maven.compiler.target} + + + + org.ow2.asm + asm + 6.2 + + + + + + + org.scala-tools + maven-scala-plugin + ${maven.scala.plugin} + + + + compile + testCompile + + + + + src/main/scala + src/test/scala + + -Xms64m + -Xmx1024m + + + + + + org.codehaus.mojo + build-helper-maven-plugin + 3.2.0 + + + generate-sources + + add-source + + + + target/generated-sources/antlr4 + + + + + + + + org.codehaus.mojo + exec-maven-plugin + 3.1.0 + + + + exec + + + + + java + + -Xmx10G + -classpath + + -Dvuu.webroot=../../vuu-ui/deployed_apps/app-vuu-example + -Dvuu.keyPath=src/main/resources/certs/key.pem + -Dvuu.certPath=src/main/resources/certs/cert.pem + -Dlogback.configurationFile=logback-netty.xml + org.finos.vuu.SimulMain + + + + + + + org.apache.maven.plugins + maven-jar-plugin + 3.1.2 + + + + test-jar + + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.7 + + + + + + + org.scalatest + scalatest-maven-plugin + 2.0.2 + + ${project.build.directory}/surefire-reports + . + test-reports.txt + + + + test + + test + + + + + + + + + + + + org.scala-tools + maven-scala-plugin + ${maven.scala.plugin} + + ${scala.version} + + + + + + \ No newline at end of file diff --git a/example/main/src/main/java/Dummy4JavaDoc.java b/example/main/src/main/java/Dummy4JavaDoc.java new file mode 100644 index 000000000..00b8d1897 --- /dev/null +++ b/example/main/src/main/java/Dummy4JavaDoc.java @@ -0,0 +1,2 @@ +public class Dummy4JavaDoc { +} diff --git a/example/main/src/main/resources/FilterSpec.txt b/example/main/src/main/resources/FilterSpec.txt new file mode 100644 index 000000000..867fd1d16 --- /dev/null +++ b/example/main/src/main/resources/FilterSpec.txt @@ -0,0 +1,35 @@ +column > {value} +column < {value} +column == {value} +column != {value} +column in [{value},{value2},{value}] +column nin [{value},{value2},{value}] + + +compound clause: +columnA gt {value} && columnB lt {value} && columnC in [{value},{value2},{value}] +columnA gt {value} || columnB lt {value} + + +tradeTime > '2015-09-12 23:59' +quantity > 700 + + +FilterSpec(s: String) +SortSpec(s:String) + + +val pipeline = Pipeline.start(condition) + +Condition.evaluate(row) + +AndCondition() + +OrCondition(AndCondition, AndCondition) + + + + + + + diff --git a/example/main/src/main/resources/application.conf b/example/main/src/main/resources/application.conf new file mode 100644 index 000000000..ae9f4e088 --- /dev/null +++ b/example/main/src/main/resources/application.conf @@ -0,0 +1,3 @@ +vuu.webroot="vuu-ui/deployed_apps/app-vuu-example" +vuu.certPath="example/main/src/main/resources/certs/cert.pem" +vuu.keyPath="example/main/src/main/resources/certs/key.pem" \ No newline at end of file diff --git a/vuu/src/main/resources/certs/cert.pem b/example/main/src/main/resources/certs/cert.pem similarity index 100% rename from vuu/src/main/resources/certs/cert.pem rename to example/main/src/main/resources/certs/cert.pem diff --git a/vuu/src/main/resources/certs/key.pem b/example/main/src/main/resources/certs/key.pem similarity index 100% rename from vuu/src/main/resources/certs/key.pem rename to example/main/src/main/resources/certs/key.pem diff --git a/example/main/src/main/resources/down.gif b/example/main/src/main/resources/down.gif new file mode 100644 index 0000000000000000000000000000000000000000..284a755339830dfe06f8ad3268e0e5966f5aac8f GIT binary patch literal 76 zcmZ?wbhEHbjEB+I7E=o--Nlj5G&n(GMaQE~LU{L(Y!pOzI$e;sK a1X9kx#MjfmlIyLUoQaX|?oDy54AuY)gcExJ literal 0 HcmV?d00001 diff --git a/example/main/src/main/resources/icon-arrow-right.png b/example/main/src/main/resources/icon-arrow-right.png new file mode 100644 index 0000000000000000000000000000000000000000..8908cf456fd3940d54f438c0068c8ca5e4166819 GIT binary patch literal 1062 zcmeAS@N?(olHy`uVBq!ia0vp^4Is?H1|$#LC7uRSEX7WqAsj$Z!;#Vf4nJ za0`PlBg3pY5)2H?Cp=voLn`LHz3abbPO`}HkNS_|JAzbPOoF`rL<>l7R5DXaR4(ff z6)V$ejo|EFcf?Q1Y?Y$m8Ubz4uens5ztFqo}{CVH|J`l@TCj9djQJNDO|es$S~JD?%?K=9Sw zVfoKu8v^(8%n96C{&m56pbfVVRF>YpzUNm=15*uOOjIe;*`@D+!sQ1_P1^&?1%Vpx zH(G0-TiCZqYypFNWBaS#MS4o&3mA?!rmyl{d~K0uqanD+3;1f=Vj zh88n&eGn~hoqF<$$6KIjbq|(tZC=^f17yY@xGVbXGEXGX;QB`QNA6clW^x;>dVXm6 z6_=Y2`(KsT+%s@3`|$d;@`FV;3QhH_zkK|~w!^9hu&A|54N3HSQ=DzWAZD5 zg7^n_tQ4(ZWR~(&DCLzn)}8Qur3%#UQ?|qRweEvE3ydYUyh*ryCH=s)8Oajs-UQsf zW|vTX!jmVYY(eZR^9R#94!^i0s)v%blDX48lKK%MvL4f7+aH~sJ^ zQ@;FzPvEh_2L*1qf16JHTOW7(7vm1aCn{`O))&masuon9G2{s^TjBdU_Q4;B3uj;P z`(q=jW_>5~tNe$OJ1?64Oi;gi{{VAi@#~g13(Qx=H(D#TU-P_~*nfTd0n>@huS0G& zu3zup*qwa*>W()T+`qCF_2`9~%qJiIp0%BEhuDwFmk;0XpKi@}?CXK*HMNSxtQErR%cr8|Bw)s3 b{%*hSvyv9mt;uD;jLzWc>gTe~DWM4f`Z)04 literal 0 HcmV?d00001 diff --git a/vuu/src/main/resources/logback-netty.xml b/example/main/src/main/resources/logback-netty.xml similarity index 100% rename from vuu/src/main/resources/logback-netty.xml rename to example/main/src/main/resources/logback-netty.xml diff --git a/vuu/src/main/resources/logback-socket.xml b/example/main/src/main/resources/logback-socket.xml similarity index 100% rename from vuu/src/main/resources/logback-socket.xml rename to example/main/src/main/resources/logback-socket.xml diff --git a/vuu/src/main/resources/logback-trace.xml b/example/main/src/main/resources/logback-trace.xml similarity index 100% rename from vuu/src/main/resources/logback-trace.xml rename to example/main/src/main/resources/logback-trace.xml diff --git a/vuu/src/main/resources/logback.xml b/example/main/src/main/resources/logback.xml similarity index 100% rename from vuu/src/main/resources/logback.xml rename to example/main/src/main/resources/logback.xml diff --git a/example/main/src/main/resources/right.png b/example/main/src/main/resources/right.png new file mode 100644 index 0000000000000000000000000000000000000000..c853585f5beeaa6424aa4987e0fbde3c1339d611 GIT binary patch literal 279 zcmeAS@N?(olHy`uVBq!ia0vp^;y^6M!3HF?%h*|g6id3JuOkD)`V;1?T`z%r$r9Iy zlHmNblJdl&R0hYC{G?O`&)mfH)S%SFl*+=BsWw1GD?MEtLn>}1{rUgjo_Q^UFf%VB zw<2p#PtP2OSJsN9H=G(Irr&3K)a!7@ZPR5(vqy&=J}@rf>DbO}sIK{JLXri?`=hCh zrabHq4?CQ3);{d`Lqg#5R$cFaedwiwB@oIk9yp!J~v_l%7%m%8!&b?PnoCm(+# z$T}iml8Py>eZ#z&D^e}4#dz@^-hNr@_vDy@jRF&|TyyBYEu!$x)k`W>X46#}UtV?& a0|viRf78!?K@WhAX7F_Nb6Mw<&;$VfKxEVa literal 0 HcmV?d00001 diff --git a/example/main/src/main/resources/sort-arrow-down.gif b/example/main/src/main/resources/sort-arrow-down.gif new file mode 100644 index 0000000000000000000000000000000000000000..284a755339830dfe06f8ad3268e0e5966f5aac8f GIT binary patch literal 76 zcmZ?wbhEHbjEB+I7E=o--Nlj5G&n(GMaQE~LU{L(Y!pOzI$e;sK a1X9kx#MjfmlIyLUoQaX|?oDy54AuY)gcExJ literal 0 HcmV?d00001 diff --git a/example/main/src/main/resources/sort-arrow-up.gif b/example/main/src/main/resources/sort-arrow-up.gif new file mode 100644 index 0000000000000000000000000000000000000000..688f4c026a5cea77e4f7dc2f522b0edb3249d005 GIT binary patch literal 76 zcmZ?wbhEHbjEB+I7E=o--Nlj5G&n(GMaQE~LU{L(Y!pOzI$e;sK a1X9kx#MjfmvU&r9@SNPB?wR*k8LR;lvlL|j literal 0 HcmV?d00001 diff --git a/example/main/src/main/resources/static/ftse100.csv b/example/main/src/main/resources/static/ftse100.csv new file mode 100644 index 000000000..aa0315f95 --- /dev/null +++ b/example/main/src/main/resources/static/ftse100.csv @@ -0,0 +1,100 @@ +Symbol,Name,Last Trade,Change,Volume, Weighting +AAL.L,Anglo American PLC,436.35�13:13,�5.35�(1.24%),5799089,0.0278736825813547 +ABF.L,Associated British Foods PLC,"3,435.60�13:12",�7.40�(0.21%),86808,0.000417248060431947 +ADM.L,Admiral Group PLC,"1,627.00�13:13",,86808,0.000417248060431947 +ADN.L,Aberdeen Asset Management PLC,334.00�13:13,�2.50�(0.75%),806880,0.00387831899135251 +AHT.L,Ashtead Group PLC,"1,027.00�13:13",�6.00�(0.59%),331255,0.00159219779580666 +ANTO.L,Antofagasta PLC,484.10�13:13,�11.70�(2.48%),1753976,0.00843059492263598 +ARM.L,ARM Holdings PLC,"1,058.00�13:13",�3.00�(0.28%),475927,0.00228757277736148 +AV.L,Aviva PLC,493.97�13:13,�2.23�(0.45%),2226835,0.0107034211668507 +AZN.L,AstraZeneca PLC,"4,399.50�13:13",�2.50�(0.06%),815133,0.00391798755004232 +BA.L,BAE Systems PLC,478.10�13:13,�4.30�(0.91%),2039934,0.00980506986578636 +BAB.L,Babcock International Group PLC,988.00�13:13,�9.50�(0.97%),209614,0.00100752275066102 +BARC.L,Barclays PLC,226.30�13:13,�1.15�(0.51%),6575664,0.0316063387021032 +BATS.L,British American Tobacco PLC,"3,803.50�13:13",�8.50�(0.22%),465110,0.0022355801929258 +BDEV.L,Barratt Developments PLC,576.00�13:13,�0.50�(0.09%),1044365,0.00501980543997108 +BG.L,BG Group PLC,"1,013.50�13:13",�5.50�(0.55%),1507332,0.00724508516988073 +BKG.L,Berkeley Group Holdings (The) PLC,"3,126.00�13:13",�15.00�(0.48%),95071,0.000456964684744788 +BLND.L,British Land Co PLC,828.06�13:12,�10.44�(1.25%),1802548,0.00866405926683583 +BLT.L,BHP Billiton PLC,881.40�13:13,�4.30�(0.49%),4947287,0.0237794431982097 +BNZL.L,Bunzl PLC,"1,875.40�13:05",�4.60�(0.24%),104541,0.000502482829757812 +BP.L,BP PLC,381.50�13:13,�2.95�(0.78%),10493561,0.0504379547308349 +BRBY.L,Burberry Group PLC,"1,269.00�13:13",�7.00�(0.55%),295647,0.00142104572530785 +BT-A.L,BT Group PLC,489.20�13:13,�3.70�(0.75%),3914982,0.0188176048996174 +CCL.L,Carnival PLC,"3,426.00�13:12",�22.00�(0.64%),86257,0.000414599644602783 +CNA.L,Centrica PLC,212.80�13:13,�0.60�(0.28%),2144540,0.0103078651220939 +CPG.L,Compass Group PLC,"1,054.00�13:08",�5.00�(0.48%),1001167,0.00481217156158961 +CPI.L,Capita PLC,"1,235.00�13:11",�1.00�(0.08%),244591,0.0011756418803464 +CRH.L,CRH PLC,"1,783.20�13:12",�17.80�(0.99%),897325,0.00431304851888186 +DC.L,DIXONS CARPHONE,462.10�13:11,,756906,0.00363811584680332 +DGE.L,Diageo PLC,"1,881.50�13:13",�6.50�(0.34%),756906,0.00363811584680332 +DLG.L,Direct Line Insurance Group PLC,403.80�13:13,�0.40�(0.10%),1095340,0.00526481995338596 +EXPN.L,Experian PLC,"1,191.00�13:12",�2.00�(0.17%),467283,0.00224602485281105 +EZJ.L,easyJet PLC,"1,682.00�13:12",�28.00�(1.64%),1191230,0.00572572121265722 +FRES.L,Fresnillo PLC,678.50�13:12,�6.50�(0.97%),381871,0.00183548675335462 +GFS.L,G4S PLC,232.30�13:03,�2.00�(0.85%),1096551,0.00527064070033535 +GKN.L,GKN PLC,294.80�13:12,�2.50�(0.86%),792247,0.00380798456516713 +GLEN.L,Glencore PLC,90.48�13:13,�1.65�(1.86%),41631528,0.200104533116974 +GSK.L,GlaxoSmithKline PLC,"1,345.00�13:13",�0.50�(0.04%),1767356,0.00849490672625522 +HIK.L,Hikma Pharmaceuticals PLC,"2,010.00�13:04",�57.00�(2.92%),261511,0.00125696891451962 +HL.L,Hargreaves Lansdown PLC,"1,488.03�13:12",�9.97�(0.67%),372261,0.00178929568961912 +HMSO.L,Hammerson PLC,597.50�13:11,�3.50�(0.58%),478301,0.0022989835562697 +HSBA.L,HSBC Holdings PLC,519.70�13:13,�0.50�(0.10%),7415629,0.0356436828072631 +IAG.L,International Consolidated Airlines Group SA,575.40�13:12,�16.10�(2.72%),4311514,0.0207235606629018 +IHG.L,InterContinental Hotels Group PLC,"2,481.00�13:12",�19.00�(0.76%),219918,0.00105704956863507 +III.L,3i Group PLC,487.30�13:11,�4.50�(0.92%),189987,0.000913184352332553 +IMT.L,Imperial Tobacco Group PLC,"3,571.00�13:13",�29.00�(0.81%),926816,0.00445479884777089 +INTU.L,intu properties plc,319.90�13:09,�4.60�(1.42%),514821,0.0024745192115892 +ISAT.L,Inmarsat PLC,"1,054.44�13:13",�3.44�(0.33%),988089,0.00474931133978598 +ITRK.L,Intertek Group PLC,"2,643.00�13:14",�3.00�(0.11%),45868,0.000220467399731505 +ITV.L,ITV PLC,267.30�13:14,�2.60�(0.96%),3453208,0.0165980593985356 +JMAT.L,Johnson Matthey PLC,"2,445.00�13:14",�29.00�(1.20%),276397,0.00132851940096775 +KGF.L,Kingfisher PLC,346.20�13:14,�4.30�(1.23%),1021408,0.00490946118917235 +LAND.L,Land Securities Group PLC,"1,239.00�13:13",�7.00�(0.56%),384973,0.00185039670961971 +LGEN.L,Legal & General Group PLC,266.00�13:14,�1.60�(0.60%),1998399,0.00960542930051541 +LLOY.L,Lloyds Banking Group PLC,73.86�13:14,�0.02�(0.03%),18907878,0.0908818936317375 +LSE.L,London Stock Exchange Group PLC,"2,544.00�13:11",�6.00�(0.24%),129657,0.000623204448569543 +MGGT.L,Meggitt PLC,386.00�13:15,�3.20�(0.84%),611044,0.00293702105610748 +MKS.L,Marks & Spencer Group PLC,514.75�13:12,�3.25�(0.63%),920128,0.00442265255908587 +MNDI.L,Mondi PLC,"1,463.00�13:14",�7.00�(0.48%),383546,0.00184353774521278 +MRW.L,Morrison (Wm) Supermarkets PLC,155.20�13:14,,920128,0.00442265255908587 +NG.L,National Grid PLC,926.40�13:14,�1.10�(0.12%),1659592,0.00797693234619361 +NXT.L,Next PLC,"7,765.00�13:11",�95.00�(1.21%),114062,0.000548246109448308 +OML.L,Old Mutual PLC,198.50�13:14,�0.40�(0.20%),2040849,0.00980946787029396 +PRU.L,Prudential PLC,"1,499.50�13:15",�14.00�(0.93%),580870,0.00279198784516525 +PSON.L,Pearson PLC,794.00�13:09,�5.00�(0.63%),1177953,0.00566190448495522 +RB.L,Reckitt Benckiser Group PLC,"6,293.00�13:14",�34.00�(0.54%),281172,0.0013514707359664 +RBS.L,Royal Bank of Scotland Group PLC,313.40�13:14,�2.40�(0.77%),2100058,0.0100940596177149 +RDSA.L,Royal Dutch Shell PLC,"1,636.00�13:14",�18.00�(1.11%),2467461,0.0118600050276642 +RDSB.L,Royal Dutch Shell PLC,"1,652.00�13:15",�14.50�(0.89%),1457434,0.0070052473240666 +REL.L,Reed Elsevier PLC,"1,170.00�13:14",0.00�(0.00%),908802,0.00436821343443777 +RIO.L,Rio Tinto PLC,"2,235.00�13:15",�21.00�(0.95%),2190722,0.0105298417823887 +RMG.L,Royal Mail PLC,453.50�13:14,�1.20�(0.26%),995316,0.00478404836555252 +RR.L,Rolls-Royce Group PLC,546.63�13:14,�8.38�(1.51%),2792915,0.0134243199555489 +RRS.L,Randgold Resources Ltd,"3,929.00�13:14",0.00�(0.00%),135524,0.000651404549603483 +RSA.L,RSA Insurance Group PLC,437.10�13:14,�0.10�(0.02%),395477,0.00190088484005443 +SAB.L,SABMiller PLC,"4,011.00�13:15",�1.00�(0.02%),892451,0.00428962133421518 +SBRY.L,Sainsbury (J) PLC,255.80�13:14,�7.40�(2.98%),2395670,0.0115149371133421 +SDR.L,Schroders PLC,"2,930.00�13:09",�12.00�(0.41%),44674,0.000214728364341268 +SGE.L,Sage Group (The) PLC,545.50�13:13,�0.50�(0.09%),539717,0.00259418338669419 +SHP.L,Shire PLC,"4,685.00�13:14",�22.00�(0.47%),221318,0.0010637787558598 +SKY.L,SKY,"1,095.00�13:12",�4.00�(0.37%),925016,0.0044461470356248 +SL.L,Standard Life PLC,399.90�13:14,�3.20�(0.79%),861636,0.00414150711683647 +SMIN.L,Smiths Group PLC,992.50�13:14,�27.50�(2.70%),640309,0.00307768510191594 +SN.L,Smith & Nephew PLC,"1,110.00�13:14",�9.00�(0.82%),480018,0.00230723642374461 +SPD.L,Sports Direct International PLC,694.50�13:11,�1.50�(0.22%),157981,0.000759345519250522 +SSE.L,SSE PLC,"1,463.00�13:13",�2.00�(0.14%),562454,0.00270347019378617 +STAN.L,Standard Chartered PLC,583.00�13:14,�0.60�(0.10%),2018697,0.00970299290214945 +STJ.L,St James's Place PLC,964.00�13:14,�11.00�(1.13%),418480,0.00201145019271912 +SVT.L,Severn Trent PLC,"2,199.00�13:12",�1.00�(0.05%),95342,0.000458267263129005 +TPK.L,Travis Perkins PLC,"1,945.00�13:13",�4.00�(0.21%),92916,0.000446606542981001 +TSCO.L,Tesco PLC,171.54�13:14,�2.54�(1.50%),9831136,0.0472539676970174 +TUI.L,TUI AG,"1,115.00�13:10",�5.00�(0.45%),458970,0.00220606790038304 +TW.L,Taylor Wimpey PLC,183.90�13:15,�1.10�(0.59%),3180729,0.0152883721086725 +ULVR.L,Unilever PLC,"2,791.00�13:14",�29.00�(1.03%),824827,0.0039645823650113 +UU.L,United Utilities Group PLC,959.00�13:10,�2.50�(0.26%),436911,0.00210003994253274 +VOD.L,Vodafone Group PLC,224.25�13:15,�1.30�(0.58%),17572036,0.0844610858312637 +WOS.L,Wolseley PLC,"3,657.00�13:14",�4.00�(0.11%),179536,0.000862950969699912 +WPP.L,WPP PLC,"1,502.00�13:15",�12.00�(0.79%),857887,0.0041234873147611 +WTB.L,Whitbread PLC,"4,484.00�13:16",�60.00�(1.32%),141036,0.000677898321019722 +,,,,208048900, diff --git a/example/main/src/main/resources/static/hsi.csv b/example/main/src/main/resources/static/hsi.csv new file mode 100644 index 000000000..fcd24d46c --- /dev/null +++ b/example/main/src/main/resources/static/hsi.csv @@ -0,0 +1,81 @@ +Name,Symbol,Last,Change,Change %,Volume,Turn.,P/E,P/B,Yield,Market Cap,Weighting +CKH HOLDINGS,00001.HK,41.9,1.15,+2.822%,5.15M,215.13M,4.38,0.31,6.98%,160.48B,0.0278736825813547 +CLP HOLDINGS,00002.HK,57.95,-0.1,-0.172%,3.32M,193.19M,156.62,1.39,5.35%,146.41B,0.000417248060431947 +HK & CHINA GAS,00003.HK,5.46,0.13,+2.439%,16.16M,88.00M,19.43,1.66,6.41%,101.88B,0.000417248060431947 +HSBC HOLDINGS,00005.HK,61.7,1.1,+1.815%,22.19M,1.37B,10.54,0.86,4.05%,1,0.00387831899135251 +POWER ASSETS,00006.HK,37.9,-0.25,-0.655%,4.23M,160.75M,14.3,0.93,7.44%,80.77B,0.00159219779580666 +HANG SENG BANK,00011.HK,97.45,2.95,+3.122%,2.54M,247.44M,19.69,1.01,4.21%,186.31B,0.00843059492263598 +HENDERSON LAND,00012.HK,20.65,0.85,+4.293%,5.07M,103.70M,10.81,0.31,8.72%,99.97B,0.00228757277736148 +SHK PPT,00016.HK,83.8,3.25,+4.035%,8.25M,685.41M,10.16,0.4,5.91%,242.83B,0.0107034211668507 +NEW WORLD DEV,00017.HK,15.24,0.8,+5.540%,12.95M,196.19M,30.48,0.18,13.52%,38.35B,0.00391798755004232 +GALAXY ENT,00027.HK,47.15,1.9,+4.199%,11.97M,560.21M,No Profit,3.22,0.00%,206.21B,0.00980506986578636 +MTR CORPORATION,00066.HK,31,0.8,+2.649%,4.68M,144.86M,19.5,1.07,4.23%,192.64B,0.00100752275066102 +HANG LUNG PPT,00101.HK,10.72,0.56,+5.512%,7.68M,81.99M,12.61,0.36,7.28%,48.23B,0.0316063387021032 +GEELY AUTO,00175.HK,9.24,0.17,+1.874%,18.77M,173.30M,16.06,1.15,2.27%,92.99B,0.0022355801929258 +ALI HEALTH,00241.HK,4.88,0.47,+10.658%,53.62M,257.82M,108.09,3.81,0.00%,66.04B,0.00501980543997108 +CITIC,00267.HK,7.2,0.2,+2.857%,11.54M,82.96M,2.78,0.28,9.04%,209.45B,0.00724508516988073 +WH GROUP,00288.HK,4.11,0.08,+1.985%,18.94M,77.65M,4.93,0.7,7.30%,52.73B,0.000456964684744788 +CHINA RES BEER,00291.HK,42.95,1.2,+2.874%,4.83M,207.98M,28.41,4.57,1.41%,139.34B,0.00866405926683583 +OOIL,00316.HK,104.5,-0.4,-0.381%,296.54K,30.98M,0.89,0.66,78.90%,69.01B,0.0237794431982097 +TINGYI,00322.HK,10.94,0.18,+1.673%,2.91M,31.81M,20.75,4.09,9.39%,61.64B,0.000502482829757812 +SINOPEC CORP,00386.HK,4.28,-0.01,-0.233%,92.43M,396.61M,6.94,0.58,9.36%,105.92B,0.0504379547308349 +HKEX,00388.HK,292.6,9,+3.173%,4.61M,1.34B,36.76,7.46,2.44%,370.97B,0.00142104572530785 +TECHTRONIC IND,00669.HK,76,1.35,+1.808%,5.47M,414.78M,16.54,3.43,2.43%,139.45B,0.0188176048996174 +CHINA OVERSEAS,00688.HK,16.24,0.52,+3.308%,13.15M,212.60M,6.76,0.44,4.93%,177.74B,0.000414599644602783 +TENCENT,00700.HK,306.2,8.8,+2.959%,11.25M,3.43B,13.74,3.6,0.78%,2,0.0103078651220939 +CHINA UNICOM,00762.HK,5.68,-0.05,-0.873%,9.23M,52.77M,9.16,0.45,5.44%,173.80B,0.00481217156158961 +LINK REIT,00823.HK,38.4,1.45,+3.924%,12.04M,460.96M,5.42,0.52,7.03%,98.38B,0.0011756418803464 +CHINA RES POWER,00836.HK,14.94,0.32,+2.189%,9.91M,147.81M,10.23,0.87,3.92%,71.87B,0.00431304851888186 +PETROCHINA,00857.HK,5.9,0,0.000%,64.23M,380.44M,6.38,0.7,8.08%,124.48B,0.00363811584680332 +XINYI GLASS,00868.HK,10.14,0.17,+1.705%,3.75M,38.02M,8.01,1.3,6.11%,42.22B,0.00363811584680332 +ZHONGSHENG HLDG,00881.HK,22.05,1.45,+7.039%,6.76M,147.71M,7.08,1.07,4.94%,52.72B,0.00526481995338596 +CNOOC,00883.HK,13.78,-0.02,-0.145%,26.37M,365.08M,4.03,0.97,19.09%,655.47B,0.00224602485281105 +CCB,00939.HK,4.42,0.06,+1.376%,233.61M,1.03B,3.06,0.35,9.93%,1,0.00572572121265722 +CHINA MOBILE,00941.HK,65.7,0.25,+0.382%,7.82M,516.10M,9.91,0.96,6.71%,1,0.00183548675335462 +LONGFOR GROUP,00960.HK,14.08,0.9,+6.829%,10.88M,150.68M,3.06,0.55,9.05%,92.81B,0.00527064070033535 +XINYI SOLAR,00968.HK,5.86,0.28,+5.018%,15.99M,92.88M,13.64,1.75,3.41%,52.17B,0.00380798456516713 +SMIC,00981.HK,20.05,0.25,+1.263%,13.10M,264.32M,11.17,1.06,0.00%,159.31B,0.200104533116974 +LENOVO GROUP,00992.HK,8.07,0.25,+3.197%,33.60M,270.50M,7.61,2.23,4.71%,97.87B,0.00849490672625522 +CKI HOLDINGS,01038.HK,37.05,-0.2,-0.537%,1.44M,53.73M,12.03,0.78,6.83%,93.35B,0.00125696891451962 +HENGAN INT'L,01044.HK,24.95,0.2,+0.808%,2.62M,64.97M,13.35,1.32,6.33%,28.99B,0.00178929568961912 +CHINA SHENHUA,01088.HK,25.4,0.35,+1.397%,7.98M,203.11M,6.14,1.13,11.33%,85.79B,0.0022989835562697 +CSPC PHARMA,01093.HK,5.74,0.05,+0.879%,29.29M,167.41M,9.96,2.01,3.66%,68.32B,0.0356436828072631 +SINOPHARM,01099.HK,22.7,0.2,+0.889%,2.07M,46.80M,7.37,0.92,4.08%,30.46B,0.0207235606629018 +CHINA RES LAND,01109.HK,31.2,1,+3.311%,9.88M,305.88M,7.02,0.81,5.07%,222.49B,0.00105704956863507 +CK ASSET,01113.HK,41.25,1.25,+3.125%,8.57M,352.44M,6.9,0.39,5.53%,146.47B,0.000913184352332553 +SINO BIOPHARM,01177.HK,2.83,0.02,+0.712%,26.30M,74.09M,18.37,1.59,4.24%,53.21B,0.00445479884777089 +CHINA RES MIXC,01209.HK,31.6,1.6,+5.333%,3.07M,96.42M,28.97,4.48,2.87%,72.13B,0.0024745192115892 +BYD COMPANY,01211.HK,242,7,+2.979%,3.90M,938.50M,37.57,5.63,0.53%,265.72B,0.00474931133978598 +AIA,01299.HK,63.85,0.95,+1.510%,38.75M,2.48B,408.88,2.53,2.41%,735.40B,0.000220467399731505 +CHINAHONGQIAO,01378.HK,7.67,0.28,+3.789%,13.05M,99.58M,7.27,0.76,6.65%,72.68B,0.0165980593985356 +ICBC,01398.HK,3.77,0.07,+1.892%,233.48M,881.67M,3.45,0.36,9.08%,327.21B,0.00132851940096775 +XIAOMI-W,01810.HK,12.34,0.62,+5.290%,78.53M,960.98M,109.39,1.9,0.00%,308.83B,0.00490946118917235 +BUD APAC,01876.HK,15.46,0.16,+1.046%,16.17M,250.45M,28.65,2.44,1.91%,204.74B,0.00185039670961971 +SANDS CHINA LTD,01928.HK,24,0.95,+4.121%,19.98M,475.93M,No Profit,N/A,0.00%,194.24B,0.00960542930051541 +CHOW TAI FOOK,01929.HK,11.8,0.28,+2.431%,4.88M,57.68M,21.93,3.64,10.34%,118.00B,0.0908818936317375 +WHARF REIC,01997.HK,30.25,1.4,+4.853%,4.23M,127.31M,No Profit,0.48,4.33%,91.85B,0.000623204448569543 +ANTA SPORTS,02020.HK,88.15,4.4,+5.254%,4.82M,422.51M,27.71,6.16,1.52%,249.70B,0.00293702105610748 +WUXI BIO,02269.HK,45.65,1.55,+3.515%,17.91M,811.49M,38.18,4.88,0.00%,194.01B,0.00442265255908587 +SHENZHOU INTL,02313.HK,75,4.6,+6.534%,5.52M,410.68M,21.87,3.25,2.55%,112.74B,0.00184353774521278 +PING AN,02318.HK,44.85,0.85,+1.932%,23.05M,1.03B,8.28,0.85,6.09%,334.02B,0.00442265255908587 +MENGNIU DAIRY,02319.HK,26.25,1.5,+6.061%,8.58M,223.15M,17.34,2.3,1.73%,103.42B,0.00797693234619361 +LI NING,02331.HK,32.95,1.5,+4.769%,22.54M,738.37M,18.8,3.16,1.58%,86.86B,0.000548246109448308 +SUNNY OPTICAL,02382.HK,54.7,1.05,+1.957%,5.62M,308.60M,22.01,2.44,0.91%,60.00B,0.00980946787029396 +BOC HONG KONG,02388.HK,21.45,0.3,+1.418%,6.53M,140.32M,8.38,0.75,6.33%,226.79B,0.00279198784516525 +CHINA LIFE,02628.HK,12.2,0.24,+2.007%,13.53M,165.07M,9.49,0.7,4.53%,90.78B,0.00566190448495522 +ENN ENERGY,02688.HK,65,1.15,+1.801%,3.06M,198.69M,11.08,1.67,4.48%,73.53B,0.0013514707359664 +ZIJIN MINING,02899.HK,11.98,0.16,+1.354%,16.20M,194.50M,13.97,3.14,1.88%,68.73B,0.0100940596177149 +MEITUAN-W,03690.HK,114.6,3.8,+3.430%,19.17M,2.19B,No Profit,4.89,0.00%,715.43B,0.0118600050276642 +HANSOH PHARMA,03692.HK,10.66,0.16,+1.524%,17.56M,187.72M,21.48,2.47,0.94%,63.25B,0.0070052473240666 +CM BANK,03968.HK,32.7,0.1,+0.307%,11.13M,363.99M,5.51,0.86,6.00%,150.12B,0.00436821343443777 +BANK OF CHINA,03988.HK,2.74,0.05,+1.859%,275.47M,754.54M,3.33,0.33,9.55%,229.13B,0.0105298417823887 +CG SERVICES,06098.HK,8.08,0.25,+3.193%,16.08M,128.87M,12.42,0.65,5.20%,27.01B,0.00478404836555252 +JD HEALTH,06618.HK,40.6,2.95,+7.835%,7.75M,312.36M,299.91,2.56,0.00%,129.12B,0.0134243199555489 +HAIER SMARTHOME,06690.HK,24.65,1.15,+4.894%,7.24M,178.37M,13.83,2.21,2.59%,70.46B,0.000651404549603483 +HAIDILAO,06862.HK,21,0.6,+2.941%,6.86M,143.79M,74.46,13.94,0.55%,117.05B,0.00190088484005443 +JD-SW,09618.HK,115.1,4,+3.600%,7.43M,852.28M,30.73,1.5,6.38%,360.24B,0.00428962133421518 +NONGFU SPRING,09633.HK,45,1.5,+3.448%,3.69M,165.62M,52.49,18.63,1.71%,226.56B,0.0115149371133421 +BIDU-SW,09888.HK,133.4,4.6,+3.571%,5.82M,772.73M,47.3,1.5,0.00%,377.37B,0.000214728364341268 +TRIP.COM-S,09961.HK,279.2,7,+2.572%,1.25M,349.59M,114.05,1.4,0.00%,176.65B,0.00259418338669419 +BABA-SW,09988.HK,85.6,2.6,+3.133%,34.61M,2.96B,21.65,1.62,0.00%,1,0.0010637787558598 +NTES-S,09999.HK,159.5,8.3,+5.489%,5.02M,797.10M,22.7,4.63,1.36%,546.99B,0.0044461470356248 diff --git a/example/main/src/main/resources/static/nasdaq100.csv b/example/main/src/main/resources/static/nasdaq100.csv new file mode 100644 index 000000000..6447cbb7a --- /dev/null +++ b/example/main/src/main/resources/static/nasdaq100.csv @@ -0,0 +1,102 @@ +#,Name,Symbol,Weighting,Last Trade,Chg,% Chg +1,Apple Inc,AAPL,11.007,174.94,0.15,(0.09%) +2,Microsoft Corp,MSFT,9.61,316.98,-0.03,(-0.01%) +3,Amazon.com Inc,AMZN,5.401,129.31,0.19,(0.14%) +4,NVIDIA Corp,NVDA,4.101,415.74,-0.36,(-0.09%) +5,Meta Platforms Inc,META,3.729,299.42,0.34,(0.11%) +6,Tesla Inc,TSLA,3.285,244.13,-0.75,(-0.31%) +7,Alphabet Inc,GOOGL,3.133,130.49,0.24,(0.18%) +8,Alphabet Inc,GOOG,3.085,131.49,0.24,(0.18%) +9,Broadcom Inc,AVGO,2.896,833.04,3.96,(0.48%) +10,Costco Wholesale Corp,COST,2.137,557.85,-0.74,(-0.13%) +11,PepsiCo Inc,PEP,2.096,174.84,-0.43,(-0.25%) +12,Adobe Inc,ADBE,2.033,511.42,-1.48,(-0.29%) +13,Cisco Systems Inc,CSCO,1.887,53.68,0.11,(0.20%) +14,Comcast Corp,CMCSA,1.633,45.30,-0.01,(-0.01%) +15,Netflix Inc,NFLX,1.478,379.89,0.08,(0.02%) +16,T-Mobile US Inc,TMUS,1.43,140.18,0.83,(0.60%) +17,Advanced Micro Devices Inc,AMD,1.348,96.09,-0.11,(-0.12%) +18,Texas Instruments Inc,TXN,1.264,161.00,0.69,(0.43%) +19,Intel Corp,INTC,1.26,34.19,0.01,(0.01%) +20,Amgen Inc,AMGN,1.251,271.18,3.48,(1.30%) +21,Intuit Inc,INTU,1.226,509.00,0.43,(0.08%) +22,Honeywell International Inc,HON,1.103,188.67,-1.12,(-0.59%) +23,QUALCOMM Inc,QCOM,1.046,107.53,-0.16,(-0.14%) +24,Applied Materials Inc,AMAT,0.982,136.32,0.15,(0.11%) +25,Booking Holdings Inc,BKNG,0.941,3,019.20,-43.30,(-1.42%) +26,Starbucks Corp,SBUX,0.926,93.80,0.12,(0.12%) +27,Intuitive Surgical Inc,ISRG,0.867,288.50,0.30,(0.10%) +28,Automatic Data Processing Inc,ADP,0.854,239.45,0.10,(0.04%) +29,Mondelez International Inc,MDLZ,0.835,71.25,0.82,(1.16%) +30,Gilead Sciences Inc,GILD,0.814,75.47,0.46,(0.61%) +31,Vertex Pharmaceuticals Inc,VRTX,0.794,353.67,4.14,(1.18%) +32,Regeneron Pharmaceuticals Inc,REGN,0.763,828.09,3.25,(0.39%) +33,Analog Devices Inc,ADI,0.752,176.82,1.34,(0.76%) +34,Lam Research Corp,LRCX,0.702,620.00,0.89,(0.14%) +35,Micron Technology Inc,MU,0.646,68.90,0.02,(0.03%) +36,Palo Alto Networks Inc,PANW,0.604,228.70,0.19,(0.08%) +37,Synopsys Inc,SNPS,0.587,447.12,0.27,(0.06%) +38,Charter Communications Inc,CHTR,0.581,441.88,-3.33,(-0.75%) +39,MercadoLibre Inc,MELI,0.562,1,275.50,-1.47,(-0.11%) +40,PayPal Holdings Inc,PYPL,0.559,57.90,0.02,(0.03%) +41,CSX Corp,CSX,0.54,31.23,0.03,(0.09%) +42,Cadence Design Systems Inc,CDNS,0.539,230.83,0.17,(0.07%) +43,KLA Corp,KLAC,0.53,456.11,4.29,(0.95%) +44,PDD Holdings Inc ADR,PDD,0.521,95.93,-0.01,(-0.01%) +45,Marriott International Inc/MD,MAR,0.505,193.90,-0.46,(-0.23%) +46,Monster Beverage Corp,MNST,0.498,54.48,-0.04,(-0.08%) +47,Airbnb Inc,ABNB,0.491,132.09,-0.11,(-0.08%) +48,O'Reilly Automotive Inc,ORLY,0.485,936.67,0.65,(0.07%) +49,Cintas Corp,CTAS,0.446,505.27,0.52,(0.10%) +50,ASML Holding NV,ASML,0.438,585.00,-2.10,(-0.36%) +51,NXP Semiconductors NV,NXPI,0.434,196.76,-0.04,(-0.02%) +52,Workday Inc,WDAY,0.414,235.55,4.73,(2.05%) +53,Lululemon Athletica Inc,LULU,0.405,386.36,-1.69,(-0.44%) +54,Keurig Dr Pepper Inc,KDP,0.404,33.25,0.13,(0.39%) +55,Fortinet Inc,FTNT,0.401,58.29,0.05,(0.09%) +56,Marvell Technology Inc,MRVL,0.388,52.38,0.08,(0.14%) +57,PACCAR Inc,PCAR,0.38,84.97,0.04,(0.04%) +58,Old Dominion Freight Line Inc,ODFL,0.38,401.01,0.35,(0.09%) +59,Autodesk Inc,ADSK,0.379,204.07,0.03,(0.01%) +60,Kraft Heinz Co/The,KHC,0.368,34.27,0.11,(0.31%) +61,Microchip Technology Inc,MCHP,0.36,77.00,-0.08,(-0.10%) +62,Copart Inc,CPRT,0.358,43.26,0.10,(0.22%) +63,American Electric Power Co Inc,AEP,0.357,79.23,0.06,(0.08%) +64,Paychex Inc,PAYX,0.355,113.01,0.06,(0.06%) +65,Exelon Corp,EXC,0.35,40.28,0.07,(0.16%) +66,ON Semiconductor Corp,ON,0.341,93.87,0.06,(0.06%) +67,AstraZeneca PLC ADR,AZN,0.339,67.35,-0.49,(-0.72%) +68,Seagen Inc,SGEN,0.336,212.18,-1.52,(-0.71%) +69,Ross Stores Inc,ROST,0.335,111.71,0.05,(0.04%) +70,Moderna Inc,MRNA,0.331,100.32,0.33,(0.33%) +71,Biogen Inc,BIIB,0.326,257.93,0.25,(0.10%) +72,Crowdstrike Holdings Inc,CRWD,0.319,162.85,0.28,(0.17%) +73,IDEXX Laboratories Inc,IDXX,0.316,439.41,3.72,(0.85%) +74,Baker Hughes Co,BKR,0.307,35.44,0.04,(0.10%) +75,Constellation Energy Corp,CEG,0.307,110.41,0.05,(0.04%) +76,Cognizant Technology Solutions Corp,CTSH,0.303,70.19,0.58,(0.83%) +77,Verisk Analytics Inc,VRSK,0.303,242.05,0.10,(0.04%) +78,Dexcom Inc,DXCM,0.3,88.30,0.80,(0.92%) +79,Trade Desk Inc/The,TTD,0.293,76.38,0.03,(0.03%) +80,Xcel Energy Inc,XEL,0.284,59.76,0.03,(0.04%) +81,Electronic Arts Inc,EA,0.279,118.38,-0.63,(-0.53%) +82,CoStar Group Inc,CSGP,0.277,78.18,0.12,(0.15%) +83,GLOBALFOUNDRIES Inc,GFS,0.273,57.21,0.38,(0.67%) +84,Fastenal Co,FAST,0.268,54.32,0.11,(0.20%) +85,Atlassian Corp,TEAM,0.253,196.01,0.55,(0.28%) +86,GE HealthCare Technologies Inc,GEHC,0.252,63.78,-0.56,(-0.86%) +87,Warner Bros Discovery Inc,WBD,0.244,11.09,-0.02,(-0.14%) +88,Diamondback Energy Inc,FANG,0.235,150.70,0.13,(0.09%) +89,Datadog Inc,DDOG,0.23,88.81,0.05,(0.06%) +90,ANSYS Inc,ANSS,0.227,300.60,-2.31,(-0.76%) +91,eBay Inc,EBAY,0.203,43.22,0.09,(0.20%) +92,Dollar Tree Inc,DLTR,0.201,104.77,0.27,(0.25%) +93,Align Technology Inc,ALGN,0.2,297.25,-1.31,(-0.44%) +94,Zscaler Inc,ZS,0.188,151.80,0.09,(0.06%) +95,Illumina Inc,ILMN,0.183,132.31,-0.13,(-0.10%) +96,Walgreens Boots Alliance Inc,WBA,0.161,21.18,0.06,(0.28%) +97,Zoom Video Communications Inc,ZM,0.151,68.57,-0.29,(-0.41%) +98,Enphase Energy Inc,ENPH,0.148,120.41,0.49,(0.41%) +99,Sirius XM Holdings Inc,SIRI,0.137,4.05,0.02,(0.50%) +100,JD.com Inc ADR,JD,0.117,30.43,0.02,(0.05%) +101,Lucid Group Inc,LCID,0.102,5.14,0.03,(0.49%) \ No newline at end of file diff --git a/example/main/src/main/resources/static/sp500.csv b/example/main/src/main/resources/static/sp500.csv new file mode 100644 index 000000000..19701b2cc --- /dev/null +++ b/example/main/src/main/resources/static/sp500.csv @@ -0,0 +1,504 @@ +#,Name,Symbol,Weighting,Price,Change,Change %, +1,Apple Inc,AAPL,6.992488,171.9,1.47,(0.86%), +2,Microsoft Corp,MSFT,6.487978,314.55,1.76,(0.56%), +3,Amazon.com Inc,AMZN,3.193379,126.25,0.27,(0.22%), +4,Nvidia Corp,NVDA,2.928461,433.11,8.43,(1.99%), +5,Alphabet Inc Cl A,GOOGL,2.162218,132.93,2.39,(1.83%), +6,Tesla Inc,TSLA,1.854311,246.56,6.06,(2.52%), +7,Alphabet Inc Cl C,GOOG,1.85251,133.81,2.35,(1.78%), +8,Meta Platforms Inc Class A,META,1.847731,305.93,8.19,(2.75%), +9,Berkshire Hathaway Inc Cl B,BRK.B,1.82184,358.67,0.89,(0.25%), +10,Exxon Mobil Corp,XOM,1.343563,118.97,-1.23,(-1.03%), +11,Unitedhealth Group Inc,UNH,1.302884,510.04,6.31,(1.25%), +12,Eli Lilly & Co,LLY,1.224046,546.65,-3.11,(-0.57%), +13,Jpmorgan Chase & Co,JPM,1.182918,148.23,2.45,(1.68%), +14,Johnson & Johnson W/d,JNJ,1.056344,156.83,-0.28,(-0.18%), +15,Visa Inc Class a Shares,V,1.029636,231.97,2.47,(1.08%), +16,Procter & Gamble Co,PG,0.969793,145.75,-1.59,(-1.08%), +17,Broadcom Inc,AVGO,0.941177,835.33,18.52,(2.27%), +18,Mastercard Inc A,MA,0.918779,400.65,5.17,(1.31%), +19,Chevron Corp,CVX,0.847353,170.55,-0.49,(-0.28%), +20,Home Depot Inc,HD,0.847289,304.35,2.53,(0.84%), +22,Abbvie Inc,ABBV,0.754672,152.14,-0.99,(-0.65%), +23,Merck & Co. Inc.,MRK,0.736434,104.2,0.26,(0.25%), +24,Costco Wholesale Corp,COST,0.697258,569.05,5.52,(0.98%), +25,Pepsico Inc,PEP,0.651768,168.92,-0.65,(-0.38%), +26,Walmart Inc,WMT,0.644449,161.87,0.15,(0.09%), +27,Adobe Inc,ADBE,0.639652,507.17,4.57,(0.91%), +28,Coca Cola Co,KO,0.60801,55.82,-0.13,(-0.23%), +29,Cisco Systems Inc,CSCO,0.605326,53.97,0.77,(1.44%), +30,Accenture Plc Cl A,ACN,0.55372,298.5,-15.9,(-5.05%), +31,Salesforce Inc,CRM,0.551342,204.46,1.73,(0.85%), +32,Thermo Fisher Scientific Inc,TMO,0.536951,503.47,5.18,(1.04%), +33,Mcdonald S Corp,MCD,0.536457,265.83,2.19,(0.83%), +34,Bank of America Corp,BAC,0.526405,27.51,0.24,(0.86%), +35,Comcast Corp Class A,CMCSA,0.512537,45.17,0.57,(1.27%), +36,Linde Plc,LIN,0.506835,375.48,3.47,(0.93%), +37,Pfizer Inc,PFE,0.506043,32.09,-0.02,(-0.05%), +38,Netflix Inc,NFLX,0.467192,377.77,0.18,(0.05%), +39,Abbott Laboratories,ABT,0.462893,97.52,1.99,(2.08%), +40,Oracle Corp,ORCL,0.459877,106.29,1.67,(1.60%), +41,Danaher Corp,DHR,0.454026,248.24,0.8,(0.32%), +42,Advanced Micro Devices,AMD,0.442473,103.74,5.67,(5.78%), +43,Wells Fargo & Co,WFC,0.417428,41.04,0.18,(0.43%), +44,Conocophillips,COP,0.411569,123.32,0.23,(0.18%), +45,Walt Disney Co,DIS,0.408438,80.35,0.45,(0.56%), +46,Intel Corp,INTC,0.404462,35.5,0.89,(2.56%), +47,Amgen Inc,AMGN,0.401904,270.91,1.93,(0.72%), +48,Texas Instruments Inc,TXN,0.400931,160.98,2.84,(1.80%), +49,Intuit Inc,INTU,0.397406,515.11,6.87,(1.35%), +50,Philip Morris International,PM,0.39143,92.66,2.34,(2.59%), +51,Caterpillar Inc,CAT,0.388444,276.34,3.63,(1.33%), +52,Verizon Communications Inc,VZ,0.380327,32.56,0.16,(0.48%), +53,Intl Business Machines Corp,IBM,0.364246,140.89,-2.28,(-1.59%), +54,Honeywell International Inc,HON,0.348317,188.68,0.8,(0.43%), +55,Union Pacific Corp,UNP,0.344419,203.88,1.48,(0.73%), +56,Qualcomm Inc,QCOM,0.340195,111.55,2.36,(2.16%), +57,Nextera Energy Inc,NEE,0.338809,57.64,-2.32,(-3.88%), +58,Lowe S Cos Inc,LOW,0.338613,209.52,2.56,(1.24%), +59,Bristol Myers Squibb Co,BMY,0.337683,58.3,0.41,(0.70%), +60,General Electric Co,GE,0.336989,112.43,1.54,(1.39%), +61,S&p Global Inc,SPGI,0.32985,369.21,6.15,(1.69%), +62,Applied Materials Inc,AMAT,0.316678,139.15,4.09,(3.03%), +63,Servicenow Inc,NOW,0.3112,552.84,6.46,(1.18%), +64,Boeing Co,BA,0.309673,193.12,-2.34,(-1.20%), +65,United Parcel Service Cl B,UPS,0.307795,154.29,1.88,(1.23%), +66,Booking Holdings Inc,BKNG,0.307126,3,86.26,3.6,(0.12%) +67,Nike Inc Cl B,NKE,0.305871,89.63,0.21,(0.24%), +68,At&t Inc,T,0.296603,14.94,0.07,(0.44%), +69,Goldman Sachs Group Inc,GS,0.296356,325.72,3.77,(1.17%), +70,Rtx Corp,RTX,0.296189,72.54,-0.34,(-0.46%), +71,Elevance Health Inc,ELV,0.292632,448.99,4.23,(0.95%), +72,Deere & Co,DE,0.291602,388.36,4,(1.04%), +73,Starbucks Corp,SBUX,0.291579,91.21,0.04,(0.04%), +74,Morgan Stanley,MS,0.29087,82.34,0.69,(0.84%), +75,Medtronic Plc,MDT,0.290688,78.77,0.55,(0.71%), +76,Prologis Inc,PLD,0.286912,112.3,1.05,(0.94%), +77,Intuitive Surgical Inc,ISRG,0.285764,296.31,4.88,(1.67%), +78,Tjx Companies Inc,TJX,0.282733,89.27,1.16,(1.32%), +79,Automatic Data Processing,ADP,0.279113,243.79,1.16,(0.48%), +80,Marsh & Mclennan Cos,MMC,0.266169,193.53,0.55,(0.29%), +81,Mondelez International Inc A,MDLZ,0.26425,69.44,-0.56,(-0.79%), +82,Gilead Sciences Inc,GILD,0.26285,75.96,0.41,(0.54%), +83,Lockheed Martin Corp,LMT,0.255775,410.4,1.68,(0.41%), +84,Blackrock Inc,BLK,0.252096,645.37,1.98,(0.31%), +85,Vertex Pharmaceuticals Inc,VRTX,0.251521,353.91,4.26,(1.22%), +86,Stryker Corp,SYK,0.250789,273.07,6.53,(2.45%), +87,Cvs Health Corp,CVS,0.250255,70.11,0.33,(0.47%), +88,Regeneron Pharmaceuticals,REGN,0.2481,835.67,3.11,(0.37%), +89,American Express Co,AXP,0.243515,150.42,0.52,(0.34%), +90,Chubb Ltd,CB,0.242706,212.92,1.29,(0.61%), +91,Analog Devices Inc,ADI,0.241943,177.01,4.2,(2.43%), +92,Schlumberger Ltd,SLB,0.241232,61.02,0.22,(0.36%), +93,Eaton Corp Plc,ETN,0.238556,216.42,2.06,(0.96%), +94,The Cigna Group,CI,0.238517,291.43,2.82,(0.98%), +95,Progressive Corp,PGR,0.229854,140.76,0.14,(0.10%), +96,Lam Research Corp,LRCX,0.228483,627.46,13.54,(2.20%), +97,Schwab (Charles) Corp,SCHW,0.225784,54.57,0.19,(0.35%), +98,Zoetis Inc,ZTS,0.224522,174.68,0,(-0.00%), +99,Citigroup Inc,C,0.217552,41.24,0.78,(1.92%), +100,Boston Scientific Corp,BSX,0.213003,53.3,1.2,(2.31%), +101,Blackstone Inc,BX,0.211158,108.88,2.33,(2.19%), +102,Eog Resources Inc,EOG,0.21104,130.56,0.75,(0.57%), +103,Becton Dickinson and Co,BDX,0.209627,262.6,3.8,(1.47%), +104,Micron Technology Inc,MU,0.208276,66.25,-1.96,(-2.87%), +105,American Tower Corp,AMT,0.207727,160.73,1.04,(0.65%), +106,Altria Group Inc,MO,0.207666,42.11,0.2,(0.47%), +107,T Mobile Us Inc,TMUS,0.20192,140.3,0.6,(0.43%), +108,Cme Group Inc,CME,0.201368,200.22,-0.14,(-0.07%), +109,Southern Co,SO,0.20116,65.04,-1.1,(-1.67%), +110,Palo Alto Networks Inc,PANW,0.198047,236.42,4.52,(1.95%), +111,Duke Energy Corp,DUK,0.193827,88.87,-1.23,(-1.36%), +112,Fiserv Inc,FI,0.192662,113.67,0.48,(0.42%), +113,Synopsys Inc,SNPS,0.189768,458.88,12.17,(2.72%), +114,Activision Blizzard Inc,ATVI,0.18717,93.71,-0.22,(-0.23%), +115,Aon Plc Class A,AON,0.186896,330.04,0.12,(0.04%), +116,Equinix Inc,EQIX,0.184757,715.84,8.74,(1.24%), +117,Illinois Tool Works,ITW,0.177501,233.17,0.77,(0.33%), +118,Air Products & Chemicals Inc,APD,0.17678,289.15,3.89,(1.36%), +119,Paypal Holdings Inc,PYPL,0.175802,58.3,0.96,(1.67%), +120,Cadence Design Sys Inc,CDNS,0.175052,235.09,4.44,(1.93%), +121,Northrop Grumman Corp,NOC,0.173654,441.3,4.06,(0.93%), +122,Intercontinental Exchange In,ICE,0.172998,109.93,1.66,(1.53%), +123,Humana Inc,HUM,0.170476,495.73,2.16,(0.44%), +124,Marathon Petroleum Corp,MPC,0.170186,155.28,2.85,(1.87%), +125,Kla Corp,KLAC,0.170079,459.61,14.05,(3.15%), +126,Fedex Corp,FDX,0.169747,266.99,4.28,(1.63%), +127,Csx Corp,CSX,0.169632,30.62,0.34,(1.14%), +128,Mckesson Corp,MCK,0.167376,445.58,1.2,(0.27%), +129,Sherwin Williams Co,SHW,0.165389,254.95,4.33,(1.73%), +130,Colgate Palmolive Co,CL,0.164,71.11,0.06,(0.08%), +131,Airbnb Inc Class A,ABNB,0.159553,137.66,3.63,(2.70%), +132,Waste Management Inc,WM,0.15893,154.17,-0.25,(-0.16%), +133,Emerson Electric Co,EMR,0.154857,97.31,0.45,(0.47%), +134,O Reilly Automotive Inc,ORLY,0.154194,918.15,3.98,(0.44%), +135,Pioneer Natural Resources Co,PXD,0.1524,234.43,0.34,(0.14%), +136,Phillips 66,PSX,0.150197,122.81,2.01,(1.66%), +137,Freeport Mcmoran Inc,FCX,0.146185,37.34,0.79,(2.17%), +138,3m Co W/d,MMM,0.144312,93.48,0.02,(0.02%), +139,Roper Technologies Inc,ROP,0.144165,486.61,-0.02,(-0.00%), +140,Valero Energy Corp,VLO,0.141937,147.59,3.64,(2.53%), +141,Nxp Semiconductors Nv,NXPI,0.141583,202.19,5.49,(2.79%), +142,Target Corp,TGT,0.141106,109.31,-0.44,(-0.40%), +143,Parker Hannifin Corp,PH,0.140358,396.29,5.18,(1.32%), +144,Us Bancorp,USB,0.139291,32.59,0.07,(0.20%), +145,General Dynamics Corp,GD,0.139193,223.44,2.44,(1.10%), +146,Chipotle Mexican Grill Inc,CMG,0.139055,1,828.59,22.51,(1.25%) +147,Hca Healthcare Inc,HCA,0.138966,251.59,4.33,(1.75%), +148,Arthur J Gallagher & Co,AJG,0.138231,231.77,1.44,(0.62%), +149,Moody S Corp,MCO,0.138162,319.07,4.56,(1.45%), +150,Amphenol Corp Cl A,APH,0.136941,84.4,2.04,(2.47%), +151,Ford Motor Co,F,0.1362,12.58,0.19,(1.49%), +152,Marriott International Cl A,MAR,0.135619,199.53,5.65,(2.92%), +153,Pnc Financial Services Group,PNC,0.135457,123.09,1.28,(1.05%), +154,Transdigm Group Inc,TDG,0.131273,860.46,8.64,(1.01%), +155,Carrier Global Corp,CARR,0.129065,56.83,1.75,(3.17%), +156,Autozone Inc,AZO,0.128857,2,556.17,15.27,(0.60%) +157,Trane Technologies Plc,TT,0.12759,207.07,7.01,(3.50%), +158,Motorola Solutions Inc,MSI,0.127284,275.18,2.2,(0.81%), +159,Arista Networks Inc,ANET,0.12715,184.23,2.63,(1.45%), +160,Norfolk Southern Corp,NSC,0.124378,197.3,1.08,(0.55%), +161,General Motors Co,GM,0.124282,33.25,0.9,(2.77%), +162,Paccar Inc,PCAR,0.123613,86.12,1.31,(1.54%), +163,Charter Communications Inc A,CHTR,0.123199,442.28,8.86,(2.04%), +164,Hess Corp,HES,0.121942,157.3,-0.74,(-0.47%), +165,Sempra,SRE,0.121909,68.15,-1.26,(-1.81%), +166,Occidental Petroleum Corp,OXY,0.121531,66.03,0.43,(0.66%), +167,American International Group,AIG,0.121272,61.73,0.72,(1.18%), +168,Autodesk Inc,ADSK,0.120711,208.03,5.75,(2.84%), +169,Edwards Lifesciences Corp,EW,0.119074,69.68,-0.43,(-0.62%), +170,Ecolab Inc,ECL,0.118911,169.5,1.63,(0.97%), +171,Public Storage,PSA,0.117206,266.58,1.6,(0.60%), +172,Microchip Technology Inc,MCHP,0.116275,78.91,2.41,(3.15%), +173,Aflac Inc,AFL,0.11627,77.65,0.62,(0.81%), +174,Cintas Corp,CTAS,0.116227,486.83,5.75,(1.19%), +175,Welltower Inc,WELL,0.116157,81.07,0.87,(1.08%), +176,Williams Cos Inc,WMB,0.115685,34.65,0.55,(1.61%), +177,Kimberly Clark Corp,KMB,0.114902,121.11,-0.55,(-0.45%), +178,Archer Daniels Midland Co,ADM,0.114307,76.74,0.38,(0.50%), +179,Msci Inc,MSCI,0.113047,518.97,7.03,(1.37%), +180,Constellation Brands Inc A,STZ,0.112869,251.62,1.03,(0.41%), +181,On Semiconductor,ON,0.111009,95.12,3.07,(3.33%), +182,Metlife Inc,MET,0.110772,63.06,0.26,(0.41%), +183,Monster Beverage Corp,MNST,0.110311,53.31,0.19,(0.35%), +184,Hilton Worldwide Holdings In,HLT,0.109054,153.24,3.88,(2.60%), +185,American Electric Power,AEP,0.108899,74.71,-1.15,(-1.51%), +186,Crown Castle Inc,CCI,0.108512,91.35,1.65,(1.83%), +187,Exelon Corp,EXC,0.107894,38.11,-0.69,(-1.78%), +188,Nucor Corp,NUE,0.107787,158.31,2.6,(1.67%), +189,Travelers Cos Inc,TRV,0.107342,167.42,-0.51,(-0.30%), +190,Dominion Energy Inc,D,0.106001,44.61,-0.86,(-1.88%), +191,Te Connectivity Ltd,TEL,0.105581,123.84,3.4,(2.82%), +192,Halliburton Co,HAL,0.105449,42.18,0.15,(0.37%), +193,Centene Corp,CNC,0.105443,69.87,0.13,(0.18%), +194,Fortinet Inc,FTNT,0.105315,59.07,0.93,(1.59%), +195,Oneok Inc,OKE,0.104854,64.86,0.35,(0.53%), +196,General Mills Inc,GIS,0.104655,63.79,-0.26,(-0.40%), +197,Copart Inc,CPRT,0.104453,43.66,0.61,(1.41%), +198,Paychex Inc,PAYX,0.104412,117.4,0.89,(0.76%), +199,Biogen Inc,BIIB,0.103916,258.95,1.43,(0.55%), +200,Truist Financial Corp,TFC,0.103679,28.15,0.18,(0.63%), +201,Ross Stores Inc,ROST,0.10361,111.18,2.26,(2.07%), +202,Johnson Controls Internation,JCI,0.103601,53.69,-0.85,(-1.55%), +203,Iqvia Holdings Inc,IQV,0.103397,200.11,-2.1,(-1.04%), +204,Capital One Financial Corp,COF,0.101688,96.63,1.14,(1.20%), +205,Baker Hughes Co,BKR,0.101425,36.62,0.37,(1.02%), +206,Idexx Laboratories Inc,IDXX,0.101263,439.37,2.51,(0.57%), +207,Corteva Inc,CTVA,0.100577,50.77,0.02,(0.05%), +208,Dow Inc,DOW,0.100258,50.87,-0.13,(-0.26%), +209,Old Dominion Freight Line,ODFL,0.100037,406.82,6.93,(1.73%), +210,Constellation Energy,CEG,0.099445,109.94,-0.81,(-0.73%), +211,Dexcom Inc,DXCM,0.099384,95.68,3.59,(3.90%), +212,Simon Property Group Inc,SPG,0.098977,108.45,0.26,(0.24%), +213,Digital Realty Trust Inc,DLR,0.098757,117.6,0.76,(0.65%), +214,Realty Income Corp,O,0.098278,49.83,0.17,(0.33%), +215,Kenvue Inc W/i,KVUE,0.097359,20.2,-0.02,(-0.12%), +216,Verisk Analytics Inc,VRSK,0.097203,241.97,2.34,(0.98%), +217,Cognizant Tech Solutions A,CTSH,0.096172,68.15,-0.05,(-0.07%), +218,P G & E Corp,PCG,0.095995,16.36,-0.09,(-0.52%), +219,Prudential Financial Inc,PRU,0.095804,94.93,0.41,(0.43%), +220,Ametek Inc,AME,0.09567,150.03,1.17,(0.79%), +221,Yum Brands Inc,YUM,0.095443,123.55,1.57,(1.29%), +222,Dupont De Nemours Inc,DD,0.094185,74.58,1.11,(1.51%), +223,Ameriprise Financial Inc,AMP,0.093691,332.11,5.16,(1.58%), +224,L3harris Technologies Inc,LHX,0.092512,173.16,-2.04,(-1.16%), +225,Fidelity National Info Serv,FIS,0.09207,56.06,0.52,(0.94%), +226,Sysco Corp,SYY,0.091968,65.99,0.78,(1.20%), +227,Moderna Inc,MRNA,0.091789,100.61,1.17,(1.18%), +228,Bank of New York Mellon Corp,BK,0.091699,42.76,0.59,(1.39%), +229,Agilent Technologies Inc,A,0.091382,111.91,1.41,(1.28%), +230,Otis Worldwide Corp,OTIS,0.091228,80.55,1.2,(1.51%), +231,Rockwell Automation Inc,ROK,0.091103,288.26,3.46,(1.21%), +232,Dr Horton Inc,DHI,0.090974,108.96,1.95,(1.82%), +233,Cummins Inc,CMI,0.090916,232.98,3.03,(1.32%), +234,Estee Lauder Companies Cl A,EL,0.090788,139.94,-0.1,(-0.07%), +235,Kinder Morgan Inc,KMI,0.090175,16.71,0.05,(0.27%), +236,Keurig Dr Pepper Inc,KDP,0.088358,31.51,-0.16,(-0.51%), +237,Fastenal Co,FAST,0.087952,55.72,0.66,(1.21%), +238,Xcel Energy Inc,XEL,0.087474,56.5,-0.71,(-1.25%), +239,Devon Energy Corp,DVN,0.087359,48.84,0,(0.01%), +240,Ww Grainger Inc,GWW,0.086956,704.07,3.96,(0.57%), +241,Costar Group Inc,CSGP,0.086756,77.1,0.75,(0.99%), +242,Cencora Inc,COR,0.086188,183.99,-1.17,(-0.63%), +243,United Rentals Inc,URI,0.085093,454.44,8.22,(1.84%), +244,Hershey Co,HSY,0.084755,201.01,-1.55,(-0.76%), +245,Arch Capital Group Ltd,ACGL,0.083799,81.62,0.54,(0.67%), +246,Ppg Industries Inc,PPG,0.083787,130.49,2.46,(1.92%), +247,Global Payments Inc,GPN,0.083671,116.72,1.47,(1.28%), +248,Consolidated Edison Inc,ED,0.083432,85.06,-1.57,(-1.81%), +249,Newmont Corp,NEM,0.082799,36.78,-0.5,(-1.34%), +250,Republic Services Inc,RSG,0.082765,145.01,0.28,(0.19%), +251,Allstate Corp,ALL,0.08254,112.77,-0.25,(-0.22%), +252,Electronic Arts Inc,EA,0.081213,119.76,1.79,(1.51%), +253,Vici Properties Inc,VICI,0.081127,29.28,0.4,(1.37%), +254,Kroger Co,KR,0.080998,44.96,0.48,(1.07%), +255,Public Service Enterprise Gp,PEG,0.080723,56.88,-1.02,(-1.75%), +256,Lennar Corp A,LEN,0.078759,113.41,1.71,(1.53%), +257,Diamondback Energy Inc,FANG,0.078498,158.01,0.78,(0.50%), +258,West Pharmaceutical Services,WST,0.077362,377.15,1.97,(0.52%), +259,Quanta Services Inc,PWR,0.077074,190.82,0.7,(0.37%), +260,Gartner Inc,IT,0.076911,347.78,-1.41,(-0.40%), +261,Aptiv Plc,APTV,0.0757,99.21,3.35,(3.50%), +262,Vulcan Materials Co,VMC,0.075604,207.6,4,(1.97%), +263,Kraft Heinz Co,KHC,0.075468,33.72,-0.31,(-0.90%), +264,Ge Healthcare Technology,GEHC,0.074734,69.81,1.53,(2.24%), +265,Cdw Corp/de,CDW,0.074375,202.53,3.84,(1.93%), +266,Fortive Corp,FTV,0.072323,74.75,1.16,(1.58%), +267,Ingersoll Rand Inc,IR,0.071683,64.52,1.25,(1.97%), +268,Ansys Inc,ANSS,0.071343,299.19,4.85,(1.65%), +269,Extra Space Storage Inc,EXR,0.071269,120.75,0.24,(0.20%), +270,Wec Energy Group Inc,WEC,0.071007,79.67,-0.91,(-1.12%), +271,Martin Marietta Materials,MLM,0.070759,418,8.05,(1.96%), +272,Edison International,EIX,0.068887,63.92,-1.38,(-2.11%), +273,American Water Works Co Inc,AWK,0.068233,123.27,-3.07,(-2.43%), +274,Warner Bros Discovery Inc,WBD,0.068207,10.89,-0.15,(-1.31%), +275,Lyondellbasell Indu Cl A,LYB,0.067294,94.86,-0.11,(-0.11%), +276,Mettler Toledo International,MTD,0.067028,1,112.26,14.48,(1.32%) +277,Avalonbay Communities Inc,AVB,0.066762,171.85,-0.6,(-0.35%), +278,Delta Air Lines Inc,DAL,0.065781,37.32,0.66,(1.79%), +279,T Rowe Price Group Inc,TROW,0.064996,104.73,1.19,(1.15%), +280,Keysight Technologies In,KEYS,0.064934,133.51,3.11,(2.38%), +281,Zimmer Biomet Holdings Inc,ZBH,0.064476,112.14,1.38,(1.24%), +282,Dollar General Corp,DG,0.064042,105.04,0.7,(0.67%), +283,Corning Inc,GLW,0.064037,30.35,0.29,(0.98%), +284,Ebay Inc,EBAY,0.063728,43.45,0.56,(1.31%), +285,Cbre Group Inc A,CBRE,0.063578,73.84,0.35,(0.48%), +286,Weyerhaeuser Co,WY,0.063312,30.4,-0.64,(-2.05%), +287,Church & Dwight Co Inc,CHD,0.062765,91.68,-0.29,(-0.31%), +288,Cardinal Health Inc,CAH,0.062583,88.18,0.14,(0.16%), +289,Hp Inc,HPQ,0.062013,25.73,0.09,(0.36%), +290,Equifax Inc,EFX,0.061821,185.4,4.68,(2.59%), +291,Tractor Supply Company,TSCO,0.061683,205.07,2.06,(1.02%), +292,Willis Towers Watson Plc,WTW,0.06168,211.96,0.35,(0.17%), +293,Hewlett Packard Enterprise,HPE,0.061499,17.7,0.63,(3.66%), +294,Fair Isaac Corp,FICO,0.061481,890.19,4.58,(0.52%), +295,Dollar Tree Inc,DLTR,0.061287,106.46,1.11,(1.05%), +296,Hartford Financial Svcs Grp,HIG,0.061236,72.24,0.53,(0.73%), +297,Resmed Inc,RMD,0.060853,149.81,1.16,(0.78%), +298,Take Two Interactive Softwre,TTWO,0.060753,139.63,1.85,(1.34%), +299,Royal Caribbean Cruises Ltd,RCL,0.060515,94.38,2.42,(2.64%), +300,Xylem Inc,XYL,0.060192,91.4,1.09,(1.20%), +301,Align Technology Inc,ALGN,0.060095,309.06,7.38,(2.45%), +302,Steris Plc,STE,0.060013,221.57,3.67,(1.69%), +303,Broadridge Financial Solutio,BR,0.059572,181.18,-0.04,(-0.02%), +304,Discover Financial Services,DFS,0.059507,86.35,1.09,(1.28%), +305,State Street Corp,STT,0.059411,67.81,1.03,(1.54%), +306,Sba Communications Corp,SBAC,0.059216,198.11,2.05,(1.05%), +307,Monolithic Power Systems Inc,MPWR,0.058699,457.69,16.51,(3.74%), +308,Illumina Inc,ILMN,0.058584,133.02,-0.28,(-0.21%), +309,Dte Energy Company,DTE,0.058057,98.82,-1.72,(-1.71%), +310,M & T Bank Corp,MTB,0.057846,126.63,2.09,(1.68%), +311,Coterra Energy Inc,CTRA,0.057589,27.48,0.34,(1.23%), +312,Eversource Energy,ES,0.057281,57.54,-1.23,(-2.09%), +313,Genuine Parts Co,GPC,0.055796,142.94,0.63,(0.45%), +314,Equity Residential,EQR,0.055712,58.67,0.23,(0.40%), +315,Entergy Corp,ETR,0.055241,92.23,-1.02,(-1.10%), +316,Dover Corp,DOV,0.055103,141.68,1.09,(0.77%), +317,Ameren Corporation,AEE,0.054981,74.6,-1.51,(-1.98%), +318,Ulta Beauty Inc,ULTA,0.054585,398.17,5.73,(1.46%), +319,Teledyne Technologies Inc,TDY,0.054228,414.36,0.92,(0.22%), +320,Nvr Inc,NVR,0.054188,6,27.42,86.42,(1.45%) +321,Targa Resources Corp,TRGP,0.05408,87.52,0.93,(1.08%), +322,Molina Healthcare Inc,MOH,0.053618,333.09,2.03,(0.61%), +323,Wabtec Corp,WAB,0.053425,108.18,1.35,(1.26%), +324,Fleetcor Technologies Inc,FLT,0.053345,260.14,1.28,(0.49%), +325,Albemarle Corp,ALB,0.053229,172.99,10.36,(6.37%), +326,Baxter International Inc,BAX,0.05272,37.54,0.21,(0.57%), +327,Raymond James Financial Inc,RJF,0.052247,101.39,1.84,(1.85%), +328,Mccormick & Co Non Vtg Shrs,MKC,0.051871,74.55,0.46,(0.63%), +329,Invitation Homes Inc,INVH,0.051153,31.73,0.03,(0.11%), +330,Firstenergy Corp,FE,0.050777,34.56,-0.69,(-1.94%), +331,Laboratory Crp of Amer Hldgs,LH,0.05072,204.23,-0.62,(-0.30%), +332,Howmet Aerospace Inc,HWM,0.050386,46.99,0.91,(1.97%), +333,Verisign Inc,VRSN,0.050215,202.93,2.46,(1.23%), +334,Ppl Corp,PPL,0.04902,23.56,-0.39,(-1.61%), +335,Iron Mountain Inc,IRM,0.047985,59.55,0.56,(0.94%), +336,Jacobs Solutions Inc,J,0.047882,136.45,0.27,(0.20%), +337,Intl Flavors & Fragrances,IFF,0.047868,67.84,0.64,(0.95%), +338,Centerpoint Energy Inc,CNP,0.047827,26.68,-0.48,(-1.75%), +339,Darden Restaurants Inc,DRI,0.047736,143.44,2.01,(1.42%), +340,Hologic Inc,HOLX,0.047358,69.99,0.75,(1.08%), +341,First Solar Inc,FSLR,0.047324,161.9,3.29,(2.07%), +342,Expeditors Intl Wash Inc,EXPD,0.046936,114.74,1.08,(0.95%), +343,Brown & Brown Inc,BRO,0.046675,71.15,0.19,(0.26%), +344,Factset Research Systems Inc,FDS,0.046601,443.66,8.47,(1.95%), +345,Fifth Third Bancorp,FITB,0.046598,25.05,0.19,(0.74%), +346,Ventas Inc,VTR,0.046351,42.18,0.77,(1.85%), +347,Marathon Oil Corp,MRO,0.046321,27.51,0.12,(0.45%), +348,Steel Dynamics Inc,STLD,0.046096,106.96,0.52,(0.48%), +349,Bunge Ltd,BG,0.046038,110.67,1.1,(1.00%), +350,Ptc Inc,PTC,0.045951,140.25,1.78,(1.28%), +351,Everest Group Ltd,EG,0.04587,381.3,-0.42,(-0.11%), +352,Cincinnati Financial Corp,CINF,0.045852,104.4,-0.3,(-0.29%), +353,Enphase Energy Inc,ENPH,0.045679,121.39,1.28,(1.07%), +354,Nasdaq Inc,NDAQ,0.04562,49.07,0.74,(1.52%), +355,Akamai Technologies Inc,AKAM,0.045578,107.75,0.79,(0.74%), +356,Cboe Global Markets Inc,CBOE,0.045525,155.28,0.51,(0.33%), +357,Cf Industries Holdings Inc,CF,0.04496,84.93,1.48,(1.78%), +358,Waters Corp,WAT,0.044936,274.46,2.12,(0.78%), +359,Pultegroup Inc,PHM,0.044848,74.85,1.65,(2.25%), +360,Tyler Technologies Inc,TYL,0.044831,387.74,2.43,(0.63%), +361,Principal Financial Group,PFG,0.044705,72.74,0.74,(1.02%), +362,Clorox Company,CLX,0.04465,128.98,-0.17,(-0.13%), +363,Southwest Airlines Co,LUV,0.044478,27.3,0.49,(1.81%), +364,Regions Financial Corp,RF,0.044397,17.16,0.22,(1.27%), +365,Garmin Ltd,GRMN,0.044336,104.65,1.42,(1.38%), +366,Atmos Energy Corp,ATO,0.044128,106.32,-0.14,(-0.13%), +367,Netapp Inc,NTAP,0.044116,76.49,1.54,(2.05%), +368,Textron Inc,TXT,0.043659,79.27,0.33,(0.41%), +369,Cooper Cos Inc,COO,0.04361,318.15,2.23,(0.71%), +370,Kellogg Co,K,0.043517,58.9,-0.22,(-0.38%), +371,Idex Corp,IEX,0.043484,210.72,3.28,(1.58%), +372,Cms Energy Corp,CMS,0.043476,52.78,-0.57,(-1.07%), +373,Skyworks Solutions Inc,SWKS,0.042974,98.55,2.25,(2.33%), +374,Alexandria Real Estate Equit,ARE,0.042466,99.48,0.59,(0.60%), +375,Hunt (Jb) Transprt Svcs Inc,JBHT,0.042319,186.54,0.95,(0.51%), +376,Las Vegas Sands Corp,LVS,0.042222,45.63,-0.53,(-1.15%), +377,Ball Corp,BALL,0.042202,48.27,0.04,(0.08%), +378,Walgreens Boots Alliance Inc,WBA,0.04215,20.97,-0.06,(-0.26%), +379,Teradyne Inc,TER,0.041494,100.04,3.56,(3.68%), +380,Mid America Apartment Comm,MAA,0.041385,128.55,0.48,(0.37%), +381,Epam Systems Inc,EPAM,0.041006,257.76,0.96,(0.37%), +382,Avery Dennison Corp,AVY,0.040961,183.42,1.39,(0.76%), +383,Omnicom Group,OMC,0.040483,74.6,1.21,(1.65%), +384,Huntington Bancshares Inc,HBAN,0.040444,10.25,0.13,(1.24%), +385,Eqt Corp,EQT,0.040251,40,0.39,(0.99%), +386,Tyson Foods Inc Cl A,TSN,0.040042,49.74,-0.37,(-0.74%), +387,Western Digital Corp,WDC,0.039814,45.5,0.94,(2.11%), +388,Northern Trust Corp,NTRS,0.039557,69.29,0.84,(1.23%), +389,Carnival Corp,CCL,0.039206,14.52,0.54,(3.88%), +390,Expedia Group Inc,EXPE,0.038585,102.75,2.5,(2.49%), +391,United Airlines Holdings Inc,UAL,0.038383,42.84,0.81,(1.94%), +392,Quest Diagnostics Inc,DGX,0.038331,123.71,0.31,(0.25%), +393,Axon Enterprise Inc,AXON,0.03828,195.69,1.04,(0.53%), +394,Packaging Corp of America,PKG,0.038236,152.79,0.9,(0.59%), +395,Revvity Inc,RVTY,0.0378,110.55,1.5,(1.38%), +396,Snap on Inc,SNA,0.037774,257.97,4,(1.58%), +397,Pool Corp,POOL,0.037475,353.56,9.86,(2.87%), +398,Essex Property Trust Inc,ESS,0.03733,210.81,0.07,(0.03%), +399,Domino S Pizza Inc,DPZ,0.037258,382.39,2.18,(0.57%), +400,Amcor Plc,AMCR,0.037101,9.09,0.06,(0.61%), +401,Best Buy Co Inc,BBY,0.037071,68.66,0.29,(0.43%), +402,Apa Corp,APA,0.03662,42.49,0.11,(0.27%), +403,Lamb Weston Holdings Inc,LW,0.036553,91.47,0.09,(0.10%), +404,Wr Berkley Corp,WRB,0.036551,65.21,0.86,(1.33%), +405,Conagra Brands Inc,CAG,0.036484,27.44,-0.1,(-0.35%), +406,Lkq Corp,LKQ,0.036449,49.51,0.72,(1.47%), +407,Jm Smucker Co,SJM,0.035767,124.48,-0.96,(-0.77%), +408,Stanley Black & Decker Inc,SWK,0.035567,83.87,0.97,(1.17%), +409,Synchrony Financial,SYF,0.035241,30.73,0.55,(1.84%), +410,Carmax Inc,KMX,0.035202,71.64,-8.05,(-10.10%), +411,Leidos Holdings Inc,LDOS,0.034943,92.2,0.21,(0.23%), +412,Seagate Technology Holdings,STX,0.034918,65.71,1.42,(2.20%), +413,Paycom Software Inc,PAYC,0.034914,259.42,2.34,(0.91%), +414,Celanese Corp,CE,0.034212,127.11,3.81,(3.09%), +415,Trimble Inc,TRMB,0.034136,52.22,3.01,(6.12%), +416,Alliant Energy Corp,LNT,0.03411,48.06,-0.49,(-1.02%), +417,Citizens Financial Group,CFG,0.033972,26.28,0.52,(2.00%), +418,International Paper Co,IP,0.033961,35.1,0.15,(0.41%), +419,Masco Corp,MAS,0.033414,54.58,1.37,(2.58%), +420,Nordson Corp,NDSN,0.033057,223.81,3.73,(1.69%), +421,Loews Corp,L,0.032942,64.16,0.36,(0.56%), +422,Evergy Inc,EVRG,0.032792,50.48,-0.58,(-1.13%), +423,Mosaic Co,MOS,0.03266,35.63,0.43,(1.22%), +424,Molson Coors Beverage Co B,TAP,0.032624,62.29,-0.12,(-0.19%), +425,Zebra Technologies Corp Cl A,ZBRA,0.03257,236.95,11.04,(4.89%), +426,Viatris Inc,VTRS,0.032115,9.8,0.21,(2.14%), +427,Live Nation Entertainment In,LYV,0.032035,83.73,2.71,(3.34%), +428,Host Hotels & Resorts Inc,HST,0.03173,16.38,0.34,(2.11%), +429,Insulet Corp,PODD,0.031493,166.19,4.49,(2.77%), +430,Match Group Inc,MTCH,0.031269,40.07,0.09,(0.23%), +431,Interpublic Group of Cos Inc,IPG,0.031184,29.12,0.39,(1.35%), +432,Hormel Foods Corp,HRL,0.030887,38.15,-0.19,(-0.48%), +433,Incyte Corp,INCY,0.03067,58.93,-0.18,(-0.30%), +434,Udr Inc,UDR,0.030252,35.67,0.28,(0.79%), +435,Jack Henry & Associates Inc,JKHY,0.030211,150.61,2.17,(1.46%), +436,Kimco Realty Corp,KIM,0.029862,17.73,0.24,(1.34%), +437,Aes Corp,AES,0.029775,15.29,-0.65,(-4.05%), +438,Bio Techne Corp,TECH,0.029742,67.67,0.1,(0.15%), +439,Pentair Plc,PNR,0.029592,65.59,0.87,(1.34%), +440,Rollins Inc,ROL,0.029276,37.64,0.2,(0.52%), +441,Mgm Resorts International,MGM,0.028601,36.76,0.27,(0.74%), +442,Ceridian Hcm Holding Inc,CDAY,0.028589,67.38,0.35,(0.52%), +443,Brown Forman Corp Class B,BF.B,0.028542,56.78,0.14,(0.25%), +444,Nisource Inc,NI,0.028365,24.84,-0.35,(-1.37%), +445,Gen Digital Inc,GEN,0.028124,17.83,-0.07,(-0.37%), +446,C.H. Robinson Worldwide Inc,CHRW,0.028048,86.31,0.02,(0.02%), +447,Camden Property Trust,CPT,0.027984,94.56,-0.32,(-0.34%), +448,Charles River Laboratories,CRL,0.027736,195.69,0.75,(0.38%), +449,Healthpeak Properties Inc,PEAK,0.027617,18.15,0.1,(0.58%), +450,Caesars Entertainment Inc,CZR,0.027217,47.52,1.54,(3.36%), +451,Regency Centers Corp,REG,0.027131,59.98,0.85,(1.43%), +452,Keycorp,KEY,0.0269,10.52,0.22,(2.09%), +453,Henry Schein Inc,HSIC,0.026715,73.88,0.62,(0.84%), +454,Globe Life Inc,GL,0.026574,110.04,0.61,(0.56%), +455,Borgwarner Inc,BWA,0.026416,40.72,0.92,(2.31%), +456,F5 Inc,FFIV,0.026087,160.33,2.74,(1.74%), +457,Qorvo Inc,QRVO,0.025849,96.39,1.83,(1.93%), +458,Teleflex Inc,TFX,0.025796,199.42,2.91,(1.48%), +459,Allegion Plc,ALLE,0.025545,104.97,1.68,(1.63%), +460,Westrock Co,WRK,0.025292,35.98,0.23,(0.64%), +461,Eastman Chemical Co,EMN,0.025003,76.99,2.35,(3.15%), +462,Wynn Resorts Ltd,WYNN,0.024938,92.21,0,(-0.00%), +463,Nrg Energy Inc,NRG,0.024681,38.55,-0.03,(-0.08%), +464,Juniper Networks Inc,JNPR,0.024655,27.92,0.42,(1.52%), +465,Pinnacle West Capital,PNW,0.02321,73.45,-0.71,(-0.95%), +466,Hasbro Inc,HAS,0.02308,65.23,0.24,(0.37%), +467,Catalent Inc,CTLT,0.023069,45.85,0.07,(0.15%), +468,American Airlines Group Inc,AAL,0.02296,13,0.39,(3.05%), +469,Fmc Corp,FMC,0.022942,66.03,0.02,(0.03%), +470,Campbell Soup Co,CPB,0.022776,41.15,-0.31,(-0.76%), +471,Smith (a.O.) Corp,AOS,0.022769,66.99,1.54,(2.35%), +472,Boston Properties Inc,BXP,0.02269,59.66,0.79,(1.34%), +473,Huntington Ingalls Industrie,HII,0.022502,204.41,1.22,(0.60%), +474,Fox Corp Class A,FOXA,0.021902,31.47,0.55,(1.76%), +475,Robert Half Inc,RHI,0.021872,73.78,0.64,(0.87%), +476,Assurant Inc,AIZ,0.021618,145.63,-0.13,(-0.09%), +477,Universal Health Services B,UHS,0.021551,127,2.8,(2.25%), +478,Etsy Inc,ETSY,0.021257,63.53,1.64,(2.65%), +479,Marketaxess Holdings Inc,MKTX,0.021132,205.89,4.11,(2.04%), +480,News Corp Class A,NWSA,0.0209,20,0.35,(1.76%), +481,Bio Rad Laboratories A,BIO,0.020548,356.1,3.63,(1.03%), +482,Bath & Body Works Inc,BBWI,0.020412,33.19,1.04,(3.23%), +483,Dentsply Sirona Inc,XRAY,0.020079,33.94,-0.17,(-0.51%), +484,Solaredge Technologies Inc,SEDG,0.020026,132.35,4.34,(3.39%), +485,Whirlpool Corp,WHR,0.019812,131.66,1.03,(0.79%), +486,Franklin Resources Inc,BEN,0.019128,24.55,0.28,(1.14%), +487,Generac Holdings Inc,GNRC,0.018958,110.73,1.84,(1.69%), +488,Norwegian Cruise Line Holdin,NCLH,0.018812,16.96,0.67,(4.08%), +489,Federal Realty Invs Trust,FRT,0.018475,91.45,1.05,(1.16%), +490,Tapestry Inc,TPR,0.01809,28.18,0.23,(0.84%), +491,Invesco Ltd,IVZ,0.017835,14.31,0.22,(1.53%), +492,Paramount Global Class B,PARA,0.017208,12.89,0.11,(0.89%), +493,Vf Corp,VFC,0.015631,16.59,-0.32,(-1.89%), +494,Comerica Inc,CMA,0.014638,41.07,1.12,(2.81%), +495,Davita Inc,DVA,0.014395,95.75,0.01,(0.01%), +496,Zions Bancorp Na,ZION,0.013918,33.96,0.79,(2.39%), +497,Ralph Lauren Corp,RL,0.013127,115.52,0.26,(0.22%), +498,Sealed Air Corp,SEE,0.012794,32.2,0.46,(1.46%), +499,Alaska Air Group Inc,ALK,0.012574,37.04,0.63,(1.73%), +500,Mohawk Industries Inc,MHK,0.011998,85.15,1.23,(1.46%), +501,Organon & Co,OGN,0.011665,16.93,0.34,(2.02%), +502,Dxc Technology Co,DXC,0.011658,20.64,0.29,(1.40%), +503,Fox Corp Class B,FOX,0.010545,29.16,0.53,(1.85%), +504,News Corp Class B,NWS,0.006575,20.75,0.36,(1.74%), diff --git a/vuu/src/main/scala/org/finos/vuu/SimulMain.scala b/example/main/src/main/scala/org/finos/vuu/SimulMain.scala similarity index 94% rename from vuu/src/main/scala/org/finos/vuu/SimulMain.scala rename to example/main/src/main/scala/org/finos/vuu/SimulMain.scala index dbc666160..f8538e78a 100644 --- a/vuu/src/main/scala/org/finos/vuu/SimulMain.scala +++ b/example/main/src/main/scala/org/finos/vuu/SimulMain.scala @@ -2,24 +2,24 @@ package org.finos.vuu import com.typesafe.config.ConfigFactory import com.typesafe.scalalogging.StrictLogging -import org.finos.vuu.core.module.authn.AuthNModule -import org.finos.vuu.core.module.metrics.MetricsModule -import org.finos.vuu.core.module.simul.SimulationModule -import org.finos.vuu.core.module.typeahead.TypeAheadModule -import org.finos.vuu.core.module.vui.VuiStateModule -import org.finos.vuu.core.{VuuSecurityOptions, VuuServer, VuuServerConfig, VuuThreadingOptions, VuuWebSocketOptions} -import org.finos.vuu.net.{AlwaysHappyLoginValidator, Authenticator, LoggedInTokenValidator} -import org.finos.vuu.net.auth.AlwaysHappyAuthenticator -import org.finos.vuu.net.http.VuuHttp2ServerOptions -import org.finos.vuu.state.{MemoryBackedVuiStateStore, VuiHeader, VuiJsonState, VuiState} import org.finos.toolbox.jmx.{JmxInfra, MetricsProvider, MetricsProviderImpl} import org.finos.toolbox.lifecycle.LifecycleContainer import org.finos.toolbox.time.{Clock, DefaultClock} +import org.finos.vuu.core._ import org.finos.vuu.core.module.TableDefContainer +import org.finos.vuu.core.module.authn.AuthNModule import org.finos.vuu.core.module.auths.PermissionModule import org.finos.vuu.core.module.basket.BasketModule import org.finos.vuu.core.module.editable.EditableModule +import org.finos.vuu.core.module.metrics.MetricsModule import org.finos.vuu.core.module.price.PriceModule +import org.finos.vuu.core.module.simul.SimulationModule +import org.finos.vuu.core.module.typeahead.TypeAheadModule +import org.finos.vuu.core.module.vui.VuiStateModule +import org.finos.vuu.net.auth.AlwaysHappyAuthenticator +import org.finos.vuu.net.http.VuuHttp2ServerOptions +import org.finos.vuu.net.{AlwaysHappyLoginValidator, Authenticator, LoggedInTokenValidator} +import org.finos.vuu.state.MemoryBackedVuiStateStore /* //to allow self signed certs diff --git a/example/order/pom.xml b/example/order/pom.xml new file mode 100644 index 000000000..ca144f61e --- /dev/null +++ b/example/order/pom.xml @@ -0,0 +1,297 @@ + + + 4.0.0 + + + org.finos.vuu + example + 0.9.36-SNAPSHOT + + + + order + + + + org.finos.vuu + vuu + 0.9.36-SNAPSHOT + + + + org.finos.vuu + permission + 0.9.36-SNAPSHOT + + + + org.finos.vuu + price + 0.9.36-SNAPSHOT + + + + org.scala-lang + scala-library + ${scala.version} + + + + org.scala-lang + scala-reflect + ${scala.version} + + + + junit + junit + 4.13.2 + test + + + + org.scalatest + scalatest_2.13 + ${scalatest.version} + test + + + org.scala-lang + scala-library + + + org.scala-lang + scala-reflect + + + + + + + + + + + sign-it + + + sign + true + + + + + + org.apache.maven.plugins + maven-gpg-plugin + 3.0.1 + + + sign-artifacts + verify + + sign + + + + --pinentry-mode + loopback + + + + + + + + + + + legal-report + + + + org.scala-tools + maven-scala-plugin + ${maven.scala.plugin} + + + **/*.scala + + + + + + + + + + src/main/java + src/test/java + + + + + org.apache.maven.plugins + maven-source-plugin + + + + compile + + jar + + + + + + + org.apache.maven.plugins + maven-release-plugin + + + + + org.apache.maven.plugins + maven-javadoc-plugin + + + attach-javadocs + + jar + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.0 + + ${maven.compiler.source} + ${maven.compiler.target} + + + + org.ow2.asm + asm + 6.2 + + + + + + + org.scala-tools + maven-scala-plugin + ${maven.scala.plugin} + + + + compile + testCompile + + + + + src/main/scala + src/test/scala + + -Xms64m + -Xmx1024m + + + + + + org.codehaus.mojo + build-helper-maven-plugin + 3.2.0 + + + generate-sources + + add-source + + + + target/generated-sources/antlr4 + + + + + + + + + + org.apache.maven.plugins + maven-jar-plugin + 3.1.2 + + + + test-jar + + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.7 + + + + + + + org.scalatest + scalatest-maven-plugin + 2.0.2 + + ${project.build.directory}/surefire-reports + . + test-reports.txt + + + + test + + test + + + + + + + + + + + org.scala-tools + maven-scala-plugin + ${maven.scala.plugin} + + ${scala.version} + + + + + + \ No newline at end of file diff --git a/example/order/src/main/java/Dummy4JavaDoc.java b/example/order/src/main/java/Dummy4JavaDoc.java new file mode 100644 index 000000000..00b8d1897 --- /dev/null +++ b/example/order/src/main/java/Dummy4JavaDoc.java @@ -0,0 +1,2 @@ +public class Dummy4JavaDoc { +} diff --git a/vuu/src/main/scala/org/finos/vuu/core/module/simul/SimulationModule.scala b/example/order/src/main/scala/org/finos/vuu/core/module/simul/SimulationModule.scala similarity index 91% rename from vuu/src/main/scala/org/finos/vuu/core/module/simul/SimulationModule.scala rename to example/order/src/main/scala/org/finos/vuu/core/module/simul/SimulationModule.scala index 7719a3e2d..2c4f66d38 100644 --- a/vuu/src/main/scala/org/finos/vuu/core/module/simul/SimulationModule.scala +++ b/example/order/src/main/scala/org/finos/vuu/core/module/simul/SimulationModule.scala @@ -1,47 +1,22 @@ package org.finos.vuu.core.module.simul import com.typesafe.scalalogging.StrictLogging +import org.finos.toolbox.lifecycle.{DefaultLifecycleEnabled, LifecycleContainer} +import org.finos.toolbox.time.Clock import org.finos.vuu.api._ import org.finos.vuu.client.messages.RequestId +import org.finos.vuu.core.module.auths.OrderPermissionChecker +import org.finos.vuu.core.module.price.PriceModule import org.finos.vuu.core.module.simul.provider._ +import org.finos.vuu.core.module.simul.service.ParentOrdersService import org.finos.vuu.core.module.{DefaultModule, ModuleFactory, TableDefContainer, ViewServerModule} import org.finos.vuu.core.table.{Columns, DataTable, TableContainer} import org.finos.vuu.net.rpc.RpcHandler import org.finos.vuu.net.{ClientSessionId, RequestContext} -import org.finos.vuu.provider.simulation.{SimulatedBigInstrumentsProvider, SimulatedPricesProvider} -import org.finos.vuu.provider.{Provider, ProviderContainer, RpcProvider} +import org.finos.vuu.provider.simulation.SimulatedBigInstrumentsProvider +import org.finos.vuu.provider.{ProviderContainer, RpcProvider} import org.finos.vuu.viewport._ -import org.finos.toolbox.lifecycle.{DefaultLifecycleEnabled, LifecycleContainer} -import org.finos.toolbox.time.Clock -import org.finos.vuu.core.module.auths.OrderPermissionChecker -import org.finos.vuu.core.module.price.PriceModule -import org.finos.vuu.core.module.simul.service.ParentOrdersService - -class PricesService(val table: DataTable, val provider: Provider) extends RpcHandler with StrictLogging { - - private val pricesProvider = provider.asInstanceOf[SimulatedPricesProvider] - def setSpeedSlow(selection: ViewPortSelection, sessionId: ClientSessionId):ViewPortAction = { - pricesProvider.setSpeed(8000) - NoAction() - } - - def setSpeedMedium(selection: ViewPortSelection, sessionId: ClientSessionId):ViewPortAction = { - pricesProvider.setSpeed(2000) - NoAction() - } - - def setSpeedFast(selection: ViewPortSelection, sessionId: ClientSessionId):ViewPortAction = { - pricesProvider.setSpeed(400) - NoAction() - } - - override def menuItems(): ViewPortMenu = ViewPortMenu("Root", - new SelectionViewPortMenuItem("Set Slow", "", this.setSpeedSlow, "SET_SPEED_SLOW"), - new SelectionViewPortMenuItem("Set Medium", "", this.setSpeedMedium, "SET_SPEED_MED"), - new SelectionViewPortMenuItem("Set Fast", "", this.setSpeedFast, "SET_SPEED_FAST") - ) -} class InstrumentsService(val table: DataTable, val providerContainer: ProviderContainer) extends RpcHandler with StrictLogging { diff --git a/vuu/src/main/scala/org/finos/vuu/core/module/simul/provider/ChildOrdersProvider.scala b/example/order/src/main/scala/org/finos/vuu/core/module/simul/provider/ChildOrdersProvider.scala similarity index 100% rename from vuu/src/main/scala/org/finos/vuu/core/module/simul/provider/ChildOrdersProvider.scala rename to example/order/src/main/scala/org/finos/vuu/core/module/simul/provider/ChildOrdersProvider.scala index 940b01b1c..475ca1fdf 100644 --- a/vuu/src/main/scala/org/finos/vuu/core/module/simul/provider/ChildOrdersProvider.scala +++ b/example/order/src/main/scala/org/finos/vuu/core/module/simul/provider/ChildOrdersProvider.scala @@ -1,9 +1,9 @@ package org.finos.vuu.core.module.simul.provider -import org.finos.vuu.core.table.{DataTable, RowWithData} -import org.finos.vuu.provider.Provider import org.finos.toolbox.lifecycle.LifecycleContainer import org.finos.toolbox.time.Clock +import org.finos.vuu.core.table.{DataTable, RowWithData} +import org.finos.vuu.provider.Provider class ChildOrdersProvider(val table: DataTable, model: ParentChildOrdersModel)(implicit clock: Clock, lifecycleContainer: LifecycleContainer) extends Provider { diff --git a/vuu/src/main/scala/org/finos/vuu/core/module/simul/provider/OrdersSimulProvider.scala b/example/order/src/main/scala/org/finos/vuu/core/module/simul/provider/OrdersSimulProvider.scala similarity index 100% rename from vuu/src/main/scala/org/finos/vuu/core/module/simul/provider/OrdersSimulProvider.scala rename to example/order/src/main/scala/org/finos/vuu/core/module/simul/provider/OrdersSimulProvider.scala index 8075f09f4..75ec1dd1c 100644 --- a/vuu/src/main/scala/org/finos/vuu/core/module/simul/provider/OrdersSimulProvider.scala +++ b/example/order/src/main/scala/org/finos/vuu/core/module/simul/provider/OrdersSimulProvider.scala @@ -1,10 +1,10 @@ package org.finos.vuu.core.module.simul.provider -import org.finos.vuu.core.table.{DataTable, RowWithData} -import org.finos.vuu.provider.Provider import org.finos.toolbox.lifecycle.LifecycleContainer import org.finos.toolbox.thread.LifeCycleRunner import org.finos.toolbox.time.Clock +import org.finos.vuu.core.table.{DataTable, RowWithData} +import org.finos.vuu.provider.Provider import java.util import java.util.Random diff --git a/vuu/src/main/scala/org/finos/vuu/core/module/simul/provider/ParentChildOrdersModel.scala b/example/order/src/main/scala/org/finos/vuu/core/module/simul/provider/ParentChildOrdersModel.scala similarity index 100% rename from vuu/src/main/scala/org/finos/vuu/core/module/simul/provider/ParentChildOrdersModel.scala rename to example/order/src/main/scala/org/finos/vuu/core/module/simul/provider/ParentChildOrdersModel.scala diff --git a/vuu/src/main/scala/org/finos/vuu/core/module/simul/provider/ParentOrdersProvider.scala b/example/order/src/main/scala/org/finos/vuu/core/module/simul/provider/ParentOrdersProvider.scala similarity index 100% rename from vuu/src/main/scala/org/finos/vuu/core/module/simul/provider/ParentOrdersProvider.scala rename to example/order/src/main/scala/org/finos/vuu/core/module/simul/provider/ParentOrdersProvider.scala index 082fd554f..9f3af7707 100644 --- a/vuu/src/main/scala/org/finos/vuu/core/module/simul/provider/ParentOrdersProvider.scala +++ b/example/order/src/main/scala/org/finos/vuu/core/module/simul/provider/ParentOrdersProvider.scala @@ -1,10 +1,10 @@ package org.finos.vuu.core.module.simul.provider -import org.finos.vuu.core.table.{DataTable, RowWithData} -import org.finos.vuu.provider.Provider import org.finos.toolbox.lifecycle.LifecycleContainer import org.finos.toolbox.thread.LifeCycleRunner import org.finos.toolbox.time.Clock +import org.finos.vuu.core.table.{DataTable, RowWithData} +import org.finos.vuu.provider.Provider class ParentOrdersProvider(val table: DataTable, val model: ParentChildOrdersModel)(implicit clock: Clock, lifecycleContainer: LifecycleContainer) extends Provider { diff --git a/vuu/src/main/scala/org/finos/vuu/core/module/simul/provider/PermissionedOrdersProvider.scala b/example/order/src/main/scala/org/finos/vuu/core/module/simul/provider/PermissionedOrdersProvider.scala similarity index 100% rename from vuu/src/main/scala/org/finos/vuu/core/module/simul/provider/PermissionedOrdersProvider.scala rename to example/order/src/main/scala/org/finos/vuu/core/module/simul/provider/PermissionedOrdersProvider.scala diff --git a/vuu/src/main/scala/org/finos/vuu/core/module/simul/service/ParentOrdersService.scala b/example/order/src/main/scala/org/finos/vuu/core/module/simul/service/ParentOrdersService.scala similarity index 95% rename from vuu/src/main/scala/org/finos/vuu/core/module/simul/service/ParentOrdersService.scala rename to example/order/src/main/scala/org/finos/vuu/core/module/simul/service/ParentOrdersService.scala index 0b775f2d2..b2ad3c11d 100644 --- a/vuu/src/main/scala/org/finos/vuu/core/module/simul/service/ParentOrdersService.scala +++ b/example/order/src/main/scala/org/finos/vuu/core/module/simul/service/ParentOrdersService.scala @@ -6,7 +6,7 @@ import org.finos.vuu.core.table.DataTable import org.finos.vuu.net.ClientSessionId import org.finos.vuu.net.rpc.RpcHandler import org.finos.vuu.provider.Provider -import org.finos.vuu.viewport.{NoAction, SelectionViewPortMenuItem, ViewPortAction, ViewPortMenu, ViewPortSelection} +import org.finos.vuu.viewport._ class ParentOrdersService(val table: DataTable, val provider: Provider) extends RpcHandler with StrictLogging { diff --git a/vuu/src/main/scala/org/finos/vuu/provider/simulation/SimulatedBigInstrumentsProvider.scala b/example/order/src/main/scala/org/finos/vuu/provider/simulation/SimulatedBigInstrumentsProvider.scala similarity index 100% rename from vuu/src/main/scala/org/finos/vuu/provider/simulation/SimulatedBigInstrumentsProvider.scala rename to example/order/src/main/scala/org/finos/vuu/provider/simulation/SimulatedBigInstrumentsProvider.scala index 53516ac55..d2929eb0f 100644 --- a/vuu/src/main/scala/org/finos/vuu/provider/simulation/SimulatedBigInstrumentsProvider.scala +++ b/example/order/src/main/scala/org/finos/vuu/provider/simulation/SimulatedBigInstrumentsProvider.scala @@ -1,12 +1,12 @@ package org.finos.vuu.provider.simulation import com.typesafe.scalalogging.StrictLogging -import org.finos.vuu.core.table.{DataTable, RowWithData} -import org.finos.vuu.provider.Provider import org.finos.toolbox.lifecycle.LifecycleContainer import org.finos.toolbox.logging.LogAtFrequency import org.finos.toolbox.thread.RunOnceLifeCycleRunner import org.finos.toolbox.time.Clock +import org.finos.vuu.core.table.{DataTable, RowWithData} +import org.finos.vuu.provider.Provider import scala.concurrent.duration.DurationInt import scala.util.Random diff --git a/vuu/src/main/scala/org/finos/vuu/provider/simulation/SimulatedInstrumentProvider.scala b/example/order/src/main/scala/org/finos/vuu/provider/simulation/SimulatedInstrumentProvider.scala similarity index 100% rename from vuu/src/main/scala/org/finos/vuu/provider/simulation/SimulatedInstrumentProvider.scala rename to example/order/src/main/scala/org/finos/vuu/provider/simulation/SimulatedInstrumentProvider.scala index f39e77168..e203d4dd2 100644 --- a/vuu/src/main/scala/org/finos/vuu/provider/simulation/SimulatedInstrumentProvider.scala +++ b/example/order/src/main/scala/org/finos/vuu/provider/simulation/SimulatedInstrumentProvider.scala @@ -1,9 +1,9 @@ package org.finos.vuu.provider.simulation import com.typesafe.scalalogging.StrictLogging +import org.finos.toolbox.time.Clock import org.finos.vuu.core.table.{DataTable, RowWithData} import org.finos.vuu.provider.Provider -import org.finos.toolbox.time.Clock class SimulatedInstrumentProvider(instruments: Array[Array[String]], table: DataTable)(implicit timeProvider: Clock) extends Provider with StrictLogging { diff --git a/vuu/src/main/scala/org/finos/vuu/provider/simulation/SimulatedPricesProvider.scala b/example/order/src/main/scala/org/finos/vuu/provider/simulation/SimulatedPricesProvider.scala similarity index 100% rename from vuu/src/main/scala/org/finos/vuu/provider/simulation/SimulatedPricesProvider.scala rename to example/order/src/main/scala/org/finos/vuu/provider/simulation/SimulatedPricesProvider.scala index fbe01b429..c7d824eda 100644 --- a/vuu/src/main/scala/org/finos/vuu/provider/simulation/SimulatedPricesProvider.scala +++ b/example/order/src/main/scala/org/finos/vuu/provider/simulation/SimulatedPricesProvider.scala @@ -1,12 +1,12 @@ package org.finos.vuu.provider.simulation import com.typesafe.scalalogging.StrictLogging -import org.finos.vuu.core.table.{DataTable, RowWithData} -import org.finos.vuu.provider.Provider import org.finos.toolbox.lifecycle.LifecycleContainer import org.finos.toolbox.logging.LogAtFrequency import org.finos.toolbox.thread.{LifeCycleRunner, RunInThread} import org.finos.toolbox.time.Clock +import org.finos.vuu.core.table.{DataTable, RowWithData} +import org.finos.vuu.provider.Provider import java.util.Random import java.util.concurrent.ConcurrentHashMap diff --git a/example/permission/pom.xml b/example/permission/pom.xml new file mode 100644 index 000000000..80fa52d78 --- /dev/null +++ b/example/permission/pom.xml @@ -0,0 +1,294 @@ + + + 4.0.0 + + + org.finos.vuu + example + 0.9.36-SNAPSHOT + + + + permission + + + + org.finos.vuu + vuu + 0.9.36-SNAPSHOT + + + + org.finos.vuu + vuu + 0.9.36-SNAPSHOT + tests + test-jar + test + + + + org.scala-lang + scala-library + ${scala.version} + + + + org.scala-lang + scala-reflect + ${scala.version} + + + + junit + junit + 4.13.2 + test + + + + org.scalatest + scalatest_2.13 + ${scalatest.version} + test + + + org.scala-lang + scala-library + + + org.scala-lang + scala-reflect + + + + + + + + + + + sign-it + + + sign + true + + + + + + org.apache.maven.plugins + maven-gpg-plugin + 3.0.1 + + + sign-artifacts + verify + + sign + + + + --pinentry-mode + loopback + + + + + + + + + + + legal-report + + + + org.scala-tools + maven-scala-plugin + ${maven.scala.plugin} + + + **/*.scala + + + + + + + + + + src/main/java + src/test/java + + + + + org.apache.maven.plugins + maven-source-plugin + + + + compile + + jar + + + + + + + org.apache.maven.plugins + maven-release-plugin + + + + + org.apache.maven.plugins + maven-javadoc-plugin + + + attach-javadocs + + jar + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.0 + + ${maven.compiler.source} + ${maven.compiler.target} + + + + org.ow2.asm + asm + 6.2 + + + + + + + org.scala-tools + maven-scala-plugin + ${maven.scala.plugin} + + + + compile + testCompile + + + + + src/main/scala + src/test/scala + + -Xms64m + -Xmx1024m + + + + + + org.codehaus.mojo + build-helper-maven-plugin + 3.2.0 + + + generate-sources + + add-source + + + + target/generated-sources/antlr4 + + + + + + + + + + org.apache.maven.plugins + maven-jar-plugin + 3.1.2 + + + + test-jar + + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.7 + + + + + + + org.scalatest + scalatest-maven-plugin + 2.0.2 + + ${project.build.directory}/surefire-reports + . + test-reports.txt + + + + test + + test + + + + + + + + + + + org.scala-tools + maven-scala-plugin + ${maven.scala.plugin} + + ${scala.version} + + + + + + \ No newline at end of file diff --git a/example/permission/src/main/java/Dummy4JavaDoc.java b/example/permission/src/main/java/Dummy4JavaDoc.java new file mode 100644 index 000000000..00b8d1897 --- /dev/null +++ b/example/permission/src/main/java/Dummy4JavaDoc.java @@ -0,0 +1,2 @@ +public class Dummy4JavaDoc { +} diff --git a/vuu/src/main/scala/org/finos/vuu/core/module/authn/AuthNModule.scala b/example/permission/src/main/scala/org/finos/vuu/core/module/authn/AuthNModule.scala similarity index 100% rename from vuu/src/main/scala/org/finos/vuu/core/module/authn/AuthNModule.scala rename to example/permission/src/main/scala/org/finos/vuu/core/module/authn/AuthNModule.scala index 0a7233b8d..2af9d7ff2 100644 --- a/vuu/src/main/scala/org/finos/vuu/core/module/authn/AuthNModule.scala +++ b/example/permission/src/main/scala/org/finos/vuu/core/module/authn/AuthNModule.scala @@ -1,9 +1,9 @@ package org.finos.vuu.core.module.authn -import org.finos.vuu.core.module.{DefaultModule, ModuleFactory, TableDefContainer, ViewServerModule} -import org.finos.vuu.net.{Authenticator, LoggedInTokenValidator} import org.finos.toolbox.lifecycle.LifecycleContainer import org.finos.toolbox.time.Clock +import org.finos.vuu.core.module.{DefaultModule, ModuleFactory, TableDefContainer, ViewServerModule} +import org.finos.vuu.net.{Authenticator, LoggedInTokenValidator} object AuthNModule extends DefaultModule { diff --git a/vuu/src/main/scala/org/finos/vuu/core/module/authn/AuthNRestService.scala b/example/permission/src/main/scala/org/finos/vuu/core/module/authn/AuthNRestService.scala similarity index 100% rename from vuu/src/main/scala/org/finos/vuu/core/module/authn/AuthNRestService.scala rename to example/permission/src/main/scala/org/finos/vuu/core/module/authn/AuthNRestService.scala index 9a3fc4575..b6c785575 100644 --- a/vuu/src/main/scala/org/finos/vuu/core/module/authn/AuthNRestService.scala +++ b/example/permission/src/main/scala/org/finos/vuu/core/module/authn/AuthNRestService.scala @@ -1,11 +1,11 @@ package org.finos.vuu.core.module.authn import com.typesafe.scalalogging.StrictLogging -import org.finos.vuu.net.{Authenticator, LoggedInTokenValidator, ServerUserPrincipal} -import org.finos.vuu.net.rest.RestService import io.vertx.core.http.Cookie import io.vertx.ext.web.RoutingContext import org.finos.toolbox.time.Clock +import org.finos.vuu.net.rest.RestService +import org.finos.vuu.net.{Authenticator, LoggedInTokenValidator, ServerUserPrincipal} import java.util.concurrent.TimeUnit import scala.util.{Failure, Success, Try} diff --git a/vuu/src/main/scala/org/finos/vuu/core/module/authn/VuuAuthHandler.scala b/example/permission/src/main/scala/org/finos/vuu/core/module/authn/VuuAuthHandler.scala similarity index 92% rename from vuu/src/main/scala/org/finos/vuu/core/module/authn/VuuAuthHandler.scala rename to example/permission/src/main/scala/org/finos/vuu/core/module/authn/VuuAuthHandler.scala index 7187ebcc2..e8b8350f2 100644 --- a/vuu/src/main/scala/org/finos/vuu/core/module/authn/VuuAuthHandler.scala +++ b/example/permission/src/main/scala/org/finos/vuu/core/module/authn/VuuAuthHandler.scala @@ -1,3 +1,5 @@ +package org.finos.vuu.core.module.authn + //package org.finos.vuu.core.module.authn // //import io.vertx.core.{AsyncResult, Handler} diff --git a/vuu/src/main/scala/org/finos/vuu/core/module/auths/OrderPermissionChecker.scala b/example/permission/src/main/scala/org/finos/vuu/core/module/auths/OrderPermissionChecker.scala similarity index 90% rename from vuu/src/main/scala/org/finos/vuu/core/module/auths/OrderPermissionChecker.scala rename to example/permission/src/main/scala/org/finos/vuu/core/module/auths/OrderPermissionChecker.scala index 4d30f79fb..42c33d4a6 100644 --- a/vuu/src/main/scala/org/finos/vuu/core/module/auths/OrderPermissionChecker.scala +++ b/example/permission/src/main/scala/org/finos/vuu/core/module/auths/OrderPermissionChecker.scala @@ -3,11 +3,9 @@ package org.finos.vuu.core.module.auths import org.finos.toolbox.lifecycle.{DefaultLifecycleEnabled, LifecycleContainer} import org.finos.toolbox.thread.LifeCycleRunner import org.finos.toolbox.time.Clock -import org.finos.vuu.core.VuuServer import org.finos.vuu.core.auths.RowPermissionChecker import org.finos.vuu.core.module.auths.PermissionModule.ColumnNames.Bitmask -import org.finos.vuu.core.sort.UserDefinedFilterAndSort -import org.finos.vuu.core.table.{DataTable, RowData, RowWithData, TableContainer} +import org.finos.vuu.core.table.{RowData, RowWithData, TableContainer} import org.finos.vuu.viewport.ViewPort class OrderPermissionChecker(val vp: ViewPort, tableContainer: TableContainer)(implicit lifecycle: LifecycleContainer, clock: Clock) extends DefaultLifecycleEnabled with RowPermissionChecker { diff --git a/vuu/src/main/scala/org/finos/vuu/core/module/auths/PermissionModule.scala b/example/permission/src/main/scala/org/finos/vuu/core/module/auths/PermissionModule.scala similarity index 100% rename from vuu/src/main/scala/org/finos/vuu/core/module/auths/PermissionModule.scala rename to example/permission/src/main/scala/org/finos/vuu/core/module/auths/PermissionModule.scala diff --git a/vuu/src/main/scala/org/finos/vuu/core/module/auths/PermissionSet.scala b/example/permission/src/main/scala/org/finos/vuu/core/module/auths/PermissionSet.scala similarity index 99% rename from vuu/src/main/scala/org/finos/vuu/core/module/auths/PermissionSet.scala rename to example/permission/src/main/scala/org/finos/vuu/core/module/auths/PermissionSet.scala index 7d82230f9..c7951617e 100644 --- a/vuu/src/main/scala/org/finos/vuu/core/module/auths/PermissionSet.scala +++ b/example/permission/src/main/scala/org/finos/vuu/core/module/auths/PermissionSet.scala @@ -29,7 +29,6 @@ object PermissionSet { roles.mkString(",") } - def toBinaryString(intRepresentation: Int): String = { val binaryString = Integer.toBinaryString(intRepresentation) padWithZeros(binaryString) diff --git a/vuu/src/main/scala/org/finos/vuu/core/module/auths/provider/PermissionsProvider.scala b/example/permission/src/main/scala/org/finos/vuu/core/module/auths/provider/PermissionsProvider.scala similarity index 100% rename from vuu/src/main/scala/org/finos/vuu/core/module/auths/provider/PermissionsProvider.scala rename to example/permission/src/main/scala/org/finos/vuu/core/module/auths/provider/PermissionsProvider.scala diff --git a/vuu/src/main/scala/org/finos/vuu/core/module/auths/service/PermissionsRpcService.scala b/example/permission/src/main/scala/org/finos/vuu/core/module/auths/service/PermissionsRpcService.scala similarity index 93% rename from vuu/src/main/scala/org/finos/vuu/core/module/auths/service/PermissionsRpcService.scala rename to example/permission/src/main/scala/org/finos/vuu/core/module/auths/service/PermissionsRpcService.scala index 583bcc78f..8ca4f71ba 100644 --- a/vuu/src/main/scala/org/finos/vuu/core/module/auths/service/PermissionsRpcService.scala +++ b/example/permission/src/main/scala/org/finos/vuu/core/module/auths/service/PermissionsRpcService.scala @@ -2,13 +2,13 @@ package org.finos.vuu.core.module.auths.service import com.typesafe.scalalogging.StrictLogging import org.finos.toolbox.time.Clock +import org.finos.vuu.core.module.auths.PermissionModule.ColumnNames._ +import org.finos.vuu.core.module.auths.PermissionSet +import org.finos.vuu.core.module.auths.PermissionSet.{AlgoCoveragePermission, HighTouchPermission, SalesTradingPermission} import org.finos.vuu.core.table.{DataTable, EmptyRowData, RowWithData} import org.finos.vuu.net.ClientSessionId import org.finos.vuu.net.rpc.RpcHandler -import org.finos.vuu.viewport.{NoAction, SelectionViewPortMenuItem, ViewPortAction, ViewPortMenu, ViewPortSelection} -import org.finos.vuu.core.module.auths.PermissionModule.ColumnNames._ -import org.finos.vuu.core.module.auths.PermissionSet -import org.finos.vuu.core.module.auths.PermissionSet.{AlgoCoveragePermission, HighTouchPermission, SalesTradingPermission, SalesTradingPermissionString} +import org.finos.vuu.viewport._ class PermissionsRpcService(val table: DataTable)(implicit clock: Clock) extends RpcHandler with StrictLogging { diff --git a/vuu/src/test/scala/org/finos/vuu/core/module/authn/AuthNServerTest.scala b/example/permission/src/test/scala/org/finos/vuu/core/module/authn/AuthNServerTest.scala similarity index 98% rename from vuu/src/test/scala/org/finos/vuu/core/module/authn/AuthNServerTest.scala rename to example/permission/src/test/scala/org/finos/vuu/core/module/authn/AuthNServerTest.scala index 1890a5f8a..bc58c0f29 100644 --- a/vuu/src/test/scala/org/finos/vuu/core/module/authn/AuthNServerTest.scala +++ b/example/permission/src/test/scala/org/finos/vuu/core/module/authn/AuthNServerTest.scala @@ -1,25 +1,25 @@ package org.finos.vuu.core.module.authn import com.typesafe.scalalogging.StrictLogging -import org.finos.vuu.core.{VuuSecurityOptions, VuuServer, VuuServerConfig, VuuWebSocketOptions} -import org.finos.vuu.core.module.vui.VuiStateModule -import org.finos.vuu.net.{Authenticator, LoggedInTokenValidator} -import org.finos.vuu.net.auth.AlwaysHappyAuthenticator -import org.finos.vuu.net.http.VuuHttp2ServerOptions -import org.finos.vuu.state.MemoryBackedVuiStateStore -import io.vertx.core.{Vertx, VertxOptions} import io.vertx.core.json.JsonObject +import io.vertx.core.{Vertx, VertxOptions} import io.vertx.ext.web.client.WebClientOptions import org.finos.toolbox.jmx.{MetricsProvider, MetricsProviderImpl} import org.finos.toolbox.lifecycle.LifecycleContainer import org.finos.toolbox.thread.Async import org.finos.toolbox.time.{Clock, DefaultClock} import org.finos.vuu.core.module.TableDefContainer +import org.finos.vuu.core.module.vui.VuiStateModule +import org.finos.vuu.core.{VuuSecurityOptions, VuuServer, VuuServerConfig, VuuWebSocketOptions} +import org.finos.vuu.net.auth.AlwaysHappyAuthenticator +import org.finos.vuu.net.http.VuuHttp2ServerOptions +import org.finos.vuu.net.{Authenticator, LoggedInTokenValidator} +import org.finos.vuu.state.MemoryBackedVuiStateStore import org.scalatest.featurespec.AnyFeatureSpec import org.scalatest.matchers.should.Matchers import java.util.concurrent.atomic.AtomicBoolean -import scala.concurrent.{Await, ExecutionContext} +import scala.concurrent.ExecutionContext class AuthNServerTest extends AnyFeatureSpec with Matchers with StrictLogging { diff --git a/example/permission/src/test/scala/org/finos/vuu/core/module/auths/PermissionFilteredViewport.scala b/example/permission/src/test/scala/org/finos/vuu/core/module/auths/PermissionFilteredViewport.scala new file mode 100644 index 000000000..47a3bc175 --- /dev/null +++ b/example/permission/src/test/scala/org/finos/vuu/core/module/auths/PermissionFilteredViewport.scala @@ -0,0 +1,158 @@ +//package org.finos.vuu.core.module.auths +// +//import org.finos.toolbox.jmx.{MetricsProvider, MetricsProviderImpl} +//import org.finos.toolbox.lifecycle.LifecycleContainer +//import org.finos.toolbox.time.{Clock, DefaultClock} +//import org.finos.vuu.api.{JoinSpec, JoinTableDef, JoinTo, LeftOuterJoin, TableDef} +//import org.finos.vuu.client.messages.RequestId +//import org.finos.vuu.core.table.{Columns, DataTable, TableContainer, ViewPortColumnCreator} +//import org.finos.vuu.net.ClientSessionId +//import org.finos.vuu.provider.{JoinTableProvider, JoinTableProviderImpl, MockProvider, ProviderContainer} +//import org.finos.vuu.util.OutboundRowPublishQueue +//import org.finos.vuu.viewport.{TestTimeStamp, ViewPortContainer, ViewPortRange} +//import org.joda.time.LocalDateTime +//import org.scalatest.featurespec.AnyFeatureSpec +//import org.scalatest.matchers.should.Matchers +//import org.scalatest.prop.Tables.Table +// +//class PermissionFilteredViewport extends AnyFeatureSpec with Matchers with ViewPortSetup { +// +// import org.finos.vuu.viewport.TestTimeStamp.EPOCH_DEFAULT +// +// def setupPermission()(implicit lifecycleContainer: LifecycleContainer, +// timeProvider: Clock, metrics: MetricsProvider): (JoinTableProvider, DataTable, DataTable, DataTable, MockProvider, MockProvider, ViewPortContainer) = { +// +// val dateTime = new LocalDateTime(2015, 7, 24, 11, 0).toDateTime.toInstant.getMillis +// +// val ordersDef = TableDef( +// name = "orderPermission", +// keyField = "orderId", +// columns = Columns.fromNames("orderId:String", "trader:String", "ric:String", "tradeTime:Long", "quantity:Double", "ownerMask:Int"), +// joinFields = "ric", "orderId" +// ).withPermissions((vp, vs) => new TestFriendlyPermissionChecker(vp)) +// +// val pricesDef = TableDef("prices", "ric", Columns.fromNames("ric:String", "bid:Double", "ask:Double", "last:Double", "open:Double", "close:Double"), "ric") +// +// val joinDef = JoinTableDef( +// name = "orderPrices", +// baseTable = ordersDef, +// joinColumns = Columns.allFrom(ordersDef) ++ Columns.allFromExcept(pricesDef, "ric"), +// joins = +// JoinTo( +// table = pricesDef, +// joinSpec = JoinSpec(left = "ric", right = "ric", LeftOuterJoin) +// ), +// joinFields = Seq() +// ) +// +// val joinProvider = JoinTableProviderImpl() +// +// val tableContainer = new TableContainer(joinProvider) +// +// val orders = tableContainer.createTable(ordersDef) +// val prices = tableContainer.createTable(pricesDef) +// val orderPrices = tableContainer.createJoinTable(joinDef) +// +// val ordersProvider = new MockProvider(orders) +// val pricesProvider = new MockProvider(prices) +// +// val providerContainer = new ProviderContainer(joinProvider) +// +// val viewPortContainer = new ViewPortContainer(tableContainer, providerContainer) +// +// (joinProvider, orders, prices, orderPrices, ordersProvider, pricesProvider, viewPortContainer) +// } +// +// +// def tickInPermissionData(ordersProvider: MockProvider, pricesProvider: MockProvider): Unit = { +// ordersProvider.tick("NYC-0001", Map("orderId" -> "NYC-0001", "trader" -> "chris", "tradeTime" -> EPOCH_DEFAULT, "quantity" -> 100, "ric" -> "VOD.L", "ownerMask" -> PermissionSet.AlgoCoveragePermission)) +// ordersProvider.tick("NYC-0002", Map("orderId" -> "NYC-0002", "trader" -> "chris", "tradeTime" -> EPOCH_DEFAULT, "quantity" -> 200, "ric" -> "VOD.L", "ownerMask" -> PermissionSet.AlgoCoveragePermission)) +// ordersProvider.tick("NYC-0003", Map("orderId" -> "NYC-0003", "trader" -> "chris", "tradeTime" -> EPOCH_DEFAULT, "quantity" -> 300, "ric" -> "VOD.L", "ownerMask" -> PermissionSet.SalesTradingPermission)) +// ordersProvider.tick("NYC-0004", Map("orderId" -> "NYC-0004", "trader" -> "chris", "tradeTime" -> EPOCH_DEFAULT, "quantity" -> 400, "ric" -> "VOD.L", "ownerMask" -> PermissionSet.SalesTradingPermission)) +// ordersProvider.tick("NYC-0005", Map("orderId" -> "NYC-0005", "trader" -> "chris", "tradeTime" -> EPOCH_DEFAULT, "quantity" -> 500, "ric" -> "VOD.L", "ownerMask" -> PermissionSet.SalesTradingPermission)) +// ordersProvider.tick("NYC-0006", Map("orderId" -> "NYC-0006", "trader" -> "steve", "tradeTime" -> EPOCH_DEFAULT, "quantity" -> 600, "ric" -> "VOD.L", "ownerMask" -> PermissionSet.HighTouchPermission)) +// ordersProvider.tick("NYC-0007", Map("orderId" -> "NYC-0007", "trader" -> "steve", "tradeTime" -> EPOCH_DEFAULT, "quantity" -> 1000, "ric" -> "BT.L", "ownerMask" -> PermissionSet.HighTouchPermission)) +// ordersProvider.tick("NYC-0008", Map("orderId" -> "NYC-0008", "trader" -> "steve", "tradeTime" -> EPOCH_DEFAULT, "quantity" -> 500, "ric" -> "BT.L", "ownerMask" -> PermissionSet.HighTouchPermission)) +// +// pricesProvider.tick("VOD.L", Map("ric" -> "VOD.L", "bid" -> 220.0, "ask" -> 222.0)) +// pricesProvider.tick("BT.L", Map("ric" -> "BT.L", "bid" -> 500.0, "ask" -> 501.0)) +// } +// +// Feature("Permissioned Vuu Port Feature") { +// +// Scenario("Check filtering table based on permissions") { +// +// implicit val clock: Clock = new DefaultClock +// implicit val lifecycle: LifecycleContainer = new LifecycleContainer +// implicit val metrics: MetricsProvider = new MetricsProviderImpl +// +// val (joinProvider, orders, _, _, ordersProvider, pricesProvider, viewPortContainer) = setupPermission() +// +// joinProvider.start() +// +// tickInPermissionData(ordersProvider, pricesProvider) +// +// joinProvider.runOnce() +// +// val queue = new OutboundRowPublishQueue() +// val session = ClientSessionId("A", "B") +// val columns = ViewPortColumnCreator.create(orders, orders.getTableDef.columns.map(_.name).toList) +// val range = ViewPortRange(0, 20) +// val viewport = viewPortContainer.create(RequestId.oneNew(), session, queue, orders, range, columns) +// +// val permissionChecker = viewport.permissionChecker().get.asInstanceOf[TestFriendlyPermissionChecker] +// permissionChecker.addRole(PermissionSet.SalesTradingPermission) +// +// runContainersOnce(viewPortContainer, joinProvider) +// +// assertVpEq(filterByVpId(combineQs(viewport), viewport)) { +// Table( +// ("orderId" ,"trader" ,"ric" ,"tradeTime","quantity","ownerMask"), +// ("NYC-0003","chris" ,"VOD.L" ,1311544800000L,300 ,1 ), +// ("NYC-0004","chris" ,"VOD.L" ,1311544800000L,400 ,1 ), +// ("NYC-0005","chris" ,"VOD.L" ,1311544800000L,500 ,1 ) +// ) +// } +// +// permissionChecker.addRole(PermissionSet.AlgoCoveragePermission) +// +// runContainersOnce(viewPortContainer, joinProvider) +// +// assertVpEq(filterByVpId(combineQs(viewport), viewport)) { +// Table( +// ("orderId" ,"trader" ,"ric" ,"tradeTime","quantity","ownerMask"), +// ("NYC-0001","chris" ,"VOD.L" ,1311544800000L,100 ,2 ), +// ("NYC-0002","chris" ,"VOD.L" ,1311544800000L,200 ,2 ), +// ("NYC-0003","chris" ,"VOD.L" ,1311544800000L,300 ,1 ), +// ("NYC-0004","chris" ,"VOD.L" ,1311544800000L,400 ,1 ), +// ("NYC-0005","chris" ,"VOD.L" ,1311544800000L,500 ,1 ) +// ) +// } +// +// permissionChecker.removeRole(PermissionSet.AlgoCoveragePermission) +// permissionChecker.removeRole(PermissionSet.SalesTradingPermission) +// +// runContainersOnce(viewPortContainer, joinProvider) +// +// assertVpEq(filterByVpId(combineQs(viewport), viewport)) { +// Table( +// ("orderId", "trader", "ric", "tradeTime", "quantity", "ownerMask"), +// ) +// } +// +// permissionChecker.addRole(PermissionSet.HighTouchPermission) +// +// runContainersOnce(viewPortContainer, joinProvider) +// +// assertVpEq(filterByVpId(combineQs(viewport), viewport)) { +// Table( +// ("orderId" ,"trader" ,"ric" ,"tradeTime","quantity","ownerMask"), +// ("NYC-0006","steve" ,"VOD.L" ,1311544800000L,600 ,4 ), +// ("NYC-0007","steve" ,"BT.L" ,1311544800000L,1000 ,4 ), +// ("NYC-0008","steve" ,"BT.L" ,1311544800000L,500 ,4 ) +// ) +// } +// +// } +// } +//} diff --git a/vuu/src/test/scala/org/finos/vuu/core/module/auths/PermissionsTest.scala b/example/permission/src/test/scala/org/finos/vuu/core/module/auths/PermissionsTest.scala similarity index 99% rename from vuu/src/test/scala/org/finos/vuu/core/module/auths/PermissionsTest.scala rename to example/permission/src/test/scala/org/finos/vuu/core/module/auths/PermissionsTest.scala index 12ddfd34e..66f3b3dab 100644 --- a/vuu/src/test/scala/org/finos/vuu/core/module/auths/PermissionsTest.scala +++ b/example/permission/src/test/scala/org/finos/vuu/core/module/auths/PermissionsTest.scala @@ -1,12 +1,11 @@ package org.finos.vuu.core.module.auths import com.typesafe.scalalogging.StrictLogging +import org.finos.vuu.core.module.auths.PermissionSet._ import org.scalatest.GivenWhenThen import org.scalatest.featurespec.AnyFeatureSpec import org.scalatest.matchers.should.Matchers -import org.finos.vuu.core.module.auths.PermissionSet._ - class PermissionsTest extends AnyFeatureSpec with Matchers with StrictLogging with GivenWhenThen { Feature("Check our example Permission Set"){ diff --git a/vuu/src/test/scala/org/finos/vuu/viewport/auths/TestFriendlyPermissionChecker.scala b/example/permission/src/test/scala/org/finos/vuu/core/module/auths/TestFriendlyPermissionChecker.scala similarity index 91% rename from vuu/src/test/scala/org/finos/vuu/viewport/auths/TestFriendlyPermissionChecker.scala rename to example/permission/src/test/scala/org/finos/vuu/core/module/auths/TestFriendlyPermissionChecker.scala index de9252159..7426bf0af 100644 --- a/vuu/src/test/scala/org/finos/vuu/viewport/auths/TestFriendlyPermissionChecker.scala +++ b/example/permission/src/test/scala/org/finos/vuu/core/module/auths/TestFriendlyPermissionChecker.scala @@ -1,8 +1,7 @@ -package org.finos.vuu.viewport.auths +package org.finos.vuu.core.module.auths import com.typesafe.scalalogging.StrictLogging import org.finos.vuu.core.auths.RowPermissionChecker -import org.finos.vuu.core.module.auths.PermissionSet import org.finos.vuu.core.table.{Column, RowData} import org.finos.vuu.viewport.ViewPort diff --git a/example/pom.xml b/example/pom.xml new file mode 100644 index 000000000..ee65b256e --- /dev/null +++ b/example/pom.xml @@ -0,0 +1,61 @@ + + + 4.0.0 + + + org.finos.vuu + vuu-parent + 0.9.36-SNAPSHOT + + + pom + + example + + + editable + main + order + permission + price + basket + + + + + + sign-it + + + sign + true + + + + + + org.apache.maven.plugins + maven-gpg-plugin + 3.0.1 + + + sign-artifacts + verify + + sign + + + + --pinentry-mode + loopback + + + + + + + + + + + \ No newline at end of file diff --git a/example/price/pom.xml b/example/price/pom.xml new file mode 100644 index 000000000..76d2577da --- /dev/null +++ b/example/price/pom.xml @@ -0,0 +1,294 @@ + + + 4.0.0 + + + org.finos.vuu + example + 0.9.36-SNAPSHOT + + + + price + + + + org.finos.vuu + vuu + 0.9.36-SNAPSHOT + + + + org.finos.vuu + vuu + 0.9.36-SNAPSHOT + tests + test-jar + test + + + + org.scala-lang + scala-library + ${scala.version} + + + + org.scala-lang + scala-reflect + ${scala.version} + + + + junit + junit + 4.13.2 + test + + + + org.scalatest + scalatest_2.13 + ${scalatest.version} + test + + + org.scala-lang + scala-library + + + org.scala-lang + scala-reflect + + + + + + + + + + + sign-it + + + sign + true + + + + + + org.apache.maven.plugins + maven-gpg-plugin + 3.0.1 + + + sign-artifacts + verify + + sign + + + + --pinentry-mode + loopback + + + + + + + + + + + legal-report + + + + org.scala-tools + maven-scala-plugin + ${maven.scala.plugin} + + + **/*.scala + + + + + + + + + + src/main/java + src/test/java + + + + + org.apache.maven.plugins + maven-source-plugin + + + + compile + + jar + + + + + + + org.apache.maven.plugins + maven-release-plugin + + + + + org.apache.maven.plugins + maven-javadoc-plugin + + + attach-javadocs + + jar + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.0 + + ${maven.compiler.source} + ${maven.compiler.target} + + + + org.ow2.asm + asm + 6.2 + + + + + + + org.scala-tools + maven-scala-plugin + ${maven.scala.plugin} + + + + compile + testCompile + + + + + src/main/scala + src/test/scala + + -Xms64m + -Xmx1024m + + + + + + org.codehaus.mojo + build-helper-maven-plugin + 3.2.0 + + + generate-sources + + add-source + + + + target/generated-sources/antlr4 + + + + + + + + + + org.apache.maven.plugins + maven-jar-plugin + 3.1.2 + + + + test-jar + + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.7 + + + + + + + org.scalatest + scalatest-maven-plugin + 2.0.2 + + ${project.build.directory}/surefire-reports + . + test-reports.txt + + + + test + + test + + + + + + + + + + + org.scala-tools + maven-scala-plugin + ${maven.scala.plugin} + + ${scala.version} + + + + + + \ No newline at end of file diff --git a/example/price/src/main/java/Dummy4JavaDoc.java b/example/price/src/main/java/Dummy4JavaDoc.java new file mode 100644 index 000000000..00b8d1897 --- /dev/null +++ b/example/price/src/main/java/Dummy4JavaDoc.java @@ -0,0 +1,2 @@ +public class Dummy4JavaDoc { +} diff --git a/vuu/src/main/scala/org/finos/vuu/core/module/price/PriceModule.scala b/example/price/src/main/scala/org/finos/vuu/core/module/price/PriceModule.scala similarity index 50% rename from vuu/src/main/scala/org/finos/vuu/core/module/price/PriceModule.scala rename to example/price/src/main/scala/org/finos/vuu/core/module/price/PriceModule.scala index a0693a425..6254f5b59 100644 --- a/vuu/src/main/scala/org/finos/vuu/core/module/price/PriceModule.scala +++ b/example/price/src/main/scala/org/finos/vuu/core/module/price/PriceModule.scala @@ -1,13 +1,44 @@ package org.finos.vuu.core.module.price +import com.typesafe.scalalogging.StrictLogging import org.finos.toolbox.lifecycle.LifecycleContainer import org.finos.toolbox.time.Clock import org.finos.vuu.api.{AutoSubscribeTableDef, ViewPortDef} import org.finos.vuu.core.module.ModuleFactory.stringToString -import org.finos.vuu.core.module.simul.PricesService import org.finos.vuu.core.module.{ModuleFactory, TableDefContainer, ViewServerModule} -import org.finos.vuu.core.table.Columns +import org.finos.vuu.core.table.{Columns, DataTable} +import org.finos.vuu.net.ClientSessionId +import org.finos.vuu.net.rpc.RpcHandler +import org.finos.vuu.provider.Provider import org.finos.vuu.provider.simulation.SimulatedPricesProvider +import org.finos.vuu.viewport._ + + +class PricesService(val table: DataTable, val provider: Provider) extends RpcHandler with StrictLogging { + + private val pricesProvider = provider.asInstanceOf[SimulatedPricesProvider] + + def setSpeedSlow(selection: ViewPortSelection, sessionId: ClientSessionId):ViewPortAction = { + pricesProvider.setSpeed(8000) + NoAction() + } + + def setSpeedMedium(selection: ViewPortSelection, sessionId: ClientSessionId):ViewPortAction = { + pricesProvider.setSpeed(2000) + NoAction() + } + + def setSpeedFast(selection: ViewPortSelection, sessionId: ClientSessionId):ViewPortAction = { + pricesProvider.setSpeed(400) + NoAction() + } + + override def menuItems(): ViewPortMenu = ViewPortMenu("Root", + new SelectionViewPortMenuItem("Set Slow", "", this.setSpeedSlow, "SET_SPEED_SLOW"), + new SelectionViewPortMenuItem("Set Medium", "", this.setSpeedMedium, "SET_SPEED_MED"), + new SelectionViewPortMenuItem("Set Fast", "", this.setSpeedFast, "SET_SPEED_FAST") + ) +} object PriceModule { diff --git a/example/price/src/main/scala/org/finos/vuu/provider/simulation/SimulatedPricesProvider.scala b/example/price/src/main/scala/org/finos/vuu/provider/simulation/SimulatedPricesProvider.scala new file mode 100644 index 000000000..c7d824eda --- /dev/null +++ b/example/price/src/main/scala/org/finos/vuu/provider/simulation/SimulatedPricesProvider.scala @@ -0,0 +1,354 @@ +package org.finos.vuu.provider.simulation + +import com.typesafe.scalalogging.StrictLogging +import org.finos.toolbox.lifecycle.LifecycleContainer +import org.finos.toolbox.logging.LogAtFrequency +import org.finos.toolbox.thread.{LifeCycleRunner, RunInThread} +import org.finos.toolbox.time.Clock +import org.finos.vuu.core.table.{DataTable, RowWithData} +import org.finos.vuu.provider.Provider + +import java.util.Random +import java.util.concurrent.ConcurrentHashMap +import scala.jdk.CollectionConverters._ + +trait SimulationMode { + def asCode: Int +} + +case class Simulation(mode: SimulationMode, beganAt: Long, endAt: Long) + +case object TakeAWalk extends SimulationMode { + override def asCode: Int = 1 +} + +case object WidenBidAsk extends SimulationMode { + override def asCode: Int = 2 +} + +case object FastTick extends SimulationMode { + override def asCode: Int = 3 +} + +case object NoOp extends SimulationMode { + override def asCode: Int = 4 +} + +case object Close extends SimulationMode { + override def asCode: Int = 5 +} + +case object Open extends SimulationMode { + override def asCode: Int = 6 +} + +object PricesFields { + final val Ric = "ric" + final val Bid = "bid" + final val Ask = "ask" + final val BidSize = "bidSize" + final val AskSize = "askSize" + final val Last = "last" + final val Close = "close" + final val Open = "open" + final val Scenario = "scenario" + final val Phase = "phase" +} + +class SimulatedPricesProvider(val table: DataTable, @volatile var maxSleep: Int = 400)(implicit val timeProvider: Clock, lifecycle: LifecycleContainer) extends Provider with StrictLogging with RunInThread { + private val currentModes = new ConcurrentHashMap[String, Simulation]() + private val states = new ConcurrentHashMap[String, Map[String, Any]]() + + private var cycleCount = 0 + + val runner = new LifeCycleRunner("pricesProvider", () => runOnce()) + + lifecycle(this).dependsOn(runner) + + val logAt = new LogAtFrequency(10_000) + + val doEvery5Mins = new LogAtFrequency(1000 * 60 * 3) + + def setSpeed(maxSpeed: Int): Unit = { + this.maxSleep = maxSpeed + } + + override def subscribe(key: String): Unit = { + //logger.info(s"Prices Subscribe Called: ${key}") + val began = timeProvider.now() + val end = began + seededRand(began, 100, 1000) + currentModes.put(key, Simulation(NoOp, began, end)) + } + + private def seededRand(seed: Long, low: Int, high: Int): Int = { + val r = new Random(seed) + r.nextInt(high - low) + low + } + + override def runOnce(): Unit = { + + val entrySet = SetHasAsScala(currentModes.entrySet()).asScala + + // if(logAt.shouldLog()){ + // logger.info("Cycle Count = " + cycleCount) + // } + + if (doEvery5Mins.shouldLog()) { + val startOfOpen = timeProvider.now() + 5_000 + logger.info("[PRICES] Moving into Closed Market...") + entrySet.foreach(me => { + closeMarket(me.getKey, startOfOpen) + }) + } + else { + entrySet.foreach(me => { + processOne(me.getKey, me.getValue) + }) + } + + cycleCount += 1 + + timeProvider.sleep(seededRand(timeProvider.now(), 10, maxSleep)) + } + + protected def closeMarket(ric: String, timeToOpen: Long): Unit = { + val newRow = getState(ric) match { + case Some(row) => mergeLeft(row, close(ric, row)) + case None => Map(f.Ric -> ric) //do nothing + } + + currentModes.put(ric, Simulation(Close, this.timeProvider.now(), timeToOpen)) + + setState(ric, newRow) + table.processUpdate(ric, RowWithData(ric, newRow), timeProvider.now()) + } + + protected def processOne(ric: String, simulation: Simulation): Unit = { + val newRow = if (simulation.endAt <= timeProvider.now()) { + if (simulation.mode.equals(Close)) { + assignSpecificSimulation(ric, Open) + } + else { + assignNewSimulation(ric) + } + } else { + simulation.mode match { + case NoOp => doNoOp(ric) + case TakeAWalk => doTakeAWalk(ric) + case WidenBidAsk => + doWidenBidAndAsk(ric) + case FastTick => doFastTick(ric) + case Close => doCloseTick(ric) + case Open => doOpenTick(ric) + } + } + + setState(ric, newRow) + + table.processUpdate(ric, RowWithData(ric, newRow), timeProvider.now()) + } + + private def getState(ric: String): Option[Map[String, Any]] = { + val theState = states.get(ric) + Option(theState) + } + + private def setState(ric: String, row: Map[String, Any]): Unit = { + states.put(ric, row) + } + + protected def doTakeAWalk(ric: String): Map[String, Any] = { + val smallInc = seededRand(timeProvider.now(), 0, 100) + + val newRow = getState(ric) match { + case Some(row) => mergeLeft(row, walkBidAndAsk(ric, row)) + case None => buildSampleRow(ric) + } + newRow + } + + val f: PricesFields.type = PricesFields + + private def close(ric: String, existing: Map[String, Any]): Map[String, Any] = { + + val price = existing.get(f.Bid) match { + case Some(bid) => bid + case None => existing.get(f.Ask) match { + case Some(ask) => ask + case None => existing.get(f.Last) match { + case Some(last) => last + case None => seededRand(timeProvider.now(), 0, 10000) + } + } + } + + Map(f.Ric -> ric, f.Close -> price, f.Open -> null, f.Scenario -> "close", f.Phase -> "X") + } + + private def walkBidAndAsk(ric: String, existing: Map[String, Any]) = { + if (!existing.contains(f.Bid)) + buildSampleRow(existing(f.Ric).asInstanceOf[String]) + else { + val bid = existing(f.Bid).asInstanceOf[Double] + val ask = existing(f.Ask).asInstanceOf[Double] + val diff = ask - bid + val inc = seededRand(timeProvider.now(), 0, 50) + val delta = (inc / 100).asInstanceOf[Double] + + Map(f.Ric -> ric, f.Bid -> (bid + delta), f.Ask -> (ask + delta), f.Scenario -> "walkBidAsk", f.Phase -> "C") + } + } + + def BidAskSize(): Map[String, Any] = { + val bidSize = seededRand(timeProvider.now(), 1, 20) * 100 + val askSize = seededRand(timeProvider.now(), 1, 20) * 100 + Map(f.BidSize -> bidSize, f.AskSize -> askSize) + } + + def BidAskSizeNull(): Map[String, Any] = { + Map(f.BidSize -> null, f.AskSize -> null) + } + + protected def mergeLeft(existing: Map[String, Any], newMap: Map[String, Any]): Map[String, Any] = { + existing ++ newMap + } + + protected def buildSampleRow(ric: String): Map[String, Any] = { + val basePrice = seededRand(timeProvider.now(), 0, 10000) + val adjusted = (basePrice / 100).asInstanceOf[Double] + val spread = seededRand(timeProvider.now(), 0, 100) + val adjustedSpread = (spread / 100).asInstanceOf[Double] + val askSize = seededRand(timeProvider.now(), 0, 1000) + val bidSize = seededRand(timeProvider.now(), 0, 2000) + + Map(f.Ric -> ric, f.Ask -> (adjusted + adjustedSpread), f.Bid -> (adjusted - adjustedSpread), f.Phase -> "C") ++ BidAskSize() + } + + final val MaxSpread = 100 + + protected def doWidenBidAndAsk(ric: String): Map[String, Any] = { + if (!states.get(ric).contains(ric)) { + seedStartValues(ric) + } else { + val spread = seededRand(timeProvider.now(), 1, 80) + getState(ric) match { + case Some(state) => + val bid = state(f.Bid).asInstanceOf[Double] + val ask = state(f.Ask).asInstanceOf[Double] + val spread = ask - bid + val activeSpread = if (spread > MaxSpread) + 0.0 + else + spread + + val newBid = bid - activeSpread + val newAsk = ask + activeSpread + + Map(f.Ric -> ric, f.Ask -> newAsk, f.Bid -> newBid, f.Scenario -> "widenBidAndAsk", f.Phase -> "C") ++ BidAskSize() + case None => throw new Exception("shouldn't get here") + } + } + } + + protected def doFastTick(ric: String): Map[String, Any] = { + + if (!states.get(ric).contains(f.Bid)) + seedStartValues(ric) + else { + val bidAdjust = seededRand(timeProvider.now(), 0, 10) + val askAdjust = seededRand(timeProvider.now(), 0, 20) + val bid = states.get(ric)(f.Bid).asInstanceOf[Double] + bidAdjust + val ask = states.get(ric)(f.Ask).asInstanceOf[Double] + askAdjust + val last = states.get(ric)(f.Ask).asInstanceOf[Double] + (askAdjust / 2) + Map(f.Ric -> ric, f.Ask -> ask, f.Bid -> bid, f.Scenario -> "fastTick", f.Last -> last, f.Phase -> "C") ++ BidAskSize() + } + } + + protected def doOpenTick(ric: String): Map[String, Any] = { + + if (!states.get(ric).contains(f.Bid)) + seedStartValues(ric) + else { + val bidAdjust = seededRand(timeProvider.now(), 0, 10) + val askAdjust = seededRand(timeProvider.now(), 0, 20) + val bid = states.get(ric)(f.Bid).asInstanceOf[Double] + bidAdjust + val ask = states.get(ric)(f.Ask).asInstanceOf[Double] + askAdjust + val open = states.get(ric)(f.Ask).asInstanceOf[Double] + (askAdjust / 2) + Map(f.Ric -> ric, f.Scenario -> "open", f.Open -> open, f.Phase -> "O") ++ BidAskSize() + } + } + + protected def doCloseTick(ric: String): Map[String, Any] = { + + if (!states.get(ric).contains(f.Bid)) + seedStartValues(ric) + else { + val bidAdjust = seededRand(timeProvider.now(), 0, 10) + val askAdjust = seededRand(timeProvider.now(), 0, 20) + val bid = states.get(ric)(f.Bid).asInstanceOf[Double] + bidAdjust + val ask = states.get(ric)(f.Ask).asInstanceOf[Double] + askAdjust + val open = states.get(ric)(f.Ask).asInstanceOf[Double] + (askAdjust / 2) + Map(f.Ric -> ric, f.Scenario -> "close", f.Phase -> "X") ++ BidAskSizeNull() + } + } + + protected def seedStartValues(ric: String): Map[String, Any] = { + val bid: Double = seededRand(timeProvider.now(), 0, 1000) + val ask: Double = bid + (bid / 100) + val bidSize = seededRand(timeProvider.now(), 0, 1000) + val askSize = seededRand(timeProvider.now(), 0, 1000) + Map(f.Ric -> ric, f.Ask -> ask, f.Bid -> bid, f.Phase -> "C") ++ BidAskSize() + } + + protected def doNoOp(ric: String): Map[String, Any] = { + getState(ric) match { + case Some(row) => mergeLeft(row, Map[String, Any](f.Scenario -> "noop")) + case None => buildSampleRow(ric) + } + } + + protected def assignNewSimulation(ric: String): Map[String, Any] = { + val strategy = seededRand(timeProvider.now(), 1, 4) + val impl = strategy match { + case 1 => TakeAWalk + case 2 => WidenBidAsk + case 3 => FastTick + case 4 => NoOp + } + + val begin = timeProvider.now() + val end = seededRand(begin, 10, 10000) + + currentModes.put(ric, Simulation(impl, begin, begin + end)) + + val existing = states.get(ric) + if (existing == null) + buildSampleRow(ric) + else + existing + } + + protected def assignSpecificSimulation(ric: String, impl: SimulationMode): Map[String, Any] = { + + val begin = timeProvider.now() + val end = seededRand(begin, 9_000, 10_000) + + currentModes.put(ric, Simulation(impl, begin, begin + end)) + + val existing = states.get(ric) + if (existing == null) + buildSampleRow(ric) + else + existing + } + + override def doStop(): Unit = {} + + override def doStart(): Unit = {} + + override def doInitialize(): Unit = {} + + override def doDestroy(): Unit = {} + + override val lifecycleId: String = "simulationPrices" +} diff --git a/vuu/src/test/scala/org/finos/vuu/provider/simulation/SimulatedPricesProviderTest.scala b/example/price/src/test/scala/org/finos/vuu/provider/simulation/SimulatedPricesProviderTest.scala similarity index 95% rename from vuu/src/test/scala/org/finos/vuu/provider/simulation/SimulatedPricesProviderTest.scala rename to example/price/src/test/scala/org/finos/vuu/provider/simulation/SimulatedPricesProviderTest.scala index 0143e9fb3..0cada0f1f 100644 --- a/vuu/src/test/scala/org/finos/vuu/provider/simulation/SimulatedPricesProviderTest.scala +++ b/example/price/src/test/scala/org/finos/vuu/provider/simulation/SimulatedPricesProviderTest.scala @@ -1,15 +1,15 @@ package org.finos.vuu.provider.simulation -import org.finos.vuu.api.TableDef -import org.finos.vuu.core.table.{Columns, SimpleDataTable, ViewPortColumnCreator} -import org.finos.vuu.provider.TestFriendlyJoinTableProvider import org.finos.toolbox.jmx.{MetricsProvider, MetricsProviderImpl} import org.finos.toolbox.lifecycle.LifecycleContainer import org.finos.toolbox.text.AsciiUtil -import org.finos.toolbox.time.{Clock, TestFriendlyClock} +import org.finos.toolbox.time.TestFriendlyClock +import org.finos.vuu.api.TableDef +import org.finos.vuu.core.table.{Columns, SimpleDataTable, ViewPortColumnCreator} import org.scalatest.featurespec.AnyFeatureSpec import org.scalatest.matchers.should.Matchers + class SimulatedPricesProviderTest extends AnyFeatureSpec with Matchers { final val TEST_TIME = 1450770869442L diff --git a/example/price/src/test/scala/org/finos/vuu/provider/simulation/TestFriendlyJoinTableProvider.scala b/example/price/src/test/scala/org/finos/vuu/provider/simulation/TestFriendlyJoinTableProvider.scala new file mode 100644 index 000000000..77769a463 --- /dev/null +++ b/example/price/src/test/scala/org/finos/vuu/provider/simulation/TestFriendlyJoinTableProvider.scala @@ -0,0 +1,21 @@ +package org.finos.vuu.provider.simulation + +import org.finos.vuu.core.table.{DataTable, JoinTableUpdate} +import org.finos.vuu.provider.JoinTableProvider + +import java.util + +class TestFriendlyJoinTableProvider extends JoinTableProvider { + override def hasJoins(tableName: String): Boolean = {false} + override def sendEvent(tableName: String, ev: util.HashMap[String, Any]): Unit = {} + override def addJoinTable(join: DataTable): Unit = {} + override def runOnce(): Unit = {} + override def start(): Unit = ??? + + override def doStop(): Unit = ??? + override def doStart(): Unit = ??? + override def doInitialize(): Unit = ??? + override def doDestroy(): Unit = ??? + override val lifecycleId: String = "testFriendlyJoinProvider" + override def drainQueue_ForTesting(): (Int, util.ArrayList[JoinTableUpdate]) = ??? +} diff --git a/pom.xml b/pom.xml index 31a023435..0625fbcf6 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ 4.0.0 org.finos.vuu vuu-parent - 0.5.09-SNAPSHOT + 0.9.36-SNAPSHOT vuu-parent Vuu - A View Server in Scala and React https://github.com/finos/vuu @@ -84,6 +84,7 @@ vuu-ui layout-server benchmark + example diff --git a/toolbox/pom.xml b/toolbox/pom.xml index 570505e93..82c59c8cc 100644 --- a/toolbox/pom.xml +++ b/toolbox/pom.xml @@ -4,7 +4,7 @@ org.finos.vuu vuu-parent - 0.5.09-SNAPSHOT + 0.9.36-SNAPSHOT toolbox diff --git a/vuu-ui/packages/vuu-data-react/src/hooks/useVuuMenuActions.ts b/vuu-ui/packages/vuu-data-react/src/hooks/useVuuMenuActions.ts index 23b750484..81d4c7f6c 100644 --- a/vuu-ui/packages/vuu-data-react/src/hooks/useVuuMenuActions.ts +++ b/vuu-ui/packages/vuu-data-react/src/hooks/useVuuMenuActions.ts @@ -1,12 +1,7 @@ import { DataSource, - DataSourceMenusMessage, DataSourceVisualLinkCreatedMessage, - DataSourceVisualLinkRemovedMessage, - DataSourceVisualLinksMessage, MenuRpcResponse, - VuuFeatureInvocationMessage, - VuuFeatureMessage, VuuUIMessageInRPCEditReject, VuuUIMessageInRPCEditResponse, } from "@finos/vuu-data"; @@ -16,8 +11,7 @@ import { MenuActionHandler, MenuBuilder, } from "@finos/vuu-data-types"; -import { GridAction } from "@finos/vuu-datagrid-types"; -import { getFilterPredicate } from "@finos/vuu-filter-parser"; +import {getFilterPredicate} from "@finos/vuu-filter-parser"; import { ClientToServerMenuCellRPC, ClientToServerMenuRowRPC, @@ -34,8 +28,8 @@ import { isGroupMenuItemDescriptor, metadataKeys, } from "@finos/vuu-utils"; -import type { MenuActionClosePopup } from "@finos/vuu-popups"; -import { useCallback } from "react"; +import type {MenuActionClosePopup} from "@finos/vuu-popups"; +import {useCallback} from "react"; export const addRowsFromInstruments = "addRowsFromInstruments"; @@ -44,12 +38,13 @@ export interface VuuCellMenuItem extends VuuMenuItem { field: string; value: VuuRowDataItemType; } + export interface VuuRowMenuItem extends VuuMenuItem { rowKey: string; row: { [key: string]: VuuRowDataItemType }; } -const { KEY } = metadataKeys; +const {KEY} = metadataKeys; const NO_CONFIG: MenuActionConfig = {}; @@ -111,7 +106,7 @@ const gridRowMeetsFilterCriteria = ( const getMenuRpcRequest = ( options: VuuMenuItem ): Omit => { - const { rpcName } = options; + const {rpcName} = options; if (isCellMenu(options)) { return { field: options.field, @@ -185,11 +180,11 @@ export type VuuServerMenuOptions = { columnMap: ColumnMap; columnName: string; row: DataSourceRow; - selectedRowsCount: number; + selectedRows: DataSourceRow[]; viewport: string; }; -const hasFilter = ({ filter }: VuuMenuItem) => +const hasFilter = ({filter}: VuuMenuItem) => typeof filter === "string" && filter.length > 0; const getMenuItemOptions = ( @@ -266,12 +261,12 @@ const buildMenuDescriptor = ( }; } else { const children = menu.menus - .map((childMenu) => - buildMenuDescriptor(childMenu, tableLocation, options) - ) - .filter( - (childMenu) => childMenu !== undefined - ) as ContextMenuItemDescriptor[]; + .map((childMenu) => + buildMenuDescriptor(childMenu, tableLocation, options) + ) + .filter( + (childMenu) => childMenu !== undefined + ) as ContextMenuItemDescriptor[]; if (children.length > 0) { return { label: menu.name, @@ -283,20 +278,20 @@ const buildMenuDescriptor = ( }; export const useVuuMenuActions = ({ - clientSideMenuActionHandler, - dataSource, - menuActionConfig = NO_CONFIG, - onRpcResponse, -}: VuuMenuActionHookProps): ViewServerHookResult => { + clientSideMenuActionHandler, + dataSource, + menuActionConfig = NO_CONFIG, + onRpcResponse, + }: VuuMenuActionHookProps): ViewServerHookResult => { const buildViewserverMenuOptions: MenuBuilder = useCallback( (location, options) => { - const { links, menu } = dataSource; - const { visualLink } = menuActionConfig; + const {links, menu} = dataSource; + const {visualLink} = menuActionConfig; const descriptors: ContextMenuItemDescriptor[] = []; if (location === "grid" && links && !visualLink) { links.forEach((linkDescriptor: LinkDescriptorWithLabel) => { - const { link, label: linkLabel } = linkDescriptor; + const {link, label: linkLabel} = linkDescriptor; const label = linkLabel ? linkLabel : link.toTable; descriptors.push({ label: `Link to ${label}`, @@ -325,7 +320,7 @@ export const useVuuMenuActions = ({ ); const handleMenuAction = useCallback( - ({ menuId, options }: MenuActionClosePopup) => { + ({menuId, options}: MenuActionClosePopup) => { if (clientSideMenuActionHandler?.(menuId, options)) { return true; } else if (menuId === "MENU_RPC_CALL") { diff --git a/vuu-ui/packages/vuu-data-test/src/TickingArrayDataSource.ts b/vuu-ui/packages/vuu-data-test/src/TickingArrayDataSource.ts index efec2dc88..cd47eda97 100644 --- a/vuu-ui/packages/vuu-data-test/src/TickingArrayDataSource.ts +++ b/vuu-ui/packages/vuu-data-test/src/TickingArrayDataSource.ts @@ -7,10 +7,6 @@ import { VuuUIMessageInRPCEditReject, VuuUIMessageInRPCEditResponse, } from "@finos/vuu-data"; -import { - UpdateGenerator, - UpdateHandler, -} from "@finos/vuu-data-test/src/rowUpdates"; import { DataSourceRow } from "@finos/vuu-data-types"; import { ClientToServerEditRpc, @@ -19,6 +15,7 @@ import { VuuRange, VuuRowDataItemType, } from "@finos/vuu-protocol-types"; +import { UpdateGenerator, UpdateHandler } from "./rowUpdates"; import { Table } from "./Table"; export type RpcService = { @@ -38,6 +35,7 @@ export interface TickingArrayDataSourceConstructorProps export class TickingArrayDataSource extends ArrayDataSource { #rpcServices: RpcService[] | undefined; #updateGenerator: UpdateGenerator | undefined; + constructor({ data, rpcServices, @@ -87,7 +85,7 @@ export class TickingArrayDataSource extends ArrayDataSource { switch (updateType) { case "U": { const [rowIndex, ...updates] = updateRecord; - const row = data[rowIndex].slice() as DataSourceRow; + const row = data[rowIndex as number].slice() as DataSourceRow; if (row) { for (let i = 0; i < updates.length; i += 2) { const colIdx = updates[i] as number; diff --git a/vuu-ui/packages/vuu-data-test/src/basket/basket-module.ts b/vuu-ui/packages/vuu-data-test/src/basket/basket-module.ts index 6feec1009..4c06d6bb5 100644 --- a/vuu-ui/packages/vuu-data-test/src/basket/basket-module.ts +++ b/vuu-ui/packages/vuu-data-test/src/basket/basket-module.ts @@ -7,7 +7,7 @@ import ftse from "./reference-data/ftse100"; import nasdaq from "./reference-data/nasdaq100"; import sp500 from "./reference-data/sp500"; import hsi from "./reference-data/hsi"; -import { VuuMenu } from "@finos/vuu-protocol-types"; +import { VuuMenu, VuuRowDataItemType } from "@finos/vuu-protocol-types"; import { Table } from "../Table"; // This is a 'local' columnMap @@ -21,7 +21,6 @@ const buildDataColumnMap = (tableName: BasketsTableName) => ); //--------------- -// export const BasketColumnMap = buildColumnMap("basket"); const { KEY } = metadataKeys; @@ -116,18 +115,18 @@ function createTradingBasket(basketId: string, basketName: string) { ); constituents.forEach(([, , description, , ric, , , quantity, weighting]) => { - const algo = undefined; + const algo = ""; const algoParams = ""; const limitPrice = 95; const notionalLocal = 0; const notionalUsd = 0; const pctFilled = 0; const priceSpread = 0; - const priceStrategyId = undefined; - const side = "buy"; + const priceStrategyId = ""; + const side = "BUY"; const venue = "venue"; - const basketTradingConstituentRow = [ + const basketTradingConstituentRow: VuuRowDataItemType[] = [ algo, algoParams, basketId, @@ -157,6 +156,7 @@ function createTradingBasket(basketId: string, basketName: string) { const open = 0; const phase = "market"; const scenario = "scenario"; + const status = "on market"; const basketTradingConstituentJoinRow = [ algo, @@ -183,6 +183,7 @@ function createTradingBasket(basketId: string, basketName: string) { ric, scenario, side, + status, venue, weighting, ]; @@ -201,7 +202,19 @@ async function createNewBasket(rpcRequest: any) { //------------------- -const tables: Record = { +const tableMaps: Record = { + algoType: buildDataColumnMap("algoType"), + basket: buildDataColumnMap("basket"), + basketTrading: buildDataColumnMap("basketTrading"), + basketTradingConstituent: buildDataColumnMap("basketTradingConstituent"), + basketConstituent: buildDataColumnMap("basketConstituent"), + basketTradingConstituentJoin: buildDataColumnMap( + "basketTradingConstituentJoin" + ), + priceStrategyType: buildDataColumnMap("priceStrategyType"), +}; + +export const tables: Record = { algoType: new Table(schemas.algoType, [ ["Sniper", 0], ["Dark Liquidity", 1], @@ -277,10 +290,11 @@ const createDataSource = (tableName: BasketsTableName) => { const { key } = schemas[tableName]; return new TickingArrayDataSource({ columnDescriptors, + dataMap: tableMaps[tableName], keyColumn: key, - table: tables[tableName], menu: menus[tableName], rpcServices: services[tableName], + table: tables[tableName], // updateGenerator: createUpdateGenerator?.(), }); }; diff --git a/vuu-ui/packages/vuu-data-test/src/basket/basket-schemas.ts b/vuu-ui/packages/vuu-data-test/src/basket/basket-schemas.ts index 6141d59d6..a22887943 100644 --- a/vuu-ui/packages/vuu-data-test/src/basket/basket-schemas.ts +++ b/vuu-ui/packages/vuu-data-test/src/basket/basket-schemas.ts @@ -53,6 +53,7 @@ export const schemas: Readonly< { name: "filledPct", serverDataType: "double" }, { name: "fxRateToUsd", serverDataType: "double" }, { name: "instanceId", serverDataType: "string" }, + { name: "side", serverDataType: "string" }, { name: "status", serverDataType: "string" }, { name: "totalNotional", serverDataType: "double" }, { name: "totalNotionalUsd", serverDataType: "double" }, @@ -78,6 +79,7 @@ export const schemas: Readonly< { name: "quantity", serverDataType: "long" }, { name: "ric", serverDataType: "string" }, { name: "side", serverDataType: "string" }, + { name: "status", serverDataType: "string" }, { name: "venue", serverDataType: "string" }, { name: "weighting", serverDataType: "double" }, ], @@ -111,6 +113,7 @@ export const schemas: Readonly< { name: "ric", serverDataType: "string" }, { name: "scenario", serverDataType: "string" }, { name: "side", serverDataType: "string" }, + { name: "status", serverDataType: "string" }, { name: "venue", serverDataType: "string" }, { name: "weighting", serverDataType: "double" }, ], diff --git a/vuu-ui/packages/vuu-data-test/src/basket/data-generators/index.ts b/vuu-ui/packages/vuu-data-test/src/basket/data-generators/index.ts index fb63f576d..5933c46ae 100644 --- a/vuu-ui/packages/vuu-data-test/src/basket/data-generators/index.ts +++ b/vuu-ui/packages/vuu-data-test/src/basket/data-generators/index.ts @@ -5,11 +5,14 @@ import basketConstituentGenerators from "./basketConstituent-generator"; import basketTradingGenerators from "./basketTrading-generator"; import basketTradingConstituentGenerators from "./basketTradingConstituent-generator"; -const generators: Record = { +const generators: Record = { + algoType: undefined, basket: basketGenerators, basketConstituent: basketConstituentGenerators, basketTrading: basketTradingGenerators, basketTradingConstituent: basketTradingConstituentGenerators, + basketTradingConstituentJoin: basketTradingConstituentGenerators, + priceStrategyType: undefined, }; export default generators; diff --git a/vuu-ui/packages/vuu-data-test/src/simul/OrderUpdateGenerator.ts b/vuu-ui/packages/vuu-data-test/src/simul/OrderUpdateGenerator.ts index 5dfa16b9d..84d8f79b5 100644 --- a/vuu-ui/packages/vuu-data-test/src/simul/OrderUpdateGenerator.ts +++ b/vuu-ui/packages/vuu-data-test/src/simul/OrderUpdateGenerator.ts @@ -8,15 +8,8 @@ import type { UpdateGenerator, UpdateHandler, } from "../rowUpdates"; -import { random } from "./reference-data"; import { metadataKeys } from "@finos/vuu-utils"; -const getNewValue = (value: number) => { - const multiplier = random(0, 100) / 1000; - const direction = random(0, 10) >= 5 ? 1 : -1; - return value + value * multiplier * direction; -}; - let _orderId = 1; const orderId = () => `0000000${_orderId++}`.slice(-3); const createOrder = (): ["I", ...VuuRowDataItemType[]] => { @@ -45,7 +38,7 @@ export class OrderUpdateGenerator implements UpdateGenerator { private timer: number | undefined; private phase: OrderPhase = "create-order"; private orderCount: number; - private columnMap: ColumnMap; + private columnMap?: ColumnMap; constructor(orderCount = 20) { this.orderCount = orderCount; @@ -103,7 +96,7 @@ export class OrderUpdateGenerator implements UpdateGenerator { console.log("fill-order"); const data = this.dataSource?.data; let filledCount = 0; - if (data) { + if (data && this.columnMap) { const count = data.length; const { IDX } = metadataKeys; const { filledQuantity: filledKey, quantity: qtyKey } = @@ -116,8 +109,8 @@ export class OrderUpdateGenerator implements UpdateGenerator { } = order; if (filledQty < quantity) { const newFilledQty = Math.min( - quantity, - Math.max(100, filledQty * 1.1) + quantity as number, + Math.max(100, (filledQty as number) * 1.1) ); updates.push(["U", rowIdx, filledKey, newFilledQty]); } else { diff --git a/vuu-ui/packages/vuu-data/src/array-data-source/array-data-source.ts b/vuu-ui/packages/vuu-data/src/array-data-source/array-data-source.ts index 7012f9505..839ea1821 100644 --- a/vuu-ui/packages/vuu-data/src/array-data-source/array-data-source.ts +++ b/vuu-ui/packages/vuu-data/src/array-data-source/array-data-source.ts @@ -6,7 +6,6 @@ import { ClientToServerMenuRPC, LinkDescriptorWithLabel, VuuAggregation, - VuuColumnDataType, VuuGroupBy, VuuMenu, VuuRange, @@ -19,10 +18,8 @@ import { EventEmitter, getAddedItems, getMissingItems, - getSelectionStatus, KeySet, logger, - metadataKeys, NULL_RANGE, rangeNewItems, resetRange, @@ -54,18 +51,18 @@ import { import { aggregateData } from "./aggregate-utils"; import { collapseGroup, expandGroup, GroupMap, groupRows } from "./group-utils"; import { sortRows } from "./sort-utils"; +import { buildDataToClientMap, toClientRow } from "./array-data-utils"; export interface ArrayDataSourceConstructorProps extends Omit { columnDescriptors: ColumnDescriptor[]; data: Array; + dataMap?: ColumnMap; keyColumn?: string; rangeChangeRowset?: "delta" | "full"; } const { debug } = logger("ArrayDataSource"); -const { RENDER_IDX, SELECTED } = metadataKeys; - const toDataSourceRow = (key: number) => (data: VuuRowDataItemType[], index: number): DataSourceRow => { @@ -88,24 +85,18 @@ const buildTableSchema = ( return schema; }; -const toClientRow = ( - row: DataSourceRow, - keys: KeySet, - selection: Selection -) => { - const [rowIndex] = row; - const clientRow = row.slice() as DataSourceRow; - clientRow[RENDER_IDX] = keys.keyFor(rowIndex); - clientRow[SELECTED] = getSelectionStatus(selection, rowIndex); - return clientRow; -}; - export class ArrayDataSource extends EventEmitter implements DataSource { private clientCallback: SubscribeCallback | undefined; private columnDescriptors: ColumnDescriptor[]; + /** sorted offsets of data within raw data, reflecting sort order + * of columns specified by client. + */ + private dataIndices: number[] | undefined; + /** Map reflecting positions of data items in raw data */ + private dataMap: ColumnMap | undefined; private disabled = false; private groupedData: undefined | DataSourceRow[]; private groupMap: undefined | GroupMap; @@ -117,6 +108,7 @@ export class ArrayDataSource private rangeChangeRowset: "delta" | "full"; private openTreeNodes: string[] = []; + /** Map reflecting positions of columns in client data sent to user */ #columnMap: ColumnMap; #config: WithFullConfig = vanillaConfig; #data: readonly DataSourceRow[]; @@ -140,6 +132,7 @@ export class ArrayDataSource // different from RemoteDataSource columnDescriptors, data, + dataMap, filter, groupBy, keyColumn, @@ -157,20 +150,19 @@ export class ArrayDataSource } this.columnDescriptors = columnDescriptors; + this.dataMap = dataMap; this.key = keyColumn ? this.columnDescriptors.findIndex((col) => col.name === keyColumn) : 0; this.rangeChangeRowset = rangeChangeRowset; this.tableSchema = buildTableSchema(columnDescriptors, keyColumn); this.viewport = viewport || uuid(); - this.#size = data.length; - this.#title = title; const columns = columnDescriptors.map((col) => col.name); - this.#columnMap = buildColumnMap(columns); + this.dataIndices = buildDataToClientMap(this.#columnMap, this.dataMap); this.#data = data.map(toDataSourceRow(this.key)); this.config = { @@ -463,7 +455,9 @@ export class ArrayDataSource const rowsWithinViewport = data .slice(rowRange.from, rowRange.to) - .map((row) => toClientRow(row, this.keys, this.selectedRows)); + .map((row) => + toClientRow(row, this.keys, this.selectedRows, this.dataIndices) + ); this.clientCallback?.({ clientViewportId: this.viewport, @@ -498,9 +492,11 @@ export class ArrayDataSource }); } this.#columnMap = buildColumnMap(columns); - console.log({ - columnMap: this.#columnMap, - }); + this.dataIndices = buildDataToClientMap(this.#columnMap, this.dataMap); + + const dataToClientMap = buildDataToClientMap(this.#columnMap, this.dataMap); + console.log({ dataToClientMap }); + this.config = { ...this.#config, columns, diff --git a/vuu-ui/packages/vuu-data/src/array-data-source/array-data-utils.ts b/vuu-ui/packages/vuu-data/src/array-data-source/array-data-utils.ts new file mode 100644 index 000000000..94b160251 --- /dev/null +++ b/vuu-ui/packages/vuu-data/src/array-data-source/array-data-utils.ts @@ -0,0 +1,69 @@ +import { DataSourceRow } from "@finos/vuu-data-types"; +import { Selection } from "@finos/vuu-datagrid-types"; +import { + ColumnMap, + getSelectionStatus, + KeySet, + metadataKeys, +} from "@finos/vuu-utils"; + +const { RENDER_IDX, SELECTED } = metadataKeys; + +export const toClientRow = ( + row: DataSourceRow, + keys: KeySet, + selection: Selection, + dataIndices?: number[] +) => { + const [rowIndex] = row; + let clientRow; + if (dataIndices) { + // If client has specified a different ordering of columns from the way they are + // ordered inn the underlying data, this is where we effect the ordering. + const { count } = metadataKeys; + clientRow = row + .slice(0, count) + .concat(dataIndices.map((idx) => row[idx])) as DataSourceRow; + } else { + clientRow = row.slice() as DataSourceRow; + } + clientRow[RENDER_IDX] = keys.keyFor(rowIndex); + clientRow[SELECTED] = getSelectionStatus(selection, rowIndex); + return clientRow; +}; + +const divergentMaps = (columnMap: ColumnMap, dataMap?: ColumnMap) => { + if (dataMap) { + const { count: mapOffset } = metadataKeys; + for (const [columnName, index] of Object.entries(columnMap)) { + const dataIdx = dataMap[columnName]; + if (dataIdx === undefined) { + throw Error( + `ArrayDataSource column ${columnName} is not in underlying data set` + ); + } else if (dataIdx !== index - mapOffset) { + return true; + } + } + } + return false; +}; + +const getDataIndices = (columnMap: ColumnMap, dataMap: ColumnMap) => { + const { count: mapOffset } = metadataKeys; + const result: number[] = []; + Object.entries(columnMap).forEach(([columnName]) => { + result.push(dataMap[columnName] + mapOffset); + }); + return result; +}; + +export const buildDataToClientMap = ( + columnMap: ColumnMap, + dataMap?: ColumnMap +): number[] | undefined => { + if (dataMap && divergentMaps(columnMap, dataMap)) { + return getDataIndices(columnMap, dataMap); + } + return undefined; +}; diff --git a/vuu-ui/packages/vuu-data/src/connection-manager.ts b/vuu-ui/packages/vuu-data/src/connection-manager.ts index 33ed5c37d..9f4f71591 100644 --- a/vuu-ui/packages/vuu-data/src/connection-manager.ts +++ b/vuu-ui/packages/vuu-data/src/connection-manager.ts @@ -6,17 +6,14 @@ import { VuuTable, VuuTableList, } from "@finos/vuu-protocol-types"; -import { - EventEmitter, - getLoggingConfigForWorker, - uuid, -} from "@finos/vuu-utils"; +import {EventEmitter, getLoggingConfigForWorker, uuid,} from "@finos/vuu-utils"; import { DataSourceCallbackMessage, shouldMessageBeRoutedToDataSource as messageShouldBeRoutedToDataSource, } from "./data-source"; import * as Message from "./server-proxy/messages"; import { + ConnectionQualityMetrics, ConnectionStatusMessage, isConnectionQualityMetrics, isConnectionStatusMessage, @@ -31,10 +28,9 @@ import { } from "./vuuUIMessageTypes"; // Note: inlined-worker is a generated file, it must be built -import { workerSourceCode } from "./inlined-worker"; -import { ConnectionQualityMetrics } from "./vuuUIMessageTypes"; -import { WebSocketProtocol } from "./websocket-connection"; -import { TableSchema } from "./message-utils"; +import {workerSourceCode} from "./inlined-worker"; +import {WebSocketProtocol} from "./websocket-connection"; +import {TableSchema} from "./message-utils"; const workerBlob = new Blob([getLoggingConfigForWorker() + workerSourceCode], { type: "text/javascript", @@ -89,17 +85,17 @@ type WorkerOptions = { // connection status messages before that, so we forward them to caller // while they wait for worker. const getWorker = async ({ - handleConnectionStatusChange, - protocol, - retryLimitDisconnect, - retryLimitStartup, - token = "", - username, - url, -}: WorkerOptions) => { + handleConnectionStatusChange, + protocol, + retryLimitDisconnect, + retryLimitStartup, + token = "", + username, + url, + }: WorkerOptions) => { if (token === "" && pendingWorker === undefined) { return new Promise((resolve) => { - pendingWorkerNoToken.push({ resolve }); + pendingWorkerNoToken.push({resolve}); }); } //FIXME If we have a pending request already and a new request arrives with a DIFFERENT @@ -119,7 +115,7 @@ const getWorker = async ({ // establishing a connection. When we resolve the worker, a runtime message // handler will replace this (see below) worker.onmessage = (msg: MessageEvent) => { - const { data: message } = msg; + const {data: message} = msg; if (message.type === "ready") { window.clearTimeout(timer); worker.postMessage({ @@ -139,7 +135,7 @@ const getWorker = async ({ } pendingWorkerNoToken.length = 0; } else if (isConnectionStatusMessage(message)) { - handleConnectionStatusChange({ data: message }); + handleConnectionStatusChange({data: message}); } else { console.warn("ConnectionManager: Unexpected message from the worker"); } @@ -150,8 +146,8 @@ const getWorker = async ({ }; function handleMessageFromWorker({ - data: message, -}: MessageEvent) { + data: message, + }: MessageEvent) { if (messageShouldBeRoutedToDataSource(message)) { const viewport = viewports.get(message.clientViewportId); if (viewport) { @@ -164,12 +160,11 @@ function handleMessageFromWorker({ } else if (isConnectionStatusMessage(message)) { ConnectionManager.emit("connection-status", message); } else if (isConnectionQualityMetrics(message)) { - console.log({ message }); ConnectionManager.emit("connection-metrics", message); } else { const requestId = (message as VuuUIMessageInRPC).requestId; if (pendingRequests.has(requestId)) { - const { resolve } = pendingRequests.get(requestId); + const {resolve} = pendingRequests.get(requestId); pendingRequests.delete(requestId); const { type: _1, @@ -214,7 +209,7 @@ const asyncRequest = ( ...msg, }); return new Promise((resolve, reject) => { - pendingRequests.set(requestId, { resolve, reject }); + pendingRequests.set(requestId, {resolve, reject}); }); }; @@ -246,11 +241,11 @@ const connectedServerAPI: ServerAPI = { request: message, postMessageToClientDataSource: callback, }); - worker.postMessage({ type: "subscribe", ...message }); + worker.postMessage({type: "subscribe", ...message}); }, unsubscribe: (viewport) => { - worker.postMessage({ type: "unsubscribe", viewport }); + worker.postMessage({type: "unsubscribe", viewport}); }, send: (message) => { @@ -268,7 +263,7 @@ const connectedServerAPI: ServerAPI = { ) => asyncRequest(message), getTableList: async () => - asyncRequest({ type: "GET_TABLE_LIST" }), + asyncRequest({type: "GET_TABLE_LIST"}), getTableSchema: async (table) => asyncRequest({ @@ -297,13 +292,13 @@ class _ConnectionManager extends EventEmitter { // The first request must have the token. We can change this to block others until // the request with token is received. async connect({ - url, - authToken, - username, - protocol, - retryLimitDisconnect, - retryLimitStartup, - }: ConnectOptions): Promise { + url, + authToken, + username, + protocol, + retryLimitDisconnect, + retryLimitStartup, + }: ConnectOptions): Promise { // By passing handleMessageFromWorker here, we can get connection status //messages while we wait for worker to resolve. worker = await getWorker({ @@ -338,13 +333,13 @@ export const ConnectionManager = new _ConnectionManager(); * @param token */ export const connectToServer = async ({ - url, - protocol = undefined, - authToken, - username, - retryLimitDisconnect, - retryLimitStartup, -}: ConnectOptions) => { + url, + protocol = undefined, + authToken, + username, + retryLimitDisconnect, + retryLimitStartup, + }: ConnectOptions) => { try { const serverAPI = await ConnectionManager.connect({ protocol, diff --git a/vuu-ui/packages/vuu-data/src/data-source.ts b/vuu-ui/packages/vuu-data/src/data-source.ts index 1a5b6ff1a..f04af2e0f 100644 --- a/vuu-ui/packages/vuu-data/src/data-source.ts +++ b/vuu-ui/packages/vuu-data/src/data-source.ts @@ -505,13 +505,6 @@ export type DataSourceStatus = | "suspended" | "unsubscribed"; -export type RpcResponse = - | MenuRpcResponse - | VuuUIMessageInRPCEditReject - | VuuUIMessageInRPCEditResponse; - -export type RpcResponseHandler = (response: RpcResponse) => boolean; - export interface DataSource extends EventEmitter { aggregations: VuuAggregation[]; applyEdit: DataSourceEditHandler; diff --git a/vuu-ui/packages/vuu-data/src/inlined-worker.js b/vuu-ui/packages/vuu-data/src/inlined-worker.js index 5b687bae0..b0715dd93 100644 --- a/vuu-ui/packages/vuu-data/src/inlined-worker.js +++ b/vuu-ui/packages/vuu-data/src/inlined-worker.js @@ -682,7 +682,6 @@ var CHANGE_VP_RANGE_SUCCESS = "CHANGE_VP_RANGE_SUCCESS"; var CLOSE_TREE_NODE = "CLOSE_TREE_NODE"; var CLOSE_TREE_SUCCESS = "CLOSE_TREE_SUCCESS"; var CREATE_VP = "CREATE_VP"; -var CREATE_VP_SUCCESS = "CREATE_VP_SUCCESS"; var DISABLE_VP = "DISABLE_VP"; var DISABLE_VP_SUCCESS = "DISABLE_VP_SUCCESS"; var ENABLE_VP = "ENABLE_VP"; @@ -692,14 +691,11 @@ var GET_VIEW_PORT_MENUS = "GET_VIEW_PORT_MENUS"; var HB = "HB"; var HB_RESP = "HB_RESP"; var LOGIN = "LOGIN"; -var LOGIN_SUCCESS = "LOGIN_SUCCESS"; var OPEN_TREE_NODE = "OPEN_TREE_NODE"; var OPEN_TREE_SUCCESS = "OPEN_TREE_SUCCESS"; var REMOVE_VP = "REMOVE_VP"; var RPC_RESP = "RPC_RESP"; var SET_SELECTION_SUCCESS = "SET_SELECTION_SUCCESS"; -var TABLE_META_RESP = "TABLE_META_RESP"; -var TABLE_LIST_RESP = "TABLE_LIST_RESP"; var TABLE_ROW = "TABLE_ROW"; // src/server-proxy/rpc-services.ts @@ -967,7 +963,6 @@ var Viewport = class { this.pendingRangeRequests = []; this.rowCountChanged = false; this.selectedRows = []; - this.tableSchema = null; this.useBatchMode = true; this.lastUpdateStatus = NO_UPDATE_STATUS; this.updateThrottleTimer = void 0; @@ -1106,7 +1101,7 @@ var Viewport = class { range, sort, groupBy - }) { + }, tableSchema) { this.serverViewportId = viewPortId; this.status = "subscribed"; this.aggregations = aggregations; @@ -1123,7 +1118,7 @@ var Viewport = class { groupBy, range, sort, - tableSchema: this.tableSchema + tableSchema }; } awaitOperation(requestId, msg) { @@ -1329,9 +1324,6 @@ var Viewport = class { clientViewportId: this.clientViewportId }; } - setTableSchema(tableSchema) { - this.tableSchema = tableSchema; - } openTreeNode(requestId, message) { if (this.useBatchMode) { this.batchMode = true; @@ -1659,9 +1651,9 @@ var ServerProxy = class { constructor(connection, callback) { this.authToken = ""; this.user = "user"; - this.pendingTableMetaRequests = /* @__PURE__ */ new Map(); this.pendingRequests = /* @__PURE__ */ new Map(); this.queuedRequests = []; + this.cachedTableMetaRequests = /* @__PURE__ */ new Map(); this.cachedTableSchemas = /* @__PURE__ */ new Map(); this.connection = connection; this.postMessageToClient = callback; @@ -1705,26 +1697,62 @@ var ServerProxy = class { } subscribe(message) { if (!this.mapClientToServerViewport.has(message.viewport)) { - if (!this.hasSchemaForTable(message.table) && // A Session table is never cached - it is limited to a single workflow interaction - // The metadata for a session table is requested even before the subscribe call. - !isSessionTable(message.table)) { - info3 == null ? void 0 : info3( - \`subscribe to \${message.table.table}, no metadata yet, request metadata\` - ); - const requestId = nextRequestId(); - this.sendMessageToServer( - { type: "GET_TABLE_META", table: message.table }, - requestId - ); - this.pendingTableMetaRequests.set(requestId, message.viewport); - } + const pendingTableSchema = this.getTableMeta(message.table); const viewport = new Viewport(message, this.postMessageToClient); this.viewports.set(message.viewport, viewport); - this.sendIfReady( + const pendingSubscription = this.awaitResponseToMessage( viewport.subscribe(), - message.viewport, - this.sessionId !== "" + message.viewport ); + const awaitPendingReponses = Promise.all([ + pendingSubscription, + pendingTableSchema + ]); + awaitPendingReponses.then(([subscribeResponse, tableSchema]) => { + const { viewPortId: serverViewportId } = subscribeResponse; + const { status: viewportStatus } = viewport; + if (message.viewport !== serverViewportId) { + this.viewports.delete(message.viewport); + this.viewports.set(serverViewportId, viewport); + } + this.mapClientToServerViewport.set(message.viewport, serverViewportId); + const clientResponse = viewport.handleSubscribed( + subscribeResponse, + tableSchema + ); + if (clientResponse) { + this.postMessageToClient(clientResponse); + if (debugEnabled4) { + debug4( + \`post DataSourceSubscribedMessage to client: \${JSON.stringify( + clientResponse + )}\` + ); + } + } + if (viewport.disabled) { + this.disableViewport(viewport); + } + if (viewportStatus === "subscribing" && // A session table will never have Visual Links, nor Context Menus + !isSessionTable(viewport.table)) { + this.sendMessageToServer({ + type: GET_VP_VISUAL_LINKS, + vpId: serverViewportId + }); + this.sendMessageToServer({ + type: GET_VIEW_PORT_MENUS, + vpId: serverViewportId + }); + Array.from(this.viewports.entries()).filter( + ([id, { disabled }]) => id !== serverViewportId && !disabled + ).forEach(([vpId]) => { + this.sendMessageToServer({ + type: GET_VP_VISUAL_LINKS, + vpId + }); + }); + } + }); } else { error3(\`spurious subscribe call \${message.viewport}\`); } @@ -1965,6 +1993,7 @@ var ServerProxy = class { this.sendMessageToServer(rpcRequest, requestId, { module }); } handleMessageFromClient(message) { + var _a; if (isViewporttMessage(message)) { if (message.type === "disable") { const viewport = this.getViewportForClient(message.viewport, false); @@ -2016,13 +2045,32 @@ var ServerProxy = class { } else { const { type, requestId } = message; switch (type) { - case "GET_TABLE_LIST": - return this.sendMessageToServer({ type }, requestId); - case "GET_TABLE_META": - return this.sendMessageToServer( - { type, table: message.table }, + case "GET_TABLE_LIST": { + (_a = this.tableList) != null ? _a : this.tableList = this.awaitResponseToMessage( + { type }, requestId ); + this.tableList.then((response) => { + this.postMessageToClient({ + type: "TABLE_LIST_RESP", + tables: response.tables, + requestId + }); + }); + return; + } + case "GET_TABLE_META": { + this.getTableMeta(message.table, requestId).then((tableSchema) => { + if (tableSchema) { + this.postMessageToClient({ + type: "TABLE_META_RESP", + tableSchema, + requestId + }); + } + }); + return; + } case "RPC_CALL": return this.rpcCall(message); default: @@ -2034,9 +2082,23 @@ var ServerProxy = class { )}\` ); } - awaitResponseToMessage(message) { + getTableMeta(table, requestId = nextRequestId()) { + if (isSessionTable(table)) { + return Promise.resolve(void 0); + } + const key = \`\${table.module}:\${table.table}\`; + let tableMetaRequest = this.cachedTableMetaRequests.get(key); + if (!tableMetaRequest) { + tableMetaRequest = this.awaitResponseToMessage( + { type: "GET_TABLE_META", table }, + requestId + ); + this.cachedTableMetaRequests.set(key, tableMetaRequest); + } + return tableMetaRequest == null ? void 0 : tableMetaRequest.then((response) => this.cacheTableMeta(response)); + } + awaitResponseToMessage(message, requestId = nextRequestId()) { return new Promise((resolve, reject) => { - const requestId = nextRequestId(); this.sendMessageToServer(message, requestId); this.pendingRequests.set(requestId, { reject, resolve }); }); @@ -2080,7 +2142,7 @@ var ServerProxy = class { "NA" ); break; - case LOGIN_SUCCESS: + case "LOGIN_SUCCESS": if (sessionId) { this.sessionId = sessionId; (_a = this.pendingLogin) == null ? void 0 : _a.resolve(sessionId); @@ -2089,53 +2151,6 @@ var ServerProxy = class { throw Error("LOGIN_SUCCESS did not provide sessionId"); } break; - case CREATE_VP_SUCCESS: - { - const viewport = viewports.get(requestId); - if (viewport) { - const { status: viewportStatus } = viewport; - const { viewPortId: serverViewportId } = body; - if (requestId !== serverViewportId) { - viewports.delete(requestId); - viewports.set(serverViewportId, viewport); - } - this.mapClientToServerViewport.set(requestId, serverViewportId); - const response = viewport.handleSubscribed(body); - if (response) { - this.postMessageToClient(response); - if (debugEnabled4) { - debug4( - \`post DataSourceSubscribedMessage to client: \${JSON.stringify( - response - )}\` - ); - } - } - if (viewport.disabled) { - this.disableViewport(viewport); - } - if (viewportStatus === "subscribing" && // A session table will never have Visual Links, nor Context Menus - !isSessionTable(viewport.table)) { - this.sendMessageToServer({ - type: GET_VP_VISUAL_LINKS, - vpId: serverViewportId - }); - this.sendMessageToServer({ - type: GET_VIEW_PORT_MENUS, - vpId: serverViewportId - }); - Array.from(viewports.entries()).filter( - ([id, { disabled }]) => id !== serverViewportId && !disabled - ).forEach(([vpId]) => { - this.sendMessageToServer({ - type: GET_VP_VISUAL_LINKS, - vpId - }); - }); - } - } - } - break; case "REMOVE_VP_SUCCESS": { const viewport = viewports.get(body.viewPortId); @@ -2288,36 +2303,6 @@ var ServerProxy = class { } } break; - case TABLE_LIST_RESP: - this.postMessageToClient({ - type: TABLE_LIST_RESP, - tables: body.tables, - requestId - }); - break; - case TABLE_META_RESP: - { - const tableSchema = this.cacheTableMeta(body); - const clientViewportId = this.pendingTableMetaRequests.get(requestId); - if (clientViewportId) { - this.pendingTableMetaRequests.delete(requestId); - const viewport = this.viewports.get(clientViewportId); - if (viewport) { - viewport.setTableSchema(tableSchema); - } else { - warn3 == null ? void 0 : warn3( - "Message has come back AFTER CREATE_VP_SUCCESS, what do we do now" - ); - } - } else { - this.postMessageToClient({ - type: TABLE_META_RESP, - tableSchema, - requestId - }); - } - } - break; case "VP_VISUAL_LINKS_RESP": { const activeLinkDescriptors = this.getActiveLinks(body.links); @@ -2445,9 +2430,6 @@ var ServerProxy = class { infoEnabled3 && info3(\`handleMessageFromServer \${body["type"]}.\`); } } - hasSchemaForTable(table) { - return this.cachedTableSchemas.has(\`\${table.module}:\${table.table}\`); - } cacheTableMeta(messageBody) { const { module, table } = messageBody.table; const key = \`\${module}:\${table}\`; diff --git a/vuu-ui/packages/vuu-data/src/json-data-source.ts b/vuu-ui/packages/vuu-data/src/json-data-source.ts index c50b74078..0055d3d63 100644 --- a/vuu-ui/packages/vuu-data/src/json-data-source.ts +++ b/vuu-ui/packages/vuu-data/src/json-data-source.ts @@ -1,16 +1,15 @@ -import { ColumnDescriptor, Selection } from "@finos/vuu-datagrid-types"; +import {ColumnDescriptor, Selection} from "@finos/vuu-datagrid-types"; import { + ClientToServerEditRpc, + ClientToServerMenuRPC, LinkDescriptorWithLabel, - VuuGroupBy, VuuAggregation, + VuuGroupBy, VuuRange, - VuuSort, - ClientToServerMenuRPC, - ClientToServerEditRpc, - VuuColumnDataType, VuuRowDataItemType, + VuuSort, } from "@finos/vuu-protocol-types"; -import { DataSourceFilter, DataSourceRow } from "@finos/vuu-data-types"; +import {DataSourceFilter, DataSourceRow} from "@finos/vuu-data-types"; import { EventEmitter, isSelected, @@ -29,21 +28,21 @@ import type { SubscribeProps, WithFullConfig, } from "./data-source"; -import { vanillaConfig } from "./data-source"; +import {vanillaConfig} from "./data-source"; import { MenuRpcResponse, VuuUIMessageInRPCEditReject, VuuUIMessageInRPCEditResponse, } from "./vuuUIMessageTypes"; -const NULL_SCHEMA = { columns: [], key: "", table: { module: "", table: "" } }; +const NULL_SCHEMA = {columns: [], key: "", table: {module: "", table: ""}}; export interface JsonDataSourceConstructorProps extends Omit { data: JsonData; } -const { DEPTH, IDX, IS_EXPANDED, IS_LEAF, KEY, SELECTED } = metadataKeys; +const {DEPTH, IDX, IS_EXPANDED, IS_LEAF, KEY, SELECTED} = metadataKeys; const toClientRow = (row: DataSourceRow, keys: KeySet) => { const [rowIndex] = row; @@ -54,8 +53,7 @@ const toClientRow = (row: DataSourceRow, keys: KeySet) => { export class JsonDataSource extends EventEmitter - implements DataSource -{ + implements DataSource { public columnDescriptors: ColumnDescriptor[]; private clientCallback: SubscribeCallback | undefined; private expandedRows = new Set(); @@ -64,12 +62,12 @@ export class JsonDataSource #aggregations: VuuAggregation[] = []; #config: WithFullConfig = vanillaConfig; #data: DataSourceRow[]; - #filter: DataSourceFilter = { filter: "" }; + #filter: DataSourceFilter = {filter: ""}; #groupBy: VuuGroupBy = []; - #range: VuuRange = { from: 0, to: 0 }; + #range: VuuRange = {from: 0, to: 0}; #selectedRowsCount = 0; #size = 0; - #sort: VuuSort = { sortDefs: [] }; + #sort: VuuSort = {sortDefs: []}; #status: DataSourceStatus = "initialising"; #title: string | undefined; @@ -79,14 +77,14 @@ export class JsonDataSource private keys = new KeySet(this.#range); constructor({ - aggregations, - data, - filter, - groupBy, - sort, - title, - viewport, - }: JsonDataSourceConstructorProps) { + aggregations, + data, + filter, + groupBy, + sort, + title, + viewport, + }: JsonDataSourceConstructorProps) { super(); if (!data) { @@ -96,10 +94,10 @@ export class JsonDataSource [this.columnDescriptors, this.#data] = jsonToDataSourceRows(data); this.visibleRows = this.#data - .filter((row) => row[DEPTH] === 0) - .map((row, index) => - ([index, index] as Partial).concat(row.slice(2)) - ) as DataSourceRow[]; + .filter((row) => row[DEPTH] === 0) + .map((row, index) => + ([index, index] as Partial).concat(row.slice(2)) + ) as DataSourceRow[]; this.viewport = viewport || uuid(); if (aggregations) { this.#aggregations = aggregations; @@ -210,14 +208,15 @@ export class JsonDataSource console.log("noop"); return this; } + set data(data: JsonData) { console.log(`set JsonDataSource data`); [this.columnDescriptors, this.#data] = jsonToDataSourceRows(data); this.visibleRows = this.#data - .filter((row) => row[DEPTH] === 0) - .map((row, index) => - ([index, index] as Partial).concat(row.slice(2)) - ) as DataSourceRow[]; + .filter((row) => row[DEPTH] === 0) + .map((row, index) => + ([index, index] as Partial).concat(row.slice(2)) + ) as DataSourceRow[]; requestAnimationFrame(() => { this.sendRowsToClient(); @@ -227,7 +226,7 @@ export class JsonDataSource select(selected: Selection) { const updatedRows: DataSourceRow[] = []; for (const row of this.#data) { - const { [IDX]: rowIndex, [SELECTED]: sel } = row; + const {[IDX]: rowIndex, [SELECTED]: sel} = row; const wasSelected = sel === 1; const nowSelected = isSelected(selected, rowIndex); if (nowSelected !== wasSelected) { @@ -251,14 +250,14 @@ export class JsonDataSource openTreeNode(key: string) { this.expandedRows.add(key); this.visibleRows = getVisibleRows(this.#data, this.expandedRows); - const { from, to } = this.#range; + const {from, to} = this.#range; this.clientCallback?.({ clientViewportId: this.viewport, mode: "batch", rows: this.visibleRows - .slice(from, to) - .map((row) => toClientRow(row, this.keys)), + .slice(from, to) + .map((row) => toClientRow(row, this.keys)), size: this.visibleRows.length, type: "viewport-update", }); @@ -306,13 +305,13 @@ export class JsonDataSource } private sendRowsToClient() { - const { from, to } = this.#range; + const {from, to} = this.#range; this.clientCallback?.({ clientViewportId: this.viewport, mode: "batch", rows: this.visibleRows - .slice(from, to) - .map((row) => toClientRow(row, this.keys)), + .slice(from, to) + .map((row) => toClientRow(row, this.keys)), size: this.visibleRows.length, type: "viewport-update", }); @@ -338,10 +337,6 @@ export class JsonDataSource this.#aggregations = aggregations; } - set data(data: JsonData) { - console.log(`set JsonDataSource data`); - } - get sort() { return this.#sort; } @@ -377,9 +372,9 @@ export class JsonDataSource } createLink({ - parentVpId, - link: { fromColumn, toColumn }, - }: LinkDescriptorWithLabel) { + parentVpId, + link: {fromColumn, toColumn}, + }: LinkDescriptorWithLabel) { console.log("create link", { parentVpId, fromColumn, @@ -419,11 +414,11 @@ export class JsonDataSource getChildRows(rowKey: string) { const parentRow = this.#data.find((row) => row[KEY] === rowKey); if (parentRow) { - const { [IDX]: parentIdx, [DEPTH]: parentDepth } = parentRow; + const {[IDX]: parentIdx, [DEPTH]: parentDepth} = parentRow; let rowIdx = parentIdx + 1; const childRows = []; do { - const { [DEPTH]: depth } = this.#data[rowIdx]; + const {[DEPTH]: depth} = this.#data[rowIdx]; if (depth === parentDepth + 1) { childRows.push(this.#data[rowIdx]); } else if (depth <= parentDepth) { @@ -453,10 +448,10 @@ type Index = { function getVisibleRows(rows: DataSourceRow[], expandedKeys: Set) { const visibleRows: DataSourceRow[] = []; - const index: Index = { value: 0 }; + const index: Index = {value: 0}; for (let i = 0; i < rows.length; i++) { const row = rows[i]; - const { [DEPTH]: depth, [KEY]: key, [IS_LEAF]: isLeaf } = row; + const {[DEPTH]: depth, [KEY]: key, [IS_LEAF]: isLeaf} = row; const isExpanded = expandedKeys.has(key); visibleRows.push(cloneRow(row, index, isExpanded)); if (!isLeaf && !isExpanded) { diff --git a/vuu-ui/packages/vuu-datagrid-types/index.d.ts b/vuu-ui/packages/vuu-datagrid-types/index.d.ts index 65fc21298..630f6dc0f 100644 --- a/vuu-ui/packages/vuu-datagrid-types/index.d.ts +++ b/vuu-ui/packages/vuu-datagrid-types/index.d.ts @@ -38,9 +38,9 @@ export interface TableCellProps { export type CommitResponse = Promise; -export type DataItemCommitHandler = ( - value: VuuRowDataItemType -) => CommitResponse; +export type DataItemCommitHandler< + T extends VuuRowDataItemType = VuuRowDataItemType +> = (value: T) => CommitResponse; export interface TableCellRendererProps extends Omit { diff --git a/vuu-ui/packages/vuu-layout/src/layout-persistence/LocalLayoutPersistenceManager.ts b/vuu-ui/packages/vuu-layout/src/layout-persistence/LocalLayoutPersistenceManager.ts index 2125ab675..519dde763 100644 --- a/vuu-ui/packages/vuu-layout/src/layout-persistence/LocalLayoutPersistenceManager.ts +++ b/vuu-ui/packages/vuu-layout/src/layout-persistence/LocalLayoutPersistenceManager.ts @@ -25,10 +25,6 @@ export class LocalLayoutPersistenceManager implements LayoutPersistenceManager { layout: LayoutJSON ): Promise { return new Promise((resolve) => { - console.log( - `Saving layout as ${metadata.name} to group ${metadata.group}...` - ); - Promise.all([this.loadLayouts(), this.loadMetadata()]).then( ([existingLayouts, existingMetadata]) => { const id = getUniqueId(); diff --git a/vuu-ui/packages/vuu-popups/src/menu/context-menu-provider.tsx b/vuu-ui/packages/vuu-popups/src/menu/context-menu-provider.tsx index a61d6a4f1..9d62dcd76 100644 --- a/vuu-ui/packages/vuu-popups/src/menu/context-menu-provider.tsx +++ b/vuu-ui/packages/vuu-popups/src/menu/context-menu-provider.tsx @@ -9,13 +9,16 @@ export const ContextMenuContext = createContext( null ); -export interface ContextMenuProviderProps { - children: ReactNode; - label?: string; +export interface ContextMenuConfiguration { menuActionHandler?: MenuActionHandler; menuBuilder: MenuBuilder; } +export interface ContextMenuProviderProps extends ContextMenuConfiguration { + children: ReactNode; + label?: string; +} + interface ProviderProps extends ContextMenuProviderProps { context: ContextMenuContextType | null; } diff --git a/vuu-ui/packages/vuu-shell/src/layout-management/LayoutList.tsx b/vuu-ui/packages/vuu-shell/src/layout-management/LayoutList.tsx index b7ba35643..82721ccd5 100644 --- a/vuu-ui/packages/vuu-shell/src/layout-management/LayoutList.tsx +++ b/vuu-ui/packages/vuu-shell/src/layout-management/LayoutList.tsx @@ -48,8 +48,8 @@ export const LayoutsList = (props: HTMLAttributes) => { {layoutMetadata.map((metadata) => (
handleLoadLayout(metadata?.id)} + key={metadata?.id} + onClick={() => handleLoadLayout(metadata?.id)} > ) => { {metadata?.name}
-
{`${metadata?.user}, ${metadata?.created}`}
+
{`${metadata?.user}, ${metadata?.created}`}
diff --git a/vuu-ui/packages/vuu-shell/src/layout-management/useLayoutManager.tsx b/vuu-ui/packages/vuu-shell/src/layout-management/useLayoutManager.tsx index 1c83e8f47..064866046 100644 --- a/vuu-ui/packages/vuu-shell/src/layout-management/useLayoutManager.tsx +++ b/vuu-ui/packages/vuu-shell/src/layout-management/useLayoutManager.tsx @@ -20,12 +20,11 @@ const local = process.env.LOCAL ?? true; let _persistenceManager: LayoutPersistenceManager; const getPersistenceManager = () => { - if (_persistenceManager == undefined) { + if (_persistenceManager === undefined) { _persistenceManager = local ? new LocalLayoutPersistenceManager() : new RemoteLayoutPersistenceManager(); } - return _persistenceManager; }; @@ -67,8 +66,9 @@ export const LayoutManagementProvider = ( ); useEffect(() => { - getPersistenceManager() - .loadMetadata() + const persistenceManager = getPersistenceManager(); + + persistenceManager.loadMetadata() .then((metadata) => { setLayoutMetadata(metadata); }) @@ -77,8 +77,7 @@ export const LayoutManagementProvider = ( console.error("Error occurred while retrieving metadata", error); }); - getPersistenceManager() - .loadApplicationLayout() + persistenceManager.loadApplicationLayout() .then((layout: LayoutJSON) => { setApplicationLayout(layout); }) @@ -93,6 +92,7 @@ export const LayoutManagementProvider = ( const saveApplicationLayout = useCallback( (layout: LayoutJSON) => { + console.log(`save application layout ${JSON.stringify(layout, null, 2)}`); setApplicationLayout(layout, false); getPersistenceManager().saveApplicationLayout(layout); }, diff --git a/vuu-ui/packages/vuu-table-extras/src/cell-edit-validators/CaseValidator.ts b/vuu-ui/packages/vuu-table-extras/src/cell-edit-validators/CaseValidator.ts index 3bf15ae23..166611ae3 100644 --- a/vuu-ui/packages/vuu-table-extras/src/cell-edit-validators/CaseValidator.ts +++ b/vuu-ui/packages/vuu-table-extras/src/cell-edit-validators/CaseValidator.ts @@ -1,7 +1,7 @@ import { EditRuleValidator, registerComponent } from "@finos/vuu-utils"; import { VuuRowDataItemType } from "@finos/vuu-protocol-types"; -const isString = (value: VuuRowDataItemType): value is string => +const isString = (value?: VuuRowDataItemType): value is string => typeof value === "string"; export const CaseValidator: EditRuleValidator = (rule, value) => { diff --git a/vuu-ui/packages/vuu-table-extras/src/cell-edit-validators/PatternValidator.ts b/vuu-ui/packages/vuu-table-extras/src/cell-edit-validators/PatternValidator.ts index 58d34f671..578e717cc 100644 --- a/vuu-ui/packages/vuu-table-extras/src/cell-edit-validators/PatternValidator.ts +++ b/vuu-ui/packages/vuu-table-extras/src/cell-edit-validators/PatternValidator.ts @@ -1,7 +1,7 @@ import { EditRuleValidator, registerComponent } from "@finos/vuu-utils"; import { VuuRowDataItemType } from "@finos/vuu-protocol-types"; -const isString = (value: VuuRowDataItemType): value is string => +const isString = (value?: VuuRowDataItemType): value is string => typeof value === "string"; const defaultMessage = "value does not match expected pattern"; diff --git a/vuu-ui/packages/vuu-table/src/table-next/TableNext.tsx b/vuu-ui/packages/vuu-table/src/table-next/TableNext.tsx index 3f2726f22..5d26c7fb0 100644 --- a/vuu-ui/packages/vuu-table/src/table-next/TableNext.tsx +++ b/vuu-ui/packages/vuu-table/src/table-next/TableNext.tsx @@ -2,7 +2,13 @@ import { ContextMenuProvider } from "@finos/vuu-popups"; import { TableProps } from "@finos/vuu-table"; import { isGroupColumn, metadataKeys, notHidden } from "@finos/vuu-utils"; import cx from "classnames"; -import { CSSProperties, ForwardedRef, forwardRef, useRef } from "react"; +import { + CSSProperties, + ForwardedRef, + forwardRef, + useEffect, + useRef, +} from "react"; import { GroupHeaderCellNext as GroupHeaderCell, HeaderCell, @@ -45,6 +51,7 @@ export const TableNext = forwardRef(function TableNext( forwardedRef: ForwardedRef ) { const id = useId(idProp); + const containerRef = useRef(null); const { columnMap, diff --git a/vuu-ui/packages/vuu-table/src/table-next/header-cell/HeaderCell.css b/vuu-ui/packages/vuu-table/src/table-next/header-cell/HeaderCell.css index e9a9a58cb..854991cc3 100644 --- a/vuu-ui/packages/vuu-table/src/table-next/header-cell/HeaderCell.css +++ b/vuu-ui/packages/vuu-table/src/table-next/header-cell/HeaderCell.css @@ -46,7 +46,7 @@ } .vuuTableNextHeaderCell.vuuPinLeft { - padding-left: 2px;; + padding-left: 2px; } .vuuTableNextHeaderCell.vuuPinLeft.vuuEndPin .vuuColumnResizerNext:before { @@ -79,7 +79,7 @@ width: var(--pin-width); top:0; bottom:0; - right: -1px; + right: 3px; height: var(--height); z-index: -5; } diff --git a/vuu-ui/packages/vuu-table/src/table-next/useTableNext.ts b/vuu-ui/packages/vuu-table/src/table-next/useTableNext.ts index 4c37b7d4a..ad72ae840 100644 --- a/vuu-ui/packages/vuu-table/src/table-next/useTableNext.ts +++ b/vuu-ui/packages/vuu-table/src/table-next/useTableNext.ts @@ -1,4 +1,5 @@ import { + DataSource, DataSourceConfig, DataSourceSubscribedMessage, JsonDataSource, @@ -36,6 +37,7 @@ import { useCallback, useEffect, useMemo, + useRef, useState, } from "react"; import { @@ -114,9 +116,14 @@ export const useTable = ({ selectionModel, }: TableHookProps) => { const [rowCount, setRowCount] = useState(dataSource.size); + const dataSourceRef = useRef(); if (dataSource === undefined) { throw Error("no data source provided to Vuu Table"); } + // // We track changes to tableConfig. When detected, these trigger an init + // // of model. We will need dataSource for that, but don't want to trigger + // // that logic when dataSource itself changes. + // dataSourceRef.current = dataSource; const [size, setSize] = useState(); const handleResize = useCallback((size: MeasuredSize) => { @@ -560,9 +567,16 @@ export const useTable = ({ [onRowClickProp, selectionHookOnRowClick] ); + useLayoutEffectSkipFirst(() => { + dispatchColumnAction({ + type: "init", + tableConfig: config, + dataSourceConfig: dataSource.config, + }); + }, [config, dataSource, dispatchColumnAction]); + useEffect(() => { dataSource.on("config", (config, confirmed) => { - // expectConfigChangeRef.current = true; dispatchColumnAction({ type: "tableConfig", ...config, diff --git a/vuu-ui/packages/vuu-table/src/table/useTableModel.ts b/vuu-ui/packages/vuu-table/src/table/useTableModel.ts index e2193e310..2d9cf212e 100644 --- a/vuu-ui/packages/vuu-table/src/table/useTableModel.ts +++ b/vuu-ui/packages/vuu-table/src/table/useTableModel.ts @@ -410,7 +410,6 @@ function pinColumn(state: TableModel, action: ColumnActionPin) { const { column, pin } = action; columns = updateColumn(columns, column.name, { pin }); columns = sortPinnedColumns(columns); - console.log({ withPins: columns }); return { ...state, columns, diff --git a/vuu-ui/packages/vuu-theme/fonts/NunitoSans.css b/vuu-ui/packages/vuu-theme/fonts/NunitoSans.css index f422339bd..023d0ba13 100644 --- a/vuu-ui/packages/vuu-theme/fonts/NunitoSans.css +++ b/vuu-ui/packages/vuu-theme/fonts/NunitoSans.css @@ -68,4 +68,4 @@ @font-face { font-family: 'Nunito Sans A-Variant'; src: url('./NunitoSans-Regular.woff') format('opentype'); -} \ No newline at end of file +} diff --git a/vuu-ui/packages/vuu-ui-controls/src/cycle-state-button/CycleStateButton.tsx b/vuu-ui/packages/vuu-ui-controls/src/cycle-state-button/CycleStateButton.tsx index 7615b6306..03d5b71eb 100644 --- a/vuu-ui/packages/vuu-ui-controls/src/cycle-state-button/CycleStateButton.tsx +++ b/vuu-ui/packages/vuu-ui-controls/src/cycle-state-button/CycleStateButton.tsx @@ -25,12 +25,19 @@ const getNextValue = (value: string, valueList: string[]) => { }; export const CycleStateButton = forwardRef(function CycleStateButton( - { className, onCommit, value, values, ...buttonProps }: CycleStateButtonProps, + { + className, + onCommit, + value = "", + values, + ...buttonProps + }: CycleStateButtonProps, forwardedRef: ForwardedRef ) { const handleClick = useCallback( (evt: SyntheticEvent) => { const nextValue = getNextValue(value, values); + console.log(`CycleStateButton handleClick ${value} => ${nextValue}`); onCommit(evt, nextValue as VuuColumnDataType).then((response) => { if (response !== true) { console.error(response); diff --git a/vuu-ui/packages/vuu-ui-controls/src/editable/editable-utils.ts b/vuu-ui/packages/vuu-ui-controls/src/editable/editable-utils.ts index 69f210922..3fd94aa4d 100644 --- a/vuu-ui/packages/vuu-ui-controls/src/editable/editable-utils.ts +++ b/vuu-ui/packages/vuu-ui-controls/src/editable/editable-utils.ts @@ -3,19 +3,18 @@ import { VuuRowDataItemType } from "@finos/vuu-protocol-types"; import { getEditRuleValidator } from "@finos/vuu-utils"; export type ClientSideValidationChecker = ( - value: VuuRowDataItemType + value?: VuuRowDataItemType ) => string | false | undefined; export const buildValidationChecker = (rules: EditValidationRule[]): ClientSideValidationChecker => - (value: VuuRowDataItemType) => + (value?: VuuRowDataItemType) => applyRules(rules, value); function applyRules( rules: EditValidationRule[], - value: VuuRowDataItemType + value?: VuuRowDataItemType ): string | false | undefined { - console.log(`apply rules to ${value}`); let result: false | string | undefined = undefined; for (const rule of rules) { const editRuleValidator = getEditRuleValidator(rule.name); @@ -43,6 +42,5 @@ function applyRules( } } - console.log(result); return result; } diff --git a/vuu-ui/packages/vuu-ui-controls/src/editable/useEditableText.ts b/vuu-ui/packages/vuu-ui-controls/src/editable/useEditableText.ts index 4e1038d6e..616a555be 100644 --- a/vuu-ui/packages/vuu-ui-controls/src/editable/useEditableText.ts +++ b/vuu-ui/packages/vuu-ui-controls/src/editable/useEditableText.ts @@ -1,6 +1,8 @@ import { VuuRowDataItemType } from "@finos/vuu-protocol-types"; -import { DataItemCommitHandler } from "packages/vuu-datagrid-types"; +import { DataItemCommitHandler } from "@finos/vuu-datagrid-types"; +import { useLayoutEffectSkipFirst } from "@finos/vuu-layout"; import { + FocusEventHandler, FormEventHandler, KeyboardEvent, useCallback, @@ -20,8 +22,9 @@ export interface EditableTextHookProps< T extends VuuRowDataItemType = VuuRowDataItemType > { clientSideEditValidationCheck?: ClientSideValidationChecker; - initialValue: T; - onCommit: DataItemCommitHandler; + initialValue?: T; + onCommit: DataItemCommitHandler; + type?: "string" | "number" | "boolean"; } export const dispatchCommitEvent = (el: HTMLElement) => { @@ -29,43 +32,54 @@ export const dispatchCommitEvent = (el: HTMLElement) => { el.dispatchEvent(commitEvent); }; -export const useEditableText = < - T extends VuuRowDataItemType = VuuRowDataItemType ->({ +export const useEditableText = ({ clientSideEditValidationCheck, initialValue, onCommit, + type, }: EditableTextHookProps) => { const [message, setMessage] = useState(); - const [value, setValue] = useState(initialValue); - const initialValueRef = useRef(initialValue); + const [value, setValue] = useState(initialValue); + const initialValueRef = useRef(initialValue); const isDirtyRef = useRef(false); const hasCommittedRef = useRef(false); + useLayoutEffectSkipFirst(() => { + //TODO this isn't right, review the state we're using + setValue(initialValue); + }, [initialValue]); + + const commit = useCallback( + (target: HTMLElement) => { + if (isDirtyRef.current) { + hasCommittedRef.current = true; + const warningMessage = clientSideEditValidationCheck?.(value); + if (warningMessage) { + setMessage(warningMessage); + } else { + setMessage(undefined); + onCommit(value as T).then((response) => { + if (response === true) { + isDirtyRef.current = false; + dispatchCommitEvent(target); + } else { + setMessage(response); + } + }); + } + } else { + // why, if not dirty ? + dispatchCommitEvent(target); + hasCommittedRef.current = false; + } + }, + [clientSideEditValidationCheck, onCommit, value] + ); + const handleKeyDown = useCallback( (evt: KeyboardEvent) => { if (evt.key === "Enter") { - evt.stopPropagation(); - if (isDirtyRef.current) { - hasCommittedRef.current = true; - const warningMessage = clientSideEditValidationCheck?.(value); - if (warningMessage) { - setMessage(warningMessage); - } else { - setMessage(undefined); - onCommit(value).then((response) => { - if (response === true) { - isDirtyRef.current = false; - dispatchCommitEvent(evt.target as HTMLInputElement); - } else { - setMessage(response); - } - }); - } - } else { - dispatchCommitEvent(evt.target as HTMLInputElement); - hasCommittedRef.current = false; - } + commit(evt.target as HTMLElement); } else if ( evt.key === "ArrowRight" || evt.key === "ArrowLeft" || @@ -81,28 +95,42 @@ export const useEditableText = < } } }, - [clientSideEditValidationCheck, onCommit, value] + [commit] + ); + + const handleBlur = useCallback>( + (evt) => { + commit(evt.target as HTMLElement); + }, + [commit] ); const handleChange = useCallback( (evt) => { - const { value } = evt.target as HTMLInputElement; + let typedValue: VuuRowDataItemType = (evt.target as HTMLInputElement) + .value; + if (type === "number" && !isNaN(parseFloat(typedValue))) { + typedValue = parseFloat(typedValue); + } isDirtyRef.current = value !== initialValueRef.current; - setValue(value as T); - if (hasCommittedRef.current) { + setValue(typedValue as T); + if (hasCommittedRef.current && value !== undefined) { const warningMessage = clientSideEditValidationCheck?.(value); if (warningMessage !== message && warningMessage !== false) { setMessage(warningMessage); } } }, - [clientSideEditValidationCheck, message] + [clientSideEditValidationCheck, message, type, value] ); return { + inputProps: { + onBlur: handleBlur, + onKeyDown: handleKeyDown, + }, onChange: handleChange, - onKeyDown: handleKeyDown, - value, + value: value ?? "", warningMessage: message, }; }; diff --git a/vuu-ui/packages/vuu-ui-controls/src/expando-input/ExpandoInput.tsx b/vuu-ui/packages/vuu-ui-controls/src/expando-input/ExpandoInput.tsx index 5b8bfd0e3..54fa022bd 100644 --- a/vuu-ui/packages/vuu-ui-controls/src/expando-input/ExpandoInput.tsx +++ b/vuu-ui/packages/vuu-ui-controls/src/expando-input/ExpandoInput.tsx @@ -19,7 +19,7 @@ export const ExpandoInput = forwardRef(function ExpandoInput( value, inputProps, onCommit = noop, - ...InputProps + ...props }: ExpandoInputProps, forwardedRef: ForwardedRef ) { @@ -31,7 +31,7 @@ export const ExpandoInput = forwardRef(function ExpandoInput( data-text={value} > = ( +export type Commithandler = ( evt: SyntheticEvent, value: T ) => void; -export interface VuuInputProps< - T extends VuuRowDataItemType = VuuRowDataItemType -> extends InputProps { +export interface VuuInputProps + extends InputProps { errorMessage?: string; onCommit: Commithandler; type?: T; diff --git a/vuu-ui/packages/vuu-utils/src/component-registry.ts b/vuu-ui/packages/vuu-utils/src/component-registry.ts index 99b2dc3f6..8e38011b9 100644 --- a/vuu-ui/packages/vuu-utils/src/component-registry.ts +++ b/vuu-ui/packages/vuu-utils/src/component-registry.ts @@ -4,7 +4,6 @@ import { ColumnDescriptorCustomRenderer, ColumnTypeRendering, EditValidationRule, - MappedValueTypeRenderer, TableCellRendererProps, } from "@finos/vuu-datagrid-types"; import { @@ -40,7 +39,7 @@ const optionsMap = new Map(); export type EditRuleValidator = ( editRule: EditValidationRule, - value: VuuRowDataItemType + value?: VuuRowDataItemType ) => boolean | string; export type ComponentType = diff --git a/vuu-ui/pom.xml b/vuu-ui/pom.xml index dcff1ee08..611cae637 100644 --- a/vuu-ui/pom.xml +++ b/vuu-ui/pom.xml @@ -4,7 +4,7 @@ org.finos.vuu vuu-parent - 0.5.09-SNAPSHOT + 0.9.36-SNAPSHOT vuu-ui diff --git a/vuu-ui/sample-apps/feature-basket-trading/src/VuuBasketTradingFeature.tsx b/vuu-ui/sample-apps/feature-basket-trading/src/VuuBasketTradingFeature.tsx index d40c26a70..56a3ccf18 100644 --- a/vuu-ui/sample-apps/feature-basket-trading/src/VuuBasketTradingFeature.tsx +++ b/vuu-ui/sample-apps/feature-basket-trading/src/VuuBasketTradingFeature.tsx @@ -33,6 +33,7 @@ const VuuBasketTradingFeature = (props: BasketTradingFeatureProps) => { activeTabIndex, basket, basketCount, + basketDesignContextMenuConfig, basketSelectorProps, contextMenuProps, dataSourceBasketTradingConstituentJoin, @@ -77,12 +78,12 @@ const VuuBasketTradingFeature = (props: BasketTradingFeatureProps) => { diff --git a/vuu-ui/sample-apps/feature-basket-trading/src/basket-table-edit/BasketTableEdit.tsx b/vuu-ui/sample-apps/feature-basket-trading/src/basket-table-edit/BasketTableEdit.tsx index d12b1b48b..668974f03 100644 --- a/vuu-ui/sample-apps/feature-basket-trading/src/basket-table-edit/BasketTableEdit.tsx +++ b/vuu-ui/sample-apps/feature-basket-trading/src/basket-table-edit/BasketTableEdit.tsx @@ -1,6 +1,10 @@ import { TableSchema } from "@finos/vuu-data"; -import { ColumnDescriptor, TableConfig } from "@finos/vuu-datagrid-types"; +import { TableConfig } from "@finos/vuu-datagrid-types"; import { TableNext, TableProps } from "@finos/vuu-table"; +import { + ContextMenuConfiguration, + ContextMenuProvider, +} from "@finos/vuu-popups"; import { useMemo } from "react"; import columns from "./basketConstituentEditColumns"; @@ -9,84 +13,16 @@ import "./BasketTableEdit.css"; const classBase = "vuuBasketTableEdit"; export interface BasketTableEditProps extends Omit { + contextMenuConfig: ContextMenuConfiguration; tableSchema: TableSchema; } -const labels: { [key: string]: string } = { - ask: "Ask", - bid: "Bid", - limitPrice: "Limit Price", - priceStrategy: "Price Strategy", - quantity: "Quantity", - weighting: "Weighting", -}; - -const applyColumnDefaults = (tableSchema: TableSchema) => - tableSchema.columns.map((column) => { - switch (column.name) { - case "limitPrice": - return { - ...column, - editable: true, - label: labels[column.name] ?? column.name, - type: { - name: "number", - formatting: { - alignOnDecimals: true, - decimals: 2, - zeroPad: true, - }, - renderer: { - name: "input-cell", - }, - }, - } as ColumnDescriptor; - case "quantity": - return { - ...column, - editable: true, - label: labels[column.name] ?? column.name, - type: { - name: "number", - formatting: { - decimals: 0, - }, - renderer: { - name: "input-cell", - }, - }, - }; - case "weighting": - return { - ...column, - editable: true, - label: labels[column.name] ?? column.name, - type: { - name: "number", - formatting: { - alignOnDecimals: true, - decimals: 2, - zeroPad: true, - }, - renderer: { - name: "input-cell", - }, - }, - }; - default: - return column; - } - }); - export const BasketTableEdit = ({ + contextMenuConfig, dataSource, tableSchema, ...props }: BasketTableEditProps) => { - useMemo(() => { - dataSource.columns = columns.map((col) => col.name); - }, [dataSource]); - const tableConfig = useMemo( () => ({ columns, @@ -96,13 +32,15 @@ export const BasketTableEdit = ({ ); return ( - + + + ); }; diff --git a/vuu-ui/sample-apps/feature-basket-trading/src/basket-table-live/BasketTableLive.tsx b/vuu-ui/sample-apps/feature-basket-trading/src/basket-table-live/BasketTableLive.tsx index 4c43ef12a..d54276fd9 100644 --- a/vuu-ui/sample-apps/feature-basket-trading/src/basket-table-live/BasketTableLive.tsx +++ b/vuu-ui/sample-apps/feature-basket-trading/src/basket-table-live/BasketTableLive.tsx @@ -1,8 +1,9 @@ import { TableSchema } from "@finos/vuu-data"; -import { ColumnDescriptor, TableConfig } from "@finos/vuu-datagrid-types"; +import { TableConfig } from "@finos/vuu-datagrid-types"; import { TableNext, TableProps } from "@finos/vuu-table"; import { useMemo } from "react"; import { StatusCell } from "../cell-renderers"; +import columns from "./basketConstituentLiveColumns"; console.log(`component loaded StatusCell ${typeof StatusCell}`); import "./BasketTableLive.css"; @@ -13,137 +14,20 @@ export interface BasketTableLiveProps extends Omit { tableSchema: TableSchema; } -const labels: { [key: string]: string } = { - ask: "Ask", - bid: "Bid", - filled: "Pct Filled", - limitPrice: "Limit Price", - priceSpread: "Price Spread", - priceStrategy: "Price Strategy", - quantity: "Quantity", - weighting: "Weighting", -}; - -const applyColumnDefaults = (tableSchema: TableSchema) => - tableSchema.columns.map((column) => { - switch (column.name) { - case "ric": - return { - ...column, - label: "Ticker", - pin: "left", - }; - case "status": - return { - ...column, - label: labels[column.name] ?? column.name, - type: { - name: "string", - renderer: { - name: "basket-status", - }, - }, - } as ColumnDescriptor; - case "ask": - case "bid": - case "last": - return { - ...column, - label: labels[column.name] ?? column.name, - type: { - name: "number", - formatting: { - alignOnDecimals: true, - decimals: 2, - zeroPad: true, - }, - }, - } as ColumnDescriptor; - case "limitPrice": - return { - ...column, - label: labels[column.name] ?? column.name, - type: { - name: "number", - formatting: { - alignOnDecimals: true, - decimals: 2, - zeroPad: true, - }, - }, - } as ColumnDescriptor; - case "priceStrategy": - return { - ...column, - label: labels[column.name] ?? column.name, - type: { - name: "string", - }, - }; - case "priceSpread": - return { - ...column, - label: labels[column.name] ?? column.name, - type: { - name: "number", - renderer: { - name: "basket-spread", - }, - }, - }; - case "quantity": - return { - ...column, - label: labels[column.name] ?? column.name, - type: { - name: "number", - formatting: { - decimals: 0, - }, - }, - }; - case "filled": - return { - ...column, - label: labels[column.name] ?? column.name, - type: { - name: "number", - renderer: { - name: "basket-progress", - associatedField: "quantity", - }, - }, - }; - case "weighting": - return { - ...column, - label: labels[column.name] ?? column.name, - type: { - name: "number", - formatting: { - alignOnDecimals: true, - decimals: 2, - zeroPad: true, - }, - }, - }; - default: - return column; - } - }); - export const BasketTableLive = ({ tableSchema, ...props }: BasketTableLiveProps) => { const tableConfig = useMemo( () => ({ - columns: applyColumnDefaults(tableSchema), + columns, rowSeparators: true, }), - [tableSchema] + [] ); + console.log({ columns }); + return (